diff options
Diffstat (limited to 'libgloss/mips')
111 files changed, 16088 insertions, 396 deletions
diff --git a/libgloss/mips/Makefile.in b/libgloss/mips/Makefile.in index 4213a1d..9e428b5 100644 --- a/libgloss/mips/Makefile.in +++ b/libgloss/mips/Makefile.in @@ -67,7 +67,8 @@ OBJCOPY = `if [ -f ${objroot}/../binutils/objcopy ] ; \ CRT0 = @MIPS_CRT0@ PCRT0 = pcrt0.o GENOBJS = syscalls.o fstat.o getpid.o isatty.o kill.o \ - lseek.o print.o putnum.o stat.o unlink.o + lseek.o print.o putnum.o stat.o unlink.o __exit.o link.o \ + get_ram_range.o GENOBJS2 = open.o close.o read.o write.o IDTOBJS = idtmon.o @MIPS_PART_SPECIFIC_OBJ@ ${GENOBJS} PMONOBJS = pmon.o @MIPS_PART_SPECIFIC_OBJ@ ${GENOBJS} @@ -77,11 +78,125 @@ JMR3904OBJS = jmr3904-io.o @MIPS_PART_SPECIFIC_OBJ@ ${GENOBJS} ${GENOBJS2} CFEOBJS = cfe.o cfe_api.o cfe_mem.o @MIPS_PART_SPECIFIC_OBJ@ ${GENOBJS} ${GENOBJS2} CYGMONOBJS = open.o close.o cygmon.o @MIPS_PART_SPECIFIC_OBJ@ ${GENOBJS} + +ISROBJS = mips_excpt_isr_fallback.o +ISROBJS += mips_excpt_isr_000.o mips_excpt_isr_001.o mips_excpt_isr_002.o +ISROBJS += mips_excpt_isr_003.o mips_excpt_isr_004.o mips_excpt_isr_005.o +ISROBJS += mips_excpt_isr_006.o mips_excpt_isr_007.o mips_excpt_isr_008.o +ISROBJS += mips_excpt_isr_009.o mips_excpt_isr_010.o mips_excpt_isr_011.o +ISROBJS += mips_excpt_isr_012.o mips_excpt_isr_013.o mips_excpt_isr_014.o +ISROBJS += mips_excpt_isr_015.o mips_excpt_isr_016.o mips_excpt_isr_017.o +ISROBJS += mips_excpt_isr_018.o mips_excpt_isr_019.o mips_excpt_isr_020.o +ISROBJS += mips_excpt_isr_021.o mips_excpt_isr_022.o mips_excpt_isr_023.o +ISROBJS += mips_excpt_isr_024.o mips_excpt_isr_025.o mips_excpt_isr_026.o +ISROBJS += mips_excpt_isr_027.o mips_excpt_isr_028.o mips_excpt_isr_029.o +ISROBJS += mips_excpt_isr_030.o mips_excpt_isr_031.o mips_excpt_isr_032.o +ISROBJS += mips_excpt_isr_033.o mips_excpt_isr_034.o mips_excpt_isr_035.o +ISROBJS += mips_excpt_isr_036.o mips_excpt_isr_037.o mips_excpt_isr_038.o +ISROBJS += mips_excpt_isr_039.o mips_excpt_isr_040.o mips_excpt_isr_041.o +ISROBJS += mips_excpt_isr_042.o mips_excpt_isr_043.o mips_excpt_isr_044.o +ISROBJS += mips_excpt_isr_045.o mips_excpt_isr_046.o mips_excpt_isr_047.o +ISROBJS += mips_excpt_isr_048.o mips_excpt_isr_049.o mips_excpt_isr_050.o +ISROBJS += mips_excpt_isr_051.o mips_excpt_isr_052.o mips_excpt_isr_053.o +ISROBJS += mips_excpt_isr_054.o mips_excpt_isr_055.o mips_excpt_isr_056.o +ISROBJS += mips_excpt_isr_057.o mips_excpt_isr_058.o mips_excpt_isr_059.o +ISROBJS += mips_excpt_isr_060.o mips_excpt_isr_061.o mips_excpt_isr_062.o +ISROBJS += mips_excpt_isr_063.o mips_excpt_isr_064.o mips_excpt_isr_065.o +ISROBJS += mips_excpt_isr_066.o mips_excpt_isr_067.o mips_excpt_isr_068.o +ISROBJS += mips_excpt_isr_069.o mips_excpt_isr_070.o mips_excpt_isr_071.o +ISROBJS += mips_excpt_isr_072.o mips_excpt_isr_073.o mips_excpt_isr_074.o +ISROBJS += mips_excpt_isr_075.o mips_excpt_isr_076.o mips_excpt_isr_077.o +ISROBJS += mips_excpt_isr_078.o mips_excpt_isr_079.o mips_excpt_isr_080.o +ISROBJS += mips_excpt_isr_081.o mips_excpt_isr_082.o mips_excpt_isr_083.o +ISROBJS += mips_excpt_isr_084.o mips_excpt_isr_085.o mips_excpt_isr_086.o +ISROBJS += mips_excpt_isr_087.o mips_excpt_isr_088.o mips_excpt_isr_089.o +ISROBJS += mips_excpt_isr_090.o mips_excpt_isr_091.o mips_excpt_isr_092.o +ISROBJS += mips_excpt_isr_093.o mips_excpt_isr_094.o mips_excpt_isr_095.o +ISROBJS += mips_excpt_isr_096.o mips_excpt_isr_097.o mips_excpt_isr_098.o +ISROBJS += mips_excpt_isr_099.o mips_excpt_isr_100.o mips_excpt_isr_101.o +ISROBJS += mips_excpt_isr_102.o mips_excpt_isr_103.o mips_excpt_isr_104.o +ISROBJS += mips_excpt_isr_105.o mips_excpt_isr_106.o mips_excpt_isr_107.o +ISROBJS += mips_excpt_isr_108.o mips_excpt_isr_109.o mips_excpt_isr_110.o +ISROBJS += mips_excpt_isr_111.o mips_excpt_isr_112.o mips_excpt_isr_113.o +ISROBJS += mips_excpt_isr_114.o mips_excpt_isr_115.o mips_excpt_isr_116.o +ISROBJS += mips_excpt_isr_117.o mips_excpt_isr_118.o mips_excpt_isr_119.o +ISROBJS += mips_excpt_isr_120.o mips_excpt_isr_121.o mips_excpt_isr_122.o +ISROBJS += mips_excpt_isr_123.o mips_excpt_isr_124.o mips_excpt_isr_125.o +ISROBJS += mips_excpt_isr_126.o mips_excpt_isr_127.o mips_excpt_isr_128.o +ISROBJS += mips_excpt_isr_129.o mips_excpt_isr_130.o mips_excpt_isr_131.o +ISROBJS += mips_excpt_isr_132.o mips_excpt_isr_133.o mips_excpt_isr_134.o +ISROBJS += mips_excpt_isr_135.o mips_excpt_isr_136.o mips_excpt_isr_137.o +ISROBJS += mips_excpt_isr_138.o mips_excpt_isr_139.o mips_excpt_isr_140.o +ISROBJS += mips_excpt_isr_141.o mips_excpt_isr_142.o mips_excpt_isr_143.o +ISROBJS += mips_excpt_isr_144.o mips_excpt_isr_145.o mips_excpt_isr_146.o +ISROBJS += mips_excpt_isr_147.o mips_excpt_isr_148.o mips_excpt_isr_149.o +ISROBJS += mips_excpt_isr_150.o mips_excpt_isr_151.o mips_excpt_isr_152.o +ISROBJS += mips_excpt_isr_153.o mips_excpt_isr_154.o mips_excpt_isr_155.o +ISROBJS += mips_excpt_isr_156.o mips_excpt_isr_157.o mips_excpt_isr_158.o +ISROBJS += mips_excpt_isr_159.o mips_excpt_isr_160.o mips_excpt_isr_161.o +ISROBJS += mips_excpt_isr_162.o mips_excpt_isr_163.o mips_excpt_isr_164.o +ISROBJS += mips_excpt_isr_165.o mips_excpt_isr_166.o mips_excpt_isr_167.o +ISROBJS += mips_excpt_isr_168.o mips_excpt_isr_169.o mips_excpt_isr_170.o +ISROBJS += mips_excpt_isr_171.o mips_excpt_isr_172.o mips_excpt_isr_173.o +ISROBJS += mips_excpt_isr_174.o mips_excpt_isr_175.o mips_excpt_isr_176.o +ISROBJS += mips_excpt_isr_177.o mips_excpt_isr_178.o mips_excpt_isr_179.o +ISROBJS += mips_excpt_isr_180.o mips_excpt_isr_181.o mips_excpt_isr_182.o +ISROBJS += mips_excpt_isr_183.o mips_excpt_isr_184.o mips_excpt_isr_185.o +ISROBJS += mips_excpt_isr_186.o mips_excpt_isr_187.o mips_excpt_isr_188.o +ISROBJS += mips_excpt_isr_189.o mips_excpt_isr_190.o mips_excpt_isr_191.o +ISROBJS += mips_excpt_isr_192.o mips_excpt_isr_193.o mips_excpt_isr_194.o +ISROBJS += mips_excpt_isr_195.o mips_excpt_isr_196.o mips_excpt_isr_197.o +ISROBJS += mips_excpt_isr_198.o mips_excpt_isr_199.o mips_excpt_isr_200.o +ISROBJS += mips_excpt_isr_201.o mips_excpt_isr_202.o mips_excpt_isr_203.o +ISROBJS += mips_excpt_isr_204.o mips_excpt_isr_205.o mips_excpt_isr_206.o +ISROBJS += mips_excpt_isr_207.o mips_excpt_isr_208.o mips_excpt_isr_209.o +ISROBJS += mips_excpt_isr_210.o mips_excpt_isr_211.o mips_excpt_isr_212.o +ISROBJS += mips_excpt_isr_213.o mips_excpt_isr_214.o mips_excpt_isr_215.o +ISROBJS += mips_excpt_isr_216.o mips_excpt_isr_217.o mips_excpt_isr_218.o +ISROBJS += mips_excpt_isr_219.o mips_excpt_isr_220.o mips_excpt_isr_221.o +ISROBJS += mips_excpt_isr_222.o mips_excpt_isr_223.o mips_excpt_isr_224.o +ISROBJS += mips_excpt_isr_225.o mips_excpt_isr_226.o mips_excpt_isr_227.o +ISROBJS += mips_excpt_isr_228.o mips_excpt_isr_229.o mips_excpt_isr_230.o +ISROBJS += mips_excpt_isr_231.o mips_excpt_isr_232.o mips_excpt_isr_233.o +ISROBJS += mips_excpt_isr_234.o mips_excpt_isr_235.o mips_excpt_isr_236.o +ISROBJS += mips_excpt_isr_237.o mips_excpt_isr_238.o mips_excpt_isr_239.o +ISROBJS += mips_excpt_isr_240.o mips_excpt_isr_241.o mips_excpt_isr_242.o +ISROBJS += mips_excpt_isr_243.o mips_excpt_isr_244.o mips_excpt_isr_245.o +ISROBJS += mips_excpt_isr_246.o mips_excpt_isr_247.o mips_excpt_isr_248.o +ISROBJS += mips_excpt_isr_249.o mips_excpt_isr_250.o mips_excpt_isr_251.o +ISROBJS += mips_excpt_isr_252.o mips_excpt_isr_253.o mips_excpt_isr_254.o +ISROBJS += mips_excpt_isr_255.o + +UHIOBJS = uhi_assert.o uhi_close.o uhi_exit.o uhi_fstat.o \ + uhi_lseek.o uhi_open.o uhi_plog.o \ + uhi_pread.o uhi_pwrite.o uhi_read.o uhi_link.o uhi_stat.o \ + uhi_unlink.o uhi_write.o uhi_getargs.o uhi_exception.o \ + uhi_get_ram_range.o uhi_indirect.o uhi_break.o \ + syscalls.o getpid.o isatty.o kill.o + +YAMONOBJS = yamon_read.o yamon_write.o yamon_exit.o yamon_close.o \ + yamon_fstat.o yamon_exception.o + +HALOBJ = mips_clean_cache.o mips_flush_cache.o mips_l2size.o \ + mips_lock_cache.o mips_size_cache.o mips_sync_cache.o \ + mips_fp.o \ + mips_excpt_entry.o mips_excpt_handler.o mips_excpt_handler_quiet.o \ + mips_excpt_register.o mips_excpt_boot.o \ + mips_intctrl.o $(ISROBJS) + +HALOBJ += mips_tlb.o + +HALOBJ += mips64_tlb.o mips_xpa.o mips_msa.o + +BOOTOBJ = reset.o init_cp0.o init_caches.o init_tlb.o init_l23caches.o + +CM3OBJ_IMPL = mips_cm3_l2size.o init_cm3l2.o + +CM3AR = libcm3.a + # Nullmon cannot support read and write, but the test cases pull them in via libs NULLMONOBJS = nullmon.o @MIPS_PART_SPECIFIC_OBJ@ ${GENOBJS} -CFLAGS = -g - GCC_LDFLAGS = `if [ -d ${objroot}/../gcc ] ; \ then echo -L${objroot}/../gcc ; fi` @@ -93,6 +208,14 @@ PART_SPECIFIC_DEFINES = @MIPS_PART_SPECIFIC_DEFINES@ # Host specific makefile fragment comes in here. @host_makefile_frag@ +HALCFLAGS += -g \ + -fdebug-prefix-map=$(srcdir)=$(DESTDIR)$(exec_prefix)/share/mips \ + -fdebug-prefix-map=$(srcdir)/include=$(DESTDIR)$(exec_prefix)/$(target_alias)/include \ + -Wa,--debug-prefix-map=$(srcdir)=$(DESTDIR)$(exec_prefix)/share/mips \ + -Wa,--debug-prefix-map=$(srcdir)/include=$(DESTDIR)$(exec_prefix)/$(target_alias)/include \ + -Werror + +HALCFLAGS += -I $(srcdir)/include # # build a test program for each target board. Just trying to get # it to link is a good test, so we ignore all the errors for now. @@ -140,6 +263,22 @@ libcfe.a: $(CFEOBJS) ${AR} ${ARFLAGS} $@ $(CFEOBJS) ${RANLIB} $@ +libuhi.a: $(UHIOBJS) + ${AR} ${ARFLAGS} $@ $(UHIOBJS) + ${RANLIB} $@ + +libyamon.a: $(YAMONOBJS) + ${AR} ${ARFLAGS} $@ $(YAMONOBJS) + ${RANLIB} $@ + +libhal.a: $(HALOBJ) $(BOOTOBJ) + ${AR} ${ARFLAGS} $@ $^ + ${RANLIB} $@ + +libcm3_impl.a: $(CM3OBJ_IMPL) + ${AR} ${ARFLAGS} $@ $^ + ${RANLIB} $@ + # nullmon.a , This is what you want if you want crt0 but NO mon services # Supports GDB sim testing, board bringups, ICE operation. libnullmon.a: $(NULLMONOBJS) @@ -191,10 +330,10 @@ cfe-test.dis: cfe-test.x $(OBJDUMP) -d cfe-test.x > $@ cfe-test: cfe-test.srec cfe-test.dis -doc: +doc: clean mostlyclean: - rm -f a.out core *.i *~ *.o *-test *.srec *.dis *.map *.x + rm -f a.out core *.i *~ *.a *.o *-test *.srec *.dis *.map *.x distclean maintainer-clean realclean: clean rm -f Makefile config.status a.out @@ -205,9 +344,32 @@ install: @for file in $(CRT0) $(PCRT0) $(BSP); do \ $(INSTALL_DATA) $${file} $(DESTDIR)$(tooldir)/lib${MULTISUBDIR}/$${file}; \ done + $(INSTALL_DATA) ${srcdir}/hal/libcm3.a $(DESTDIR)$(tooldir)/lib${MULTISUBDIR}/libcm3.a @for script in ${SCRIPTS}; do\ $(INSTALL_DATA) ${srcdir}/$${script}.ld $(DESTDIR)$(tooldir)/lib${MULTISUBDIR}/$${script}.ld; \ done + mkdir -p $(DESTDIR)$(tooldir)/include/mips + @for header in ${srcdir}/include/mips/*.h; do\ + $(INSTALL_DATA) $${header} $(DESTDIR)$(tooldir)/include/mips; \ + done + @for file in ${srcdir}/include/mips/*.S; do\ + $(INSTALL_DATA) $${file} $(DESTDIR)$(tooldir)/include/mips; \ + done + mkdir -p $(DESTDIR)$(exec_prefix)/share/mips/boot + @for file in ${srcdir}/boot/*.[hS] ; do\ + $(INSTALL_DATA) $${file} $(DESTDIR)$(exec_prefix)/share/mips/boot/; \ + done + mkdir -p $(DESTDIR)$(exec_prefix)/share/mips/hal + @for file in ${srcdir}/hal/*.[hSc]; do\ + $(INSTALL_DATA) $${file} $(DESTDIR)$(exec_prefix)/share/mips/hal/; \ + done + mkdir -p $(DESTDIR)$(exec_prefix)/share/mips/uhi + @for file in ${srcdir}/uhi/uhi_*.[hSc] ${srcdir}/uhi/yamon_*.[hSc]; do\ + $(INSTALL_DATA) $${file} $(DESTDIR)$(exec_prefix)/share/mips/uhi/; \ + done + mkdir -p $(DESTDIR)$(exec_prefix)/share/mips/rules + @$(INSTALL_DATA) ${srcdir}/rules/mipshal.mk $(DESTDIR)$(exec_prefix)/share/mips/rules/ + @$(INSTALL_PROGRAM) ${srcdir}/rules/srec2hex.pl $(DESTDIR)$(exec_prefix)/share/mips/rules/ info: install-info: @@ -216,39 +378,43 @@ clean-info: test.o: ${srcdir}/test.c # these are for the BSPs -crt0.o: ${srcdir}/crt0.S -pcrt0.o: ${srcdir}/crt0.S - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) -DGCRT0 ${srcdir}/crt0.S -o ${PCRT0} +crt0.o: ${srcdir}/hal/crt0.S + $(CC) -c $(CFLAGS_FOR_TARGET) $(HALCFLAGS) $(CFLAGS) $(INCLUDES) $^ -o $@ +pcrt0.o: ${srcdir}/hal/crt0.S + $(CC) -c $(CFLAGS_FOR_TARGET) $(HALCFLAGS) $(CFLAGS) $(INCLUDES) -DGCRT0 $^ -o ${PCRT0} crt0_cfe.o: ${srcdir}/crt0_cfe.S crt0_cygmon.o: ${srcdir}/crt0_cygmon.S idtmon.o: ${srcdir}/idtmon.S pmon.o: ${srcdir}/pmon.S - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $(PART_SPECIFIC_DEFINES) ${srcdir}/pmon.S -o pmon.o + $(CC) -c $(CFLAGS_FOR_TARGET) $(HALCFLAGS) $(CFLAGS) $(PART_SPECIFIC_DEFINES) $^ -o $@ vr4300.o: ${srcdir}/vr4300.S - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/vr4300.S + $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $^ -o $@ vr5xxx.o: ${srcdir}/vr5xxx.S - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/vr5xxx.S + $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $^ -o $@ lsipmon.o: $(srcdir)/lsipmon.S $(srcdir)/pmon.S +__exit.o: ${srcdir}/hal/__exit.c + $(CC) -c $(CFLAGS_FOR_TARGET) $(HALCFLAGS) $(INCLUDES) $(CFLAGS) $^ -o $@ jmr3904-io.o: ${srcdir}/jmr3904-io.c - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/jmr3904-io.c -o $@ + $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $^ -o $@ cfe.o: ${srcdir}/cfe.c ${srcdir}/cfe_api.h - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/cfe.c -o $@ + $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $< -o $@ cfe_api.o: ${srcdir}/cfe_api.c ${srcdir}/cfe_api.h ${srcdir}/cfe_api_int.h - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/cfe_api.c -o $@ + $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $< -o $@ cfe_mem.o: ${srcdir}/cfe_mem.c ${srcdir}/cfe_api.h - $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/cfe_mem.c -o $@ + $(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $< -o $@ # cma101 can not be compiled mips16, if a mips16 version is needed then # it will have to be built, then this rule can be scrapped, allowing # the implicit rule to run. cma101.o: ${srcdir}/cma101.c - $(CC) -c $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) $(CFLAGS) -mno-mips16 ${srcdir}/cma101.c + $(CC) -c $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) $(CFLAGS) -mno-mips16 $^ # cygmon can not be compiled as mips16 since it uses the syscall instruction cygmon.o: ${srcdir}/cygmon.c - $(CC) -c $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) $(CFLAGS) -mno-mips16 ${srcdir}/cygmon.c + $(CC) -c $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) $(CFLAGS) -mno-mips16 $^ -syscalls.o: ${srcdir}/syscalls.c +syscalls.o: ${srcdir}/hal/syscalls.c + $(CC) -c $(CFLAGS_FOR_TARGET) $(HALCFLAGS) $(INCLUDES) $(CFLAGS) $< -o $@ # target specific makefile fragment comes in here. @target_makefile_frag@ diff --git a/libgloss/mips/acinclude.m4 b/libgloss/mips/acinclude.m4 index 6061d8d..cda8d77 100644 --- a/libgloss/mips/acinclude.m4 +++ b/libgloss/mips/acinclude.m4 @@ -9,18 +9,16 @@ case "${target}" in MIPS_SCRIPT_LIST="dve idt jmr3904app jmr3904dram jmr3904dram-java jmr3904app-java sde32 sde64 mti32 mti64 mti64_n32 mti64_64" MIPS_BSP_LIST="libdve.a libidt.a libjmr3904.a" ;; - mipsisa32-*-* | mipsisa32el-*-* | \ - mipsisa32r2-*-* | mipsisa32r2el-*-* | \ - mipsisa64*-*-*) - MIPS_CRT0="crt0_cfe.o crt0_cygmon.o crt0.o" - MIPS_SCRIPT_LIST="idt32 idt64 cfe" - MIPS_BSP_LIST="libcygmon.a libidt.a libcfe.a" - ;; mips*-lsi*-*) MIPS_PART_SPECIFIC_OBJ="entry.o" MIPS_SCRIPT_LIST="lsi" MIPS_BSP_LIST=liblsi.a ;; + mips*-mti*-* | mips*-img*-*) + MIPS_CRT0="crt0.o" + MIPS_SCRIPT_LIST="idt nullmon mti32 mti64_n32 mti64_64 uhi32 uhi64_64 uhi64_n32 malta32-yamon bootcode" + MIPS_BSP_LIST="libidt.a libnullmon.a libuhi.a libyamon.a libhal.a libcm3_impl.a" + ;; mips64vr5*-*-*) MIPS_PART_SPECIFIC_OBJ="vr5xxx.o cma101.o" MIPS_PART_SPECIFIC_DEFINES=-DR5000 @@ -32,6 +30,13 @@ case "${target}" in MIPS_SCRIPT_LIST="ddb ddb-kseg0 nullmon" MIPS_BSP_LIST="libpmon.a libnullmon.a" ;; + mipsisa32-*-* | mipsisa32el-*-* | \ + mipsisa32r2-*-* | mipsisa32r2el-*-* | \ + mipsisa64*-*-*) + MIPS_CRT0="crt0_cfe.o crt0_cygmon.o crt0.o" + MIPS_SCRIPT_LIST="idt32 idt64 cfe" + MIPS_BSP_LIST="libcygmon.a libidt.a libcfe.a" + ;; mips*) MIPS_CRT0="crt0_cfe.o crt0.o" MIPS_PART_SPECIFIC_OBJ="vr4300.o cma101.o" diff --git a/libgloss/mips/boot/corecheck_predef.S b/libgloss/mips/boot/corecheck_predef.S new file mode 100644 index 0000000..62f1b2c --- /dev/null +++ b/libgloss/mips/boot/corecheck_predef.S @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _RESETCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/cm3.h> +#include "predef.h" + +MIPS_NOMIPS16 + +/* Config 0 has some RO fields. */ +#if defined (C0_CONFIG0_VALUE) +#define C0_CONFIG0_RO (CFG0_M | CFG0_AT_MASK | CFG0_AR_MASK | \ + CFG0_MT_MASK | CFG0_VI) +#define C0_CONFIG0_EXP (C0_CONFIG0_RO & C0_CONFIG0_VALUE) +#endif + +/* Config 1 has no RW fields. */ +#if defined(C0_CONFIG1_VALUE) +#define C0_CONFIG1_RO (0xffffffff) +#define C0_CONFIG1_EXP (C0_CONFIG1_RO & C0_CONFIG1_VALUE) +#endif + +/* Config 2 has 2 RW fields. */ +#if defined(C0_CONFIG2_VALUE) +#define C0_CONFIG2_RO ~(CFG2_TU_MASK | CFG2_SU_MASK) +#define C0_CONFIG2_EXP (C0_CONFIG2_RO & C0_CONFIG2_VALUE) +#endif + +/* Config 3 has only 1 R/W bit (microMIPS on exception) */ +#if defined(C0_CONFIG3_VALUE) +#define C0_CONFIG3_RO (~CFG3_IOE) +#define C0_CONFIG3_EXP (C0_CONFIG3_RO & C0_CONFIG3_VALUE) +#endif + + +/* Config 4 has only 1 field R/W (FTLB page size) */ +#if defined(C0_CONFIG4_VALUE) +#define C0_CONFIG4_RO (~CFG4_FTLBPS_MASK) +#define C0_CONFIG4_EXP (C0_CONFIG4_RO & C0_CONFIG4_VALUE) +#endif + +/* Config 5 has only a few fields and some of them are RO. */ +#if defined(C0_CONFIG5_VALUE) +#define C0_CONFIG5_RO (CFG5_MVH | CFG5_LLB | CFG5_MRP | CFG5_NF) +#define C0_CONFIG5_EXP (C0_CONFIG5_RO & C0_CONFIG5_VALUE) +#endif + +#if defined(C0_CMGCRBASE_VALUE) +#define C0_CMGCRBASE_ADDR ((C0_CMGCRBASE_VALUE << 4) | (0xb << 28)) +#define C0_CMGCRBASE_RO (0xffffffff) +#define C0_CMGCRBASE_EXP C0_CMGCRBASE_VALUE +#endif + +/* GCR L2 config has REG_EXISTS and L2 config as readonly nozero fields. */ +#if defined(GCR_L2_CONFIG) +#define GCR_L2_CONFIG_RO ((1<<31) | ((1<<16) - 1)) +#define GCR_L2_CONFIG_EXP GCR_L2_CONFIG_VALUE +#endif + +LEAF(__core_check) + /* + * Compare the expected value to the RO fields + * of the config register + */ +#if defined(C0_CONFIG0_VALUE) + li t0, C0_CONFIG0_EXP + li t1, C0_CONFIG0_RO + mfc0 t3, C0_CONFIG + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG1_VALUE) + li t0, C0_CONFIG1_EXP + li t1, C0_CONFIG1_RO + mfc0 t3, C0_CONFIG1 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG2_VALUE) + li t0, C0_CONFIG2_EXP + li t1, C0_CONFIG2_RO + mfc0 t3, C0_CONFIG2 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG3_VALUE) + li t0, C0_CONFIG3_EXP + li t1, C0_CONFIG3_RO + mfc0 t3, C0_CONFIG3 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG4_VALUE) + li t0, C0_CONFIG4_EXP + li t1, C0_CONFIG4_RO + mfc0 t3, C0_CONFIG4 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CONFIG5_VALUE) + li t0, C0_CONFIG5_EXP + li t1, C0_CONFIG5_RO + mfc0 t3, C0_CONFIG5 + and t2, t1, t3 + bne t2, t0, 1f +#endif + +#if defined(C0_CMGCRBASE_VALUE) + li t0, C0_CMGCRBASE_EXP + li t1, C0_CMGCRBASE_RO + mfc0 t3, C0_CMGCRBASE + and t2, t1, t3 + bne t2, t0, 1f +#if defined(GCR_L2_CONFIG_VALUE) + li t0, GCR_L2_CONFIG_EXP + li t1, GCR_L2_CONFIG_RO + li t2, C0_CMGCRBASE_ADDR + lw t3, GCR_L2_CONFIG(t2) + and t2, t1, t3 + bne t2, t0, 1f +#endif +#endif + +#if defined(C0_WATCHHI_VALUE) + mfc0 t0, C0_WATCHHI, 0 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI1_VALUE) + mfc0 t0, C0_WATCHHI, 1 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI1_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI2_VALUE) + mfc0 t0, C0_WATCHHI, 2 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI2_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI3_VALUE) + mfc0 t0, C0_WATCHHI, 3 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI3_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI4_VALUE) + mfc0 t0, C0_WATCHHI, 4 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI4_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI5_VALUE) + mfc0 t0, C0_WATCHHI, 5 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI5_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + +#if defined(C0_WATCHHI6_VALUE) + mfc0 t0, C0_WATCHHI, 6 + ext t0, t0, WATCHHI_M_SHIFT, 1 + + li t1, ((C0_WATCHHI6_VALUE & WATCHHI_M) >> WATCHHI_M_SHIFT) + bne t0, t1, 1f +#endif + + b 2f +1: + /* Incorrect config supplied, report a boot failure through UHI */ + li t9, 23 + /* Reason - Predef config incorrect */ + li a0, 2 + /* Trigger the UHI operation */ + sdbbp 1 + /* In case a debugger corrects this failure */ + +2: + jr ra + +END(__core_check) diff --git a/libgloss/mips/boot/init_caches.S b/libgloss/mips/boot/init_caches.S new file mode 100644 index 0000000..fb5ef11 --- /dev/null +++ b/libgloss/mips/boot/init_caches.S @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + +#define LINE_SIZE vt0 +#define SET_SIZE vt1 +#define ASSOC a0 +#define TOTAL_BYTES a1 +#define CURR_ADDR1 a2 +#define CURR_ADDR2 a3 +#define END_ADDR t0 +#define CONFIG t1 +#define CONFIG1 t2 +#define TEMP t3 + + .set noat + +/* + * init_icache invalidates all instruction cache entries + */ + +LEAF(__init_icache) + mfc0 CONFIG1, C0_CONFIG1 + + ext LINE_SIZE, CONFIG1, CFG1_IL_SHIFT, 3 + + /* Skip ahead if No I$ */ + li TEMP, 2 + beqz LINE_SIZE, $Ldone_icache + sllv LINE_SIZE, TEMP, LINE_SIZE /* Now have true I$ line size in bytes */ + + ext SET_SIZE, CONFIG1, CFG1_IS_SHIFT, 3 + addiu SET_SIZE, SET_SIZE, 1 /* Rotate to account for 7 == 32 sets */ + andi SET_SIZE, SET_SIZE, 7 /* Mask down to 3-bit */ + li TEMP, 32 + sllv SET_SIZE, TEMP, SET_SIZE /* I$ Sets per way */ + + // Config1IA == I$ Assoc - 1 + ext ASSOC, CONFIG1, CFG1_IA_SHIFT, 3 + addiu ASSOC, ASSOC, 1 + + mul SET_SIZE, SET_SIZE, ASSOC /* Total number of sets */ + mul TOTAL_BYTES, SET_SIZE, LINE_SIZE /* Total number of bytes */ + + li CURR_ADDR2, 0x80000000 /* Get a KSeg0 address for cacheops */ + subu CURR_ADDR2, CURR_ADDR2, LINE_SIZE /* Pre-bias the addresses as the loop */ + subu CURR_ADDR1, CURR_ADDR2, LINE_SIZE /* increments them first */ + + addu END_ADDR, CURR_ADDR1, TOTAL_BYTES /* END_ADDR is last line to invalidate */ + sll LINE_SIZE, LINE_SIZE, 1 /* Double line size as we process two */ + /* per loop */ + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + +$Lnext_icache_tag: + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ + addu CURR_ADDR1, LINE_SIZE + addu CURR_ADDR2, LINE_SIZE + cache Index_Store_Tag_I, 0(CURR_ADDR1) + cache Index_Store_Tag_I, 0(CURR_ADDR2) + bne CURR_ADDR1, END_ADDR, $Lnext_icache_tag + +$Ldone_icache: + jr ra +END(__init_icache) + +/* + * init_dcache invalidates all data cache entries + */ + +LEAF(__init_dcache) + mfc0 CONFIG1, C0_CONFIG1 + ext LINE_SIZE, CONFIG1, CFG1_DL_SHIFT, 3 + + /* Skip ahead if No D$ */ + li TEMP, 2 + beqz LINE_SIZE, $Ldone_dcache + + sllv LINE_SIZE, TEMP, LINE_SIZE /* Now have true D$ line size in bytes */ + + ext SET_SIZE, CONFIG1, CFG1_DS_SHIFT, 3 + addiu SET_SIZE, SET_SIZE, 1 /* Rotate to account for 7 == 32 sets */ + andi SET_SIZE, SET_SIZE, 7 /* Mask down to 3-bit */ + li TEMP, 32 + sllv SET_SIZE, TEMP, SET_SIZE /* D$ Sets per way */ + + /* Config1.DA == D$ Assoc - 1 */ + ext ASSOC, CONFIG1, CFG1_DA_SHIFT, 3 + addiu ASSOC, 1 + + mul SET_SIZE, SET_SIZE, ASSOC /* Get total number of sets */ + mul TOTAL_BYTES, SET_SIZE, LINE_SIZE /* Total number of bytes */ + + li CURR_ADDR2, 0x80000000 /* Get a KSeg0 address for cacheops */ + subu CURR_ADDR2, CURR_ADDR2, LINE_SIZE /* Pre-bias the addresses as the loop */ + subu CURR_ADDR1, CURR_ADDR2, LINE_SIZE /* increments them first */ + + addu END_ADDR, CURR_ADDR1, TOTAL_BYTES /* END_ADDR is last line to invalidate */ + sll LINE_SIZE, LINE_SIZE, 1 /* Double line size as we process two */ + /* per loop*/ + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + mtc0 zero, C0_TAGLO, 2 + mtc0 zero, C0_TAGHI, 2 + +$Lnext_dcache_tag: + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ + addu CURR_ADDR1, LINE_SIZE + addu CURR_ADDR2, LINE_SIZE + cache Index_Store_Tag_D, 0(CURR_ADDR1) + cache Index_Store_Tag_D, 0(CURR_ADDR2) + bne CURR_ADDR1, END_ADDR, $Lnext_dcache_tag + +$Ldone_dcache: + jr ra + +END(__init_dcache) + +/* + * __change_k0_cca essentially turns the cache on + */ + +LEAF(__change_k0_cca) + /* + * NOTE! This code must be executed in KSEG1 (not KSEG0 uncached) + * Set CCA for kseg0 to cacheable + */ + mfc0 CONFIG, C0_CONFIG + li TEMP, CFG_C_NONCOHERENT + +$Lset_kseg0_cca: + ins CONFIG, TEMP, 0, 3 + mtc0 CONFIG, C0_CONFIG + MIPS_JRHB (ra) + +END(__change_k0_cca) diff --git a/libgloss/mips/boot/init_caches_predef.S b/libgloss/mips/boot/init_caches_predef.S new file mode 100644 index 0000000..27e82b0 --- /dev/null +++ b/libgloss/mips/boot/init_caches_predef.S @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + +/* + * Depending on the range of the displacement field of the CACHE instruction + * we can do multiple cacheops per iteration. With a cache present there + * is a guarantee of 32 lines minimum so a power of 2 less than or equal + * to 32 means there is no remainder after the loop. + * The maximum number of lines per iteration is the range of the CACHE + * displacement divided by the line_size. We cap this at 8 as a sensible + * bound. + */ + +#if __mips_isa_rev < 6 +/* MicroMIPS Release 3 has a 12-bit displacement for CACHE */ +# define ILINES_PER_ITER 8 +# define DLINES_PER_ITER 8 +#else +/* MIPS Release 6 has a 9-bit signed displacement for CACHE */ +#if ILINE_SIZE == 128 +# define ILINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define ILINES_PER_ITER 8 +#endif +#if DLINE_SIZE == 128 +# define DLINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define DLINES_PER_ITER 8 +#endif +#endif + +/* + * Start off pointing to one block below where we want to invalidate the cache + * as the pointer is moved on at the start of the loop. Also offset the start + * address for each set of cache lines so that the positive and negative + * displacements from the CACHE ops can be used. + */ + +#define ICACHE_START (0x80000000 - (ILINE_SIZE * ILINES_PER_ITER / 2)) +#define ICACHE_END (0x80000000 + ITOTAL_BYTES - (ILINE_SIZE * ILINES_PER_ITER / 2)) +#define DCACHE_START (0x80000000 - (DLINE_SIZE * DLINES_PER_ITER / 2)) +#define DCACHE_END (0x80000000 + DTOTAL_BYTES - (DLINE_SIZE * DLINES_PER_ITER / 2)) + +#define CURRENT_ADDR a0 +#define END_ADDR a1 +#define CONFIG a2 +#define TEMP a3 + + .set noat + +/* + * init_icache invalidates all instruction cache entries + */ +#if defined(ILINE_ENC) && ILINE_ENC != 0 +LEAF(__init_icache) + /* Use KSEG0 base address */ + li CURRENT_ADDR, ICACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, ICACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_icache_tag: + addu CURRENT_ADDR, (ILINE_SIZE * ILINES_PER_ITER) + cache Index_Store_Tag_I, (ILINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*1)(CURRENT_ADDR) +#if ILINES_PER_ITER == 8 + cache Index_Store_Tag_I, (ILINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_I, (ILINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_icache_tag + +$Ldone_icache: + jr ra +END(__init_icache) + +#endif // ILINE_ENC != 0 + +/* + * init_dcache invalidates all data cache entries + */ + +#if defined(DLINE_ENC) && DLINE_ENC != 0 +LEAF(__init_dcache) + /* Use KSEG0 base address */ + li CURRENT_ADDR, DCACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, DCACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI + mtc0 zero, C0_TAGLO, 2 + mtc0 zero, C0_TAGHI, 2 + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_dcache_tag: + addu CURRENT_ADDR, (DLINE_SIZE * DLINES_PER_ITER) + cache Index_Store_Tag_D, (DLINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*1)(CURRENT_ADDR) +#if DLINES_PER_ITER == 8 + cache Index_Store_Tag_D, (DLINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_D, (DLINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_dcache_tag + +$Ldone_dcache: + jr ra + +END(__init_dcache) +#endif // DLINE_ENC != 0 + +/* + * __change_k0_cca essentially turns the cache on + */ + +#if ILINE_ENC != 0 || DLINE_ENC != 0 +LEAF(__change_k0_cca) + /* + * NOTE! This code must be executed in KSEG1 (not KSEG0 uncached) + * Set CCA for kseg0 to cacheable + */ + mfc0 CONFIG, C0_CONFIG + li TEMP, CFG_C_NONCOHERENT + +$Lset_kseg0_cca: + ins CONFIG, TEMP, 0, 3 + mtc0 CONFIG, C0_CONFIG + MIPS_JRHB (ra) + +END(__change_k0_cca) +#endif // ILINE_ENC != 0 || DLINE_ENC != 0 diff --git a/libgloss/mips/boot/init_cm3l2.S b/libgloss/mips/boot/init_cm3l2.S new file mode 100644 index 0000000..4ac9b0b --- /dev/null +++ b/libgloss/mips/boot/init_cm3l2.S @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/cm3.h> + +MIPS_NOMIPS16 + +#define CM3_BASE t8 +LEAF(__init_l23cache) + /* Check for memory mapped L2 cache config */ + mfc0 t0, C0_CONFIG3 + ext t1, t0, CFG3_M_SHIFT, 1 + beqz t1, err + + mfc0 t0, C0_CONFIG4 + ext t1, t0, CFG4_M_SHIFT, 1 + beqz t1, err + + mfc0 t0, C0_CONFIG5 + ext t1, t0, CFG5_L2C_SHIFT, 1 + bnez t1, disable_cache +err: + /* + * CM3 L2 code supplied but we have a Config2 L2 setup + * Report a Boot failure through UHI + */ + li t9, 23 + /* Reason - L2 cache config */ + li a0, 1 + /* Trigger the UHI operation */ + sdbbp 1 + /* In case a debugger corrects this failure */ + jr ra + +disable_cache: + /* Read CMGCRBase to find CMGCR_BASE_ADDR */ + PTR_MFC0 t1,C0_CMGCRBASE + sll t1, t1, CMGCR_BASE_ADDR_LSHIFT + li CM3_BASE, 0xa0000000 /* Make it virtual */ + or CM3_BASE, CM3_BASE, t1 + + /* Disable L2 cache by setting it to bypass mode */ + PTR_L a0, GCR_L2_CONFIG(CM3_BASE) + li a2, 1 + ins a0, a2, GCR_L2_BYPASS_SHIFT, GCR_L2_BYPASS_BITS + PTR_S a0, GCR_L2_CONFIG(CM3_BASE) + sync +ret: + jr ra +END(__init_l23cache) + +LEAF(__init_l23cache_cached) + /* Read CMGCRBase to find CMGCR_BASE_ADDR */ + PTR_MFC0 t3,C0_CMGCRBASE + sll t3, t3, CMGCR_BASE_ADDR_LSHIFT + li CM3_BASE, 0xa0000000 /* Make it virtual */ + or CM3_BASE, CM3_BASE, t3 + + /* Read GCR_L2_CONFIG */ + move t2, a0 + ext t3, t2, GCR_L2_SL_SHIFT, GCR_L2_SL_BITS + beqz t3, done_cm3l2cache # No L2 cache + + /* Unusual case, hardware cache initialization support & init finished. */ + PTR_L t1, GCR_L2_RAM_CONFIG(CM3_BASE) + ext t0, t1, GCR_L2_RAM_HCIS_SHIFT, (GCR_L2_RAM_HCID_BITS +\ + GCR_L2_RAM_HCIS_BITS) + li t1, 3 + beq t0, t1, done_cm3l2cache + + li a2, 2 + sllv a1, a2, t3 /* Now have L2 line size */ + + ext a0, t2, GCR_L2_SS_SHIFT, GCR_L2_SS_BITS + li a2, 64 + sllv a0, a2, a0 /* Now have L2 sets/way */ + + ext t3, t2, GCR_L2_SA_SHIFT, GCR_L2_SA_BITS + addiu t3, t3, 1 /* Set associativity */ + mul a0, t3, a0 /* Get total number of sets */ + + sw zero, GCR_TAG_ADDR(CM3_BASE) + sw zero, (GCR_TAG_ADDR+4)(CM3_BASE) + sw zero, GCR_TAG_STATE(CM3_BASE) + sw zero, (GCR_TAG_STATE+4)(CM3_BASE) + sw zero, GCR_TAG_DATA(CM3_BASE) + sw zero, (GCR_TAG_DATA+4)(CM3_BASE) + sw zero, GCR_TAG_ECC(CM3_BASE) + sw zero, (GCR_TAG_ECC+4)(CM3_BASE) + sync + + li a2, 0x80000000 + +next_cm3l2cache_tag: + cache Index_Store_Tag_S, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_cm3l2cache_tag + +done_cm3l2cache: + move a2, zero + PTR_L t0, GCR_L2_CONFIG(CM3_BASE) + ins t0, a2, GCR_L2_BYPASS_SHIFT, GCR_L2_BYPASS_BITS + PTR_S t0, GCR_L2_CONFIG(CM3_BASE) + + jr ra +END(__init_l23cache_cached) diff --git a/libgloss/mips/boot/init_cm3l2_predef.S b/libgloss/mips/boot/init_cm3l2_predef.S new file mode 100644 index 0000000..83be64b --- /dev/null +++ b/libgloss/mips/boot/init_cm3l2_predef.S @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/cm3.h> +#include "predef.h" + +MIPS_NOMIPS16 + +#define CM3_BASE a3 + +# ifndef C0_CMGCRBASE_VALUE +# error "Static CM3 cache initialization decisions require C0_CMGCRBASE_VALUE" +# else +# define C0_CMGCRBASE_ADDR ((C0_CMGCRBASE_VALUE << 4) | (0xa << 28)) +# ifndef GCR_L2_CONFIG_VALUE +# error "Static CM3 cache initialization decisions require GCR_L2_CONFIG_VALUE" +# endif +# endif + +#undef SLINE_ENC +#undef SSET_ENC +#undef SASSOC_ENC +#undef SLINE_SIZE +#undef SSET_SIZE +#undef SASSOC + +#define SLINE_ENC ((GCR_L2_CONFIG_VALUE & GCR_L2_SL_MASK) >> GCR_L2_CFG_SL_SHIFT) +#define SSET_ENC ((GCR_L2_CONFIG_VALUE & GCR_L2_SS_MASK) >> GCR_L2_CFG_SS_SHIFT) +#define SASSOC_ENC ((GCR_L2_CONFIG_VALUE & GCR_L2_SA_MASK) >> GCR_L2_CFG_SA_SHIFT) +#define SLINE_SIZE (2 << SLINE_ENC) +#define SSET_SIZE (64 << SSET_ENC) +#define SASSOC (SASSOC_ENC + 1) + + +LEAF(__init_l23cache) + li CM3_BASE, C0_CMGCRBASE_ADDR + /* Disable L2 cache */ + /* Reg exists, L2 cache does TAG/DATA ECC. */ + /* LRU is updated on store tag operation */ + li t0, GCR_L2_CONFIG_VALUE | GCR_L2_BYPASS_MASK + PTR_S t0, GCR_L2_CONFIG(CM3_BASE) + sync + + jr ra +END(__init_l23cache) + +LEAF(__init_l23cache_cached) + li CM3_BASE, C0_CMGCRBASE_ADDR + +#if SLINE_ENC != 0 + /* Unusual case, hardware cache initialization support & init finished. */ + PTR_L t1, GCR_L2_RAM_CONFIG(CM3_BASE) + ext t0, t1, GCR_L2_RAM_HCIS_SHIFT, (GCR_L2_RAM_HCID_BITS +\ + GCR_L2_RAM_HCIS_BITS) + li t1, 3 + beq t0, t1, done_cm3l2cache + + /* Compute L2 cache size */ + li a1, SLINE_SIZE + li a0, SSET_SIZE * SASSOC + + sw zero, GCR_TAG_ADDR(CM3_BASE) + sw zero, (GCR_TAG_ADDR+4)(CM3_BASE) + sw zero, GCR_TAG_STATE(CM3_BASE) + sw zero, (GCR_TAG_STATE+4)(CM3_BASE) + sw zero, GCR_TAG_DATA(CM3_BASE) + sw zero, (GCR_TAG_DATA+4)(CM3_BASE) + sw zero, GCR_TAG_ECC(CM3_BASE) + sw zero, (GCR_TAG_ECC+4)(CM3_BASE) + sync + + li a2, 0x80000000 + +next_cm3l2cache_tag: + cache Index_Store_Tag_S, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_cm3l2cache_tag +#endif /* SLINE_ENC != 0 */ + +done_cm3l2cache: + li t0, GCR_L2_CONFIG_VALUE + PTR_S t0, GCR_L2_CONFIG(CM3_BASE) + sync + + jr ra +END(__init_l23cache_cached) diff --git a/libgloss/mips/boot/init_cp0.S b/libgloss/mips/boot/init_cp0.S new file mode 100644 index 0000000..15ac1c8 --- /dev/null +++ b/libgloss/mips/boot/init_cp0.S @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + + .set noat + +LEAF(__init_cp0) + + /* Initialize Status */ + li t1, SR_ERL | SR_BEV + mtc0 t1, C0_STATUS + + /* Initialize Watch registers if implemented */ + mfc0 t0, C0_CONFIG1 + ext t1, t0, CFG1_WR_SHIFT, 1 + beqz t1, $Ldone_wr + li t1, WATCHHI_I | WATCHHI_R | WATCHHI_W + + /* Clear Watch Status bits and disable watch exceptions */ + mtc0 t1, C0_WATCHHI + mfc0 t0, C0_WATCHHI + mtc0 zero, C0_WATCHLO + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 1 + mfc0 t0, C0_WATCHHI, 1 + mtc0 zero, C0_WATCHLO, 1 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 2 + mfc0 t0, C0_WATCHHI, 2 + mtc0 zero, C0_WATCHLO, 2 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 3 + mfc0 t0, C0_WATCHHI, 3 + mtc0 zero, C0_WATCHLO, 3 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 4 + mfc0 t0, C0_WATCHHI, 4 + mtc0 zero, C0_WATCHLO, 4 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 5 + mfc0 t0, C0_WATCHHI, 5 + mtc0 zero, C0_WATCHLO, 5 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 6 + mfc0 t0, C0_WATCHHI, 6 + mtc0 zero, C0_WATCHLO, 6 + bgez t0, $Ldone_wr + + mtc0 t1, C0_WATCHHI, 7 + mfc0 t0, C0_WATCHHI, 7 + mtc0 zero, C0_WATCHLO, 7 + +$Ldone_wr: + /* + * Clear WP bit to avoid watch exception upon user code entry, IV, + * and software interrupts. + */ + mtc0 zero, C0_CAUSE + + /* + * Clear timer interrupt. (Count was cleared at the reset vector to + * allow timing boot.) + */ + mtc0 zero, C0_COMPARE + + jr ra +END(__init_cp0) diff --git a/libgloss/mips/boot/init_cp0_predef.S b/libgloss/mips/boot/init_cp0_predef.S new file mode 100644 index 0000000..abc1888 --- /dev/null +++ b/libgloss/mips/boot/init_cp0_predef.S @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + + .set noat + +LEAF(__init_cp0) + + /* Initialize Status */ + li t1, SR_BEV | SR_ERL + mtc0 t1, C0_STATUS + +#if (C0_CONFIG1_VALUE & CFG1_WR) != 0 + li t1, WATCHHI_I | WATCHHI_R | WATCHHI_W + + /* Clear Watch Status bits and disable watch exceptions */ + mtc0 t1, C0_WATCHHI + mtc0 zero, C0_WATCHLO + +# ifndef C0_WATCHHI_VALUE +# error "C0_WATCHHI_VALUE is required" +# endif + +# if (C0_WATCHHI_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 1 + mtc0 zero, C0_WATCHLO, 1 + +# ifndef C0_WATCHHI1_VALUE +# error "C0_WATCHHI1_VALUE is required" +# endif + +# if (C0_WATCHHI1_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 2 + mtc0 zero, C0_WATCHLO, 2 + +# ifndef C0_WATCHHI2_VALUE +# error "C0_WATCHHI2_VALUE is required" +# endif + +# if (C0_WATCHHI2_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 3 + mtc0 zero, C0_WATCHLO, 3 + +# ifndef C0_WATCHHI3_VALUE +# error "C0_WATCHHI3_VALUE is required" +# endif + +# if (C0_WATCHHI3_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 4 + mtc0 zero, C0_WATCHLO, 4 + +# ifndef C0_WATCHHI4_VALUE +# error "C0_WATCHHI4_VALUE is required" +# endif + +# if (C0_WATCHHI4_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 5 + mtc0 zero, C0_WATCHLO, 5 + +# ifndef C0_WATCHHI5_VALUE +# error "C0_WATCHHI5_VALUE is required" +# endif + +# if (C0_WATCHHI5_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 6 + mtc0 zero, C0_WATCHLO, 6 + +# ifndef C0_WATCHHI6_VALUE +# error "C0_WATCHHI6_VALUE is required" +# endif + +# if (C0_WATCHHI6_VALUE & WATCHHI_M) != 0 + mtc0 t1, C0_WATCHHI, 7 + mtc0 zero, C0_WATCHLO, 7 + +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif + + /* + * Clear WP bit to avoid watch exception upon user code entry, IV, and + * software interrupts. + */ + mtc0 zero, C0_CAUSE + + /* + * Clear timer interrupt. (Count was cleared at the reset vector to + * allow timing boot.) + */ + mtc0 zero, C0_COMPARE + + jr ra +END(__init_cp0) diff --git a/libgloss/mips/boot/init_l23caches.S b/libgloss/mips/boot/init_l23caches.S new file mode 100644 index 0000000..3b3ffed --- /dev/null +++ b/libgloss/mips/boot/init_l23caches.S @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + .set noat + +LEAF(__init_l23cache) + /* L2 Cache initialization routine */ + /* Check for memory mapped L2 cache config */ + mfc0 a3, C0_CONFIG3 + ext a3, a3, CFG3_M_SHIFT, 1 + beqz a3, l23_init + mfc0 a3, C0_CONFIG4 + ext a3, a3, CFG4_M_SHIFT, 1 + beqz a3, l23_init + mfc0 a3, C0_CONFIG5 + ext a3, a3, CFG5_L2C_SHIFT, 1 + beqz a3, l23_init + + /* + * No CM3 code supplied but we have a memory mapped L2 configuration + * Report a Boot failure through UHI + */ + li t9, 23 + /* Reason - L2 cache config */ + li a0, 1 + /* Trigger the UHI operation */ + sdbbp 1 + /* In case a debugger corrects this failure */ + b done_l3cache + +l23_init: + /* Check L2 cache size */ + mfc0 t0, C0_CONFIG2 + + /* Isolate L2$ Line Size */ + ext t1, t0, CFG2_SL_SHIFT, CFG2_SL_BITS + + /* Skip ahead if No L2$ */ + beqz t1, done_l2cache + + li a2, 2 + sllv a1, a2, t1 /* Decode L2$ line size in bytes */ + + /* Isolate L2$ Sets per Way */ + ext a0, t0, CFG2_SS_SHIFT, CFG2_SS_BITS + li a2, 64 + sllv a0, a2, a0 /* L2$ Sets per way */ + + /* Isolate L2$ Associativity */ + ext t1, t0, CFG2_SA_SHIFT, CFG2_SA_BITS + addiu t1, t1, 1 + + mul a0, a0, t1 /* Get total number of sets */ + +l2cache_init: + li a2, 0x80000000 /* Get a KSeg0 address for cacheops */ + + /* Clear L23TagLo/L23TagHi registers */ + mtc0 zero, C0_TAGLO, 4 + + /* + * L2$ Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +next_L2cache_tag: + cache Index_Store_Tag_S, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_L2cache_tag + +done_l2cache: + /* Isolate L3$ Line Size */ + ext t1, t0, CFG2_TL_SHIFT, CFG2_TL_BITS + + /* Skip ahead if No L3$ */ + beqz t1, done_l3cache + + li a2, 2 + sllv a1, a2, t1 /* Decode L3$ line size in bytes */ + + /* Isolate L3$ Sets per Way */ + ext a0, t0, CFG2_TS_SHIFT, CFG2_TS_BITS + li a2, 64 + sllv a0, a2, a0 /* Decode L3 Sets per way */ + + /* Isolate L3$ Associativity */ + ext t1, t0, CFG2_TA_SHIFT, CFG2_TA_BITS + addiu t1, t1, 1 /* Decode L3 associativity (number of sets) */ + mul a0, a0, t1 /* Compute total number of sets */ + +l3cache_init: + li a2, 0x80000000 /* Get a KSeg0 address for cacheops */ + + /* Clear L23Tag register */ + mtc0 zero, C0_TAGLO, 4 + + /* + * L3$ Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +next_L3cache_tag: + cache Index_Store_Tag_T, 0(a2) + addiu a0, a0, -1 + addu a2, a2, a1 + bnez a0, next_L3cache_tag + +done_l3cache: + jr ra +END(__init_l23cache) diff --git a/libgloss/mips/boot/init_l23caches_predef.S b/libgloss/mips/boot/init_l23caches_predef.S new file mode 100644 index 0000000..d21c69f --- /dev/null +++ b/libgloss/mips/boot/init_l23caches_predef.S @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + +/* + * Depending on the range of the displacement field of the CACHE instruction + * we can do multiple cacheops per iteration. With a cache present there + * is a guarantee of 32 lines minimum so a power of 2 less than or equal + * to 32 means there is no remainder after the loop. + * The maximum number of lines per iteration is the range of the CACHE + * displacement divided by the line_size. We cap this at 8 as a sensible + * bound. + */ + +#if __mips_isa_rev < 6 +/* MicroMIPS Release 3 has a 12-bit displacement for CACHE */ +# define SLINES_PER_ITER 8 +# define TLINES_PER_ITER 8 +#else +/* MIPS Release 6 has a 9-bit signed displacement for CACHE */ +#if SLINE_SIZE == 128 +# define SLINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define SLINES_PER_ITER 8 +#endif +#if TLINE_SIZE == 128 +# define TLINES_PER_ITER 4 /* Requires both positive and negative disp */ +#else +# define TLINES_PER_ITER 8 +#endif +#endif + +#ifdef MEM_MAPPED_L2C +# error MEM_MAPPED_L2C used with Config L2 code +#endif + +/* + * Start off pointing to one block below where we want to invalidate the cache + * as the pointer is moved on at the start of the loop. Also offset the start + * address for each set of cache lines so that the positive and negative + * displacements from the CACHE ops can be used. + */ + +#define SCACHE_START (0x80000000 - (SLINE_SIZE * SLINES_PER_ITER / 2)) +#define SCACHE_END (0x80000000 + STOTAL_BYTES - (SLINE_SIZE * SLINES_PER_ITER / 2)) +#define TCACHE_START (0x80000000 - (TLINE_SIZE * TLINES_PER_ITER / 2)) +#define TCACHE_END (0x80000000 + TTOTAL_BYTES - (TLINE_SIZE * TLINES_PER_ITER / 2)) + +#define CURRENT_ADDR a0 +#define END_ADDR a1 +#define CONFIG a2 +#define TEMP a3 + + .set noat + +/* + * __init_l23cache invalidates all secondary/tertiary data cache entries + */ + +#if defined(SLINE_ENC) && SLINE_ENC != 0 +LEAF(__init_l23cache) + /* Use KSEG0 base address */ + li CURRENT_ADDR, SCACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, SCACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO, 4 + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_scache_tag: + addu CURRENT_ADDR, (SLINE_SIZE * SLINES_PER_ITER) + cache Index_Store_Tag_S, (SLINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*1)(CURRENT_ADDR) +#if SLINES_PER_ITER == 8 + cache Index_Store_Tag_S, (SLINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_S, (SLINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_scache_tag + +$Ldone_scache: + +#if defined(TLINE_ENC) && TLINE_ENC != 0 + + /* Use KSEG0 base address */ + li CURRENT_ADDR, TCACHE_START + /* Get the address of the last batch of lines */ + li END_ADDR, TCACHE_END + + /* Clear TagLo/TagHi registers */ + mtc0 zero, C0_TAGLO, 4 + + /* + * Index Store Tag Cache Op will invalidate the tag entry, clear + * the lock bit, and clear the LRF bit + */ +$Lnext_tcache_tag: + addu CURRENT_ADDR, (TLINE_SIZE * TLINES_PER_ITER) + cache Index_Store_Tag_T, (TLINE_SIZE*-2)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*-1)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*0)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*1)(CURRENT_ADDR) +#if TLINES_PER_ITER == 8 + cache Index_Store_Tag_T, (TLINE_SIZE*-4)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*-3)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*2)(CURRENT_ADDR) + cache Index_Store_Tag_T, (TLINE_SIZE*3)(CURRENT_ADDR) +#endif + bne CURRENT_ADDR, END_ADDR, $Lnext_tcache_tag + +$Ldone_tcache: + +#endif // TLINE_ENC != 0 + jr ra +END(__init_l23cache) + +LEAF(__init_l23cache_cached) + jr ra +END(__init_l23cache_cached) + +#endif // SLINE_ENC != 0 diff --git a/libgloss/mips/boot/init_tlb.S b/libgloss/mips/boot/init_tlb.S new file mode 100644 index 0000000..20cf0b8 --- /dev/null +++ b/libgloss/mips/boot/init_tlb.S @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + +/* + * int, int __tlb_size(); + * + * Return number of entries in TLB. + * Entries in va0, number of sets in va1. + * Must not use registers t8 or a3 + * + */ +SLEAF(__tlb_size) + /* first see if we've got a TLB */ + mfc0 t0, C0_CONFIG + mfc0 t1, C0_CONFIG1 + move va0, zero + + ext t0, t0, CFG0_MT_SHIFT, CFG0_MT_BITS + /* No MMU test, 0 entries */ + beqz t0, 1f + + /* Fixed Address Translation, 0 entries */ + li t2, (CFG0_MT_FIXED >> CFG0_MT_SHIFT) + beq t0, t2, 1f + + /* Block Address Translator, 0 entries */ + li t2, (CFG0_MT_BAT >> CFG0_MT_SHIFT) + beq t0, t2, 1f + + /* (D)TLB or not? */ + andi t2, t0, (CFG0_MT_TLB | CFG0_MT_DUAL) >> CFG0_MT_SHIFT + beqz t2, 1f + + /* + * As per PRA, field holds No. of entries -1 + * Standard TLBs and Dual TLBs have extension fields. + */ + ext va0, t1, CFG1_MMUS_SHIFT, CFG1_MMUS_BITS + addiu va0, va0, 1 + + mfc0 t1, C0_CONFIG3 + ext t1, t1, CFG3_M_SHIFT, 1 + beqz t1, 1f + + mfc0 t1, C0_CONFIG4 +#if __mips_isa_rev < 6 + ext t3, t1, CFG4_MMUED_SHIFT, CFG4_MMUED_BITS + + li t2, (CFG4_MMUED_FTLBVEXT >> CFG4_MMUED_SHIFT) + beq t3, t2, 2f /* FTLB + VTLBExt */ + + li t2, (CFG4_MMUED_SIZEEXT >> CFG4_MMUED_SHIFT) + beq t3, t2, 3f /* SizeExt for VTLBEXT */ + + li t2, (CFG4_MMUED_FTLB >> CFG4_MMUED_SHIFT) + beq t3, t2, 4f /* FTLB Size */ + + /* No extension */ + jr ra + +3: + ext t3, t1, CFG4_MMUSE_SHIFT, CFG4_MMUSE_BITS + sll t2, t3, CFG1_MMUS_BITS + addu va0, va0, t2 + jr ra +#endif /* __mips_isa_rev < 6 */ +2: + ext t2, t1, CFG4_VTLBSEXT_SHIFT, CFG4_VTLBSEXT_BITS + sll t2, t2, CFG1_MMUS_BITS + addu va0, va0, t2 +4: + /* Skip FTLB size calc if Config MT != 4 */ + li t3, (CFG0_MT_DUAL >> CFG0_MT_SHIFT) + bne t3, t0, 1f + + /* Ways */ + li t2, 2 + ext t3, t1, CFG4_FTLBW_SHIFT, CFG4_FTLBW_BITS + addu t2, t2, t3 + + /* Sets per way */ + ext t3, t1, CFG4_FTLBS_SHIFT, CFG4_FTLBS_BITS + li va1, 1 + sllv va1, va1, t3 + + /* Total sets */ + sllv t2, t2, t3 + addu va0, va0, t2 + +1: jr ra +SEND(__tlb_size) + +/* + * void __tlbinvalall() + * + * Invalidate the TLB. + * Must not use register a3 + */ +SLEAF(__tlbinvalall) + + mfc0 t0, C0_CONFIG + and t2, t0, CFG0_MT_MASK + beqz t2, $Lexit /* Config[MT] test, return if no TLB */ + + li t1, CFG0_MT_BAT + beq t1, t2, $Lexit /* return as there is a BAT */ + + li t1, CFG0_MT_FIXED /* return as there is a FMT */ + beq t1, t2, $Lexit + + PTR_MTC0 zero, C0_ENTRYLO0 + PTR_MTC0 zero, C0_ENTRYLO1 + PTR_MTC0 zero, C0_PAGEMASK + + /* Fetch size & number of sets in va0, va1 */ + move t8, ra + jal __tlb_size + move ra, t8 + + /* If Config4 does not exist then use old method for invalidation */ + mfc0 t1, C0_CONFIG3 + ext t1, t1, CFG3_M_SHIFT, 1 + beqz t1, $Llegacy_init + + /* If Config4[IE] = 0, use old method for invalidation */ + mfc0 t9, C0_CONFIG4 + ext t2, t9, CFG4_IE_SHIFT, CFG4_IE_BITS + beqz t2, $Llegacy_init + + /* If Config4[IE] = 1, EHINV loop */ + li t1, (CFG4_IE_EHINV >> CFG4_IE_SHIFT) + beq t1, t2, $Lehinv_init + + /* + * If Config4[IE] = 2, tlbinvf loop. Handles Config[MT] being either + * 1 or 4. + */ + li t1, (CFG4_IE_INV >> CFG4_IE_SHIFT) + beq t1, t2, $Ltlbinvf_init + + /* TLB walk done by hardware, Config4[IE] = 3 */ + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + b $Lexit + +$Ltlbinvf_init: + /* + * TLB walk done by software, Config4[IE] = 2, Config[MT] = 4 or 1 + * + * one TLBINVF is executed with an index in VTLB range to + * invalidate all VTLB entries. + * + * For Dual TLBs additionally, one TLBINVF is executed per FTLB set. + */ + + /* Flush the VTLB */ + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + + /* + * For JTLB MMUs (Config[MT] = 1) only 1 tlbinvf is required + * early out in that case. + */ + mfc0 t0, C0_CONFIG + ext t3, t0, CFG0_MT_SHIFT, CFG0_MT_BITS + li t1, (CFG0_MT_TLB >> CFG0_MT_SHIFT) + beq t1, t3, $Lexit + + /* + * va0 contains number of TLB entries + * va1 contains number of sets per way + */ + lui t9, %hi(__tlb_stride_length) /* Fetch the tlb stride for */ + addiu t9, %lo(__tlb_stride_length) /* stepping through FTLB sets */ + mul va1, va1, t9 + subu t2, va0, va1 /* End pointer */ + +1: subu va0, va0, t9 + mtc0 va0, C0_INDEX + ehb /* mtc0, hazard on tlbinvf */ + .set push + .set eva + tlbinvf + .set pop + bne va0, t2, 1b + + b $Lexit + +$Lehinv_init: + /* + * Config4[IE] = 1. EHINV supported, but not tlbinvf. + * + * Invalidate the TLB for R3 onwards by loading EHINV and writing to all + * tlb entries. + */ + move t0, zero + li t1, C0_ENTRYHI_EHINV_MASK + mtc0 t1, C0_ENTRYHI +1: + mtc0 t0, C0_INDEX + ehb /* mtc0, hazard on tlbwi */ + + tlbwi + addiu t0, t0, 1 + bne va0, t0, 1b + + b $Lexit + +$Llegacy_init: + /* + * Invalidate the TLB for R1 onwards by loading + * 0x(FFFFFFFF)KSEG0_BASE into EntryHi and writing it into index 0 + * incrementing by a pagesize, writing into index 1, etc. + */ + + /* + * If large physical addressing is enabled, load 0xFFFFFFFF + * into the top half of EntryHi. + */ + move t0, zero /* t0 == 0 if XPA disabled */ + mfc0 t9, C0_CONFIG3 /* or not present */ + and t9, t1, CFG3_LPA + beqz t9, $Lno_xpa + + mfc0 t9, C0_PAGEGRAIN + ext t9, t1, PAGEGRAIN_ELPA_SHIFT, PAGEGRAIN_ELPA_BITS + bnez t9, $Lno_xpa + + li t0, -1 /* t0 == 0xFFFFFFFF if XPA is used */ +$Lno_xpa: + li t1, (KSEG0_BASE - 2<<13) + + move t2, zero +1: addiu t1, t1, (2<<13) + PTR_MTC0 t1, C0_ENTRYHI + + beqz t0, $Lskip_entryhi + .set push + .set xpa + mthc0 t0, C0_ENTRYHI /* Store 0xFFFFFFFF to upper half of EntryHI */ + .set pop + +$Lskip_entryhi: + ehb /* mtc0, hazard on tlbp */ + + tlbp /* Probe for a match */ + ehb /* tlbp, Hazard on mfc0 */ + + mfc0 t8, C0_INDEX + bgez t8, 1b /* Skip this address if it exists */ + + mtc0 t2, C0_INDEX + ehb /* mtc0, hazard on tlbwi */ + + tlbwi + addiu t2, t2, 1 + bne va0, t2, 1b + +$Lexit: + PTR_MTC0 zero, C0_ENTRYHI /* Unset EntryHI, upper half is cleared */ + /* autmatically as mtc0 writes zeroes */ + MIPS_JRHB (ra) +SEND(__tlbinvalall) + +LEAF(__init_tlb) + + mfc0 t0, C0_CONFIG + and t2, t0, CFG0_MT_MASK + beqz t2, 1f /* return if no tlb present */ + + li t1, CFG0_MT_BAT + beq t1, t2, 1f /* return as there is a BAT */ + + li t1, CFG0_MT_FIXED /* return as there is a FMT */ + beq t1, t2, 1f + + lui t1, %hi(__enable_xpa) /* Test for XPA usage */ + ori t1, %lo(__enable_xpa) + beqz t1, 2f + + mfc0 t0, C0_CONFIG3 + and t0, t0, CFG3_LPA + bnez t0, 3f + + /* + * Raise an error because XPA was requested but LPA support is not + * available. + */ + /* Incorrect config supplied, report a boot failure through UHI */ + li t9, 23 + /* Reason - Predef/requested config incorrect */ + li a0, 2 + /* Trigger the UHI operation */ + sdbbp 1 + +3: li t1, 1 + mfc0 t0, C0_PAGEGRAIN + ins t0, t1, PAGEGRAIN_ELPA_SHIFT, PAGEGRAIN_ELPA_BITS + mtc0 t0, C0_PAGEGRAIN +2: + move a3, ra + jal __tlbinvalall + move ra, a3 + + mtc0 zero, C0_PAGEMASK +1: jr ra +END(__init_tlb) diff --git a/libgloss/mips/boot/init_tlb_predef.S b/libgloss/mips/boot/init_tlb_predef.S new file mode 100644 index 0000000..e092d0a --- /dev/null +++ b/libgloss/mips/boot/init_tlb_predef.S @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _BOOTCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + +LEAF(__init_tlb) +#if HAVE_LPA && ENABLE_XPA + mfc0 t0, C0_PAGEGRAIN + li t1, 1 + ins t0, t1, PAGEGRAIN_ELPA_SHIFT, PAGEGRAIN_ELPA_BITS + mtc0 t0, C0_PAGEGRAIN +#endif + # Top halves of registers are cleared impicitly with mtc0 + PTR_MTC0 zero, C0_PAGEMASK + PTR_MTC0 zero, C0_ENTRYLO0 + PTR_MTC0 zero, C0_ENTRYLO1 + +#if HAVE_HW_TLB_WALK + /* TLB walk done by hardware, Config4[IE] = 3 or Config[MT] = 1 */ + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop +#endif + +#if HAVE_SW_TLB_WALK + /* + * TLB walk done by software, Config4[IE] = 2, Config[MT] = 4 + * + * one TLBINVF is executed with an index in VTLB range to + * invalidate all VTLB entries. + * + * One TLBINVF is executed per FTLB entry. + * + */ + li t2, MMU_SIZE /* Start pointer/finger */ + li t8, FTLB_SETS + li t9, %hi(__tlb_stride_length) + addiu t9, %lo(__tlb_stride_length) + mul t8, t8, t9 + subu t1, t2, t8 /* End pointer */ + + mtc0 zero, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + +1: subu t2, t2, t9 + mtc0 t2, C0_INDEX + ehb + .set push + .set eva + tlbinvf + .set pop + bne t1, t2, 1b +#endif + +#if HAVE_EHINV_WALK + li v0, MMU_SIZE + move v1, zero + li t0, C0_ENTRYHI_EHINV_MASK + PTR_MTC0 t0, C0_ENTRYHI +1: + mtc0 v1, C0_INDEX + ehb + + tlbwi + addiu v1, v1, 1 + bne v0, v1, 1b +#endif + +#if HAVE_NO_INV + /* + * Clean invalidate TLB for R1 onwards by loading + * 0x(FFFFFFFF)KSEG0_BASE into EntryHi and writing it into index MAX + * incrementing EntryHi by a pagesize, writing into index MAX-1, etc. + */ + li v0, MMU_SIZE + + /* + * If large physical addressing is enabled, load 0xFFFFFFFF + * into the top half of EntryHi. + */ +#if HAVE_LPA && ENABLE_LPA + li t0, -1 +#endif + li t1, (KSEG0_BASE - 2<<13) + + move v1, zero +1: addiu t1, t1, (2<<13) + PTR_MTC0 t1, C0_ENTRYHI +#if HAVE_LPA && ENABLE_LPA + mthc0 t0, C0_ENTRYHI +#endif + ehb /* mt(h)c0, hazard on tlbp */ + + tlbp /* Probe for a match */ + ehb /* tlbp, hazard on MFC0 */ + + mfc0 t8, C0_INDEX + bgez t8, 1b /* Skip this address if it exists */ + + mtc0 v0, C0_INDEX + ehb /* mtc0, hazard on tlbwi */ + + tlbwi + addiu v1, v1, 1 + bne v0, v1, 1b +#endif + + PTR_MTC0 zero, C0_ENTRYHI /* Unset EntryHI, top half */ + MIPS_JRHB (ra) +END(__init_tlb) diff --git a/libgloss/mips/boot/predef.h b/libgloss/mips/boot/predef.h new file mode 100644 index 0000000..eeaa79e --- /dev/null +++ b/libgloss/mips/boot/predef.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef C0_CONFIG0_VALUE +#error "Static TLB initialisation decisions require C0_CONFIG0_VALUE" +#endif + +#ifndef C0_CONFIG1_VALUE +#error "Static TLB/cache initialisation decisions require C0_CONFIG1_VALUE" +#endif + +#define ILINE_ENC ((C0_CONFIG1_VALUE & CFG1_IL_MASK) >> CFG1_IL_SHIFT) +#define ILINE_SIZE (2 << ILINE_ENC) +#define ISET_ENC ((C0_CONFIG1_VALUE & CFG1_IS_MASK) >> CFG1_IS_SHIFT) +#define ISET_SIZE (32 << ((ISET_ENC + 1) & 0x7)) +#define IASSOC_ENC ((C0_CONFIG1_VALUE & CFG1_IA_MASK) >> CFG1_IA_SHIFT) +#define IASSOC (IASSOC_ENC + 1) +#define ITOTAL_BYTES (ILINE_SIZE * ISET_SIZE * IASSOC) +#define DLINE_ENC ((C0_CONFIG1_VALUE & CFG1_DL_MASK) >> CFG1_DL_SHIFT) +#define DLINE_SIZE (2 << DLINE_ENC) +#define DSET_ENC ((C0_CONFIG1_VALUE & CFG1_DS_MASK) >> CFG1_DS_SHIFT) +#define DSET_SIZE (32 << ((DSET_ENC + 1) & 0x7)) +#define DASSOC_ENC ((C0_CONFIG1_VALUE & CFG1_DA_MASK) >> CFG1_DA_SHIFT) +#define DASSOC (DASSOC_ENC + 1) +#define DTOTAL_BYTES (DLINE_SIZE * DSET_SIZE * DASSOC) + +#ifndef C0_CONFIG2_VALUE +# error "Static cache initialisation decisions require C0_CONFIG2_VALUE" +#endif + +#ifndef C0_CONFIG3_VALUE +# error "Static TLB initialisation decisions require C0_CONFIG3_VALUE" +#endif + +#if (C0_CONFIG3_VALUE & CFG4_M) != 0 +# ifndef C0_CONFIG4_VALUE +# error "Static TLB/cache initialisation decisions require C0_CONFIG4_VALUE" +# endif +# if (C0_CONFIG4_VALUE & CFG4_M) != 0 +# ifndef C0_CONFIG5_VALUE +# error "Static cache initialisation decisions require C0_CONFIG5_VALUE" +# endif +# if (C0_CONFIG5_VALUE & CFG5_L2C) != 0 +# define MEM_MAPPED_L2C 1 +# endif +# endif +#endif + +#define SLINE_ENC ((C0_CONFIG2_VALUE & CFG2_SL_MASK) >> CFG2_SL_SHIFT) +#define SSET_ENC ((C0_CONFIG2_VALUE & CFG2_SS_MASK) >> CFG2_SS_SHIFT) +#define SASSOC_ENC ((C0_CONFIG2_VALUE & CFG2_SA_MASK) >> CFG2_SA_SHIFT) + +#define SLINE_SIZE (2 << SLINE_ENC) +#define SSET_SIZE (64 << SSET_ENC) +#define SASSOC (SASSOC_ENC + 1) +#define STOTAL_BYTES (SLINE_SIZE * SSET_SIZE * SASSOC) + +#define TLINE_ENC ((C0_CONFIG2_VALUE & CFG2_TL_MASK) >> CFG2_TL_SHIFT) +#define TLINE_SIZE (2 << TLINE_ENC) +#define TSET_ENC ((C0_CONFIG2_VALUE & CFG2_TS_MASK) >> CFG2_TS_SHIFT) +#define TSET_SIZE (64 << TSET_ENC) +#define TASSOC_ENC ((C0_CONFIG2_VALUE & CFG2_TA_MASK) >> CFG2_TA_SHIFT) +#define TASSOC (TASSOC_ENC + 1) +#define TTOTAL_BYTES (TLINE_SIZE * TSET_SIZE * TASSOC) + +/* TLB Macros */ + +// TLB Type +#define TLB_STANDARD ((C0_CONFIG0_VALUE & CFG0_MT_MASK) == CFG0_MT_TLB) +#define TLB_DUAL ((C0_CONFIG0_VALUE & CFG0_MT_MASK) == CFG0_MT_DUAL) +#define HAVE_TLB (TLB_STANDARD || TLB_DUAL) + +// Size definitions. +// FTLBs may be present. +#ifdef C0_CONFIG4_VALUE +# define FTLB_SET_ENC (C0_CONFIG4_VALUE & CFG4_FTLBS_MASK) >> (CFG4_FTLBS_SHIFT) +# define FTLB_WAY_ENC ((C0_CONFIG4_VALUE & CFG4_FTLBW_MASK) >> CFG4_FTLBW_SHIFT) +# if TLB_DUAL +# define FTLB_SETS (1 << FTLB_SET_ENC) +# define FTLB_SIZE (2 + FTLB_WAY_ENC) * FTLB_SETS +# else +# define FTLB_SETS 1 +# define FTLB_SIZE 0 +# endif + +// VTLB May be present +# define VTLB_SIZE_ENC ((C0_CONFIG4_VALUE & CFG4_VTLBSEXT_MASK) \ + >> CFG4_VTLBSEXT_SHIFT) +# define VTLB_SIZE (VTLB_SIZE_ENC << CFG1_MMUS_BITS) +#endif + +// Size +#define TLB_SIZE ((C0_CONFIG1_VALUE & CFG1_MMUS_MASK) >> CFG1_MMUS_SHIFT) + +// ISA < 6 relys on CFG4 MMU Extension definition +#if __mips_isa_rev < 6 + +#if !defined(C0_CONFIG4_VALUE) || (C0_CONFIG4_VALUE & CFG4_MMUED) == 0 +# define MMU_SIZE (TLB_SIZE + 1) +#elif (C0_CONFIG4_VALUE & CFG4_MMUED) == CFG4_MMUED_FTLBVEXT +# define MMU_SIZE (FTLB_SIZE + VTLB_SIZE + TLB_SIZE + 1) +#elif (C0_CONFIG4_VALUE & CFG4_MMUED) == CFG4_MMUED_SIZEEXT +# define MMUSE_ENC (C0_CONFIG4_VALUE & CFG4_MMUSE_MASK) >> CFG4_MMUSE_SHIFT +# define TLB_EXT_SIZE (MMUSE_ENC << CFG1_MMUS_BITS) +# define MMU_SIZE (TLB_EXT_SIZE + TLB_SIZE + 1) +#elif (C0_CONFIG4_VALUE & CFG4_MMUED) == CFG4_MMUED_FTLB +# define MMU_SIZE (FTLB_SIZE + TLB_SIZE + 1) +#endif /* C0_CONFIG4_VALUE & ...*/ + +#else + +// ISA >= 6 always uses the FTLB + VTLB fields. +#define MMU_SIZE (FTLB_SIZE + VTLB_SIZE + TLB_SIZE + 1) + +#endif /* __mips_isa_rev < 6 */ + + +// Invalidation +#ifdef C0_CONFIG4_VALUE +# define HAVE_HW_TLB_WALK ((C0_CONFIG4_VALUE & CFG4_IE_MASK) == CFG4_IE_INVALL) +# define HAVE_SW_TLB_WALK ((C0_CONFIG4_VALUE & CFG4_IE_MASK) == CFG4_IE_INV) +# define HAVE_EHINV_WALK ((C0_CONFIG4_VALUE & CFG4_IE_MASK) == CFG4_IE_EHINV) +# define HAVE_NO_INV (!(HAVE_HW_TLB_WALK || HAVE_SW_TLB_WALK || HAVE_EHINV_WALK)) +#else +# define HAVE_NO_INV 1 +#endif + +// LPA +#define HAVE_LPA (C0_CONFIG3_VALUE & CFG3_LPA) diff --git a/libgloss/mips/boot/reset.S b/libgloss/mips/boot/reset.S new file mode 100644 index 0000000..37c674d --- /dev/null +++ b/libgloss/mips/boot/reset.S @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _RESETCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + + .set push + MIPS_NOMICROMIPS + +LEAF(__reset_vector) + lui k1, %hi(__cpu_init) + addiu k1, %lo(__cpu_init) + mtc0 zero, C0_COUNT /* Clear CP0 Count (Used to measure boot time.) */ + jr k1 + .space 32 /* Just to cope with a quirk of MIPS malta boards */ + /* this can be deleted for anything else */ +END(__reset_vector) + .set pop + +LEAF(__cpu_init) + + /* + * Verify the code is here due to a reset and not NMI. If this is an NMI then trigger + * a debugger breakpoint using a sdbbp instruction. + */ + + mfc0 k1, C0_STATUS + ext k1, k1, SR_NMI_SHIFT, 1 + beqz k1, $Lnot_nmi + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ + +$Lnot_nmi: + + /* Init CP0 Status, Count, Compare, Watch*, and Cause */ + jal __init_cp0 + + /* + * Initialise L2/L3 cache + * This could be done from cached code if there is a cca override or similar + */ + jal __init_l23cache + /* Save the L2 config register */ + move s0, a0 + + /* Initialize the L1 instruction cache */ + jal __init_icache + + /* + * The changing of Kernel mode cacheability must be done from KSEG1 + * Since the code is executing from KSEG0 it needs to do a jump to KSEG1, change K0 + * and jump back to KSEG0. + */ + + lui a2, %hi(__change_k0_cca) + addiu a2, a2, %lo(__change_k0_cca) + li a1, 0xf + ins a2, a1, 29, 1 /* changed to KSEG1 address by setting bit 29 */ + jalr a2 + + .weak __init_l23cache_cached + lui a2, %hi(__init_l23cache_cached) + addiu a2, a2, %lo(__init_l23cache_cached) + beqz a2, 1f + /* Pass in the L2 config register */ + move a0, s0 + jalr a2 +1: + /* Initialize the L1 data cache */ + jal __init_dcache + + /* Initialize the TLB */ + jal __init_tlb + + /* Allow everything else to be initialized via a hook */ + .weak __boot_init_hook + lui a2, %hi(__boot_init_hook) + addiu a2, a2, %lo(__boot_init_hook) + beqz a2, 1f + jalr a2 +1: + /* Skip copy to ram when executing in place */ + .weak __xip + lui a1, %hi(__xip) + addiu a1, a1, %lo(__xip) + bnez a1, $Lcopy_to_ram_done + /* Copy code and data to RAM */ + li s1, 0xffffffff + + /* Copy code and read-only/initialized data from FLASH to (uncached) RAM */ + lui a1, %hi(__flash_app_start) + addiu a1, a1, %lo(__flash_app_start) + ins a1, s1, 29, 1 /* Make it uncached (kseg1) */ + lui a2, %hi(__app_start) + addiu a2, a2, %lo(__app_start) + ins a2, s1, 29, 1 /* Make it uncached (kseg1) */ + lui a3, %hi(_edata) + addiu a3, a3, %lo(_edata) + ins a3, s1, 29, 1 /* Make it uncached (kseg1) */ + beq a2, a3, $Lcopy_to_ram_done +$Lnext_ram_word: + lw a0, 0(a1) + addiu a2, a2, 4 + addiu a1, a1, 4 + sw a0, -4(a2) + bne a3, a2, $Lnext_ram_word +$Lcopy_to_ram_done: + + # Prepare for eret to _start + lui ra, %hi($Lall_done) /* If main returns then go to all_done */ + addiu ra, ra, %lo($Lall_done) + lui t0, %hi(_start) + addiu t0, t0, %lo(_start) + mtc0 t0, C0_ERRPC /* Set ErrorEPC to _start */ + ehb + li a0, 0 /* UHI compliant null argument setup */ + + /* Return from exception will now execute the application startup code */ + eret + +$Lall_done: + /* Allow an exit hook to intercept the end of execution */ + .weak __boot_exit_hook + lui a2, %hi(__boot_exit_hook) + addiu a2, a2, %lo(__boot_exit_hook) + beqz a2, 1f + jalr a2 +1: + /* + * If _start returns it will return to this point. + * Just spin here reporting the exit. + */ + li t9, 1 /* UHI exit operation */ + move a0, va0 /* Collect exit code for UHI exit */ + sdbbp 1 /* Invoke UHI operation */ + b $Lall_done +END(__cpu_init) + +/************************************************************************************** + B O O T E X C E P T I O N H A N D L E R S (CP0 Status[BEV] = 1) +**************************************************************************************/ +/* NOTE: the linker script must insure that this code starts at start + 0x200 so the exception */ +/* vectors will be addressed properly. */ + +/* TLB refill, 32 bit task. */ +.org 0x200 +LEAF(__boot_tlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_tlb_refill) + +/* XTLB refill, 64 bit task. */ +.org 0x280 +LEAF(__boot_xtlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_xtlb_refill) + +/* Cache error exception. */ +.org 0x300 +LEAF(__boot_cache_error) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_cache_error) + +/* General exception. */ +.org 0x380 +LEAF(__boot_general_exception) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_general_exception) + +# If you want the above code to fit into 1k flash you will need to leave out the +# code below. This is the code that covers the debug exception which you normally will not get. + +/* EJTAG Debug */ +.org 0x480 +LEAF(__boot_debug_exception) + PTR_MFC0 k1, C0_DEPC + PTR_MTC0 k1, C0_DESAVE + lui k1, %hi(1f) + addiu k1, %lo(1f) + PTR_MTC0 k1, C0_DEPC + ehb + deret +1: wait + b 1b /* Stay here */ +END(__boot_debug_exception) diff --git a/libgloss/mips/boot/reset_predef.S b/libgloss/mips/boot/reset_predef.S new file mode 100644 index 0000000..d987ef7 --- /dev/null +++ b/libgloss/mips/boot/reset_predef.S @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _RESETCODE + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "predef.h" + +MIPS_NOMIPS16 + + .set push + MIPS_NOMICROMIPS + +LEAF(__reset_vector) + lui k1, %hi(__cpu_init) + addiu k1, %lo(__cpu_init) + mtc0 zero, C0_COUNT /* Clear CP0 Count (Used to measure boot time.) */ + jr k1 + .space 32 /* Just to cope with a quirk of MIPS malta boards */ + /* this can be deleted for anything else */ +END(__reset_vector) + .set pop + +LEAF(__cpu_init) + + /* + * Verify the code is here due to a reset and not NMI. If this is an NMI then trigger + * a debugger breakpoint using a sdbbp instruction. + */ + + mfc0 k1, C0_STATUS + ext k1, k1, SR_NMI_SHIFT, 1 + beqz k1, $Lnot_nmi + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ + +$Lnot_nmi: + +#ifndef SKIP_CORE_CHECK + jal __core_check +#endif + + /* Init CP0 Status, Count, Compare, Watch*, and Cause */ + jal __init_cp0 + +#if !defined(HCI) + +#if (defined(SLINE_ENC) && SLINE_ENC != 0) || (defined(MEM_MAPPED_L2C) && MEM_MAPPED_L2C != 0) + /* + * Initialise L2/L3 cache + * This could be done from cached code if there is a cca override or similar + */ + jal __init_l23cache + /* Save the L2 config register */ + move s0, a0 +#endif + +#if defined(ILINE_ENC) && ILINE_ENC != 0 + /* Initialize the L1 instruction cache */ + jal __init_icache +#endif + +#endif /* !defined(HCI) */ + + /* + * The changing of Kernel mode cacheability must be done from KSEG1 + * Since the code is executing from KSEG0 it needs to do a jump to KSEG1, change K0 + * and jump back to KSEG0. + */ + + lui a2, %hi(__change_k0_cca) + addiu a2, a2, %lo(__change_k0_cca) + li a1, 0xf + ins a2, a1, 29, 1 /* changed to KSEG1 address by setting bit 29 */ + jalr a2 + +#if !defined(HCI) + +#if (defined(SLINE_ENC) && SLINE_ENC != 0) || (defined(MEM_MAPPED_L2C) && MEM_MAPPED_L2C != 0) + /* Pass in the L2 config register */ + move a0, s0 + /* Support initialising L2 with L1 cache enabled */ + jal __init_l23cache_cached +#endif + +#if defined(DLINE_ENC) && DLINE_ENC != 0 + /* Initialize the L1 data cache */ + jal __init_dcache +#endif + +#endif /* !defined(HCI) */ + +#if defined(HAVE_TLB) && HAVE_TLB + /* Initialize the TLB */ + jal __init_tlb +#endif + + /* Allow everything else to be initialized via a hook */ + .weak __boot_init_hook + lui a2, %hi(__boot_init_hook) + addiu a2, a2, %lo(__boot_init_hook) + beqz a2, 1f + jalr a2 +1: + /* Skip copy to ram when executing in place */ + .weak __xip + lui a1, %hi(__xip) + addiu a1, a1, %lo(__xip) + bnez a1, $Lcopy_to_ram_done + + /* Copy code and data to RAM */ + li s1, 0xffffffff + + /* Copy code and read-only/initialized data from FLASH to (uncached) RAM */ + lui a1, %hi(__flash_app_start) + addiu a1, a1, %lo(__flash_app_start) +#if defined(ILINE_ENC) && ILINE_ENC != 0 + ins a1, s1, 29, 1 /* Make it uncached (kseg1) */ +#endif + lui a2, %hi(__app_start) + addiu a2, a2, %lo(__app_start) +#if defined(ILINE_ENC) && ILINE_ENC != 0 + ins a2, s1, 29, 1 /* Make it uncached (kseg1) */ +#endif + lui a3, %hi(_edata) + addiu a3, a3, %lo(_edata) +#if defined(ILINE_ENC) && ILINE_ENC != 0 + ins a3, s1, 29, 1 /* Make it uncached (kseg1) */ +#endif + beq a2, a3, $Lcopy_to_ram_done +$Lnext_ram_word: + lw a0, 0(a1) + addiu a2, a2, 4 + addiu a1, a1, 4 + sw a0, -4(a2) + bne a3, a2, $Lnext_ram_word +$Lcopy_to_ram_done: + + # Prepare for eret to _start + lui ra, %hi($Lall_done) /* If main returns then go to all_done */ + addiu ra, ra, %lo($Lall_done) + lui t0, %hi(_start) + addiu t0, t0, %lo(_start) + mtc0 t0, C0_ERRPC /* Set ErrorEPC to _start */ + ehb + li a0, 0 /* UHI compliant null argument setup */ + + /* Return from exception will now execute the application startup code */ + eret + +$Lall_done: + /* Allow an exit hook to intercept the end of execution */ + .weak __boot_exit_hook + lui a2, %hi(__boot_exit_hook) + addiu a2, a2, %lo(__boot_exit_hook) + beqz a2, 1f + jalr a2 +1: + /* + * If _start returns it will return to this point. + * Just spin here reporting the exit. + */ + li t9, 1 /* UHI exit operation */ + move a0, va0 /* Collect exit code for UHI exit */ + sdbbp 1 /* Invoke UHI operation */ + b $Lall_done + +END(__cpu_init) + +/************************************************************************************** + B O O T E X C E P T I O N H A N D L E R S (CP0 Status[BEV] = 1) +**************************************************************************************/ +/* NOTE: the linker script must insure that this code starts at start + 0x200 so the exception */ +/* vectors will be addressed properly. */ + +/* TLB refill, 32 bit task. */ +.org 0x200 +LEAF(__boot_tlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_tlb_refill) + +/* XTLB refill, 64 bit task. */ +.org 0x280 +LEAF(__boot_xtlb_refill) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_xtlb_refill) + +/* Cache error exception. */ +.org 0x300 +LEAF(__boot_cache_error) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_cache_error) + +/* General exception. */ +.org 0x380 +LEAF(__boot_general_exception) + move k0, t9 /* Preserve t9 */ + move k1, a0 /* Preserve a0 */ + li t9, 15 /* UHI exception operation */ + li a0, 0 /* Use hard register context */ + sdbbp 1 /* Invoke UHI operation */ +END(__boot_general_exception) + +# If you want the above code to fit into 1k flash you will need to leave out the +# code below. This is the code that covers the debug exception which you normally will not get. + +/* EJTAG Debug */ +.org 0x480 +LEAF(__boot_debug_exception) + PTR_MFC0 k1, C0_DEPC + PTR_MTC0 k1, C0_DESAVE + lui k1, %hi(1f) + addiu k1, %lo(1f) + PTR_MTC0 k1, C0_DEPC + ehb + deret +1: wait + b 1b /* Stay here */ +END(__boot_debug_exception) diff --git a/libgloss/mips/bootcode.ld b/libgloss/mips/bootcode.ld new file mode 100644 index 0000000..5c1bcbf --- /dev/null +++ b/libgloss/mips/bootcode.ld @@ -0,0 +1,14 @@ +/* This script forces the inclusion of boot code by creating references + to all the initialisation functions. These early references also + ensure custom versions of code are pulled out of user supplied + objects and libraries before default implementations. */ + +EXTERN (__reset_vector); +EXTERN (__init_cp0); +EXTERN (__init_l23cache); +EXTERN (__init_icache); +EXTERN (__change_k0_cca); +EXTERN (__init_dcache); +EXTERN (__init_tlb); +EXTERN (__boot_init_hook); +PROVIDE (__boot_init_hook = 0); diff --git a/libgloss/mips/crt0.S b/libgloss/mips/crt0.S deleted file mode 100644 index 2549982..0000000 --- a/libgloss/mips/crt0.S +++ /dev/null @@ -1,316 +0,0 @@ -/* - * crt0.S -- startup file for MIPS. - * - * Copyright (c) 1995, 1996, 1997, 2001 Cygnus Support - * - * The authors hereby grant permission to use, copy, modify, distribute, - * and license this software and its documentation for any purpose, provided - * that existing copyright notices are retained in all copies and that this - * notice is included verbatim in any distributions. No written agreement, - * license, or royalty fee is required for any of the authorized uses. - * Modifications to this software may be copyrighted by their authors - * and need not follow the licensing terms described here, provided that - * the new terms are clearly indicated on the first page of each file where - * they apply. - */ - -/* This file does not use any floating-point ABI. */ - .gnu_attribute 4,0 - -#ifdef __mips16 -/* This file contains 32 bit assembly code. */ - .set nomips16 -#endif - -#include "regs.S" -#include "abiflags.S" - -/* - * Set up some room for a stack. We just grab a chunk of memory. - */ -#define STACK_SIZE 0x4000 -#define GLOBAL_SIZE 0x2000 - -#define STARTUP_STACK_SIZE 0x0100 - -/* This is for referencing addresses that are not in the .sdata or - .sbss section under embedded-pic, or before we've set up gp. */ -#ifdef __mips_embedded_pic -# ifdef __mips64 -# define LA(t,x) la t,x-PICBASE ; daddu t,s0,t -# else -# define LA(t,x) la t,x-PICBASE ; addu t,s0,t -# endif -#else /* __mips_embedded_pic */ -# define LA(t,x) la t,x -#endif /* __mips_embedded_pic */ - - .comm __memsize, 12 - .comm __lstack, STARTUP_STACK_SIZE - - .text - .align 2 - -/* Without the following nop, GDB thinks _start is a data variable. - * This is probably a bug in GDB in handling a symbol that is at the - * start of the .text section. - */ - nop - - .globl hardware_hazard_hook .text - .globl _start - .ent _start -_start: -#ifdef __mips_embedded_pic -#define PICBASE start_PICBASE - .set noreorder - PICBASE = .+8 - bal PICBASE - nop - move s0,$31 - .set reorder -#endif -#if __mips<3 -# define STATUS_MASK (SR_CU1|SR_PE) -#else -/* Post-mips2 has no SR_PE bit. */ -# ifdef __mips64 -/* Turn on 64-bit addressing and additional float regs. */ -# define STATUS_MASK (SR_CU1|SR_FR|SR_KX|SR_SX|SR_UX) -# else -# if __mips_fpr==32 -# define STATUS_MASK (SR_CU1) -# else -/* Turn on additional float regs. */ -# define STATUS_MASK (SR_CU1|SR_FR) -# endif -# endif -#endif - - /* Clear Cause register. */ - mtc0 zero,C0_CAUSE - nop - - /* Read MIPS_abiflags structure and set status/config registers - accordingly. */ - .weak __MIPS_abiflags_start - .weak __MIPS_abiflags_end - LA (t0,__MIPS_abiflags_start) - LA (t1,__MIPS_abiflags_end) - addiu t1,t1,-24 - move v0,zero /* Mask for C0_SR. */ - - /* Branch to 1f is the .MIPS.abiflags section is not 24 bytes. This - indicates it is either missing or corrupt. */ - bne t0,t1,1f - - /* Check isa_level. */ - lbu t1,ABIFlags_isa_level(t0) - sltu v1,t1,3 /* Is MIPS < 3? */ - xori t1,t1,64 /* Is MIPS64? */ - beq v1,zero,4f - li v1,SR_PE - or v0,v0,v1 /* Enable soft reset. */ -4: - li v1,(SR_KX|SR_SX|SR_UX) - bne t1,zero,5f - or v0,v0,v1 /* Enable extended addressing. */ -5: - /* Check fp_abi. */ - lbu t1,ABIFlags_fp_abi(t0) - xori t1,t1,Val_GNU_MIPS_ABI_FP_SOFT - li v1,SR_CU1 - beq t1,zero,2f /* Skip MSA and cpr1_size checks. */ - or v0,v0,v1 /* Enable co-processor 1. */ - - /* Check cpr1_size. */ - lbu t1,ABIFlags_cpr1_size(t0) - xori t1,t1,AFL_REG_64 - li v1,SR_FR - bne t1,zero,3f - or v0,v0,v1 /* Enable 64-bit FPU registers. */ -3: - /* Check ases. */ - lw t1,ABIFlags_ases(t0) - andi t1,t1,AFL_ASE_MSA - li v1,SR_FR - beq t1,zero,2f - or v0,v0,v1 /* Enable 64-bit FPU registers. */ - li v1,SR_MSA - .set push - .set mips32 - mtc0 v1,C0_CONFIG,5 /* Enable MSA. */ - .set pop - b 2f - -1: - /* MIPS_abiflags structure is not available. Set status/config - registers based on flags defined by compiler. */ -#ifdef __mips_soft_float - li v0,(STATUS_MASK-(STATUS_MASK & SR_CU1)) -#else - li v0,STATUS_MASK -#endif - -2: - /* Set C0_SR, */ - mtc0 v0,C0_SR - nop - - /* Avoid hazard from C0_SR changes. */ - LA (t0, hardware_hazard_hook) - beq t0,zero,2f - jalr t0 -2: - - -/* Fix high bits, if any, of the PC so that exception handling doesn't get - confused. */ - LA (v0, 3f) - jr v0 -3: - LA (gp, _gp) # set the global data pointer - .end _start - -/* - * zero out the bss section. - */ - .globl __memsize - .globl get_mem_info .text - .globl __stack - .globl __global - .ent zerobss -zerobss: - LA (v0, _fbss) - LA (v1, _end) - beq v0,v1,2f -1: - addiu v0,v0,4 - sw zero,-4(v0) - bne v0,v1,1b -2: - la t0, __lstack # make a small stack so we - addiu sp, t0, STARTUP_STACK_SIZE # can run some C code - la a0, __memsize # get the usable memory size - jal get_mem_info - - /* setup the stack pointer */ - LA (t0, __stack) # is __stack set ? - bne t0,zero,4f - - /* NOTE: a0[0] contains the amount of memory available, and - not the last memory address. */ - la a0, __memsize - lw t0,0(a0) # last address of memory available - la t1,K0BASE # cached kernel memory - addu t0,t0,t1 # get the end of memory address - /* Allocate 32 bytes for the register parameters. Allocate 16 - bytes for a null argv and envp. Round the result up to 64 - bytes to preserve alignment. */ - subu t0,t0,64 -4: - move sp,t0 # set stack pointer - .end zerobss - -/* - * initialize target specific stuff. Only execute these - * functions it they exist. - */ - .globl hardware_init_hook .text - .globl software_init_hook .text - .type _fini,@function - .type _init,@function - .globl atexit .text - .globl exit .text - .ent init -init: - LA (t9, hardware_init_hook) # init the hardware if needed - beq t9,zero,6f - jalr t9 -6: - LA (t9, software_init_hook) # init the hardware if needed - beq t9,zero,7f - jalr t9 -7: - LA (a0, _fini) - jal atexit - -#ifdef GCRT0 - .globl _ftext - .globl _extext - LA (a0, _ftext) - LA (a1, _etext) - jal monstartup -#endif - - - jal _init # run global constructors - - addiu a1,sp,32 # argv = sp + 32 - addiu a2,sp,40 # envp = sp + 40 -#if __mips64 - sd zero,(a1) # argv[argc] = 0 - sd zero,(a2) # envp[0] = 0 -#else - sw zero,(a1) - sw zero,(a2) -#endif - move a0,zero # set argc to 0 - jal main # call the program start function - - # fall through to the "exit" routine - move a0,v0 # pass through the exit code - jal exit # call libc exit to run the G++ - # destructors - .end init - - -/* Assume the PICBASE set up above is no longer valid below here. */ -#ifdef __mips_embedded_pic -#undef PICBASE -#endif - -/* - * _exit -- Exit from the application. Normally we cause a user trap - * to return to the ROM monitor for another run. NOTE: This is - * the only other routine we provide in the crt0.o object, since - * it may be tied to the "_start" routine. It also allows - * executables that contain a complete world to be linked with - * just the crt0.o object. - */ - .globl hardware_exit_hook .text - .globl _exit - .ent _exit -_exit: -7: -#ifdef __mips_embedded_pic - /* Need to reinit PICBASE, since we might be called via exit() - rather than via a return path which would restore old s0. */ -#define PICBASE exit_PICBASE - .set noreorder - PICBASE = .+8 - bal PICBASE - nop - move s0,$31 - .set reorder -#endif -#ifdef GCRT0 - LA (t0, _mcleanup) - jalr t0 -#endif - LA (t0, hardware_exit_hook) - beq t0,zero,1f - jalr t0 -1: - - # break instruction can cope with 0xfffff, but GAS limits the range: - break 1023 - b 7b # but loop back just in-case - .end _exit - -/* Assume the PICBASE set up above is no longer valid below here. */ -#ifdef __mips_embedded_pic -#undef PICBASE -#endif - -/* EOF crt0.S */ diff --git a/libgloss/mips/fstat.c b/libgloss/mips/fstat.c new file mode 100644 index 0000000..d8f94af --- /dev/null +++ b/libgloss/mips/fstat.c @@ -0,0 +1,32 @@ +/* fstat.c -- get status of a file. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <sys/stat.h> +#include "glue.h" + +/* + * fstat -- Since we have no file system, we just return an error. + */ +int +#if defined(__mips__) && defined(__mips16) +__attribute__((nomips16)) +#endif +fstat (int fd, + struct stat *buf) +{ + buf->st_mode = S_IFCHR; /* Always pretend to be a tty */ + buf->st_blksize = 0; + + return (0); +} diff --git a/libgloss/mips/hal/__exit.c b/libgloss/mips/hal/__exit.c new file mode 100644 index 0000000..9041f85 --- /dev/null +++ b/libgloss/mips/hal/__exit.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis void __exit (int32_t exit_code); + * + * Parameters: + * $4 - Exit code + * + * Return: + * None + * + * @Description Transfer control to the debug port +*/ + +#include <stdint.h> + +void +__exit (int32_t exit_code) +{ + return; +} + diff --git a/libgloss/mips/hal/abiflags.S b/libgloss/mips/hal/abiflags.S new file mode 100644 index 0000000..e965adb --- /dev/null +++ b/libgloss/mips/hal/abiflags.S @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * abiflags.S - MIPS ABI flags. + */ + +/* Values for the xxx_size bytes of an ABI flags structure. */ +#define AFL_REG_NONE 0x00 /* No registers. */ +#define AFL_REG_32 0x01 /* 32-bit registers. */ +#define AFL_REG_64 0x02 /* 64-bit registers. */ +#define AFL_REG_128 0x03 /* 128-bit registers. */ + +/* Masks for the ases word of an ABI flags structure. */ +#define AFL_ASE_DSP 0x00000001 /* DSP ASE. */ +#define AFL_ASE_DSPR2 0x00000002 /* DSP R2 ASE. */ +#define AFL_ASE_EVA 0x00000004 /* Enhanced VA Scheme. */ +#define AFL_ASE_MCU 0x00000008 /* MCU (MicroController) ASE. */ +#define AFL_ASE_MDMX 0x00000010 /* MDMX ASE. */ +#define AFL_ASE_MIPS3D 0x00000020 /* MIPS-3D ASE. */ +#define AFL_ASE_MT 0x00000040 /* MT ASE. */ +#define AFL_ASE_SMARTMIPS 0x00000080 /* SmartMIPS ASE. */ +#define AFL_ASE_VIRT 0x00000100 /* VZ ASE. */ +#define AFL_ASE_MSA 0x00000200 /* MSA ASE. */ +#define AFL_ASE_MIPS16 0x00000400 /* MIPS16 ASE. */ +#define AFL_ASE_MICROMIPS 0x00000800 /* MICROMIPS ASE. */ +#define AFL_ASE_XPA 0x00001000 /* XPA ASE. */ + +/* Values for the isa_ext word of an ABI flags structure. */ +#define AFL_EXT_XLR 1 /* RMI Xlr instruction. */ +#define AFL_EXT_OCTEON2 2 /* Cavium Networks Octeon2. */ +#define AFL_EXT_OCTEONP 3 /* Cavium Networks OcteonP. */ +#define AFL_EXT_LOONGSON_3A 4 /* Loongson 3A. */ +#define AFL_EXT_OCTEON 5 /* Cavium Networks Octeon. */ +#define AFL_EXT_5900 6 /* MIPS R5900 instruction. */ +#define AFL_EXT_4650 7 /* MIPS R4650 instruction. */ +#define AFL_EXT_4010 8 /* LSI R4010 instruction. */ +#define AFL_EXT_4100 9 /* NEC VR4100 instruction. */ +#define AFL_EXT_3900 10 /* Toshiba R3900 instruction. */ +#define AFL_EXT_10000 11 /* MIPS R10000 instruction. */ +#define AFL_EXT_SB1 12 /* Broadcom SB-1 instruction. */ +#define AFL_EXT_4111 13 /* NEC VR4111/VR4181 instruction. */ +#define AFL_EXT_4120 14 /* NEC VR4120 instruction. */ +#define AFL_EXT_5400 15 /* NEC VR5400 instruction. */ +#define AFL_EXT_5500 16 /* NEC VR5500 instruction. */ +#define AFL_EXT_LOONGSON_2E 17 /* ST Microelectronics Loongson 2E. */ +#define AFL_EXT_LOONGSON_2F 18 /* ST Microelectronics Loongson 2F. */ + +/* Values defined for Tag_GNU_MIPS_ABI_FP. */ +#define Val_GNU_MIPS_ABI_FP_ANY 0 /* Not tagged or not using any ABIs affected by the differences. */ +#define Val_GNU_MIPS_ABI_FP_DOUBLE 1 /* Using hard-float -mdouble-float. */ +#define Val_GNU_MIPS_ABI_FP_SINGLE 2 /* Using hard-float -msingle-float. */ +#define Val_GNU_MIPS_ABI_FP_SOFT 3 /* Using soft-float. */ +#define Val_GNU_MIPS_ABI_FP_OLD_64 4 /* Using -mips32r2 -mfp64. */ +#define Val_GNU_MIPS_ABI_FP_XX 5 /* Using -mfpxx */ +#define Val_GNU_MIPS_ABI_FP_64 6 /* Using -mips32r2 -mfp64. */ +#define Val_GNU_MIPS_ABI_MSA_ANY 0 /* Not tagged or not using any ABIs affected by the differences. */ +#define Val_GNU_MIPS_ABI_MSA_128 1 /* Using 128-bit MSA. */ + +/* MIPS ABI flags structure */ + .struct 0 +ABIFlags_version: + .struct ABIFlags_version + 2 +ABIFlags_isa_level: + .struct ABIFlags_isa_level + 1 +ABIFlags_isa_rev: + .struct ABIFlags_isa_rev + 1 +ABIFlags_gpr_size: + .struct ABIFlags_gpr_size + 1 +ABIFlags_cpr1_size: + .struct ABIFlags_cpr1_size + 1 +ABIFlags_cpr2_size: + .struct ABIFlags_cpr2_size + 1 +ABIFlags_fp_abi: + .struct ABIFlags_fp_abi + 1 +ABIFlags_isa_ext: + .struct ABIFlags_isa_ext + 4 +ABIFlags_ases: + .struct ABIFlags_ases + 4 +ABIFlags_flags1: + .struct ABIFlags_flags1 + 4 +ABIFlags_flags2: + .struct ABIFlags_flags2 + 4 + +/*> EOF abiflags.S <*/ diff --git a/libgloss/mips/hal/cache.h b/libgloss/mips/hal/cache.h new file mode 100644 index 0000000..5cb90e2 --- /dev/null +++ b/libgloss/mips/hal/cache.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define __MIPS_NO_IMPLICIT_EHB /* No implicit EHB after mtc0 */ +#include <mips/cpu.h> +#include <mips/cm3.h> +#include <mips/m32c0.h> +#include <mips/m64c0.h> +#include <mips/hal.h> + +#if defined(__mips64) || (__mips == 64) +#define mips_getentryhi() mips64_getentryhi() +#define mips_setentryhi(v) mips64_setentryhi(v) +#define mips_getentrylo0() mips64_getentrylo0() +#define mips_setentrylo0(v) mips64_setentrylo0(v) +#define mips_getentrylo1() mips64_getentrylo1() +#define mips_setentrylo1(v) mips64_setentrylo1(v) +#define mips_getpagemask() mips64_getpagemask() +#define mips_setpagemask(v) mips64_setpagemask(v) +#define mips_getindex() mips64_getindex() +#define mips_setindex(v) mips64_setindex(v) +#define mips_getcmgcrbase() mips64_get_c0(C0_CMGCRBASE) +#else +#define mips_getentryhi() mips32_getentryhi() +#define mips_setentryhi(v) mips32_setentryhi(v) +#define mips_getentrylo0() mips32_getentrylo0() +#define mips_setentrylo0(v) mips32_setentrylo0(v) +#define mips_getentrylo1() mips32_getentrylo1() +#define mips_setentrylo1(v) mips32_setentrylo1(v) +#define mips_getpagemask() mips32_getpagemask() +#define mips_setpagemask(v) mips32_setpagemask(v) +#define mips_getindex() mips32_getindex() +#define mips_setindex(v) mips32_setindex(v) +#define mips_getcmgcrbase() mips32_get_c0(C0_CMGCRBASE) +#endif + +static inline __attribute__((always_inline)) _MIPS_HAL_NOMIPS16 +void mips_cache_op (vaddr_t kva, size_t n, int lsize, const int op) +{ + vaddr_t addr, maxaddr, mask; + + if (n <= 0) + return; + + mask = ~ (lsize - 1); + addr = (kva & mask) - lsize; + maxaddr = ((kva + n) - 1) & mask; + + do + { + addr = addr + lsize; + mips_cache (op, addr); + } + while (addr != maxaddr); + + return; +} diff --git a/libgloss/mips/hal/crt0.S b/libgloss/mips/hal/crt0.S new file mode 100644 index 0000000..ac6e614 --- /dev/null +++ b/libgloss/mips/hal/crt0.S @@ -0,0 +1,312 @@ +/* + * crt0.S -- startup file for MIPS. + * + * Copyright (c) 1995, 1996, 1997, 2001 Cygnus Support + * Copyright (C) 2016-2018 MIPS Tech, LLC + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +/* This file does not use any floating-point ABI. */ + .gnu_attribute 4,0 + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include "abiflags.S" + +MIPS_NOMIPS16 + +#define STARTUP_STACK_SIZE 0x40 /* Temporary stack size to run C code */ + + .section .startdata, "aw", @nobits + .balign 16 + .space STARTUP_STACK_SIZE +__lstack: # Points to the end of the stack +__ram_extent: + .space 8 + + .data + + .balign SZREG +__temp_space: /* Temporary space to save arguments */ + .space SZREG * 3 + + .text + .align 2 + +/* + * Without the following nop, GDB thinks _start is a data variable. + * This is probably a bug in GDB in handling a symbol that is at the + * start of the .text section. + */ + nop + + .globl hardware_hazard_hook .text + .globl _start + .ent _start +_start: +#if __mips<3 +# define STATUS_MASK (SR_CU1|SR_PE) +#else +/* Post-mips2 has no SR_PE bit. */ +# ifdef __mips64 +/* Turn on 64-bit addressing and additional float regs. */ +# define STATUS_MASK (SR_CU1|SR_FR|SR_KX|SR_SX|SR_UX) +# else +# if __mips_fpr==32 +# define STATUS_MASK (SR_CU1) +# else +/* Turn on additional float regs. */ +# define STATUS_MASK (SR_CU1|SR_FR) +# endif +# endif +#endif + + /* Save argument registers */ + LA t0, __temp_space + REG_S a0, (SZREG * 0)(t0) + REG_S a1, (SZREG * 1)(t0) + REG_S a2, (SZREG * 2)(t0) + + /* + * Save k0, k1, ra and sp and register + * default exception handler. + */ + .weak __register_excpt_handler + LA t9, __register_excpt_handler + beqz t9, 1f + move a0, ra /* save ra */ + jalr t9 + b 2f +1: + /* Clear Cause register. */ + mtc0 zero,C0_CAUSE + move va0,zero /* Mask for C0_SR. */ +2: + /* Read MIPS_abiflags structure and set status/config registers + accordingly. */ + .weak __MIPS_abiflags_start + .weak __MIPS_abiflags_end + LA t0,__MIPS_abiflags_start + LA t1,__MIPS_abiflags_end + PTR_ADDU t1,t1,-24 + + /* Branch to 1f is the .MIPS.abiflags section is not 24 bytes. This + indicates it is either missing or corrupt. */ + bne t0,t1,1f + + /* Check isa_level. */ + lbu t1,ABIFlags_isa_level(t0) + sltu t2,t1,3 /* Is MIPS < 3? */ + xori t1,t1,64 /* Is MIPS64? */ + beq t2,zero,3f + li t2,SR_PE + or va0,va0,t2 /* Enable soft reset. */ +3: + li t2,(SR_KX|SR_SX|SR_UX) + bne t1,zero,3f + or va0,va0,t2 /* Enable extended addressing. */ +3: + /* Check DSP,DSP2,MDMX ase. */ + lw t1,ABIFlags_ases(t0) + andi t1,t1,(AFL_ASE_DSP|AFL_ASE_DSPR2|AFL_ASE_MDMX) + li t2,SR_MX + beq t1,zero,3f + or va0,va0,t2 +3: + /* Check fp_abi. */ + lbu t1,ABIFlags_fp_abi(t0) + xori t1,t1,Val_GNU_MIPS_ABI_FP_SOFT + li t2,SR_CU1 + beq t1,zero,2f /* Skip MSA and cpr1_size checks. */ + or va0,va0,t2 /* Enable co-processor 1. */ + + /* Check cpr1_size. */ + lbu t1,ABIFlags_cpr1_size(t0) + xori t1,t1,AFL_REG_64 + li t2,SR_FR + bne t1,zero,3f + or va0,va0,t2 /* Enable 64-bit FPU registers. */ +3: + /* Check MSA ASE. */ + lw t1,ABIFlags_ases(t0) + andi t1,t1,AFL_ASE_MSA + li t2,SR_FR + beq t1,zero,2f + or va0,va0,t2 /* Enable 64-bit FPU registers. */ + li t2,CFG5_MSAEN + mtc0 t2,C0_CONFIG,5 /* Enable MSA. */ + b 2f + +1: + /* MIPS_abiflags structure is not available. Set status/config + registers based on flags defined by compiler. */ +#ifdef __mips_soft_float + li va0,(STATUS_MASK-(STATUS_MASK & SR_CU1)) +#else + li va0,STATUS_MASK +#endif + +2: + /* Set C0_SR, */ + mtc0 va0,C0_SR + ehb + + /* set the global data pointer */ + LA gp, _gp + .end _start + +/* + * zero out the bss section. + */ + .globl _get_ram_info .text + .globl __stack + .globl __global + .ent zerobss +zerobss: + LA t0, _fbss + LA t1, _end + beq t0,t1,1f +2: + PTR_ADDU t0,t0,4 + sw zero,-4(t0) + bne t0,t1,2b +1: + /* setup the stack pointer */ + LA t0, __stack /* is __stack set? */ + bne t0,zero,1f + + LA sp, __lstack /* make a small stack so we can */ + /* run some C code */ + li a0,0 /* no need for the ram base */ + LA a1, __ram_extent /* storage for the extent of ram */ + jal _get_ram_range + + /* NOTE: a0[0] contains the last address+1 of memory. */ + LA a0, __ram_extent + PTR_L t0,0(a0) /* the extent of ram */ + lw $0,-4(t0) /* check for valid memory */ + /* Allocate 32 bytes for the register parameters. Allocate 16 + bytes for a null argv and envp. Round the result up to 64 + bytes to preserve alignment. */ +1: + PTR_ADDU t0,t0,-64 + move sp,t0 /* set stack pointer */ + .end zerobss + +/* + * initialize target specific stuff. Only execute these + * functions it they exist. + */ + .globl hardware_init_hook .text + .globl software_init_hook .text + .type _fini,@function + .type _init,@function + .globl atexit .text + .globl exit .text + .ent init +init: + /* Init the hardware if needed */ + LA t9, hardware_init_hook + beq t9,zero,1f + jalr t9 +1: + /* Init the software if needed */ + LA t9, software_init_hook + beq t9,zero,1f + jalr t9 +1: + /* Register exit handlers */ + LA a0, _fini + jal atexit + + /* run global constructors */ + jal _init + + /* Restore argument registers */ + LA t0, __temp_space + REG_L a0,(SZREG * 0)(t0) + REG_L a1,(SZREG * 1)(t0) + REG_L a2,(SZREG * 2)(t0) + + /* Convert pointers potentially */ + .weak __convert_argv_pointers + LA t0, __convert_argv_pointers + beqz t0, 1f + jalr t0 +1: + /* if a0 > 0 then we have arguments ready in a0 to a2 registers */ + bgtz a0,.Lmain + /* if a0 == 0 then no arguments have been set up */ + beqz a0, 1f + /* if a0 < -1 then we have undefined behaviour so assume no + arguments have been set up */ + addiu t0, a0, 1 + bltz t0, 1f + + /* a0 == -1 */ + .weak __getargs + LA t0, __getargs + beqz t0, 1f + jalr t0 /* get arguments */ + b .Lmain +1: + /* no arguments */ + move a0,zero /* set argc to 0 */ + PTR_ADDU a1,sp,32 /* argv = sp + 32 */ + PTR_ADDU a2,sp,40 /* envp = sp + 40 */ + REG_S zero,(a1) /* argv[argc] = 0 */ + REG_S zero,(a2) /* envp[0] = 0 */ + +.Lmain: + jal main /* call the program start function */ + move a0,va0 /* pass through the exit code */ + jal exit /* call libc exit to run the G++ */ + /* destructors */ + .end init + +/* + * _exit -- Exit from the application. Normally we cause a user trap + * to return to the ROM monitor for another run. NOTE: This is + * the only other routine we provide in the crt0.o object, since + * it may be tied to the "_start" routine. It also allows + * executables that contain a complete world to be linked with + * just the crt0.o object. + */ + .globl hardware_exit_hook .text + .globl _exit + .ent _exit +_exit: +1: + /* Save exit code */ + LA t0, __temp_space + REG_S a0,0(t0) + + LA t0, hardware_exit_hook + beq t0,zero,2f + jalr t0 +2: + + /* Restore return value from main */ + LA t0, __temp_space + REG_L a0,0(t0) + + .global __exit .text + jal __exit + + /* The BREAK instruction can cope with 0xfffff, but GAS limits the + range */ + break 1023 + b 1b # but loop back just in-case + .end _exit + +/* EOF crt0.S */ diff --git a/libgloss/mips/hal/get_ram_range.c b/libgloss/mips/hal/get_ram_range.c new file mode 100644 index 0000000..429d948 --- /dev/null +++ b/libgloss/mips/hal/get_ram_range.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <_ansi.h> +#include <sys/types.h> +#include <sys/stat.h> + +#if _MIPS_SIM == _ABI64 +# define K0BASE 0xFFFFFFFF80000000LL +#else +# define K0BASE 0x80000000 +#endif +void +_get_ram_range (void **ram_base, void **ram_extent) +{ + struct s_mem + { + unsigned int size; + unsigned int icsize; + unsigned int dcsize; + } mem; + void get_mem_info (struct s_mem*); + + /* The sizeof (s_mem.size) must be 4 bytes. The compiler should be + able to eliminate this check */ + if (sizeof (unsigned int) != 4) + { + *ram_extent = 0; + return; + } + + get_mem_info (&mem); + + /* NOTE: The value returned from the get_mem_info call is the amount + of memory, and not the address of the (last byte + 1) */ + + if (ram_base) + *ram_base = (void*)K0BASE; + *ram_extent = (void*)(uintptr_t)(K0BASE + mem.size); +} diff --git a/libgloss/mips/hal/libcm3.a b/libgloss/mips/hal/libcm3.a new file mode 100644 index 0000000..7b7f49b --- /dev/null +++ b/libgloss/mips/hal/libcm3.a @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * libcm3.a - Create a reference to __cache_size_hook near the + * start of the link to include the actual implementation. + */ +EXTERN (__cache_size_hook); +GROUP(-lcm3_impl); diff --git a/libgloss/mips/hal/link.c b/libgloss/mips/hal/link.c new file mode 100644 index 0000000..d4de6f9 --- /dev/null +++ b/libgloss/mips/hal/link.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <errno.h> + +int +link (const char *oldname, const char *newname) +{ + (void) oldname; + (void) newname; + errno = EIO; + return -1; +} + diff --git a/libgloss/mips/hal/minicrt.S b/libgloss/mips/hal/minicrt.S new file mode 100644 index 0000000..bcf6caf --- /dev/null +++ b/libgloss/mips/hal/minicrt.S @@ -0,0 +1,41 @@ +#include <mips/asm.h> +#include <mips/m32c0.h> +#include <mips/regdef.h> + +LEAF(_start) +#ifdef __mips_dsp + mfc0 t0, C0_STATUS + or t0, t0, SR_MX + mtc0 t0, C0_STATUS +#endif + /* Preserve return address */ + move s0, ra + /* Set up global pointer for small data access */ + LA gp, _gp + /* Set up stack pointer */ + LA sp, __stack + /* Zero the BSS */ + LA t0, _fbss + LA t1, _end + beq t0,t1,2f +1: + addiu t0,t0,4 + sw zero,-4(t0) + bne t0,t1,1b +2: + /* Set arguments to be null for main */ + li a0, 0 + + /* Reserve the ABI required argument area */ + addiu sp, sp, -(NARGSAVE * SZARG) + /* Jump to C code */ + jal main + /* Call the exit handler */ + move a0, va0 + jal __exit + /* Return to boot */ + move ra, s0 + .weak __exit +AENT(__exit) + jr ra +END(_start) diff --git a/libgloss/mips/hal/mips64_tlb.c b/libgloss/mips/hal/mips64_tlb.c new file mode 100644 index 0000000..6e96e75 --- /dev/null +++ b/libgloss/mips/hal/mips64_tlb.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" +#include <mips/hal.h> + +/* Writes hi, lo0, lo1 and mask into the TLB entry specified by index */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +m64_tlbwi2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1, + unsigned long long mask, + int index) +{ + mips64_setentryhi (hi); + mips64_setentrylo0 (lo0); + mips64_setentrylo1 (lo1); + mips64_setpagemask (mask); + mips64_setindex (index); + mips_ehb (); + mips_tlbwi (); + return; +} + +/* + * Writes hi, lo0, lo1 and mask into the TLB entry specified by the + * Random register. +*/ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +m64_tlbwr2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1, + unsigned long long mask) +{ + mips64_setentryhi (hi); + mips64_setentrylo0 (lo0); + mips64_setentrylo1 (lo1); + mips64_setpagemask (mask); + mips_ehb (); + mips_tlbwr (); + return; +} + +/* + * Probes the TLB for an entry matching hi and if present rewrites that entry, + * otherwise updates a random entry. A safe way to update the TLB. +*/ +int __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +m64_tlbrwr2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1, + unsigned long long mask) +{ + tlbhi64_t prev_hi; + int index; + + prev_hi = mips64_getentryhi (); + mips64_setentryhi (hi); + + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + + index = mips64_getindex (); + + mips64_setentrylo0 (lo0); + mips64_setentrylo1 (lo1); + mips64_setpagemask (mask); + + mips_ehb (); /* mtc0 hazard on tlbwi/tlbwr */ + + if (index < 0) + mips_tlbwr (); + else + mips_tlbwi (); + + mips64_setentryhi (prev_hi); + + return index; +} + +/* + * Reads the TLB entry specified index, and returns the EntryHi, + * EntryLo0, EntryLo1 and PageMask parts in *phi, *plo0, *plo1 and *pmask + * respectively. +*/ +void _MIPS_HAL_NOMIPS16 +m64_tlbri2 (tlbhi64_t *phi, tlblo64_t *plo0, tlblo64_t *plo1, + unsigned long long *pmask, int index) +{ + mips64_setindex (index); + mips_ehb (); /* mtc0 hazard on tlbr */ + mips_tlbr (); + mips_ehb (); /* tlbr hazard on mfc0 */ + *phi = mips64_getentryhi (); + *plo0 = mips64_getentrylo0 (); + *plo1 = mips64_getentrylo1 (); + *pmask = mips64_getpagemask (); + return; +} + +/* + * Probes the TLB for an entry matching hi and returns its index, or -1 if + * not found. If found, then the EntryLo0, EntryLo1 and PageMask parts of the + * entry are also returned in *plo0, *plo1 and *pmask respectively. +*/ +int __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +m64_tlbprobe2 (tlbhi64_t hi, tlblo64_t *plo0, tlblo64_t *plo1, + unsigned long long *pmask) +{ + tlbhi64_t prev_hi; + int index; + + prev_hi = mips64_getentryhi (); + mips64_setentryhi (hi); + + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + + index = mips64_getindex (); + + if (index >= 0) + { + mips_tlbr (); + mips_ehb (); /* tlbr hazard on mfc0 */ + *plo0 = mips64_getentrylo0 (); + *plo1 = mips64_getentrylo1 (); + *pmask = mips64_getpagemask (); + } + else + index = -1; + + mips64_setentryhi (prev_hi); + + return index; +} + +/* Probes the TLB for an entry matching hi, and if present invalidates it */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +m64_tlbinval (tlbhi64_t hi) +{ + int index, tmp_idx; + tlbhi64_t prev_hi, tmp_hi; + register const unsigned long zero = 0; + unsigned long cfg; + + prev_hi = mips64_getentryhi (); + mips64_setentryhi (hi); + + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + + index = mips64_getindex (); + + if (index < 0) + goto restore; + + mips64_setentrylo0 (zero); + mips64_setentrylo1 (zero); + + /* Check if Config4 is implemented */ + cfg = mips64_getconfig3 (); + if ((cfg & CFG3_M) != 0) + { + cfg = mips64_getconfig4 (); + if ((cfg & CFG4_IE_MASK) != 0) + { + tmp_hi = C0_ENTRYHI_EHINV_MASK; + goto do_tlbwi; + } + } + + tmp_hi = (tlbhi64_t) ((unsigned long) KSEG0_BASE - 0x4000); + + do + { + tmp_hi = tmp_hi + 0x4000; + mips64_setentryhi (tmp_hi); + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + tmp_idx = mips64_getindex (); + } + while (tmp_idx >= 0); + + mips64_setindex (index); /* restore Index */ + +do_tlbwi: + mips64_setentryhi (tmp_hi); + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbwi (); + mips_ehb (); /* tlbwi hazard on mfc0 */ + +restore: + mips64_setentryhi (prev_hi); /* restore EntryHi */ + + return; +} diff --git a/libgloss/mips/hal/mips_clean_cache.c b/libgloss/mips/hal/mips_clean_cache.c new file mode 100644 index 0000000..e749e8f --- /dev/null +++ b/libgloss/mips/hal/mips_clean_cache.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/hal.h> +#include "cache.h" + +/* Writeback and invalidate address range in all caches */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_clean_cache (vaddr_t kva, size_t n) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If D-cache is present */ + if (mips_dcache_linesize > 0) + mips_cache_op (kva, n, mips_dcache_linesize, Hit_Writeback_Inv_D); + + /* If I-cache is present */ + if (mips_icache_linesize > 0) + mips_cache_op (kva, n, mips_icache_linesize, Hit_Invalidate_I); + + /* If L2-cache is present */ + if (mips_scache_linesize > 0) + mips_cache_op (kva, n, mips_scache_linesize, Hit_Writeback_Inv_S); + + mips_sync (); + return; +} + +/* Writeback and invalidate address range in I-cache */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_clean_icache (vaddr_t kva, size_t n) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If I-cache is present */ + if (mips_icache_linesize > 0) + mips_cache_op (kva, n, mips_icache_linesize, Hit_Invalidate_I); + + /* If L2-cache is present */ + if (mips_scache_linesize > 0) + mips_cache_op (kva, n, mips_scache_linesize, Hit_Writeback_Inv_S); + + mips_sync (); + return; +} + +/* Writeback and invalidate address range in D-cache */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_clean_dcache (vaddr_t kva, size_t n) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If D-cache is present */ + if (mips_dcache_linesize > 0) + mips_cache_op (kva, n, mips_dcache_linesize, Hit_Writeback_Inv_D); + + /* If L2-cache is present */ + if (mips_scache_linesize > 0) + mips_cache_op (kva, n, mips_scache_linesize, Hit_Writeback_Inv_S); + + mips_sync (); + return; +} + +/* + * Invalidate but don't writeback address range in data caches + * Only safe if region is totally cache-line aligned. +*/ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_clean_dcache_nowrite (vaddr_t kva, size_t n) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If D-cache is present */ + if (mips_dcache_linesize > 0) + mips_cache_op (kva, n, mips_dcache_linesize, Hit_Invalidate_D); + + /* If L2-cache is present */ + if (mips_scache_linesize > 0) + mips_cache_op (kva, n, mips_scache_linesize, Hit_Invalidate_S); + + mips_sync (); + return; +} diff --git a/libgloss/mips/hal/mips_cm3_l2size.c b/libgloss/mips/hal/mips_cm3_l2size.c new file mode 100644 index 0000000..ae93202 --- /dev/null +++ b/libgloss/mips/hal/mips_cm3_l2size.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" + +_MIPS_HAL_NOMIPS16 +void __def_cache_size_hook (void); + +/* + * Routine for calculating L2 cache size from CM3 configuration + * registers. Sizing information is stored directly to memory. +*/ +void _MIPS_HAL_NOMIPS16 +__cache_size_hook (void) +{ + unsigned long cm_gcr_base, cm_gcr_l2_config; + int associ; + + /* + * Fall back to Config2 based L2 if Config3[M] or Config4[M] + * or Config5[L2C] is not present. + */ + if ((mips32_getconfig3 () & CFG3_M) == 0 + || (mips32_getconfig4 () & CFG4_M) == 0 + || (mips32_getconfig5 () & CFG5_L2C) == 0) + { + __def_cache_size_hook (); + return; + } + + /* Read CMGCRBase to find CMGCR_BASE_ADDR */ + cm_gcr_base = (mips_getcmgcrbase () << 4) | 0xB0000000UL; + + /* Read GCR_L2_CONFIG */ + cm_gcr_l2_config = * ((unsigned long *) (cm_gcr_base + GCR_L2_CONFIG)); + + /* Extract line size */ + mips_scache_linesize = (cm_gcr_l2_config & GCR_L2_SL_MASK) >> GCR_L2_SL_SHIFT; + + /* Check for no cache */ + if (mips_scache_linesize == 0) + return; + + /* Now have true L2 line size */ + mips_scache_linesize = 2 << mips_scache_linesize; + + /* Extract sets/way */ + mips_scache_ways = (cm_gcr_l2_config & GCR_L2_SS_MASK) >> GCR_L2_SS_SHIFT; + + /* Now we have true L2 sets/way */ + mips_scache_ways = 64 << mips_scache_ways; + + /* Extract L2 associativity */ + associ = (cm_gcr_l2_config & GCR_L2_SA_MASK) >> GCR_L2_SA_SHIFT; + + /* Get total number of sets */ + associ = (associ + 1) * mips_scache_ways; + + /* L2 cache size */ + mips_scache_size = mips_scache_linesize * associ; + + return; +} diff --git a/libgloss/mips/hal/mips_dsp.S b/libgloss/mips/hal/mips_dsp.S new file mode 100644 index 0000000..da4b8b3 --- /dev/null +++ b/libgloss/mips/hal/mips_dsp.S @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +.set nomips16 +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> + +# +# FUNCTION: _dsp_save +# DESCRIPTION: save the DSP context. +# RETURNS: int +# 0: No context saved +# CTX_*: Type of conext stored +# +LEAF(_dsp_save) + move a1, a0 + PTR_S zero, LINKCTX_NEXT(a1) + move va0, zero + + /* Test for DSP support */ + mfc0 t0, C0_CONFIG3 + ext t0, t0, CFG3_DSPP_SHIFT, 1 + beqz t0, 1f + + /* Test for DSP enabled */ + mfc0 t0, C0_STATUS + ext t0, t0, SR_MX_SHIFT, 1 + beqz t0, 1f + + li va0, LINKCTX_TYPE_DSP + .set push + .set dsp + rddsp t1 + mfhi t2, $ac1 + mflo t3, $ac1 + mfhi t4, $ac2 + mflo t5, $ac2 + mfhi t6, $ac3 + mflo t7, $ac3 + .set pop + sw t1, DSPCTX_DSPC(a1) + sw t2, DSPCTX_HI1(a1) + sw t3, DSPCTX_LO1(a1) + sw t4, DSPCTX_HI2(a1) + sw t5, DSPCTX_LO2(a1) + sw t6, DSPCTX_HI3(a1) + sw t7, DSPCTX_LO3(a1) + REG_S va0, LINKCTX_ID(a1) +1: + jr ra +END(_dsp_save) + +# +# FUNCTION: _dsp_load +# DESCRIPTION: load the DSP context. +# RETURNS: int +# 0: Unrecognised context +# CTX_*: Type of context restored +# +LEAF(_dsp_load) + move a1, a0 + REG_L va0, LINKCTX_ID(a1) + li v1, LINKCTX_TYPE_DSP + bne va0,v1,1f + + /* Test for DSP support */ + mfc0 t0, C0_CONFIG3 + ext t0, t0, CFG3_DSPP_SHIFT, 1 + beqz t0, 1f + + /* Force on DSP */ + di t3 + ehb + or t3, t3, SR_MX + mtc0 t3, C0_STATUS + ehb + + lw t1, DSPCTX_DSPC(a1) + lw t2, DSPCTX_HI1(a1) + lw t3, DSPCTX_LO1(a1) + lw t4, DSPCTX_HI2(a1) + lw t5, DSPCTX_LO2(a1) + lw t6, DSPCTX_HI3(a1) + lw t7, DSPCTX_LO3(a1) + .set push + .set dsp + wrdsp t1 + mthi t2, $ac1 + mtlo t3, $ac1 + mthi t4, $ac2 + mtlo t5, $ac2 + mthi t6, $ac3 + mtlo t7, $ac3 + .set pop + jr ra +1: + /* Don't recognise this context, fail */ + move va0, zero + jr ra +END(_dsp_load) diff --git a/libgloss/mips/hal/mips_excpt_boot.S b/libgloss/mips/hal/mips_excpt_boot.S new file mode 100644 index 0000000..342afb9 --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_boot.S @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> + +MIPS_NOMIPS16 + + # Create space to store k0, k1, ra and sp + .data + .global __start_ctx + .balign SZREG +__start_ctx: + .space SZREG * 18 +#define start_ctx_sr (SZREG * 0) +#define start_ctx_s0 (SZREG * 1) +#define start_ctx_s1 (SZREG * 2) +#define start_ctx_s2 (SZREG * 3) +#define start_ctx_s3 (SZREG * 4) +#define start_ctx_s4 (SZREG * 5) +#define start_ctx_s5 (SZREG * 6) +#define start_ctx_s6 (SZREG * 7) +#define start_ctx_s7 (SZREG * 8) +#define start_ctx_k0 (SZREG * 9) +#define start_ctx_k1 (SZREG * 10) +#define start_ctx_gp (SZREG * 11) +#define start_ctx_sp (SZREG * 12) +#define start_ctx_fp (SZREG * 13) +#define start_ctx_ra (SZREG * 14) +#define start_ctx_ictl (SZREG * 15) +#define start_ctx_ebase (SZREG * 16) /* saved EBASE */ +#define chain_ebase (SZREG * 17) /* chained EBASE */ + +#if defined (__mips_micromips) + .space SZREG +#define start_ctx_conf3 (SZREG * 18) /* saved Config3 $16,3 for micromips */ +#endif + +# +# FUNCTION: void* __register_excpt_boot (void*, int, void*) +# +# DESCRIPTION: Save all boot state. Some state is already clobbered but passed +# in as arguments: +# a0 = Boot ra +# a1 = Boot SR +# a2 = caller's RA (to be returned back) +# +WLEAF(__register_excpt_boot) + .set push + .set noat + + /* Save C0_SR IE and BEV */ + LA t1, __start_ctx + REG_S a0, start_ctx_ra(t1) + REG_S a1, start_ctx_sr(t1) + + REG_S s0, start_ctx_s0(t1) + REG_S s1, start_ctx_s1(t1) + REG_S s2, start_ctx_s2(t1) + REG_S s3, start_ctx_s3(t1) + REG_S s4, start_ctx_s4(t1) + REG_S s5, start_ctx_s5(t1) + REG_S s6, start_ctx_s6(t1) + REG_S s7, start_ctx_s7(t1) + REG_S k0, start_ctx_k0(t1) + REG_S k1, start_ctx_k1(t1) + REG_S gp, start_ctx_gp(t1) + REG_S sp, start_ctx_sp(t1) + REG_S fp, start_ctx_fp(t1) + +#if defined (__mips_micromips) + /* Save Config3 */ + mfc0 t0, C0_CONFIG3 + REG_S t0, start_ctx_conf3(t1) +#endif + mfc0 t0, C0_INTCTL + REG_S t0, start_ctx_ictl(t1) + + /* Save C0_EBASE */ + PTR_MFC0 t2, C0_EBASE + REG_S t2, start_ctx_ebase(t1) + + /* Check if we booted with BEV==1 */ + ext t3, a1, SR_BEV_SHIFT, 1 + beqz t3, 1f + + /* + * BEV==0 - set chain_ebase to 0xbfc00200 + * Apply the offset of 0x200 so that the boot vector entries line up + * with the offsets in a non-boot vectora. + */ + li t2, 0xbfc00200 + + /* No - set chain_ebase to C0_EBASE */ +1: REG_S t2, chain_ebase(t1) + + /* Return the third argument */ + move va0, a2 + jr ra + + .set pop +WEND(__register_excpt_boot) + +# +# FUNCTION: int __return_to_boot (int) +# +# DESCRIPTION: This is used if UHI EXIT was not handled. Return back to +# caller of _start. +# a0 = exit code to return to caller +# +WLEAF(__return_to_boot) + .set push + .set noat + /* Disable interrupts for safety */ + di + ehb + /* Set BEV=1 to allow changing EBASE */ + mfc0 t0, C0_SR + li t1, SR_BEV + or t0, t0, t1 + mtc0 t0, C0_SR + ehb + + /* Restore C0_EBASE */ + LA t0, __start_ctx + REG_L t0, start_ctx_ebase(t0) + /* Set the write gate to potentially change upper bits */ + ori t1, t0, EBASE_WG + PTR_MTC0 t1, C0_EBASE + ehb + /* Check if the write gate was set on startup */ + andi t1, t0, EBASE_WG + bnez t1, 1f + + /* If write gate wasn't set then clear the write gate again */ + PTR_MTC0 t0, C0_EBASE + ehb + +1: /* Restore original state */ + LA t0, __start_ctx + REG_L s0, start_ctx_s0(t0) + REG_L s1, start_ctx_s1(t0) + REG_L s2, start_ctx_s2(t0) + REG_L s3, start_ctx_s3(t0) + REG_L s4, start_ctx_s4(t0) + REG_L s5, start_ctx_s5(t0) + REG_L s6, start_ctx_s6(t0) + REG_L s7, start_ctx_s7(t0) + REG_L k0, start_ctx_k0(t0) + REG_L k1, start_ctx_k1(t0) + REG_L gp, start_ctx_gp(t0) + REG_L sp, start_ctx_sp(t0) + REG_L fp, start_ctx_fp(t0) + REG_L ra, start_ctx_ra(t0) + +#if defined (__mips_micromips) + /* Restore Config3 */ + REG_L t1, start_ctx_conf3(t0) + mtc0 t1, C0_CONFIG3 +#endif + /* Restore IntCtl */ + REG_L t1, start_ctx_ictl(t0) + mtc0 t1, C0_INTCTL + + REG_L t0, start_ctx_sr(t0) + + /* Restore C0_STATUS IE and BEV to boot value */ + mtc0 t0, C0_SR + mtc0 zero, C0_CAUSE + + /* Return with exit code */ + move va0, a0 + MIPS_JRHB(ra) + .set pop +WEND(__return_to_boot) + +# +# FUNCTION: void __chain_uhi_excpt (struct gpctx *); +# +# DESCRIPTION: Transfer to the exception handler in the boot environment. +# a0 == pointer to the context to restore +# +WLEAF(__chain_uhi_excpt) + .set push + .set noat + + /* + * Move context pointer into position. Use $3 as scratch + * as it is the only register that is clobbered by all + * UHI calls and is not used as an input. + */ + move r3, a0 + +#if (__mips_isa_rev < 6) + REG_L t0, CTX_HI0(r3) + REG_L t1, CTX_LO0(r3) + mthi t0 + mtlo t1 +#endif + + lw t0, CTX_STATUS(r3) + mtc0 t0, C0_SR + REG_L t0, CTX_EPC(r3) + PTR_MTC0 t0, C0_EPC + ehb + + /* Restore the common context */ + REG_L r1, CTX_REG(1)(r3) + REG_L r2, CTX_REG(2)(r3) + REG_L r4, CTX_REG(4)(r3) + REG_L r5, CTX_REG(5)(r3) + REG_L r6, CTX_REG(6)(r3) + REG_L r7, CTX_REG(7)(r3) + REG_L r8, CTX_REG(8)(r3) + REG_L r9, CTX_REG(9)(r3) + REG_L r10, CTX_REG(10)(r3) + REG_L r11, CTX_REG(11)(r3) + REG_L r12, CTX_REG(12)(r3) + REG_L r13, CTX_REG(13)(r3) + REG_L r14, CTX_REG(14)(r3) + REG_L r15, CTX_REG(15)(r3) + REG_L r16, CTX_REG(16)(r3) + REG_L r17, CTX_REG(17)(r3) + REG_L r18, CTX_REG(18)(r3) + REG_L r19, CTX_REG(19)(r3) + REG_L r20, CTX_REG(20)(r3) + REG_L r21, CTX_REG(21)(r3) + REG_L r22, CTX_REG(22)(r3) + REG_L r23, CTX_REG(23)(r3) + REG_L r24, CTX_REG(24)(r3) + REG_L r25, CTX_REG(25)(r3) + REG_L r28, CTX_REG(28)(r3) + REG_L r29, CTX_REG(29)(r3) + REG_L r30, CTX_REG(30)(r3) + REG_L r31, CTX_REG(31)(r3) + + /* Restore chained exception handlers kernel regs */ + LA r3, __start_ctx + REG_L k0, start_ctx_k0(r3) + REG_L k1, start_ctx_k1(r3) + +#if defined (__mips_micromips) + /* OR the address with Config3.ISAOnExc bit */ + REG_L r3, start_ctx_conf3(r3) + ext r3, r3, CFG3_IOE_SHIFT, 1 + beqz r3, 1f + + /* Compute exception vector */ + LA r3, __start_ctx + REG_L r3, chain_ebase(r3) + PTR_ADDU r3, r3, 0x181 # OR ISAOnExc bit + + /* Chain */ + jr r3 +1: + /* Compute exception vector */ + LA r3, __start_ctx +#endif + + REG_L r3, chain_ebase(r3) + PTR_ADDU r3, r3, 0x180 + + /* Chain */ + jr r3 + + .set pop +WEND(__chain_uhi_excpt) + +# +# FUNCTION: int __get_startup_BEV (void) +# +# DESCRIPTION: Return value of BEV flag saved in __register_excpt_handler. +# +WLEAF(__get_startup_BEV) + .set push + .set noat + + LA t0, __start_ctx + REG_L va0, start_ctx_sr(t0) + li t1, SR_BEV + and va0, va0, t1 + jr ra + + .set pop +WEND(__get_startup_BEV) + + +EXPORTS(__MIPS_UHI_BAD_POINTER, 32) + .ascii "UHI: BAD POINTER\000" + +# +# FUNCTION: __convert_argv_pointers (int, char*[], char*[]) +# +# DESCRIPTION: Convert 64-bit pointers to 32-bit. This allocates the new +# argument structure on the stack and verifies all pointers are +# canonical for a 32-bit address space. +# +#if _MIPS_SIM==_ABIO32 || _MIPS_SIM==_ABIN32 +WLEAF(__convert_argv_pointers) + /* Early out if a0 <= 0 */ + blez a0, .Lend + + /* Verify we came from 64-bit mode */ + LA t0, __start_ctx + REG_L t0, start_ctx_sr(t0) + ext t1, t0, SR_KX_SHIFT, 1 + beqz t1, .Lend + + /* Set up stack pointer */ + move t0, a0 + sll t1, t0, 2 + /* Round to stack alignment */ + addiu t1, t1, ALSZ + and t1, t1, ALMASK + + PTR_SUBU sp, sp, t1 + move t2, sp + move t3, a1 + li t1, -1 + +.Lloop: +#if BYTE_ORDER == LITTLE_ENDIAN + lw t8, 0(t3) + lw t9, 4(t3) +#elif BYTE_ORDER == BIG_ENDIAN + lw t9, 0(t3) + lw t8, 4(t3) +#else +#error BYTE_ORDER +#endif + /* if s1 != 0 && s1 != 0xFFFFFFFF */ + beqz t9, .LGoodp + beq t9, t1, .LGoodp + /* Overwrite bad pointer with stock bad value */ + LA t8, __MIPS_UHI_BAD_POINTER +.LGoodp: + sw t8, 0(t2) + + PTR_ADDU t2, t2, 4 + PTR_ADDU t3, t3, 8 + addiu t0, t0, -1 + bnez t0, .Lloop + + move a1, sp + PTR_SUBU sp, sp, (NARGSAVE*SZARG) + + move a2, zero +.Lend: + jr ra +WEND(__convert_argv_pointers) +#endif /* ABI TEST */ diff --git a/libgloss/mips/hal/mips_excpt_entry.S b/libgloss/mips/hal/mips_excpt_entry.S new file mode 100644 index 0000000..f1e6a41 --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_entry.S @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _FUNCTION_SECTIONS_ + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> +#include <mips/ctx.S> + +MIPS_NOMIPS16 + +/* Stack adjustment for ABI parameter area. */ +#define ADJ (NARGSAVE * SZARG) +/* + * Round the context size up to a 16-byte boundary which is the maximum + * stack alignment required for any supported ABI. + */ +#define CTX_SIZEROUND ((CTX_SIZE + ALSZ) & ALMASK) + +/* + * Exception entry points. These are designed for use at EBASE when + * STATUS.BEV is clear. + * The entry points will either chain on to a user-supplied function + * or loop indefinitely. + */ + +LEAF(__exception_entry) + .set push + .set noat +.weak _mips_tlb_refill + _mips_tlb_refill = __exception_save +__tlb_refill_loop: + /* + * Support an alternative entry point at the start of the exception + * vector. Since the exception vector is normally placed first + * in the link map this allows a user to start execution from the + * same address that an executable is loaded to. + */ + LA k1, __first_boot + lw k1, 0(k1) + beqz k1, 1f + /* + * The start code is responsible for clearing __first_boot prior + * to installing the exception handlers. + */ + LA k1, _start + jr k1 +1: + /* Support the case where no handler is defined. */ + LA k1, _mips_tlb_refill + beqz k1, __tlb_refill_loop + jr k1 + + .org 0x80 +.weak _mips_xtlb_refill + _mips_xtlb_refill = __exception_save +__xtlb_refill_loop: + LA k1, _mips_xtlb_refill + beqz k1, __xtlb_refill_loop + jr k1 + + .org 0x100 +.weak _mips_cache_error +__cache_error_loop: + LA k1, _mips_cache_error + beqz k1, __cache_error_loop + jr k1 + + .org 0x180 +.weak _mips_general_exception +__general_exception_loop: + /* + * Free up k1, defering sp adjustment until later. Preserving k1 + * may be undesirable if an exception occurs due to a corrupt + * stack but since the default handlers use the user-stack to + * store the context then there is nothing to lose. + */ + REG_S k1, (-CTX_SIZEROUND + CTX_K1)(sp) + + LA k1, _mips_general_exception + beqz k1, __general_exception_loop + jr k1 + .set pop +END(__exception_entry) + +/* + * FUNCTION: __exception_save + * + * DESCRIPTION: Saves the GP context to the stack and invokes + * _mips_handle_exception with appropriate arguments. +*/ +ANESTED(__exception_save, _mips_general_exception, CTX_SIZEROUND + ADJ, zero) + .globl __exception_save; + .set push + .set noat + + /* Create pointer to gp_ctx. */ + PTR_ADDU k1, sp, -CTX_SIZEROUND + + /* Save context. */ + _gpctx_save + /* va0 now holds C0_STATUS. */ + + /* Finish storing the rest of the CP0 registers. */ + PTR_MFC0 t0, C0_BADVADDR + REG_S t0, CTX_BADVADDR(k1) + +#if __mips_isa_rev < 6 + move t0, zero + move t1, zero + mfc0 t2, C0_CONFIG3 + ext t3, t2, CFG3_BP_SHIFT, 1 + beqz t3, 1f +#else + /* MIPSR6 guarantees all CP0 regs are defined to at + least return zero. */ +#endif + mfc0 t0, C0_BADPINSTR +#if __mips_isa_rev < 6 +1: + ext t2, t2, CFG3_BI_SHIFT, 1 + beqz t2, 1f +#endif + mfc0 t1, C0_BADINSTR +1: + sw t0, CTX_BADPINSTR(k1) + sw t1, CTX_BADINSTR(k1) + + /* Get and store the exception cause. */ + mfc0 t0, C0_CR + sw t0, CTX_CAUSE(k1) + + /* Extract the cause code for argument 1. */ + ext a1, t0, CR_X_SHIFT, CR_X_BITS + + /* Create the argument space. */ + addiu sp, k1, -ADJ + + /* Clear EXL. Exceptions can now nest. */ + ins va0, zero, SR_EXL_SHIFT, 1 + mtc0 va0, C0_SR + + /* Move the gp_ctx pointer for argument 0. */ + addiu a0, sp, ADJ + + /* Manually set up the return address to restore the context below. */ + LA ra, __exception_restore + + /* Call the handler, indirect through t9 albeit not for any specific + reason. */ + LA t9, _mips_handle_exception + jr t9 + + .set pop +END(__exception_save) + +/* + * FUNCTION: __exception_restore + * + * DESCRIPTION: Load the GP context from immediately above the stack + * pointer and eret. + */ +LEAF(__exception_restore) + .set push + .set noat + + /* Skip past the argument save area and fall through. */ + addiu a0, sp, ADJ + +/* + * FUNCTION: __gpctx_load_eret + * + * DESCRIPTION: Load the GP context from the address in register a0 + * and eret. + */ +AENT(__gpctx_load_eret) + + _gpctx_load + + /* Return from exception. */ + eret + .set pop +END(__exception_restore) diff --git a/libgloss/mips/hal/mips_excpt_handler.c b/libgloss/mips/hal/mips_excpt_handler.c new file mode 100644 index 0000000..c763d7f --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_handler.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <mips/cpu.h> +#include <mips/fpa.h> +#include <mips/hal.h> +#include <mips/uhi_syscalls.h> + +/* Defined in .ld file */ +extern char __use_excpt_boot[]; +extern char __attribute__((weak)) __flush_to_zero[]; + +#ifdef VERBOSE_EXCEPTIONS +/* + * Write a string, a formatted number, then a string. + */ +static void +putsnds (const char *pre, reg_t value, int digits, const char *post) +{ + char buf[digits]; + int shift; + int idx = 0; + + if (pre != NULL) + write (1, pre, strlen (pre)); + + for (shift = ((digits - 1) * 4) ; shift >= 0 ; shift -= 4) + buf[idx++] = "0123456789ABCDEF"[(value >> shift) & 0xf]; + write (1, buf, digits); + + if (post != NULL) + write (1, post, strlen (post)); +} + +static void +putsns (const char *pre, reg_t value, const char *post) +{ + putsnds (pre, value, sizeof (reg_t) * 2, post); +} + +# define WRITE(MSG) write (1, (MSG), strlen (MSG)) +# define PUTSNDS(PRE, VALUE, DIGITS, POST) \ + putsnds ((PRE), (VALUE), (DIGITS), (POST)) +# define PUTSNS(PRE, VALUE, POST) \ + putsns ((PRE), (VALUE), (POST)) + +#else + +# define WRITE(MSG) +# define PUTSNDS(PRE, VALUE, DIGITS, POST) +# define PUTSNS(PRE, VALUE, POST) + +#endif // !VERBOSE_EXCEPTIONS + +/* Handle an exception */ +#ifdef VERBOSE_EXCEPTIONS +void _MIPS_HAL_NOMIPS16 +__exception_handle_verbose (struct gpctx *ctx, int exception) +#else +void _MIPS_HAL_NOMIPS16 +__exception_handle_quiet (struct gpctx *ctx, int exception) +#endif +{ + switch (exception) + { + case EXC_MOD: + WRITE ("TLB modification exception\n"); + break; + case EXC_TLBL: + PUTSNS ("TLB error on load from 0x", ctx->badvaddr, NULL); + PUTSNS (" @0x", ctx->epc, "\n"); + break; + case EXC_TLBS: + PUTSNS ("TLB error on store to 0x", ctx->badvaddr, NULL); + PUTSNS (" @0x", ctx->epc, "\n"); + break; + case EXC_ADEL: + PUTSNS ("Address error on load from 0x", ctx->badvaddr, NULL); + PUTSNS (" @0x", ctx->epc, "\n"); + break; + case EXC_ADES: + PUTSNS ("Address error on store to 0x", ctx->badvaddr, NULL); + PUTSNS (" @0x", ctx->epc, "\n"); + break; + case EXC_IBE: + WRITE ("Instruction bus error\n"); + break; + case EXC_DBE: + WRITE ("Data bus error\n"); + break; + case EXC_SYS: + /* Process a UHI SYSCALL, all other SYSCALLs should have been processed + by our caller. __use_excpt_boot has following values: + 0 = Do not use exception handler present in boot. + 1 = Use exception handler present in boot if BEV + is 0 at startup. + 2 = Always use exception handler present in boot. */ + + /* Special handling for boot/low level failures. */ + if (ctx->t2[1] == __MIPS_UHI_BOOTFAIL) + { + switch (ctx->a[0]) + { + case __MIPS_UHI_BF_CACHE: + WRITE ("L2 cache configuration error\n"); + break; + default: + WRITE ("Unknown boot failure error\n"); + break; + } + + /* These are unrecoverable. Abort. */ + ctx->epc = (sreg_t)(long)&__exit; + /* Exit code of 255 */ + ctx->a[0] = 0xff; + return; + } + + if (((long) __use_excpt_boot == 2 + || ((long) __use_excpt_boot == 1 + && __get_startup_BEV + && __get_startup_BEV () == 0)) + && __chain_uhi_excpt) + /* This will not return. */ + __chain_uhi_excpt (ctx); + else + __uhi_indirect (ctx); + return; + case EXC_BP: + /* Return from exception handler if breakpoint is handled. */ + if (__uhi_break && __uhi_break (ctx)) + return; + PUTSNS ("Breakpoint @0x", ctx->epc, "\n"); + break; + case EXC_RI: + PUTSNS ("Illegal instruction @0x", ctx->epc, "\n"); + break; + case EXC_CPU: + PUTSNS ("Coprocessor unusable @0x", ctx->epc, "\n"); + break; + case EXC_OVF: + WRITE ("Overflow\n"); + break; + case EXC_TRAP: + WRITE ("Trap\n"); + break; + case EXC_MSAFPE: +#if MIPS_MSA_USABLE + if (__flush_to_zero + && (msa_getsr () & FPA_CSR_UNI_X) + && (msa_getsr () & FPA_CSR_FS) == 0) + { + unsigned int sr = msa_getsr (); + sr &= ~FPA_CSR_UNI_X; + sr |= FPA_CSR_FS; + msa_setsr (sr); + return; + } +#endif + WRITE ("MSA Floating point error\n"); + break; + case EXC_FPE: + /* Turn on flush to zero the first time we hit an unimplemented + operation. If we hit it again then stop. */ + if (__flush_to_zero + && (fpa_getsr () & FPA_CSR_UNI_X) + && (fpa_getsr () & FPA_CSR_FS) == 0) + { + unsigned int sr = fpa_getsr (); + sr &= ~FPA_CSR_UNI_X; + sr |= FPA_CSR_FS; + fpa_setsr (sr); + + return; + } + WRITE ("Floating point error\n"); + break; + case EXC_IS1: + WRITE ("Implementation specific exception (16)\n"); + break; + case EXC_IS2: + WRITE ("Implementation specific exception (17)\n"); + break; + case EXC_C2E: + WRITE ("Precise Coprocessor 2 exception\n"); + break; + case EXC_TLBRI: + WRITE ("TLB read inhibit exception\n"); + break; + case EXC_TLBXI: + WRITE ("TLB execute inhibit exception\n"); + break; + case EXC_MSAU: + PUTSNS ("MSA unusable @0x", ctx->epc, "\n"); + break; + case EXC_MDMX: + PUTSNS ("MDMX exception @0x", ctx->epc, "\n"); + break; + case EXC_WATCH: + PUTSNS ("Watchpoint @0x", ctx->epc, "\n"); + break; + case EXC_MCHECK: + WRITE ("Machine check error\n"); + break; + case EXC_THREAD: + WRITE ("Thread exception\n"); + break; + case EXC_DSPU: + WRITE ("DSP unusable\n"); + break; + case EXC_RES30: + WRITE ("Cache error\n"); + break; + default: + PUTSNS ("Unhandled exception ", exception, "\n"); + } + + /* Dump registers */ + PUTSNS (" 0:\t", 0, "\t"); + PUTSNS ("at:\t", ctx->at, "\t"); + PUTSNS ("v0:\t", ctx->v[0], "\t"); + PUTSNS ("v1:\t", ctx->v[1], "\n"); + + PUTSNS ("a0:\t", ctx->a[0], "\t"); + PUTSNS ("a1:\t", ctx->a[1], "\t"); + PUTSNS ("a2:\t", ctx->a[2], "\t"); + PUTSNS ("a3:\t", ctx->a[3], "\n"); + + PUTSNS ("t0:\t", ctx->t[0], "\t"); + PUTSNS ("t1:\t", ctx->t[1], "\t"); + PUTSNS ("t2:\t", ctx->t[2], "\t"); + PUTSNS ("t3:\t", ctx->t[3], "\n"); + + PUTSNS ("t4:\t", ctx->t[4], "\t"); + PUTSNS ("t5:\t", ctx->t[5], "\t"); + PUTSNS ("t6:\t", ctx->t[6], "\t"); + PUTSNS ("t7:\t", ctx->t[7], "\n"); + + PUTSNS ("s0:\t", ctx->s[0], "\t"); + PUTSNS ("s1:\t", ctx->s[1], "\t"); + PUTSNS ("s2:\t", ctx->s[2], "\t"); + PUTSNS ("s3:\t", ctx->s[3], "\n"); + + PUTSNS ("s4:\t", ctx->s[4], "\t"); + PUTSNS ("s5:\t", ctx->s[5], "\t"); + PUTSNS ("s6:\t", ctx->s[6], "\t"); + PUTSNS ("s7:\t", ctx->s[7], "\n"); + + PUTSNS ("t8:\t", ctx->t2[0], "\t"); + PUTSNS ("t9:\t", ctx->t2[1], "\t"); + PUTSNS ("k0:\t", ctx->k[0], "\t"); + PUTSNS ("k1:\t", ctx->k[1], "\n"); + + PUTSNS ("gp:\t", ctx->gp, "\t"); + PUTSNS ("sp:\t", ctx->sp, "\t"); + PUTSNS ("fp:\t", ctx->fp, "\t"); + PUTSNS ("ra:\t", ctx->ra, "\n"); + +#if __mips_isa_rev < 6 + PUTSNS ("hi:\t", ctx->hi, "\t"); + PUTSNS ("lo:\t", ctx->lo, "\n"); +#endif + + PUTSNS ("epc: \t", ctx->epc, "\n"); + PUTSNS ("BadVAddr:\t", ctx->badvaddr, "\n"); + + PUTSNDS ("Status: \t", ctx->status, 8, "\n"); + PUTSNDS ("Cause: \t", ctx->cause, 8, "\n"); + PUTSNDS ("BadInstr: \t", ctx->badinstr, 8, "\n"); + PUTSNDS ("BadPInstr:\t", ctx->badpinstr, 8, "\n"); + + /* Raise UHI exception which may or may not return. */ + if (__uhi_exception (ctx, UHI_ABI) != 0) + { + /* The exception was acknowledged but not handled. Abort. */ + ctx->epc = (sreg_t)(long)&__exit; + /* Exit code of 255 */ + ctx->a[0] = 0xff; + } +} diff --git a/libgloss/mips/hal/mips_excpt_isr_fallback.S b/libgloss/mips/hal/mips_excpt_isr_fallback.S new file mode 100644 index 0000000..54cac97 --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_isr_fallback.S @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _FUNCTION_SECTIONS_ + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> + +.set noat +MIPS_NOMIPS16 + +_TEXT_SECTION_NAMED(__isr_vec_fallback) + + /* The alignment used here must match __isr_vec_space. */ + .balign (SZPTR * 8); + .globl __isr_vec_fallback; + .ent __isr_vec_fallback; +__isr_vec_fallback: +.weak _mips_interrupt +1: + LA k1, _mips_interrupt + beqz k1, 1b + jr k1 +END(__isr_vec_fallback) diff --git a/libgloss/mips/hal/mips_excpt_isr_fragment.S b/libgloss/mips/hal/mips_excpt_isr_fragment.S new file mode 100644 index 0000000..e71f356 --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_isr_fragment.S @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _FUNCTION_SECTIONS_ + +#include <mips/regdef.h> +#include <mips/asm.h> +#include <mips/cpu.h> + +.set noat +MIPS_NOMIPS16 + +.extern __isr_vec_fallback + +/* For the vectors shared between VINT and VEIC we rename the numeric + * vector indices to the named form instead. */ + +#define _mips_isr_000 _mips_isr_sw0 +#define _mips_isr_001 _mips_isr_sw1 +#define _mips_isr_002 _mips_isr_hw0 +#define _mips_isr_003 _mips_isr_hw1 +#define _mips_isr_004 _mips_isr_hw2 +#define _mips_isr_005 _mips_isr_hw3 +#define _mips_isr_006 _mips_isr_hw4 +#define _mips_isr_007 _mips_isr_hw5 + +.extern REF +.weak ISR + +#ifdef __mips_micromips +# define NOP nop32 +#else +# define NOP nop +#endif + +_TEXT_SECTION_NAMED(DEF); +/* The alignment used here must match __isr_vec_space. */ + .balign (SZPTR * 8); + .globl DEF; + .ent DEF; +DEF: + NOP /* May become: mtc0 k1, C0_KSCRATCH1 */ + LA k1, ISR + beqz k1, __isr_vec_fallback + jr k1 +END(DEF) diff --git a/libgloss/mips/hal/mips_excpt_register.S b/libgloss/mips/hal/mips_excpt_register.S new file mode 100644 index 0000000..72eab49 --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_register.S @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> + +MIPS_NOMIPS16 + +/* + * Used to support an alternate entry point that overlays the TLB refill + * exception entry point. This flag must be cleared before exceptions + * are ready to be handled. + */ +.data +EXPORTS(__first_boot, 4) + .word 0x1 + +_TEXT_SECTION + +/* + * FUNCTION: __register_excpt_handler + * + * DESCRIPTION: Register __exception_entry at EBASE+0x180. Return the new + * value for C0_SR. + */ +WLEAF(__register_excpt_handler) + .set push + .set noat + + /* Fetch initial status */ + mfc0 a1, C0_SR + + /* + * Get into a clean state. + * Important things: base mode is kernel and ERL, ESL, IE are clear + * Set BEV=1 to allow changing EBASE later. + */ + li t0, SR_BEV + mtc0 t0, C0_SR + ehb + + /* + * Enable use of a boot state hook + * a0 = Boot time RA + * a1 = Boot time SR + * a2 = Current RA. There is no stack so get the callee to pass this + * back. + */ +.weak __register_excpt_boot + LA t0, __register_excpt_boot + beqz t0, 1f + move a2, ra + jalr t0 + move ra, va0 +1: + /* Clear first boot flag */ + LA t0, __first_boot + sw zero, 0(t0) + + mfc0 t3, C0_CONFIG3 +#if defined (__mips_micromips) + /* Set Config3.ISAOnExc for microMIPS */ + li t0, CFG3_IOE + or t0, t0, t3 + mtc0 t0, C0_CONFIG3 +#endif + + /* Set desired EBASE */ + LA t0, __excpt_ebase + /* + * Always set the write gate as the requested EBASE may not be in kseg0. + * This may or may not exist in hardware but if it doesn't then the + * ebase address will simply get masked with inevitable consequences. + */ + ori t0, t0, EBASE_WG + PTR_MTC0 t0, C0_EBASE + ehb + + /* Set up new empty status value */ + move va0, zero + + /* Set up vector spacing */ + LA t0, __isr_vec_space + + /* Check for vectored interrupt support */ + andi t1, t3, CFG3_VI | CFG3_VEIC + /* Skip vector spacing setup if neither VINT nor VEIC is present */ + beqz t1, 1f + + /* Set vector spacing */ + mfc0 t1, C0_INTCTL + srl t0, t0, 5 + ins t1, t0, INTCTL_VS_SHIFT, INTCTL_VS_BITS + mtc0 t1, C0_INTCTL + b 2f +1: + /* + * Check non-zero vector spacing without vectored interrupt support. + * If so, do not enable interrupts. + */ + bnez t0, 3f +2: + /* Turn on use of the special exception vector and enable interrupts */ + li t0, CR_IV + mtc0 t0, C0_CAUSE + ehb + + /* Check for VEIC and do not enable interrupts if EIC is active */ + ext t0, t3, CFG3_VEIC_SHIFT, 1 + bnez t0, 3f + + /* Enable interrupts in the new status value */ + ori va0, va0, SR_IE +3: + jr ra + + .set pop +WEND(__register_excpt_handler) diff --git a/libgloss/mips/hal/mips_excpt_timer.S b/libgloss/mips/hal/mips_excpt_timer.S new file mode 100644 index 0000000..f4420f3 --- /dev/null +++ b/libgloss/mips/hal/mips_excpt_timer.S @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/cpu.h> +#include <mips/asm.h> + +MIPS_NOMIPS16 + +EXPORTS(_count_wrap, 4) + .word 0x0 + +# +# FUNCTION: +# +# DESCRIPTION: +# +LEAF(mips_start_minimal_counter) + di $8 + ehb + ori $8, $8, SR_HINT5 + ori $8, $8, SR_IE + LA $9, _count_wrap + sw $0, 0($9) + li $9, 1 + mtc0 $9, C0_COUNT + mtc0 $0, C0_COMPARE + mtc0 $8, C0_SR + ehb + jr $31 +END(mips_start_minimal_counter) + +LEAF(_mips_isr_sw0) + .set push + .set noreorder + .set noat + LA $k0, _count_wrap + lw $k1, 0($k0) + addiu $k1, $k1, 1 + sw $k1, 0($k0) + mtc0 $0, C0_COMPARE + eret + .set pop +END(_mips_isr_sw0) + +LEAF(_mips_interrupt) + .set push + .set noreorder + .set noat + LA $k0, _count_wrap + lw $k1, 0($k0) + addiu $k1, $k1, 1 + sw $k1, 0($k0) + mtc0 $0, C0_COMPARE + eret + .set pop +END(_mips_interrupt) + +LEAF(mips_stop_minimal_counter) + LA $11, _count_wrap + mfc0 $9, C0_COUNT + di $8 + ehb + lw $11, 0($11) + li $12, ~SR_HINT5 + and $8, $8, $12 + mfc0 $10, C0_COUNT + sltu $9, $10, $9 + ori $8, $8, SR_IE + beqz $9, 1f + addiu $11, $11, 1 +1: + sw $11, 0($4) + sw $10, 0($5) + mtc0 $8, C0_SR + jr $31 +END(mips_stop_minimal_counter) diff --git a/libgloss/mips/hal/mips_flush_cache.c b/libgloss/mips/hal/mips_flush_cache.c new file mode 100644 index 0000000..09f2dbf --- /dev/null +++ b/libgloss/mips/hal/mips_flush_cache.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" + +/* Writeback and invalidate all caches */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_flush_cache (void) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If D-cache is present */ + if (mips_dcache_size > 0) + mips_cache_op ((vaddr_t) KSEG0_BASE, mips_dcache_size, + mips_dcache_linesize, Index_Writeback_Inv_D); + + /* If I-cache is present */ + if (mips_icache_size > 0) + mips_cache_op ((vaddr_t) KSEG0_BASE, mips_icache_size, + mips_icache_linesize, Index_Invalidate_I); + + /* If L2-cache is present */ + if (mips_scache_size > 0) + { + mips_sync (); + mips_cache_op ((vaddr_t) KSEG0_BASE, mips_scache_size, + mips_scache_linesize, Index_Writeback_Inv_S); + } + + mips_sync (); + return; +} + +/* Writeback and invalidate D-cache */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_flush_dcache (void) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If D-cache is present */ + if (mips_dcache_size > 0) + mips_cache_op ((vaddr_t) KSEG0_BASE, mips_dcache_size, + mips_dcache_linesize, Index_Writeback_Inv_D); + + /* If L2-cache is present */ + if (mips_scache_size > 0) + { + mips_sync (); + mips_cache_op ((vaddr_t) KSEG0_BASE, mips_scache_size, + mips_scache_linesize, Index_Writeback_Inv_S); + } + + mips_sync (); + return; +} + +/* Writeback and invalidate I-cache */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_flush_icache (void) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If I-cache is present */ + if (mips_icache_size > 0) + mips_cache_op ((vaddr_t) KSEG0_BASE, mips_icache_size, + mips_icache_linesize, Index_Invalidate_I); + + /* If L2-cache is present */ + if (mips_scache_size > 0) + { + mips_sync (); + mips_cache_op ((vaddr_t) KSEG0_BASE, mips_scache_size, + mips_scache_linesize, Index_Writeback_Inv_S); + } + + mips_sync (); + return; +} diff --git a/libgloss/mips/hal/mips_fp.S b/libgloss/mips/hal/mips_fp.S new file mode 100644 index 0000000..6d15aa6 --- /dev/null +++ b/libgloss/mips/hal/mips_fp.S @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +.module hardfloat +.module doublefloat +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> + +MIPS_NOMIPS16 + +#undef fp + +/* + * FUNCTION: _fpctx_save + * DESCRIPTION: save floating point registers to memory starting at a0 + * RETURNS: int + * 0: No context saved + * CTX_*: Type of context stored + */ +LEAF(_fpctx_save) + move a1, a0 + PTR_S zero, LINKCTX_NEXT(a1) + mfc0 t0, C0_STATUS + li t1, SR_CU1 + and t1, t0, t1 + bnez t1, 1f + /* FP not enabled, bail out */ + move va0, zero + jr ra + +1: /* Save FP32 base */ + li t1, SR_FR + and t0, t0, t1 + cfc1 t2, $31 + REG_S t2, FP32CTX_CSR(a1) + sdc1 $f0, FP32CTX_0(a1) + sdc1 $f2, FP32CTX_2(a1) + sdc1 $f4, FP32CTX_4(a1) + sdc1 $f6, FP32CTX_6(a1) + sdc1 $f8, FP32CTX_8(a1) + sdc1 $f10, FP32CTX_10(a1) + sdc1 $f12, FP32CTX_12(a1) + sdc1 $f14, FP32CTX_14(a1) + sdc1 $f16, FP32CTX_16(a1) + sdc1 $f18, FP32CTX_18(a1) + sdc1 $f20, FP32CTX_20(a1) + sdc1 $f22, FP32CTX_22(a1) + sdc1 $f24, FP32CTX_24(a1) + sdc1 $f26, FP32CTX_26(a1) + sdc1 $f28, FP32CTX_28(a1) + sdc1 $f30, FP32CTX_30(a1) + bnez t0, 2f + li va0, LINKCTX_TYPE_FP32 + REG_S va0, LINKCTX_ID(a1) + jr ra + +2: /* Save FP64 extra */ +.set push +.set fp=64 + sdc1 $f1, FP64CTX_1(a1) + sdc1 $f3, FP64CTX_3(a1) + sdc1 $f5, FP64CTX_5(a1) + sdc1 $f7, FP64CTX_7(a1) + sdc1 $f9, FP64CTX_9(a1) + sdc1 $f11, FP64CTX_11(a1) + sdc1 $f13, FP64CTX_13(a1) + sdc1 $f15, FP64CTX_15(a1) + sdc1 $f17, FP64CTX_17(a1) + sdc1 $f19, FP64CTX_19(a1) + sdc1 $f21, FP64CTX_21(a1) + sdc1 $f23, FP64CTX_23(a1) + sdc1 $f25, FP64CTX_25(a1) + sdc1 $f27, FP64CTX_27(a1) + sdc1 $f29, FP64CTX_29(a1) + sdc1 $f31, FP64CTX_31(a1) +.set pop + li va0, LINKCTX_TYPE_FP64 + REG_S va0, LINKCTX_ID(a0) + jr ra +END(_fpctx_save) + +/* + * FUNCTION: _fpctx_load + * DESCRIPTION: load floating point registers from context chain starting at a0 + * RETURNS: int + * 0: Unrecognised context + * CTX_*: Type of context restored + */ +LEAF(_fpctx_load) + move a1, a0 + REG_L va0, LINKCTX_ID(a1) + /* Detect type */ + li t0, LINKCTX_TYPE_FP64 + li t1, LINKCTX_TYPE_FP32 + li t2, SR_CU1 + beq va0, t0, 0f + beq va0, t1, 1f + /* Don't recognise this context, fail */ + move va0, zero + jr ra + +0: /* FP64 context - Enable CU1 */ + di t3 + ehb + or t3, t3, t2 + mtc0 t3, C0_STATUS + ehb + /* Load FP64 extra */ +.set push +.set fp=64 + ldc1 $f1, FP64CTX_1(a1) + ldc1 $f3, FP64CTX_3(a1) + ldc1 $f5, FP64CTX_5(a1) + ldc1 $f7, FP64CTX_7(a1) + ldc1 $f9, FP64CTX_9(a1) + ldc1 $f11, FP64CTX_11(a1) + ldc1 $f13, FP64CTX_13(a1) + ldc1 $f15, FP64CTX_15(a1) + ldc1 $f17, FP64CTX_17(a1) + ldc1 $f19, FP64CTX_19(a1) + ldc1 $f21, FP64CTX_21(a1) + ldc1 $f23, FP64CTX_23(a1) + ldc1 $f25, FP64CTX_25(a1) + ldc1 $f27, FP64CTX_27(a1) + ldc1 $f29, FP64CTX_29(a1) + ldc1 $f31, FP64CTX_31(a1) +.set pop +1: /* FP32 context - Enable CU1 */ + di t3 + ehb + or t3, t3, t2 + mtc0 t3, C0_STATUS + ehb + /* Load FP32 base */ + REG_L t1, FP32CTX_CSR(a1) + ctc1 t1, $31 + ldc1 $f0, FP32CTX_0(a1) + ldc1 $f2, FP32CTX_2(a1) + ldc1 $f4, FP32CTX_4(a1) + ldc1 $f6, FP32CTX_6(a1) + ldc1 $f8, FP32CTX_8(a1) + ldc1 $f10, FP32CTX_10(a1) + ldc1 $f12, FP32CTX_12(a1) + ldc1 $f14, FP32CTX_14(a1) + ldc1 $f16, FP32CTX_16(a1) + ldc1 $f18, FP32CTX_18(a1) + ldc1 $f20, FP32CTX_20(a1) + ldc1 $f22, FP32CTX_22(a1) + ldc1 $f24, FP32CTX_24(a1) + ldc1 $f26, FP32CTX_26(a1) + ldc1 $f28, FP32CTX_28(a1) + ldc1 $f30, FP32CTX_30(a1) + /* Return CTX_FP32/64 */ + jr ra +END(_fpctx_load) diff --git a/libgloss/mips/hal/mips_intctrl.c b/libgloss/mips/hal/mips_intctrl.c new file mode 100644 index 0000000..a2bd2a1 --- /dev/null +++ b/libgloss/mips/hal/mips_intctrl.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <mips/cpu.h> +#include <mips/hal.h> +#include <mips/intctrl.h> + +#define _mips_intpatch_kscratch1 0x00 +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || defined (__mips_micromips) +# define _mips_intpatch_isroff1 0x06 +# define _mips_intpatch_isroff2 0x0a +# define _mips_intpatch_isroff3 0x12 +# define _mips_intpatch_isroff4 0x1a +#else +# define _mips_intpatch_isroff1 0x04 +# define _mips_intpatch_isroff2 0x08 +# define _mips_intpatch_isroff3 0x10 +# define _mips_intpatch_isroff4 0x1c +#endif + +extern void m32_sync_icache(unsigned kva, size_t n); + +void _MIPS_HAL_NOMIPS16 +_mips_intpatch (const reg_t index, uintptr_t handler, bool k1_to_kscratch1) +{ + extern void *__isr_vec_space; + uint16_t *patch; + uint32_t *patch32; + uintptr_t isrbase = (uintptr_t) (mips32_getebase() & EBASE_BASE) + + 0x200 + (index * ((uintptr_t) &__isr_vec_space)); + if (k1_to_kscratch1) + { +#ifdef __mips_micromips + patch = (uint16_t *) (isrbase + _mips_intpatch_kscratch1); + *(patch++) = 0x037f; + *(patch) = 0x12fc; +#else + patch32 = (uint32_t *) (isrbase + _mips_intpatch_kscratch1); + *patch32 = 0x409bf802; +#endif + } +#if SZPTR==4 + handler += (handler & 0x8000) << 1; + patch = (uint16_t *) (isrbase + _mips_intpatch_isroff1); + *patch = (uint16_t) (handler >> 16); /* %hi */ + patch = (uint16_t *) (isrbase + _mips_intpatch_isroff2); + *patch = (uint16_t) (handler & 0xffff); /* %lo */ + m32_sync_icache (isrbase, 32); +#elif SZPTR==8 + handler += (handler & 0x800080008000) << 1; + patch = (uint16_t *) (isrbase + _mips_intpatch_isroff1); + *patch = (uint16_t) (handler >> 48); /* %highest */ + patch = (uint16_t *) (isrbase + _mips_intpatch_isroff2); + *patch = (uint16_t) ((handler >> 32) & 0xffff); /* %higher */ + patch = (uint16_t *) (isrbase + _mips_intpatch_isroff3); + *patch = (uint16_t) ((handler >> 16) & 0xffff); /* %hi */ + patch = (uint16_t *) (isrbase + _mips_intpatch_isroff4); + *patch = (uint16_t) (handler & 0xffff); /* %lo */ + m32_sync_icache (isrbase, 64); +#else +# error "Unknown pointer size" +#endif +} + +/* + * Interrupt masking and acknowledging functions - these are weak so they can + * be replaced with versions that understand more complex interrupt models. + */ + +reg_t __attribute__ ((weak)) _MIPS_HAL_NOMIPS16 +_mips_intmask (const reg_t index, const reg_t enable) +{ + register reg_t enbefore, valbefore = 0, indexedbit; + + /* + * Calculate which bit upfront to minimise critical section. + * Note that this function supports the MCU ASE, unlike the .h files. + */ + if ((index >= 0) && (index <= 8)) + /* Traditional/1st MCU ASE interrupt. */ + indexedbit = SR_IM0 << index; + else if (index == 9) + /* 2nd MCU ASE interrupt. */ + indexedbit = SR_IM7 << 2; + + /* Make sure we can safely adjust the mask. */ + enbefore = _mips_intdisable (); + + /* Make the change. */ + valbefore = mips32_bcssr (indexedbit, enable ? indexedbit : 0); + + /* Go live again. */ + _mips_intrestore (enbefore); + + /* Return true if it was enabled, again outside critical section. */ + return (valbefore & indexedbit) != 0; +} + +reg_t __attribute__ ((weak)) _MIPS_HAL_NOMIPS16 +_mips_intack (const reg_t index) +{ + reg_t enbefore, indexedbit; + reg_t valbefore = 0; + + /* We only handle software interrupts - bail out otherwise. */ + if ((index < 0) && (index > 1)) + return 0; + + /* Calculate which bit upfront to minimise critical section. */ + indexedbit = CR_IP0 << index; + + /* Make sure we can safely adjust the state. */ + enbefore = _mips_intdisable (); + + /* Make the change. */ + valbefore = mips32_bicsr (indexedbit); + + /* Go live again. */ + _mips_intrestore (enbefore); + + /* Return true if it was enabled, again outside critical section. */ + return (valbefore & indexedbit) != 0; +} diff --git a/libgloss/mips/hal/mips_l2size.c b/libgloss/mips/hal/mips_l2size.c new file mode 100644 index 0000000..b97edd4 --- /dev/null +++ b/libgloss/mips/hal/mips_l2size.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" +#include <mips/uhi_syscalls.h> + +static void __attribute__ ((noreturn)) _MIPS_HAL_NOMIPS16 +__boot_fail (void) +{ + register long arg1 asm ("$4") = __MIPS_UHI_BF_CACHE; /* L2 cache configuration error */ + register long op asm ("$25") = __MIPS_UHI_BOOTFAIL; + register long ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + + __asm__ volatile (" # %0 = bootfail(%0, %1) op=%2\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret) + : "r" (arg1), "r" (op)); + + __boot_fail (); +} + +/* + * Internal routine to determine cache sizes by looking at config + * registers. Sizing information is stored directly to memory. +*/ +void _MIPS_HAL_NOMIPS16 +__def_cache_size_hook (void) +{ + /* + * Fall back to Config2 based L2 if Config3[M] or Config4[M] + * or Config5[L2C] is not present. + */ + if ((mips32_getconfig3 () & CFG3_M) == 0 + || (mips32_getconfig4 () & CFG4_M) == 0 + || (mips32_getconfig5 () & CFG5_L2C) == 0) + { + unsigned int cfg, tmp1, tmp2; + + cfg = mips32_getconfig2 (); + + /* Get S-cache line size (log2) */ + tmp1 = (cfg & CFG2_SL_MASK) >> CFG2_SL_SHIFT; + if (tmp1 == 0) + return; /* No S-cache */ + + tmp1++; + + /* Get number of S-cache ways */ + mips_scache_ways = ((cfg & CFG2_SA_MASK) >> CFG2_SA_SHIFT) + 1; + + /* Total scache size = lines/way * linesize * ways */ + mips_scache_linesize = 1 << tmp1; + tmp2 = mips_scache_ways << tmp1; + + /* Get scache lines per way */ + tmp1 = ((cfg & CFG2_SS_MASK) >> CFG2_SS_SHIFT) + 6; + mips_scache_size = tmp2 << tmp1; + + return; + } + + /* + * No CM3 code supplied but we have a memory mapped L2 config. + * Report a boot failure through UHI. + */ + __boot_fail (); +} + +void __cache_size_hook (void) __attribute__ ((weak, alias ("__def_cache_size_hook"))); diff --git a/libgloss/mips/hal/mips_lock_cache.c b/libgloss/mips/hal/mips_lock_cache.c new file mode 100644 index 0000000..35011ab --- /dev/null +++ b/libgloss/mips/hal/mips_lock_cache.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" + +/* + * The MIPS32 cache architecture does support per-line cache locking. + * If you lock any cache lines, then don't call the mips_flush_cache + * routine, because these will flush the locked data out of the cache + * too; use only mips_clean_xcache routines. +*/ + +/* Load and lock a block of data into the D-cache */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_lock_dcache (vaddr_t data, size_t n) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If D-cache is present */ + if (mips_dcache_linesize > 0) + mips_cache_op (data, n, mips_dcache_linesize, Fetch_Lock_D); + + mips_sync (); + return; +} + +/* Load and lock a block of instructions into the I-cache */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_lock_icache (vaddr_t code, size_t n) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If I-cache is present */ + if (mips_icache_linesize > 0) + mips_cache_op (code, n, mips_icache_linesize, Fetch_Lock_I); + + mips_sync (); + return; +} + +/* Load and lock a block of data into the L2-cache */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_lock_scache (vaddr_t data, size_t n) +{ + /* Calculate cache sizes */ + mips_size_cache (); + + /* If L2-cache is present */ + if (mips_scache_linesize > 0) + mips_cache_op (data, n, mips_scache_linesize, Fetch_Lock_S); + + mips_sync (); + return; +} diff --git a/libgloss/mips/hal/mips_msa.S b/libgloss/mips/hal/mips_msa.S new file mode 100644 index 0000000..1e03503 --- /dev/null +++ b/libgloss/mips/hal/mips_msa.S @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#if __mips_isa_rev < 6 || !defined(__mips_micromips) +.module hardfloat +.module doublefloat +#undef fp +.module fp=64 +.module msa + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> + +MIPS_NOMIPS16 + +/* + * FUNCTION: _msactx_save + * DESCRIPTION: save MSA registers to memory starting at a0 + * RETURNS: int + * 0: No context saved + * CTX_*: Type of context stored + */ +LEAF(_msactx_save) + move a1, a0 + PTR_S zero, LINKCTX_NEXT(a1) + mfc0 t0, C0_CONFIG5 + ext t0, t0, CFG5_MSAEN_SHIFT, 1 + bnez t0, 1f + /* MSA not enabled, bail out */ + move va0, zero + jr ra + + /* Save FCSR if necessary */ +1: mfc0 t0, C0_STATUS + ext t1, t0, SR_CU1_SHIFT, 1 + lui va0, %hi(LINKCTX_TYPE_MSA) + beqz t1, 2f + lui va0, %hi(LINKCTX_TYPE_FMSA) + cfc1 t2, $31 + REG_S t2, MSACTX_FCSR(a1) + /* Save MSA */ +2: ori va0, va0, %lo(LINKCTX_TYPE_MSA) + cfcmsa t0, $1 + REG_S t0, MSACTX_MSACSR(a1) + st.d $w0, MSACTX_0(a1) + st.d $w1, MSACTX_1(a1) + st.d $w2, MSACTX_2(a1) + st.d $w3, MSACTX_3(a1) + st.d $w4, MSACTX_4(a1) + st.d $w5, MSACTX_5(a1) + st.d $w6, MSACTX_6(a1) + st.d $w7, MSACTX_7(a1) + st.d $w8, MSACTX_8(a1) + st.d $w9, MSACTX_9(a1) + st.d $w10, MSACTX_10(a1) + st.d $w11, MSACTX_11(a1) + st.d $w12, MSACTX_12(a1) + st.d $w13, MSACTX_13(a1) + st.d $w14, MSACTX_14(a1) + st.d $w15, MSACTX_15(a1) + st.d $w16, MSACTX_16(a1) + st.d $w17, MSACTX_17(a1) + st.d $w18, MSACTX_18(a1) + st.d $w19, MSACTX_19(a1) + st.d $w20, MSACTX_20(a1) + st.d $w21, MSACTX_21(a1) + st.d $w22, MSACTX_22(a1) + st.d $w23, MSACTX_23(a1) + st.d $w24, MSACTX_24(a1) + st.d $w25, MSACTX_25(a1) + st.d $w26, MSACTX_26(a1) + st.d $w27, MSACTX_27(a1) + st.d $w28, MSACTX_28(a1) + st.d $w29, MSACTX_29(a1) + st.d $w30, MSACTX_30(a1) + st.d $w31, MSACTX_31(a1) + REG_S va0, LINKCTX_ID(a1) + jr ra +END(_msactx_save) + +/* + * FUNCTION: _msactx_load + * DESCRIPTION: load MSA/floating point registers from memory starting at a0 + * RETURNS: int + * 0: Unrecognised context + * CTX_*: Type of context restored + */ +LEAF(_msactx_load) + move a1, a0 + REG_L va0, LINKCTX_ID(a1) + /* Detect type */ + li t0, LINKCTX_TYPE_FMSA + li t1, LINKCTX_TYPE_MSA + li t2, SR_CU1 + beq va0, t0, 0f + beq va0, t1, 1f + /* Don't recognise this context, fail */ + move va0, zero + jr ra + +0: /* FPU+MSA context - Enable CU1 */ + di t3 + ehb + or t3, t3, t2 + mtc0 t3, C0_STATUS + ehb + REG_L t1, MSACTX_FCSR(a1) + ctc1 t1, $31 +1: /* MSA context - Enable MSA */ + li t3, CFG5_MSAEN + mfc0 t2, C0_CONFIG5 + or t2, t3, t2 + mtc0 t2, C0_CONFIG5 + ehb + /* Load MSA */ + lw t3, MSACTX_MSACSR(a1) + ctcmsa $1, t3 + ld.d $w0, MSACTX_0(a1) + ld.d $w1, MSACTX_1(a1) + ld.d $w2, MSACTX_2(a1) + ld.d $w3, MSACTX_3(a1) + ld.d $w4, MSACTX_4(a1) + ld.d $w5, MSACTX_5(a1) + ld.d $w6, MSACTX_6(a1) + ld.d $w7, MSACTX_7(a1) + ld.d $w8, MSACTX_8(a1) + ld.d $w9, MSACTX_9(a1) + ld.d $w10, MSACTX_10(a1) + ld.d $w11, MSACTX_11(a1) + ld.d $w12, MSACTX_12(a1) + ld.d $w13, MSACTX_13(a1) + ld.d $w14, MSACTX_14(a1) + ld.d $w15, MSACTX_15(a1) + ld.d $w16, MSACTX_16(a1) + ld.d $w17, MSACTX_17(a1) + ld.d $w18, MSACTX_18(a1) + ld.d $w19, MSACTX_19(a1) + ld.d $w20, MSACTX_20(a1) + ld.d $w21, MSACTX_21(a1) + ld.d $w22, MSACTX_22(a1) + ld.d $w23, MSACTX_23(a1) + ld.d $w24, MSACTX_24(a1) + ld.d $w25, MSACTX_25(a1) + ld.d $w26, MSACTX_26(a1) + ld.d $w27, MSACTX_27(a1) + ld.d $w28, MSACTX_28(a1) + ld.d $w29, MSACTX_29(a1) + ld.d $w30, MSACTX_30(a1) + ld.w $w31, MSACTX_31(a1) + /* Return CTX_(F)MSA */ + jr ra +END(_msactx_load) + +#endif // __mips_isa_rev < 6 || !defined(__micromips__) diff --git a/libgloss/mips/hal/mips_size_cache.c b/libgloss/mips/hal/mips_size_cache.c new file mode 100644 index 0000000..75f8897 --- /dev/null +++ b/libgloss/mips/hal/mips_size_cache.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" + +int mips_icache_size = -1; +int mips_icache_linesize = -1; +int mips_icache_ways = 1; + +int mips_dcache_size = -1; +int mips_dcache_linesize = -1; +int mips_dcache_ways = 1; + +int mips_scache_size = -1; +int mips_scache_linesize = -1; +int mips_scache_ways = 1; + +int mips_tcache_size = -1; +int mips_tcache_linesize = -1; +int mips_tcache_ways = 1; + +extern void __cache_size_hook (void); + +/* + * Size caches without reinitialising and losing dirty cache lines. + * Update mips_icache_* and mips_dcache_* global variables. +*/ +void _MIPS_HAL_NOMIPS16 +mips_size_cache (void) +{ + int lsize, ways; + unsigned int cfg; + + /* Return if sizes are already known */ + if (mips_icache_size > 0) + return; + + /* Check presence of Config1 */ + cfg = mips32_getconfig0 (); + if ((cfg & CFG0_M)) + { + /* Check if I-cache is present */ + cfg = mips32_getconfig1 (); + lsize = (cfg & CFG1_IL_MASK) >> CFG1_IL_SHIFT; + if (lsize) + { + lsize++; + + /* Get number of I-cache ways */ + ways = ((cfg & CFG1_IA_MASK) >> CFG1_IA_SHIFT) + 1; + mips_icache_ways = ways; + mips_icache_linesize = 1 << lsize; + ways = ways << lsize; + + /* Get I-cache lines per way */ + lsize = ((((cfg & CFG1_IS_MASK) >> CFG1_IS_SHIFT) + 1) & 7) + 5; + mips_icache_size = ways << lsize; + } + + /* Check if D-cache is present */ + lsize = (cfg & CFG1_DL_MASK) >> CFG1_DL_SHIFT; + if (lsize) + { + lsize++; + + /* Get number of D-cache ways */ + ways = ((cfg & CFG1_DA_MASK) >> CFG1_DA_SHIFT) + 1; + mips_dcache_ways = ways; + mips_dcache_linesize = 1 << lsize; + ways = ways << lsize; + + /* Get D-cache lines per way */ + lsize = ((((cfg & CFG1_DS_MASK) >> CFG1_DS_SHIFT) + 1) & 7) + 5; + mips_dcache_size = ways << lsize; + } + } + + __cache_size_hook (); + + return; +} diff --git a/libgloss/mips/hal/mips_sync_cache.c b/libgloss/mips/hal/mips_sync_cache.c new file mode 100644 index 0000000..98fd2a0 --- /dev/null +++ b/libgloss/mips/hal/mips_sync_cache.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" + +/* Synchronise I-cache for virtual address range */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_sync_icache (vaddr_t kva, size_t n) +{ + int step; + vaddr_t addr, maxaddr, mask; + + /* Check for bad size */ + if (n <= 0) + return; + + /* Get synci step and skip if not required */ + step = mips_synci_step (); + if (step == 0) + return; + + mips_sync (); + + mask = ~ (step - 1); + addr = (kva & mask) - step; + maxaddr = ((kva + n) - 1) & mask; + + do + { + addr = addr + step; + mips_synci (addr); + } + while (addr != maxaddr); + + mips_sync (); + return; +} diff --git a/libgloss/mips/hal/mips_tlb.c b/libgloss/mips/hal/mips_tlb.c new file mode 100644 index 0000000..0b12179 --- /dev/null +++ b/libgloss/mips/hal/mips_tlb.c @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "cache.h" +#include <mips/hal.h> +#include <mips/m32tlb.h> + +/* Writes hi, lo0, lo1 and mask into the TLB entry specified by index */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_tlbwi2 (tlbhi_t hi, tlblo_t lo0, tlblo_t lo1, unsigned int mask, + int index) +{ + mips32_setentryhi (hi); + mips32_setentrylo0 (lo0); + mips32_setentrylo1 (lo1); + mips32_setpagemask (mask); + mips32_setindex (index); + mips_ehb (); + mips_tlbwi (); + return; +} + +/* + * Writes hi, lo0, lo1 and mask into the TLB entry specified by the + * random register. +*/ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_tlbwr2 (tlbhi_t hi, tlblo_t lo0, tlblo_t lo1, unsigned int mask) +{ + mips32_setentryhi (hi); + mips32_setentrylo0 (lo0); + mips32_setentrylo1 (lo1); + mips32_setpagemask (mask); + mips_ehb (); + mips_tlbwr (); + return; +} + +/* + * Probes the TLB for an entry matching hi and if present rewrites that entry, + * otherwise updates a random entry. A safe way to update the TLB. +*/ +int __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_tlbrwr2 (tlbhi_t hi, tlblo_t lo0, tlblo_t lo1, unsigned int mask) +{ + int index; + tlbhi_t prev_hi; + + prev_hi = mips32_getentryhi (); + mips32_setentryhi (hi); + + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + + index = mips32_getindex (); + mips32_setentrylo0 (lo0); + mips32_setentrylo1 (lo1); + mips32_setpagemask (mask); + mips_ehb (); /* mtc0 hazard on tlbwi/tlbwr */ + + /* Check if entry matches */ + if (index >= 0) + mips_tlbwi (); + else + mips_tlbwr (); + + mips32_setentryhi (prev_hi); + + return index; +} + +/* + * Reads the TLB entry specified by index, and returns the EntryHi, + * EntryLo0, EntryLo1 and PageMask parts in *phi, *plo0, *plo1 and *pmask + * respectively. +*/ +void _MIPS_HAL_NOMIPS16 +mips_tlbri2 (tlbhi_t *phi, tlblo_t *plo0, tlblo_t *plo1, + unsigned int *pmask, int index) +{ + mips32_setindex (index); + mips_ehb (); /* mtc0 hazard on tlbr */ + mips_tlbr (); + mips_ehb (); /* tlbr hazard on mfc0 */ + *phi = mips32_getentryhi (); + *plo0 = mips32_getentrylo0 (); + *plo1 = mips32_getentrylo1 (); + *pmask = mips32_getpagemask (); + return; +} + +/* + * Probes the TLB for an entry matching hi and return its index, or -1 if + * not found. If found, the EntryLo0, EntryLo1 and PageMask parts of the + * entry are also returned in *plo0, *plo1 and *pmask respectively. +*/ +int __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_tlbprobe2 (tlbhi_t hi, tlblo_t *plo0, tlblo_t *plo1, + unsigned int *pmask) +{ + int index; + tlbhi_t prev_hi; + + prev_hi = mips32_getentryhi (); + mips32_setentryhi (hi); + + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + + index = mips32_getindex (); + + if (index >= 0) + { + mips_tlbr (); + mips_ehb (); /* tlbr hazard on mfc0 */ + *plo0 = mips32_getentrylo0 (); + *plo1 = mips32_getentrylo1 (); + *pmask = mips32_getpagemask (); + } + else + index = -1; + + mips32_setentryhi (prev_hi); /* restore EntryHi */ + + return index; +} + +/* Probes the TLB for an entry matching hi, and if present invalidates it */ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_tlbinval (tlbhi_t hi) +{ + int index, tmp_idx; + tlbhi_t prev_hi, tmp_hi = 0; + register const int zero = 0; + unsigned int cfg; + + prev_hi = mips32_getentryhi (); + mips32_setentryhi (hi); + + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + + index = mips32_getindex (); + + if (index < 0) + goto restore; + + mips32_setentrylo0 (zero); + mips32_setentrylo1 (zero); + + /* Check if Config4 is implemented */ + cfg = mips32_getconfig3 (); + if ((cfg & CFG3_M) != 0) + { + cfg = mips32_getconfig4 (); + if ((cfg & CFG4_IE_MASK) != 0) + { + tmp_hi = C0_ENTRYHI_EHINV_MASK; + goto do_tlbwi; + } + } + + tmp_hi = (tlbhi_t) ((unsigned long) KSEG0_BASE - 0x4000); + + do + { + tmp_hi = tmp_hi + 0x4000; + mips32_setentryhi (tmp_hi); + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + tmp_idx = mips32_getindex (); + } + while (tmp_idx >= 0); + + mips32_setindex (index); /* restore Index */ + +do_tlbwi: + mips32_setentryhi (tmp_hi); + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbwi (); + mips_ehb (); /* tlbwi hazard on mfc0 */ + +restore: + mips32_setentryhi (prev_hi); /* restore EntryHi */ + + return; +} + +/* + * Return number of entries and sets in TLB. + * Return number of entries in *pentries and + * sets in *psets +*/ +static void _MIPS_HAL_NOMIPS16 +mips_tlb_entries_sets (int *pentries, int *psets) +{ + int entries = 0, sets = 0, ways = 0; + unsigned int cfg, cfg1, tcfg, tmp; + + cfg = mips32_getconfig (); + cfg = (cfg & CFG0_MT_MASK) >> CFG0_MT_SHIFT; + if ((cfg == 0) /* No MMU */ + || (cfg == (CFG0_MT_FIXED >> CFG0_MT_SHIFT)) /* fixed address translation */ + || (cfg == (CFG0_MT_BAT >> CFG0_MT_SHIFT)) /* block address translator */ + || ((cfg & ((CFG0_MT_TLB | CFG0_MT_DUAL) >> CFG0_MT_SHIFT)) == 0)) /* presence of TLB */ + { + *pentries = 0; + *psets = 0; + return; + } + + cfg1 = mips32_getconfig1 (); + + /* + * As per PRA, field holds number of entries - 1 + * Standard TLBs and dual TLBs have extension fields. + */ + entries = ((cfg1 & CFG1_MMUS_MASK) >> CFG1_MMUSSHIFT) + 1; + + tcfg = mips32_getconfig3 (); + if ((tcfg & CFG3_M) == 0) + goto doReturn; + + tcfg = mips32_getconfig4 (); + +#if (__mips_isa_rev < 6) + tmp = (tcfg & CFG4_MMUED) >> CFG4_MMUED_SHIFT; + + /* MMU Extension Definition */ + if (tmp == (CFG4_MMUED_FTLBVEXT >> CFG4_MMUED_SHIFT)) + goto doFTLBVTLB; + + /* MMUSizeExt */ + if (tmp == (CFG4_MMUED_SIZEEXT >> CFG4_MMUED_SHIFT)) + goto doSizeExt; + + if (tmp == 0) + goto doReturn; + + goto doFTLBSize; + +doSizeExt: + entries += ((tcfg & CFG4_MMUSE_MASK) >> CFG4_MMUSE_SHIFT) + << CFG1_MMUS_BITS; + goto doReturn; +#endif + +doFTLBVTLB: + entries += ((tcfg & CFG4_VTLBSEXT_MASK) >> CFG4_VTLBSEXT_SHIFT) + << CFG1_MMUS_BITS; + +doFTLBSize: + /* Skip FTLB size calculations if Config:MT != 4 */ + if (cfg != (CFG0_MT_DUAL >> CFG0_MT_SHIFT)) + goto doReturn; + + /* Ways */ + ways = 2 + ((tcfg & CFG4_FTLBW_MASK) >> CFG4_FTLBW_SHIFT); + + /* Sets per way */ + tmp = ((tcfg & CFG4_FTLBS_MASK) >> CFG4_FTLBS_SHIFT); + sets = 1 << tmp; + + /* Total sets */ + entries += ways << tmp; + +doReturn: + *pentries = entries; + *psets = sets; + + return; +} + +/* + * Return number of entries in TLB + * This function is used for both mips64 and mips32 +*/ +int _MIPS_HAL_NOMIPS16 +mips_tlb_size (void) +{ + int entries = 0, sets = 0; + mips_tlb_entries_sets (&entries, &sets); + (void) sets; + return entries; +} + +/* + * Invalidate the whole TLB. + * This function is used for both mips64 and mips32 +*/ +void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16 +mips_tlbinvalall (void) +{ + unsigned int cfg0, cfg; + unsigned long tmp_hi, tmp_hi2; + int entries = 0, sets = 0, tlb_stride = 0; + int end_ptr = 0, index = 0; + register const unsigned long zero = 0; + extern void *__tlb_stride_length; + + cfg0 = mips32_getconfig (); + cfg0 = (cfg0 & CFG0_MT_MASK) >> CFG0_MT_SHIFT; + if ((cfg0 == 0) /* No MMU */ + || (cfg0 == (CFG0_MT_FIXED >> CFG0_MT_SHIFT)) /* fixed address translation */ + || (cfg0 == (CFG0_MT_BAT >> CFG0_MT_SHIFT))) /* block address translator */ + goto doReturn; + + mips_setentrylo0 (zero); + mips_setentrylo1 (zero); + mips_setpagemask (zero); + + /* Fetch size & number of sets */ + mips_tlb_entries_sets (&entries, &sets); + + cfg = mips32_getconfig3 (); + if ((cfg & CFG3_M) == 0) + goto doBasicInval; + + cfg = mips32_getconfig4 (); + cfg = (cfg & CFG4_IE_MASK) >> CFG4_IE_SHIFT; + + /* If Config4[IE] = 0, use old method for invalidation */ + if (cfg == 0) + goto doBasicInval; + + /* If Config4[IE] = 1, EHINV loop */ + if (cfg == (CFG4_IE_EHINV >> CFG4_IE_SHIFT)) + goto doEHINV; + + /* If Config[MT] = 1, one instruction required */ + if (cfg0 == (CFG0_MT_TLB >> CFG0_MT_SHIFT) + || cfg == (CFG4_IE_INVALL >> CFG4_IE_SHIFT)) + { + /* TLB walk done by hardware, Config4[IE] = 3 or Config[MT] = 1 */ + mips32_setindex (zero); + mips_ehb (); + mips_eva_tlbinvf (); + goto doReturn; + } + + /* + * TLB walk done by software, Config4[IE] = 2, Config[MT] = 4 + * + * One TLBINVF is executed with an index in VTLB range to + * invalidate all VTLB entries. + * + * One TLBINVF is executed per FTLB set. + * + * We'll clean out the TLB by computing the Size of the VTLB + * but not add the 1. This will give us a finger that points + * at the last VTLB entry. + */ + + /* Clear VTLB */ + mips32_setindex (zero); + mips_ehb (); + mips_eva_tlbinvf (); + + tlb_stride = (int) ((unsigned long) &__tlb_stride_length); + sets = sets * tlb_stride; + end_ptr = entries - sets; + + do + { + entries = entries - tlb_stride; + mips32_setindex (entries); + mips_ehb (); + mips_eva_tlbinvf (); + } + while (entries != end_ptr); + + goto doReturn; + +doEHINV: + /* + * Config4[IE] = 1. EHINV supported, but not tlbinvf. + * + * Invalidate the TLB for R3 onwards by loading EHINV and writing to all + * TLB entries. + */ + index = 0; + tmp_hi = C0_ENTRYHI_EHINV_MASK; + mips_setentryhi (tmp_hi); + do + { + mips32_setindex (index); + mips_ehb (); /* mtc0 hazard on tlbwi */ + mips_tlbwi (); + index++; + } + while (entries != index); + + goto doReturn; + +doBasicInval: + /* + * Perform a basic invalidation of the TLB for R1 onwards by loading + * 0x(FFFFFFFF)KSEG0_BASE into EntryHi and writing it into index 0 + * incrementing by a pagesize, writing into index 1, etc. + * If large physical addressing is enabled, load 0xFFFFFFFF + * into the top half of EntryHi. + */ + tmp_hi = 0; + cfg = mips32_getconfig3 (); + + /* If XPA is present */ + if ((cfg & CFG3_LPA) != 0) + { + cfg = mips32_getpagegrain (); + if ((cfg & PAGEGRAIN_ELPA) == 0) + tmp_hi = 0xFFFFFFFF; + } + + tmp_hi2 = (unsigned long) KSEG0_BASE - 0x4000; + index = 0; + + do + { + tmp_hi2 += 0x4000; + mips_setentryhi (tmp_hi2); + if (tmp_hi != 0) + mips32_sethientryhi (tmp_hi); + mips_ehb (); /* mtc0 hazard on tlbp */ + mips_tlbp (); + mips_ehb (); /* tlbp hazard on mfc0 */ + if (mips32_getindex () == 0) + continue; + mips32_setindex (index); + mips_ehb (); /* mtc0 hazard on tlbwi */ + mips_tlbwi (); + index++; + } + while (entries != index); + +doReturn: + /* + * Clear EntryHI. The upper half is cleared + * autmatically as mtc0 writes zeroes. + */ + mips_setentryhi (zero); + + return; +} + +_MIPS_HAL_NOMIPS16 +int m64_tlb_size (void) __attribute__ ((alias ("mips_tlb_size"))); +_MIPS_HAL_NOMIPS16 +void m64_tlbinvalall (void) __attribute__ ((alias ("mips_tlbinvalall"))); diff --git a/libgloss/mips/hal/mips_xpa.S b/libgloss/mips/hal/mips_xpa.S new file mode 100644 index 0000000..a2bf981 --- /dev/null +++ b/libgloss/mips/hal/mips_xpa.S @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/asm.h> +#include <mips/hal.h> + +MIPS_NOMIPS16 + +/* + * FUNCTION: _xpa_save + * DESCRIPTION: save the XPA version of badvaddr. + * RETURNS: int + * 0: No context saved + * CTX_*: Type of conext stored + */ +LEAF(_xpa_save) + move a1, a0 + PTR_S zero, LINKCTX_NEXT(a1) + /* Test for LPA support */ + mfc0 t0, C0_CONFIG3 + ext t0, t0, CFG3_LPA_SHIFT, 1 + beqz t0, 1f + /* Test for LPA enabled */ + mfc0 t0, C0_PAGEGRAIN + ext t0, t0, PAGEGRAIN_ELPA_SHIFT, PAGEGRAIN_ELPA_BITS + bnez t0, 2f + + /* LPA either unavailable or not enabled - return 0 */ +1: move va0, zero + jr ra + +2: lui va0, %hi(LINKCTX_TYPE_XPA) + addiu va0, va0, %lo(LINKCTX_TYPE_XPA) + mfc0 t0, C0_BADVADDR + .set push + .set xpa + mfhc0 t1, C0_BADVADDR + .set pop +#if BYTE_ORDER == BIG_ENDIAN + sw t0, XPACTX_BADVADDR(a1) + sw t1, (XPACTX_BADVADDR+4)(a1) +#else /* BYTE ORDER == LITTLE_ENDIAN */ + sw t1, XPACTX_BADVADDR(a1) + sw t0, (XPACTX_BADVADDR+4)(a1) +#endif + REG_S va0, LINKCTX_ID(a1) + jr ra +END(_xpa_save) diff --git a/libgloss/mips/hal/syscalls.c b/libgloss/mips/hal/syscalls.c new file mode 100644 index 0000000..7c3ffec --- /dev/null +++ b/libgloss/mips/hal/syscalls.c @@ -0,0 +1,52 @@ +#include <_ansi.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <mips/hal.h> + +extern char _end[]; + +/* FIXME: This is not ideal, since we do a get_ram_range() call for + every sbrk() call. */ +char * +sbrk (int nbytes) +{ + static char *heap_ptr = NULL; + static char *heap_start = NULL; + static unsigned long heap_size = 0; + char *base; + ptrdiff_t avail = 0; + void *ram_base; + void *ram_extent; + + if (heap_start == NULL) + { + _get_ram_range (&ram_base, &ram_extent); + + /* If the _end symbol is within the RAM then use _end. */ + if ((void*)_end > ram_base && (void*)_end < ram_extent) + { + heap_start = _end; + heap_ptr = _end; + heap_size = ram_extent - (void*)_end; + } + else + { + heap_start = ram_base; + heap_ptr = ram_base; + heap_size = ram_extent - ram_base; + } + } + + if ((heap_ptr >= heap_start) && + (heap_ptr < (heap_start + heap_size))) { + avail = (heap_start + heap_size) - heap_ptr; + base = heap_ptr; + } /* else will fail since "nbytes" will be greater than zeroed "avail" value */ + + if ((nbytes > avail) || (heap_ptr + nbytes < heap_start)) + base = (char *)-1; + else + heap_ptr += nbytes; + + return base; +} diff --git a/libgloss/mips/idtmon.S b/libgloss/mips/idtmon.S index 304aaa4..d09b2e0 100644 --- a/libgloss/mips/idtmon.S +++ b/libgloss/mips/idtmon.S @@ -28,7 +28,8 @@ #define INDIRECT(name,index) \ .globl name; \ .ent name; \ -name: la $2,+(0xbfc00000+((index)*8)); \ +name: lui $2,%hi(0xbfc00000+((index)*8)); \ + addiu $2,$2,%lo(0xbfc00000+((index)*8)); \ j $2; \ .end name diff --git a/libgloss/mips/include/mips/asm.h b/libgloss/mips/include/mips/asm.h new file mode 100644 index 0000000..209d151 --- /dev/null +++ b/libgloss/mips/include/mips/asm.h @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS_ASM_H_ +#define _MIPS_ASM_H_ + +/* + * asm.h: various macros to help assembly language writers + */ + +/* ABI specific stack frame layout and manipulation. */ +#if _MIPS_SIM==_ABIO32 +/* Standard O32 */ +#define SZREG 4 /* saved register size */ +#define REG_S sw /* store saved register */ +#define REG_L lw /* load saved register */ +#define SZARG 4 /* argument register size */ +#define NARGSAVE 4 /* arg register space on caller stack */ +#define ALSZ 7 /* stack alignment - 1 */ +#define ALMASK (~7) /* stack alignment mask */ +#define LOG2_STACK_ALGN 3 /* log2(8) */ +#define SZPTR 4 /* pointer size */ +#define LOG2_SZPTR 2 /* log2(4) */ +#define PTR_S sw /* store pointer */ +#define PTR_L lw /* load pointer */ +#define PTR_SUBU subu /* decrement pointer */ +#define PTR_ADDU addu /* increment pointer */ +#define PTR_MFC0 mfc0 /* access CP0 pointer width register */ +#define PTR_MTC0 mtc0 /* access CP0 pointer width register */ +#define LA la /* load an address */ +#define PTR .word /* pointer type pseudo */ +#elif _MIPS_SIM==_ABIO64 +/* Cygnus O64 */ +#define SZREG 8 /* saved register size */ +#define REG_S sd /* store saved register */ +#define REG_L ld /* load saved register */ +#define SZARG 8 /* argument register size */ +#define NARGSAVE 4 /* arg register space on caller stack */ +#define ALSZ 7 /* stack alignment - 1 */ +#define ALMASK (~7) /* stack alignment mask */ +#define LOG2_STACK_ALGN 3 /* log2(8) */ +#define SZPTR 4 /* pointer size */ +#define LOG2_SZPTR 2 /* log2(4) */ +#define PTR_S sw /* store pointer */ +#define PTR_L lw /* load pointer */ +#define PTR_SUBU subu /* decrement pointer */ +#define PTR_ADDU addu /* increment pointer */ +#define PTR_MFC0 dmfc0 /* access CP0 pointer width register */ +#define PTR_MTC0 mtc0 /* access CP0 pointer width register */ +#define LA la /* load an address */ +#define PTR .word /* pointer type pseudo */ +#elif _MIPS_SIM==_ABIN32 +/* Standard N32 */ +#define SZREG 8 /* saved register size */ +#define REG_S sd /* store saved register */ +#define REG_L ld /* load saved register */ +#define SZARG 8 /* argument register size */ +#define NARGSAVE 0 /* arg register space on caller stack */ +#define ALSZ 15 /* stack alignment - 1 */ +#define ALMASK (~15) /* stack alignment mask */ +#define LOG2_STACK_ALGN 4 /* log2(16) */ +#define SZPTR 4 /* pointer size */ +#define LOG2_SZPTR 2 /* log2(4) */ +#define PTR_S sw /* store pointer */ +#define PTR_L lw /* load pointer */ +#define PTR_SUBU subu /* decrement pointer (SGI uses sub) */ +#define PTR_ADDU addu /* increment pointer (SGI uses add) */ +#define PTR_MFC0 mfc0 /* access CP0 pointer width register */ +#define PTR_MTC0 mtc0 /* access CP0 pointer width register */ +#define LA la /* load an address */ +#define PTR .word /* pointer type pseudo */ +#elif _MIPS_SIM==_ABI64 +/* Standard N64 */ +#define SZREG 8 /* saved register size */ +#define REG_S sd /* store saved register */ +#define REG_L ld /* load saved register */ +#define SZARG 8 /* argument register size */ +#define NARGSAVE 0 /* arg register space on caller stack */ +#define ALSZ 15 /* stack alignment - 1 */ +#define ALMASK (~15) /* stack alignment mask */ +#define LOG2_STACK_ALGN 4 /* log2(16) */ +#define SZPTR 8 /* pointer size */ +#define LOG2_SZPTR 3 /* log2(8) */ +#define PTR_S sd /* store pointer */ +#define PTR_L ld /* load pointer */ +#define PTR_SUBU dsubu /* decrement pointer */ +#define PTR_ADDU daddu /* increment pointer */ +#define PTR_MFC0 dmfc0 /* access CP0 pointer width register */ +#define PTR_MTC0 dmtc0 /* access CP0 pointer width register */ +#define LA dla /* load an address */ +#define PTR .dword /* pointer type pseudo */ +#else +#error Unknown ABI +#endif + +#if defined(__ASSEMBLER__) + +/* Concatenate two names. */ +#ifdef __STDC__ +# define _ASMCONCAT(A, B) A ## B +#else +# define _ASMCONCAT(A, B) A/**/B +#endif + +/* Name of reset code section. */ +#ifndef _RESET_SECTION +# define _RESET_SECTION .section .reset, "ax", @progbits +#endif + +#ifndef _RESET_SECTION_NAMED +/* No function section support for now, since binutils fails to cope with + external branches. */ +# define _RESET_SECTION_NAMED(name) .pushsection .reset, "ax", @progbits +#endif + +/* Name of boot code section. */ +#ifndef _BOOT_SECTION +# define _BOOT_SECTION .section .boot, "ax", @progbits +#endif + +#ifndef _BOOT_SECTION_NAMED +/* No function section support for now, since binutils fails to cope with + external branches. */ +# define _BOOT_SECTION_NAMED(name) .pushsection .boot, "ax", @progbits +#endif + +/* Name of standard code section. */ +#ifndef _NORMAL_SECTION_UNNAMED +# define _NORMAL_SECTION_UNNAMED .section .text, "ax", @progbits +#endif + +#ifndef _NORMAL_SECTION_NAMED +# ifdef _FUNCTION_SECTIONS_ +# define _NORMAL_SECTION_NAMED(name) .pushsection .text ##.name, "ax", @progbits +# else +# define _NORMAL_SECTION_NAMED(name) .pushsection .text, "ax", @progbits +# endif +#endif + +/* Default code section. */ +#ifndef _TEXT_SECTION_NAMED +# if defined(_RESETCODE) +# define _TEXT_SECTION_NAMED _RESET_SECTION_NAMED +# elif defined(_BOOTCODE) +# define _TEXT_SECTION_NAMED _BOOT_SECTION_NAMED +# else +# define _TEXT_SECTION_NAMED _NORMAL_SECTION_NAMED +# endif +#endif + +#ifndef _TEXT_SECTION +# if defined(_RESETCODE) +# define _TEXT_SECTION _RESET_SECTION +# elif defined(_BOOTCODE) +# define _TEXT_SECTION _BOOT_SECTION +# else +# define _TEXT_SECTION _NORMAL_SECTION_UNNAMED +# endif + _TEXT_SECTION +#endif + +/* + * Leaf functions declarations. + */ + +/* Global leaf function. */ +#define LEAF(name) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .globl name; \ + .ent name; \ +name: + +/* Static/Local leaf function. */ +#define SLEAF(name) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .ent name; \ +name: + +/* Weak leaf function. */ +#define WLEAF(name) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .weak name; \ + .ent name; \ +name: + +/* Weak alias leaf function. */ +#define ALEAF(name,alias) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .weak alias; \ + .ent name; \ + alias = name; \ +name: + +/* + * Alternative function entrypoints. + */ + +/* Global alternative entrypoint. */ +#define AENT(name) \ + .globl name; \ + .aent name; \ +name: +#define XLEAF(name) AENT(name) + +/* Local/static alternative entrypoint. */ +#define SAENT(name) \ + .aent name; \ +name: +#define SXLEAF(name) SAENT(name) + + +/* + * Leaf functions declarations. + */ + +/* Global nested function. */ +#define NESTED(name, framesz, rareg) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .globl name; \ + .ent name; \ + .frame sp, framesz, rareg; \ +name: + +/* Static/Local nested function. */ +#define SNESTED(name, framesz, rareg) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .ent name; \ + .frame sp, framesz, rareg; \ +name: + +/* Weak nested function. */ +#define WNESTED(name, framesz, rareg) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .weak name; \ + .ent name; \ + .frame sp, framesz, rareg; \ +name: + +/* Weak alias nested function. */ +#define ANESTED(name, alias, framesz, rareg) \ + _TEXT_SECTION_NAMED(name); \ + .balign 4; \ + .weak alias; \ + .ent name; \ + alias = name; \ + .frame sp, framesz, rareg; \ +name: + +/* + * Function termination + */ +#define END(name) \ + .size name,.-name; \ + .end name; \ + .popsection + +#define SEND(name) END(name) +#define WEND(name) END(name) +#define AEND(name,alias) END(name) + +/* + * Global data declaration. + */ +#define EXPORT(name) \ + .globl name; \ + .type name,@object; \ +name: + +/* + * Global data declaration with size. + */ +#define EXPORTS(name,sz) \ + .globl name; \ + .type name,@object; \ + .size name,sz; \ +name: + +/* + * Weak data declaration with size. + */ +#define WEXPORT(name,sz) \ + .weak name; \ + .type name,@object; \ + .size name,sz; \ +name: + +/* + * Global data reference with size. + */ +#define IMPORT(name, size) \ + .extern name,size + +/* + * Global zeroed data. + */ +#define BSS(name,size) \ + .type name,@object; \ + .comm name,size + +/* + * Local zeroed data. + */ +#define LBSS(name,size) \ + .lcomm name,size + +/* + * Insert call to _mcount if profiling. + */ +#ifdef __PROFILING__ +#define _MCOUNT \ + .set push; \ + .set noat; \ + move $1,$31; \ + jal _mcount; \ + .set pop +#else +#define _MCOUNT +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /*_MIPS_ASM_H_*/ diff --git a/libgloss/mips/include/mips/cm3.h b/libgloss/mips/include/mips/cm3.h new file mode 100644 index 0000000..3a1c5a1 --- /dev/null +++ b/libgloss/mips/include/mips/cm3.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _CM3_H_ +#define _CM3_H_ + +#define CMGCR_BASE_ADDR_SHIFT 11 + +#define CMGCR_BASE_ADDR_LSHIFT 4 +/* Offsets of memory-mapped registers */ +#define GCR_L2_CONFIG 0x130 +#define GCR_L2_RAM_CONFIG 0x240 +#define GCR_TAG_ADDR 0x600 +#define GCR_TAG_STATE 0x608 +#define GCR_TAG_DATA 0x610 +#define GCR_TAG_ECC 0x618 + +/* Contents of L2 RAM field */ +#define GCR_L2_RAM_HCID_SHIFT 30 +#define GCR_L2_RAM_HCID_BITS 1 +#define GCR_L2_RAM_HCIS_SHIFT 29 +#define GCR_L2_RAM_HCIS_BITS 1 + +/* L2 Configuration Register */ +#define GCR_L2_REG_EXISTS_MASK 0x80000000 +#define GCR_L2_REG_EXISTS_SHIFT 31 +#define GCR_L2_REG_EXISTS_BITS 1 +#define GCR_L2_LRU_WE_MASK (1<<GCR_L2_LRU_WE_SHIFT) +#define GCR_L2_LRU_WE_SHIFT 26 +#define GCR_L2_LRU_WE_BITS 1 +#define GCR_L2_TAG_WE_MASK (1<<GCR_L2_TAG_WE_SHIFT) +#define GCR_L2_TAG_WE_SHIFT 25 +#define GCR_L2_TAG_WE_BITS 1 +#define GCR_L2_ECC_WE_MASK (1<<GCR_L2_ECC_WE_SHIFT) +#define GCR_L2_ECC_WE_SHIFT 24 +#define GCR_L2_ECC_WE_BITS 1 +#define GCR_L2_BYPASS_MASK (1<<GCR_L2_BYPASS_SHIFT) +#define GCR_L2_BYPASS_SHIFT 20 +#define GCR_L2_BYPASS_BITS 1 +#define GCR_L2_SS_MASK 0x0000F000 +#define GCR_L2_SS_SHIFT 12 +#define GCR_L2_SS_BITS 4 +#define GCR_L2_SL_MASK 0x00000F00 +#define GCR_L2_SL_SHIFT 8 +#define GCR_L2_SL_BITS 4 +#define GCR_L2_SA_MASK 0x000000FF +#define GCR_L2_SA_SHIFT 0 +#define GCR_L2_SA_BITS 8 + +#endif /* _CM3_H_ */ diff --git a/libgloss/mips/include/mips/cpu.h b/libgloss/mips/include/mips/cpu.h new file mode 100644 index 0000000..d67a058 --- /dev/null +++ b/libgloss/mips/include/mips/cpu.h @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _CPU_H_ +#define _CPU_H_ + +#if !defined(__ASSEMBLER__) +#include <sys/types.h> +#endif + +#ifndef SR_IMASK +#if __mips == 64 +#include <mips/m64c0.h> +#elif __mips == 32 +#include <mips/m32c0.h> +#endif +#endif /* SR_IMASK */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(__ASSEMBLER__) +/* + * Generic MIPS cache handling + * + * primary: virtual index, physical tag, write back; + * secondary: physical index, physical tag, write back; + * pass correct virtual address to primary cache routines. + */ + +#ifdef __mips16 +# define _MIPS_CPU_NOMIPS16 __attribute__((nomips16)) +#else +# define _MIPS_CPU_NOMIPS16 +#endif + +extern int mips_icache_size, mips_icache_linesize, mips_icache_ways; +extern int mips_dcache_size, mips_dcache_linesize, mips_dcache_ways; +extern int mips_scache_size, mips_scache_linesize, mips_scache_ways; +extern int mips_tcache_size, mips_tcache_linesize, mips_tcache_ways; + +/* these are now the only standard interfaces to the caches */ +_MIPS_CPU_NOMIPS16 +extern void mips_size_cache (void); +_MIPS_CPU_NOMIPS16 +extern void mips_flush_cache (void); +_MIPS_CPU_NOMIPS16 +extern void mips_flush_dcache (void); +_MIPS_CPU_NOMIPS16 +extern void mips_flush_icache (void); +_MIPS_CPU_NOMIPS16 +extern void mips_sync_icache (vaddr_t, size_t); +_MIPS_CPU_NOMIPS16 +extern void mips_clean_cache (vaddr_t, size_t); +_MIPS_CPU_NOMIPS16 +extern void mips_clean_dcache (vaddr_t, size_t); +_MIPS_CPU_NOMIPS16 +extern void mips_clean_dcache_nowrite (vaddr_t, size_t); +_MIPS_CPU_NOMIPS16 +extern void mips_clean_icache (vaddr_t, size_t); +_MIPS_CPU_NOMIPS16 +extern void mips_lock_dcache (vaddr_t, size_t); +_MIPS_CPU_NOMIPS16 +extern void mips_lock_icache (vaddr_t, size_t); +_MIPS_CPU_NOMIPS16 +extern void mips_lock_scache (vaddr_t, size_t); + +/* + * Other common utilities for all CPUs + */ +extern void mips_wbflush (void); +extern void mips_cycle (unsigned); +_MIPS_CPU_NOMIPS16 +extern int mips_tlb_size (void); + +/* + * Coprocessor 0 register manipulation + * Warning: all non-atomic in face of interrupts. + */ +#if defined(_mips_mfc0) + +/* exchange (swap) VAL and cp0 register REG */ +#define _mips_mxc0(reg, val) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _mips_mfc0 (reg); \ + _mips_mtc0 (reg, (val)); \ + __o; \ +}) + +/* bit clear non-zero bits from CLR in cp0 register REG */ +#define _mips_bcc0(reg, clr) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _mips_mfc0 (reg); \ + _mips_mtc0 (reg, __o & ~(clr)); \ + __o; \ +}) + +/* bit set non-zero bits from SET in cp0 register REG */ +#define _mips_bsc0(reg, set) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _mips_mfc0 (reg); \ + _mips_mtc0 (reg, __o | (set)); \ + __o; \ +}) + +/* bit clear nz bits in from CLR and set nz bits from SET in REG */ +#define _mips_bcsc0(reg, clr, set) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _mips_mfc0 (reg); \ + _mips_mtc0 (reg, (__o & ~(clr)) | (set)); \ + __o; \ +}) + +/* + * Standard MIPS CP0 register access functions + */ + +/* CP0 Status register (NOTE: not atomic operations) */ +#define mips_getsr() _mips_mfc0(C0_SR) +#define mips_setsr(v) _mips_mtc0(C0_SR,v) +#define mips_xchsr(v) _mips_mxc0(C0_SR,v) +#define mips_bicsr(clr) _mips_bcc0(C0_SR,clr) +#define mips_bissr(set) _mips_bsc0(C0_SR,set) +#define mips_bcssr(c,s) _mips_bcsc0(C0_SR,c,s) + +/* CP0 Cause register (NOTE: not atomic operations) */ +#define mips_getcr() _mips_mfc0(C0_CR) +#define mips_setcr(v) _mips_mtc0(C0_CR,v) +#define mips_xchcr(v) _mips_mxc0(C0_CR,v) +#define mips_biccr(clr) _mips_bcc0(C0_CR,clr) +#define mips_biscr(set) _mips_bsc0(C0_CR,set) +#define mips_bcscr(c,s) _mips_bcsc0(C0_CR,c,s) + +/* CP0 PrID register */ +#define mips_getprid() _mips_mfc0(C0_PRID) + +#ifdef C0_COUNT +/* CP0 Count register */ +#define mips_getcount() _mips_mfc0(C0_COUNT) +#define mips_setcount(v) _mips_mtc0(C0_COUNT,v) +#define mips_xchcount(v) _mips_mxc0(C0_COUNT,v) +#endif + +#ifdef C0_COMPARE +/* CP0 Compare register*/ +#define mips_getcompare() _mips_mfc0(C0_COMPARE) +#define mips_setcompare(v) _mips_mtc0(C0_COMPARE,v) +#define mips_xchcompare(v) _mips_mxc0(C0_COMPARE,v) +#endif + +#ifdef C0_CONFIG +/* CP0 Config register */ +#define mips_getconfig() _mips_mfc0(C0_CONFIG) +#define mips_setconfig(v) _mips_mtc0(C0_CONFIG,v) +#define mips_xchconfig(v) _mips_mxc0(C0_CONFIG,v) +#define mips_bicconfig(c) _mips_bcc0(C0_CONFIG,c) +#define mips_bisconfig(s) _mips_bsc0(C0_CONFIG,s) +#define mips_bcsconfig(c,s) _mips_bcsc0(C0_CONFIG,c,s) +#endif + +#ifdef C0_ECC +/* CP0 ECC register */ +#define mips_getecc() _mips_mfc0(C0_ECC) +#define mips_setecc(x) _mips_mtc0(C0_ECC, x) +#define mips_xchecc(x) _mips_mxc0(C0_ECC, x) +#endif + +#ifdef C0_TAGLO +/* CP0 TagLo register */ +#define mips_gettaglo() _mips_mfc0(C0_TAGLO) +#define mips_settaglo(x) _mips_mtc0(C0_TAGLO, x) +#define mips_xchtaglo(x) _mips_mxc0(C0_TAGLO, x) +#endif + +#ifdef C0_TAGHI +/* CP0 TagHi register */ +#define mips_gettaghi() _mips_mfc0(C0_TAGHI) +#define mips_settaghi(x) _mips_mtc0(C0_TAGHI, x) +#define mips_xchtaghi(x) _mips_mxc0(C0_TAGHI, x) +#endif + +#ifdef C0_WATCHLO +/* CP0 WatchLo register */ +#define mips_getwatchlo() _mips_mfc0(C0_WATCHLO) +#define mips_setwatchlo(x) _mips_mtc0(C0_WATCHLO, x) +#define mips_xchwatchlo(x) _mips_mxc0(C0_WATCHLO, x) +#endif + +#ifdef C0_WATCHHI +/* CP0 WatchHi register */ +#define mips_getwatchhi() _mips_mfc0(C0_WATCHHI) +#define mips_setwatchhi(x) _mips_mtc0(C0_WATCHHI, x) +#define mips_xchwatchhi(x) _mips_mxc0(C0_WATCHHI, x) +#endif + +#endif /*_mips_mfc0*/ + +/* + * Count-leading zeroes and ones. + * Simulate with a function call if this CPU hasn't defined a + * macro with a suitable asm. + */ +#if !defined(mips_clz) +extern unsigned int _mips_clz(unsigned int); +#define mips_clz(x) _mips_clz(x) +#define mips_clo(x) _mips_clz(~(x)) +#else +#define _mips_have_clz 1 +#endif + +#if !defined(mips_dclz) +extern unsigned int _mips_dclz(unsigned long long); +#define mips_dclz(x) _mips_dclz(x) +#define mips_dclo(x) _mips_dclz(~(x)) +#else +#define _mips_have_dclz 1 +#endif + +/* + * Generic MIPS prefetch instruction for MIPS IV and + * above. CPU-specific include files must define + * prefetch "hint" codes. + */ +#if __mips >= 4 +#define _mips_pref(OP,LOC) \ +do { \ + __asm__ ("pref %0,%1" : : "n" (OP), "m" (LOC)); \ +} while (0) +#else +/* pref not available for MIPS16 */ +#define _mips_pref(OP,LOC) (void)0 +#endif + +#ifndef PREF_LOAD +#define PREF_LOAD 0 +#endif +#ifndef PREF_STORE +#define PREF_STORE 0 +#endif +#ifndef PREF_LOAD_STREAMED +#define PREF_LOAD_STREAMED PREF_LOAD +#define PREF_STORE_STREAMED PREF_STORE +#endif +#ifndef PREF_LOAD_RETAINED +#define PREF_LOAD_RETAINED PREF_LOAD +#define PREF_STORE_RETAINED PREF_STORE +#endif + +#define mips_prefetch __builtin_prefetch + +#ifdef PREF_WRITEBACK_INVAL +/* MIPS specific "nudge" (push to memory) operation */ +#define mips_nudge(ADDR) \ + _mips_pref(PREF_WRITEBACK_INVAL, *(ADDR)) +#else +#define mips_nudge(ADDR) (void)0 +#endif + +#ifdef PREF_PREPAREFORSTORE +/* MIPS specific "prepare for store" operation */ +/* XXX Warning - may zero whole cache line, ensure cache line alignment */ +#define mips_prepare_for_store(ADDR) \ + _mips_pref(PREF_PREPAREFORSTORE, *(ADDR)) +#else +#define mips_prepare_for_store(ADDR) (void)0 +#endif + +/* + * Default versions of get/put for any MIPS CPU. + */ +#ifndef mips_get_byte +#define mips_get_byte(addr, errp) (*(volatile unsigned char *)(addr)) +#define mips_get_half(addr, errp) (*(volatile unsigned short *)(addr)) +#define mips_get_word(addr, errp) (*(volatile unsigned int *)(addr)) +#define mips_get_dword(addr, errp) (*(volatile unsigned long long *)(addr)) + +#define mips_put_byte(addr, v) (*(volatile unsigned char *)(addr)=(v), 0) +#define mips_put_half(addr, v) (*(volatile unsigned short *)(addr)=(v), 0) +#define mips_put_word(addr, v) (*(volatile unsigned int *)(addr)=(v), 0) +#define mips_put_dword(addr, v) (*(volatile unsigned long long *)(addr)=(v), 0) +#endif /* mips_get_byte */ + +/* unoptimisable 2 instruction loop */ + +#define mips_cycle(count) \ + do { \ + unsigned int __count = (count); \ + __asm__ volatile ("%(nop; nop; 1: bnez %0,1b; subu %0,1%)" \ + : "+d" (__count)); \ + } while (0) + +/* default implementation of _mips_intdisable is a function */ + +/* There are no microMIPS implementations that support MSA currently. */ +#if !defined(__mips_micromips) +# define MIPS_MSA_USABLE 1 +#else +# define MIPS_MSA_USABLE 0 +#endif + +#else /* ASSEMBLER */ + +/* The correct way to use a hazard barrier return */ + +/* JR.HB does not resolve hazards from its delay slot. */ +#define MIPS_JRHB(REG) \ + .set push; \ + .set noreorder; \ + jr.hb REG; \ + nop; \ + .set pop + +#define MIPS_NOMICROMIPS \ + .set nomicromips + +#define MIPS_NOMIPS16 \ + .set nomips16 + +#endif /* !ASSEMBLER */ + +#ifdef __cplusplus +} +#endif +#endif /*_CPU_H_*/ diff --git a/libgloss/mips/include/mips/ctx.S b/libgloss/mips/include/mips/ctx.S new file mode 100644 index 0000000..74124d6 --- /dev/null +++ b/libgloss/mips/include/mips/ctx.S @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2016-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/regdef.h> +#include <mips/asm.h> +#include <mips/cpu.h> +#include <mips/hal.h> + +/* Save the hard context to a gp_ctx pointed to by k1. + Leave the value of C0_STATUS in the return register. + Leave the value of k1 unchanged. */ + +.macro _gpctx_save + /* Save general registers. */ + REG_S $1, CTX_REG(1) (k1) + REG_S $2, CTX_REG(2) (k1) + REG_S $3, CTX_REG(3) (k1) + REG_S $4, CTX_REG(4) (k1) + REG_S $5, CTX_REG(5) (k1) + REG_S $6, CTX_REG(6) (k1) + REG_S $7, CTX_REG(7) (k1) + REG_S $8, CTX_REG(8) (k1) + REG_S $9, CTX_REG(9) (k1) + REG_S $10, CTX_REG(10) (k1) + REG_S $11, CTX_REG(11) (k1) + REG_S $12, CTX_REG(12) (k1) + REG_S $13, CTX_REG(13) (k1) + REG_S $14, CTX_REG(14) (k1) + REG_S $15, CTX_REG(15) (k1) + REG_S $16, CTX_REG(16) (k1) + REG_S $17, CTX_REG(17)(k1) + REG_S $18, CTX_REG(18)(k1) + REG_S $19, CTX_REG(19)(k1) + REG_S $20, CTX_REG(20)(k1) + REG_S $21, CTX_REG(21)(k1) + REG_S $22, CTX_REG(22)(k1) + REG_S $23, CTX_REG(23)(k1) + REG_S $24, CTX_REG(24)(k1) + REG_S $25, CTX_REG(25)(k1) + REG_S $26, CTX_REG(26)(k1) + /* $27/k1 must be saved prior to using this macro. */ + REG_S $28, CTX_REG(28)(k1) + REG_S $29, CTX_REG(29)(k1) + REG_S $30, CTX_REG(30)(k1) + REG_S $31, CTX_REG(31)(k1) + PTR_S $0, CTX_LINK(k1) /* Clear the link field. */ + + /* Check ISA release and optionally restore HI/LO registers. */ +#if (__mips_isa_rev < 6) + mfhi $9 + REG_S $9, CTX_HI0(k1) + mflo $10 + REG_S $10, CTX_LO0(k1) +#endif + + /* Save CP0 registers. */ + PTR_MFC0 $31, C0_EPC + REG_S $31, CTX_EPC(k1) + mfc0 va0, C0_STATUS + sw va0, CTX_STATUS(k1) +.endm + +/* Restores a gp_ctx pointed to by a0. Leaves interrupts disabled and + C0_EPC ready to eret. */ + +.macro _gpctx_load + + /* Check ISA release and optionally restore HI/LO registers. */ +#if (__mips_isa_rev < 6) + REG_L $9, CTX_HI0(a0) + REG_L $10, CTX_LO0(a0) + mthi $9 + mtlo $10 +#endif + + /* Restore the general registers. */ + REG_L $1, CTX_REG(1)(a0) + REG_L $2, CTX_REG(2)(a0) + REG_L $3, CTX_REG(3)(a0) + /* Do not restore $4 until the end. */ + REG_L $5, CTX_REG(5)(a0) + REG_L $6, CTX_REG(6)(a0) + REG_L $7, CTX_REG(7)(a0) + REG_L $8, CTX_REG(8)(a0) + REG_L $9, CTX_REG(9)(a0) + REG_L $10, CTX_REG(10)(a0) + REG_L $11, CTX_REG(11)(a0) + REG_L $12, CTX_REG(12)(a0) + REG_L $13, CTX_REG(13)(a0) + REG_L $14, CTX_REG(14)(a0) + REG_L $15, CTX_REG(15)(a0) + REG_L $16, CTX_REG(16)(a0) + REG_L $17, CTX_REG(17)(a0) + REG_L $18, CTX_REG(18)(a0) + REG_L $19, CTX_REG(19)(a0) + REG_L $20, CTX_REG(20)(a0) + REG_L $21, CTX_REG(21)(a0) + REG_L $22, CTX_REG(22)(a0) + REG_L $23, CTX_REG(23)(a0) + REG_L $24, CTX_REG(24)(a0) + REG_L $25, CTX_REG(25)(a0) + + /* Restore CP0 registers, kernel registers and stack with + interrupts disabled. */ + di + lw $27, CTX_STATUS(a0) + REG_L $26, CTX_EPC(a0) + mtc0 $27, C0_STATUS + PTR_MTC0 $26, C0_EPC + ehb + + REG_L $26, CTX_REG(26)(a0) + REG_L $27, CTX_REG(27)(a0) + REG_L $28, CTX_REG(28)(a0) + REG_L $29, CTX_REG(29)(a0) + REG_L $30, CTX_REG(30)(a0) + REG_L $31, CTX_REG(31)(a0) + + /* Finally restore a0/$4. */ + REG_L $4, CTX_REG(4)(a0) + +.endm diff --git a/libgloss/mips/include/mips/dsp.h b/libgloss/mips/include/mips/dsp.h new file mode 100644 index 0000000..5d3b56c --- /dev/null +++ b/libgloss/mips/include/mips/dsp.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS_ASE_H_ +#define _MIPS_ASE_H_ + +/* 32-bit DSP Control register */ +#define DSPCTL_POS_SHIFT 0 +#define DSPCTL_POS_MASK 0x0000007f +#define DSPCTL_SCOUNT_SHIFT 7 +#define DSPCTL_SCOUNT_MASK 0x00001f80 +#define DSPCTL_C 0x00002000 +#define DSPCTL_OU_SHIFT 16 +#define DSPCTL_OU_MASK 0x00ff0000 +#define DSPCTL_OU_AC0OVF 0x00010000 +#define DSPCTL_OU_AC1OVF 0x00020000 +#define DSPCTL_OU_AC2OVF 0x00040000 +#define DSPCTL_OU_AC3OVF 0x00080000 +#define DSPCTL_OU_ALUOVF 0x00100000 +#define DSPCTL_OU_MULOVF 0x00200000 +#define DSPCTL_OU_SHFOVF 0x00400000 +#define DSPCTL_OU_EXTOVF 0x00800000 +#define DSPCTL_CCOND_SHIFT 24 +#define DSPCTL_CCOND_MASK 0x0f000000 + +/* RDDSP/WRDSP instruction mask bits */ +#define RWDSP_POS 0x01 +#define RWDSP_SCOUNT 0x02 +#define RWDSP_C 0x04 +#define RWDSP_OU 0x08 +#define RWDSP_CCOND 0x10 + +#endif /* _MIPS_DSP_H_ */ diff --git a/libgloss/mips/include/mips/endian.h b/libgloss/mips/include/mips/endian.h new file mode 100644 index 0000000..bb44217 --- /dev/null +++ b/libgloss/mips/include/mips/endian.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __MACHINE_ENDIAN_H__ +#error "must be included via <machine/endian.h>" +#endif /* !__MACHINE_ENDIAN_H__ */ + +#ifndef __ASSEMBLER__ +#include <stdint.h> /* get compiler types */ +#include <sys/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _BYTE_ORDER +/* + * Definitions for byte order, + * according to byte significance from low address to high. + */ +#define _LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */ +#define _BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ + +#if defined(__MIPSEB__) || defined(MIPSEB) +#define _BYTE_ORDER _BIG_ENDIAN +#elif defined(__MIPSEL__) || defined(MIPSEL) +#define _BYTE_ORDER _LITTLE_ENDIAN +#else +#error _BYTE_ORDER +#endif + +#ifndef __ASSEMBLER__ + +#if __mips_isa_rev >= 2 && ! __mips16 + +/* MIPS32r2 & MIPS64r2 can use the wsbh and rotate instructions, define + MD_SWAP so that <sys/endian.h> will use them. */ + +#define MD_SWAP + +#define __swap16md(x) __extension__({ \ + uint16_t __swap16md_x = (x); \ + uint16_t __swap16md_v; \ + __asm__ ("wsbh %0,%1" \ + : "=d" (__swap16md_v) \ + : "d" (__swap16md_x)); \ + __swap16md_v; \ +}) + +#define __swap32md(x) __extension__({ \ + uint32_t __swap32md_x = (x); \ + uint32_t __swap32md_v; \ + __asm__ ("wsbh %0,%1; rotr %0,16" \ + : "=d" (__swap32md_v) \ + : "d" (__swap32md_x)); \ + __swap32md_v; \ +}) + +#endif +#endif /* __ASSEMBLER__ */ +#endif /* _BYTE_ORDER */ + +#ifdef __cplusplus +} +#endif diff --git a/libgloss/mips/include/mips/fgregdef.h b/libgloss/mips/include/mips/fgregdef.h new file mode 100644 index 0000000..a03009f --- /dev/null +++ b/libgloss/mips/include/mips/fgregdef.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS_FPREGDEF_H_ +#define _MIPS_FPREGDEF_H_ + +/* result registers */ +#define fv0 $f0 +#define fv1 $f2 + +/* argument registers */ +#define fa0 $f12 +#if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \ + || (defined _ABI64 && _MIPS_SIM == _ABI64) +#define fa1 $f13 +#else +#define fa1 $f14 +#endif + +#if __mips_fpr == 64 + +/* 64-bit f.p. registers (-mips3 and above) */ + +/* temporary registers */ +#define ft0 $f4 +#define ft1 $f5 +#define ft2 $f6 +#define ft3 $f7 +#define ft4 $f8 +#define ft5 $f9 +#define ft6 $f10 +#define ft7 $f11 +#define ft8 $f16 +#define ft9 $f17 +#define ft10 $f18 +#define ft11 $f19 + +# if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \ + || (defined _ABI64 && _MIPS_SIM == _ABI64) +/* saved registers */ +# define fs0 $f20 +# define fs1 $f21 +# define fs2 $f22 +# define fs3 $f23 +# define fs4 $f24 +# define fs5 $f35 +# define fs6 $f26 +# define fs7 $f27 +# define fs8 $f28 +# define fs9 $f29 +# define fs10 $f30 +# define fs11 $f31 +# else +/* o32 FP64 */ +# define ft12 $f21 +# define ft13 $f23 +# define ft14 $f35 +# define ft15 $f27 +# define ft16 $f29 +# define ft17 $f31 +# define fs0 $f20 +# define fs1 $f22 +# define fs2 $f24 +# define fs3 $f26 +# define fs4 $f28 +# define fs5 $f30 +# endif + +#else + +/* 32-bit f.p. registers */ + +/* temporary registers */ +#define ft0 $f4 +#define ft1 $f5 +#define ft2 $f6 +#define ft3 $f7 +#define ft4 $f8 +#define ft5 $f9 +#define ft6 $f10 +#define ft7 $f11 +#define ft8 $f12 +#define ft9 $f13 +#define ft10 $f14 +#define ft11 $f15 +#define ft12 $f16 +#define ft13 $f17 +#define ft14 $f18 +#define ft15 $f19 + +/* saved registers */ +#define fs0 $f20 +#define fs1 $f22 +#define fs2 $f24 +#define fs3 $f26 +#define fs4 $f28 +#define fs5 $f30 + +#endif + +#endif /*_MIPS_FPREGDEF_H_*/ diff --git a/libgloss/mips/include/mips/fpa.h b/libgloss/mips/include/mips/fpa.h new file mode 100644 index 0000000..622a88a --- /dev/null +++ b/libgloss/mips/include/mips/fpa.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#if __mips == 32 || __mips == 64 +#include <mips/m32c1.h> +#endif diff --git a/libgloss/mips/include/mips/hal.h b/libgloss/mips/include/mips/hal.h new file mode 100644 index 0000000..31f614e --- /dev/null +++ b/libgloss/mips/include/mips/hal.h @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HAL_H +#define _HAL_H + +#include <mips/asm.h> +#include <mips/m32c0.h> + +#if _MIPS_SIM == _ABIO32 +#define UHI_ABI 0 +#elif _MIPS_SIM == _ABIN32 +#define UHI_ABI 1 +#elif _MIPS_SIM == _ABI64 +#define UHI_ABI 2 +#else +#error "UHI context structure is not defined for current ABI" +#endif + +#define CTX_REG(REGNO) ((SZREG)*((REGNO)-1)) + +#define CTX_AT (CTX_REG(1)) +#define CTX_V0 (CTX_REG(2)) +#define CTX_V1 (CTX_REG(3)) +#define CTX_A0 (CTX_REG(4)) +#define CTX_A1 (CTX_REG(5)) +#define CTX_A2 (CTX_REG(6)) +#define CTX_A3 (CTX_REG(7)) +#if _MIPS_SIM==_ABIN32 || _MIPS_SIM==_ABI64 || _MIPS_SIM==_ABIEABI +# define CTX_A4 (CTX_REG(8)) +# define CTX_A5 (CTX_REG(9)) +# define CTX_A6 (CTX_REG(10)) +# define CTX_A7 (CTX_REG(11)) +# define CTX_T0 (CTX_REG(12)) +# define CTX_T1 (CTX_REG(13)) +# define CTX_T2 (CTX_REG(14)) +# define CTX_T3 (CTX_REG(15)) +#else +# define CTX_T0 (CTX_REG(8)) +# define CTX_T1 (CTX_REG(9)) +# define CTX_T2 (CTX_REG(10)) +# define CTX_T3 (CTX_REG(11)) +# define CTX_T4 (CTX_REG(12)) +# define CTX_T5 (CTX_REG(13)) +# define CTX_T6 (CTX_REG(14)) +# define CTX_T7 (CTX_REG(15)) +#endif +#define CTX_S0 (CTX_REG(16)) +#define CTX_S1 (CTX_REG(17)) +#define CTX_S2 (CTX_REG(18)) +#define CTX_S3 (CTX_REG(19)) +#define CTX_S4 (CTX_REG(20)) +#define CTX_S5 (CTX_REG(21)) +#define CTX_S6 (CTX_REG(22)) +#define CTX_S7 (CTX_REG(23)) +#define CTX_T8 (CTX_REG(24)) +#define CTX_T9 (CTX_REG(25)) +#define CTX_K0 (CTX_REG(26)) +#define CTX_K1 (CTX_REG(27)) +#define CTX_GP (CTX_REG(28)) +#define CTX_SP (CTX_REG(29)) +#define CTX_FP (CTX_REG(30)) +#define CTX_RA (CTX_REG(31)) +#define CTX_EPC (CTX_REG(32)) +#define CTX_BADVADDR (CTX_REG(33)) +#define CTX_HI0 (CTX_REG(34)) +#define CTX_LO0 (CTX_REG(35)) +#define CTX_HILO_SIZE (2*SZREG) +#define CTX_LINK (CTX_REG(34)+CTX_HILO_SIZE) +#define CTX_STATUS ((CTX_REG(34))+CTX_HILO_SIZE+SZPTR) +#define CTX_CAUSE ((CTX_REG(34))+CTX_HILO_SIZE+SZPTR+4) +#define CTX_BADINSTR ((CTX_REG(34))+CTX_HILO_SIZE+SZPTR+8) +#define CTX_BADPINSTR ((CTX_REG(34))+CTX_HILO_SIZE+SZPTR+12) +#define CTX_SIZE ((CTX_REG(34))+CTX_HILO_SIZE+SZPTR+16) + +#define DSPCTX_DSPC ((SZREG)*2) +#define DSPCTX_HI1 ((SZREG)*3) +#define DSPCTX_HI2 ((SZREG)*4) +#define DSPCTX_HI3 ((SZREG)*5) +#define DSPCTX_LO1 ((SZREG)*6) +#define DSPCTX_LO2 ((SZREG)*7) +#define DSPCTX_LO3 ((SZREG)*8) +#define DSPCTX_SIZE ((SZREG)*9) + +#define FP32CTX_CSR ((SZREG)*2) +#define FP64CTX_CSR ((SZREG)*2) +#define MSACTX_FCSR ((SZREG)*2) +#define MSACTX_MSACSR ((SZREG)*3) + +#define MSACTX_0 ((SZREG)*4) +#define MSACTX_1 (MSACTX_0 + (1 * 16)) +#define MSACTX_2 (MSACTX_0 + (2 * 16)) +#define MSACTX_3 (MSACTX_0 + (3 * 16)) +#define MSACTX_4 (MSACTX_0 + (4 * 16)) +#define MSACTX_5 (MSACTX_0 + (5 * 16)) +#define MSACTX_6 (MSACTX_0 + (6 * 16)) +#define MSACTX_7 (MSACTX_0 + (7 * 16)) +#define MSACTX_8 (MSACTX_0 + (8 * 16)) +#define MSACTX_9 (MSACTX_0 + (9 * 16)) +#define MSACTX_10 (MSACTX_0 + (10 * 16)) +#define MSACTX_11 (MSACTX_0 + (11 * 16)) +#define MSACTX_12 (MSACTX_0 + (12 * 16)) +#define MSACTX_13 (MSACTX_0 + (13 * 16)) +#define MSACTX_14 (MSACTX_0 + (14 * 16)) +#define MSACTX_15 (MSACTX_0 + (15 * 16)) +#define MSACTX_16 (MSACTX_0 + (16 * 16)) +#define MSACTX_17 (MSACTX_0 + (17 * 16)) +#define MSACTX_18 (MSACTX_0 + (18 * 16)) +#define MSACTX_19 (MSACTX_0 + (19 * 16)) +#define MSACTX_20 (MSACTX_0 + (20 * 16)) +#define MSACTX_21 (MSACTX_0 + (21 * 16)) +#define MSACTX_22 (MSACTX_0 + (22 * 16)) +#define MSACTX_23 (MSACTX_0 + (23 * 16)) +#define MSACTX_24 (MSACTX_0 + (24 * 16)) +#define MSACTX_25 (MSACTX_0 + (25 * 16)) +#define MSACTX_26 (MSACTX_0 + (26 * 16)) +#define MSACTX_27 (MSACTX_0 + (27 * 16)) +#define MSACTX_28 (MSACTX_0 + (28 * 16)) +#define MSACTX_29 (MSACTX_0 + (29 * 16)) +#define MSACTX_30 (MSACTX_0 + (30 * 16)) +#define MSACTX_31 (MSACTX_0 + (31 * 16)) +#define MSACTX_SIZE (MSACTX_0 + (32 * 16)) + +#define FP32CTX_0 ((SZREG)*4) +#define FP32CTX_2 (FP32CTX_0 + (1 * 8)) +#define FP32CTX_4 (FP32CTX_0 + (2 * 8)) +#define FP32CTX_6 (FP32CTX_0 + (3 * 8)) +#define FP32CTX_8 (FP32CTX_0 + (4 * 8)) +#define FP32CTX_10 (FP32CTX_0 + (5 * 8)) +#define FP32CTX_12 (FP32CTX_0 + (6 * 8)) +#define FP32CTX_14 (FP32CTX_0 + (7 * 8)) +#define FP32CTX_16 (FP32CTX_0 + (8 * 8)) +#define FP32CTX_18 (FP32CTX_0 + (9 * 8)) +#define FP32CTX_20 (FP32CTX_0 + (10 * 8)) +#define FP32CTX_22 (FP32CTX_0 + (11 * 8)) +#define FP32CTX_24 (FP32CTX_0 + (12 * 8)) +#define FP32CTX_26 (FP32CTX_0 + (13 * 8)) +#define FP32CTX_28 (FP32CTX_0 + (14 * 8)) +#define FP32CTX_30 (FP32CTX_0 + (15 * 8)) +#define FP32CTX_SIZE (FP32CTX_30 + (17 * 8)) + +#define FP64CTX_0 ((SZREG)*4) +#define FP64CTX_2 (FP64CTX_0 + (1 * 8)) +#define FP64CTX_4 (FP64CTX_0 + (2 * 8)) +#define FP64CTX_6 (FP64CTX_0 + (3 * 8)) +#define FP64CTX_8 (FP64CTX_0 + (4 * 8)) +#define FP64CTX_10 (FP64CTX_0 + (5 * 8)) +#define FP64CTX_12 (FP64CTX_0 + (6 * 8)) +#define FP64CTX_14 (FP64CTX_0 + (7 * 8)) +#define FP64CTX_16 (FP64CTX_0 + (8 * 8)) +#define FP64CTX_18 (FP64CTX_0 + (9 * 8)) +#define FP64CTX_20 (FP64CTX_0 + (10 * 8)) +#define FP64CTX_22 (FP64CTX_0 + (11 * 8)) +#define FP64CTX_24 (FP64CTX_0 + (12 * 8)) +#define FP64CTX_26 (FP64CTX_0 + (13 * 8)) +#define FP64CTX_28 (FP64CTX_0 + (14 * 8)) +#define FP64CTX_30 (FP64CTX_0 + (15 * 8)) +#define FP64CTX_1 (FP64CTX_30 + (1 * 8)) +#define FP64CTX_3 (FP64CTX_30 + (2 * 8)) +#define FP64CTX_5 (FP64CTX_30 + (3 * 8)) +#define FP64CTX_7 (FP64CTX_30 + (4 * 8)) +#define FP64CTX_9 (FP64CTX_30 + (5 * 8)) +#define FP64CTX_11 (FP64CTX_30 + (6 * 8)) +#define FP64CTX_13 (FP64CTX_30 + (7 * 8)) +#define FP64CTX_15 (FP64CTX_30 + (8 * 8)) +#define FP64CTX_17 (FP64CTX_30 + (9 * 8)) +#define FP64CTX_19 (FP64CTX_30 + (10 * 8)) +#define FP64CTX_21 (FP64CTX_30 + (11 * 8)) +#define FP64CTX_23 (FP64CTX_30 + (12 * 8)) +#define FP64CTX_25 (FP64CTX_30 + (13 * 8)) +#define FP64CTX_27 (FP64CTX_30 + (14 * 8)) +#define FP64CTX_29 (FP64CTX_30 + (15 * 8)) +#define FP64CTX_31 (FP64CTX_30 + (16 * 8)) +#define FP64CTX_SIZE (FP64CTX_31 + (17 * 8)) + +#define FPCTX_SIZE() (mips_getsr() & SR_FR ? FP64CTX_SIZE : FP32CTX_SIZE) + +#define XPACTX_BADVADDR ((SZREG)*2) + +#define LINKCTX_TYPE_MSA 0x004D5341 +#define LINKCTX_TYPE_FP32 0x46503332 +#define LINKCTX_TYPE_FP64 0x46503634 +#define LINKCTX_TYPE_FMSA 0x463D5341 +#define LINKCTX_TYPE_DSP 0x00445350 +#define LINKCTX_TYPE_STKSWP 0x53574150 +#define LINKCTX_TYPE_XPA 0x00585041 + +#define LINKCTX_ID ((SZREG)*0) +#define LINKCTX_NEXT ((SZREG)*1) + +#define LINKCTX_TYPE(X) (((struct linkctx *)(X))->id) + +#define SWAPCTX_OLDSP ((SZREG)*2) +#define SWAPCTX_SIZE ((SZREG)*3) + +#if !defined(__ASSEMBLER__) + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct linkctx; + +#define C_CTX_REGNO(REGNO) ((REGNO) - 1) + +struct gpctx +{ + union + { + struct + { + reg_t at; + reg_t v[2]; +# if _MIPS_SIM==_ABIN32 || _MIPS_SIM==_ABI64 || _MIPS_SIM==_ABIEABI + reg_t a[8]; + reg_t t[4]; +# else + reg_t a[4]; + reg_t t[8]; +# endif + reg_t s[8]; + reg_t t2[2]; + reg_t k[2]; + reg_t gp; + reg_t sp; + reg_t fp; + reg_t ra; + }; + reg_t r[31]; + }; + + reg_t epc; + reg_t badvaddr; + reg_t hi; + reg_t lo; + /* This field is for future extension */ + struct linkctx *link; + /* Status at the point of the exception. This may not be restored + on return from exception if running under an RTOS */ + uint32_t status; + /* These fields should be considered read-only */ + uint32_t cause; + uint32_t badinstr; + uint32_t badpinstr; +}; + +struct linkctx +{ + reg_t id; + struct linkctx *next; +}; + +struct swapctx +{ + struct linkctx link; + reg_t oldsp; +}; + +static inline void +_linkctx_append (struct gpctx *gp, struct linkctx *nu) +{ + struct linkctx **ctx = (struct linkctx **)&gp->link; + while (*ctx) + ctx = &(*ctx)->next; + *ctx = nu; +} + +struct dspctx +{ + struct linkctx link; + reg_t dspc; + reg_t hi[3]; + reg_t lo[3]; +}; + +struct fpctx +{ + struct linkctx link; + reg_t fcsr; + reg_t reserved; +}; + +typedef char _msareg[16] __attribute__ ((aligned(16))); + +struct msactx +{ + struct linkctx link; + reg_t fcsr; + reg_t msacsr; + union + { + _msareg w[32]; + double d[64]; + float s[128]; + }; +}; + +#define MSAMSACTX_D(CTX, N) (CTX)->w[(N)] +#define MSACTX_DBL(CTX, N) (CTX)->d[(N) << 1] +#ifdef __MIPSEL__ +#define MSACTX_SGL(CTX, N) (CTX)->s[(N) << 2] +#else +#define MSACTX_SGL(CTX, N) (CTX)->s[((N) << 2) | 1] +#endif + +struct fp32ctx +{ + struct fpctx fp; + union + { + double d[16]; /* even doubles */ + float s[32]; /* even singles, padded */ + }; +}; + +#define FP32CTX_DBL(CTX, N) (CTX)->d[(N)] +#ifdef __MIPSEL__ +#define FP32CTX_SGL(CTX, N) (CTX)->s[(N)] +#else +#define FP32CTX_SGL(CTX, N) (CTX)->s[(N) ^ 1] +#endif + +struct fp64ctx +{ + struct fpctx fp; + union + { + double d[32]; /* even doubles, followed by odd doubles */ + float s[64]; /* even singles, followed by odd singles, padded */ + }; +}; + +#define FP64CTX_DBL(CTX, N) (CTX)->d[((N) >> 1) + (((N) & 1) << 4)] +#ifdef __MIPSEL__ +#define FP64CTX_SGL(CTX, N) (CTX)->s[((N) & ~1) + (((N) & 1) << 5)] +#else +#define FP64CTX_SGL(CTX, N) (CTX)->s[((N) | 1) + (((N) & 1) << 5)] +#endif + +struct xpactx +{ + struct linkctx link; + reg64_t badvaddr; +}; + +#ifdef __mips16 +# define _MIPS_HAL_NOMIPS16 __attribute__((nomips16)) +#else +# define _MIPS_HAL_NOMIPS16 +#endif + +extern reg_t _MIPS_HAL_NOMIPS16 + _dspctx_save (struct dspctx *ptr); +extern reg_t _MIPS_HAL_NOMIPS16 + _dspctx_load (struct dspctx *ptr); + +extern reg_t _MIPS_HAL_NOMIPS16 + _xpa_save (struct xpactx *ptr); + +extern reg_t _MIPS_HAL_NOMIPS16 + _fpctx_save (struct fpctx *ptr); +extern reg_t _MIPS_HAL_NOMIPS16 + _fpctx_load (struct fpctx *ptr); +extern reg_t _MIPS_HAL_NOMIPS16 + _msactx_save (struct msactx *ptr); +extern reg_t _MIPS_HAL_NOMIPS16 + _msactx_load (struct msactx *ptr); + +/* Fall back exception handlers: + _mips_handle_exception - May be implemented by a user but is aliased + to __exception_handle by default. + __exception_handle - Toolchain provided fallback handler. +*/ +extern void _MIPS_HAL_NOMIPS16 + _mips_handle_exception (struct gpctx *ctx, int exception); +extern void _MIPS_HAL_NOMIPS16 + __exception_handle (struct gpctx *ctx, int exception); + +/* Obtain the largest available region of RAM */ +extern void _MIPS_HAL_NOMIPS16 + _get_ram_range (void **ram_base, void **ram_extent); + +/* Invoke a UHI operation via SDBBP using the provided context */ +extern int _MIPS_HAL_NOMIPS16 + __uhi_indirect (struct gpctx *); + +/* Report an unhandled exception */ +extern int32_t _MIPS_HAL_NOMIPS16 + __uhi_exception (struct gpctx *, int32_t); + +/* Print a message to a logger. Minimal formatting support for one + integer argument. */ +extern int32_t _MIPS_HAL_NOMIPS16 + __plog (int8_t *, int32_t); + +/* Boot context support functions */ +extern int _MIPS_HAL_NOMIPS16 + __get_startup_BEV (void) __attribute__((weak)); +extern int _MIPS_HAL_NOMIPS16 + __chain_uhi_excpt (struct gpctx *) __attribute__((weak)); + +/* Emergency exit, use it when unrecoverable errors occur */ +extern int _MIPS_HAL_NOMIPS16 + __exit (int); + +/* UHI assert support. This function can return. */ +extern void _MIPS_HAL_NOMIPS16 + __uhi_assert (const char *, const char *, int32_t); + +/* Forward a breakpoint exception to boot. */ +extern int _MIPS_HAL_NOMIPS16 + __uhi_break (struct gpctx *) __attribute__((weak)); + +#ifdef NDEBUG /* required by ANSI standard */ +# define uhi_assert(__e) ((void)0) +#else +# define uhi_assert(__e) ((__e) ? (void)0 : \ + __uhi_assert (#__e, __FILE__, __LINE__)) +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _HAL_H diff --git a/libgloss/mips/include/mips/intctrl.h b/libgloss/mips/include/mips/intctrl.h new file mode 100644 index 0000000..866e167 --- /dev/null +++ b/libgloss/mips/include/mips/intctrl.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <mips/hal.h> +#include <stdint.h> +#include <stdbool.h> + +/* + * Use the macros themselves for idempotency to ease replacement at the OS + * level. + */ +#ifndef _mips_intpatch +/* + * Install a handler into the template vector code by patching the address + * calculation instructions. The INDEX is the interrupt number with SW0 + * being index 0 and HW5 being index 7, this also applies to EIC vectors + * where the INDEX represents the vector number. K1_TO_KSCRATCH1 should be + * set if an instruction should be injected to move K1 to KSCRATCH1 before + * clobbering it. + */ +_MIPS_HAL_NOMIPS16 +void _mips_intpatch (const reg_t index, const uintptr_t handler, + bool k1_to_kscratch1); +#endif /* _mips_intpatch */ + +#ifndef _mips_intmask +/* + * Enable or disable an interrupt at INDEX where INDEX has the same meaning + * as in _mips_intpatch. Returns nonzero if the interrupt was already + * enabled. + */ +_MIPS_HAL_NOMIPS16 +reg_t _mips_intmask (const reg_t index, const reg_t enable); +#endif /* _mips_intmask */ + +#ifndef _mips_intack +/* + * Acknowledge (clear) an interrupt at INDEX where INDEX has the same meaning + * as in _mips_intpatch. Returns nonzero if the interrupt needed + * acknowledging. + */ +_MIPS_HAL_NOMIPS16 +reg_t _mips_intack (const reg_t index); +#endif /* _mips_intack */ diff --git a/libgloss/mips/include/mips/m32c0.h b/libgloss/mips/include/mips/m32c0.h new file mode 100644 index 0000000..6ed8319 --- /dev/null +++ b/libgloss/mips/include/mips/m32c0.h @@ -0,0 +1,1605 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _M32C0_H_ +#define _M32C0_H_ + +#ifndef _M64C0_H_ +/* MIPS32-specific MMU interface */ +#include <mips/m32tlb.h> +#endif +/* + * MIPS32 Exception Codes + */ +#define EXC_INTR 0 /* interrupt */ +#define EXC_MOD 1 /* tlb modification */ +#define EXC_TLBL 2 /* tlb miss (load/i-fetch) */ +#define EXC_TLBS 3 /* tlb miss (store) */ +#define EXC_ADEL 4 /* address error (load/i-fetch) */ +#define EXC_ADES 5 /* address error (store) */ +#define EXC_IBE 6 /* bus error (i-fetch) */ +#define EXC_DBE 7 /* data bus error (load/store) */ +#define EXC_SYS 8 /* system call */ +#define EXC_BP 9 /* breakpoint */ +#define EXC_RI 10 /* reserved instruction */ +#define EXC_CPU 11 /* coprocessor unusable */ +#define EXC_OVF 12 /* integer overflow */ +#define EXC_TRAP 13 /* trap exception */ +#define EXC_MSAFPE 14 /* MSA floating point exception */ +#define EXC_FPE 15 /* floating point exception */ +#define EXC_IS1 16 /* implementation-specific 1 */ +#define EXC_IS2 17 /* implementation-specific 2 */ +#define EXC_C2E 18 /* coprocessor 2 exception */ +#define EXC_TLBRI 19 /* TLB read inhibit */ +#define EXC_TLBXI 20 /* TLB execute inhibit */ +#define EXC_MSAU 21 /* MSA unusable exception */ +#define EXC_MDMX 22 /* mdmx unusable */ +#define EXC_WATCH 23 /* watchpoint */ +#define EXC_MCHECK 24 /* machine check */ +#define EXC_THREAD 25 /* thread */ +#define EXC_DSPU 26 /* dsp unusable */ +#define EXC_RES27 27 +#define EXC_RES28 28 +#define EXC_RES29 29 +#define EXC_RES30 30 +#define EXC_RES31 31 + + +/* + * MIPS32 Cause Register (CP0 Register 13, Select 0) + */ +#define CR_BD 0x80000000 /* branch delay */ +#define CR_BD_SHIFT 31 +#define CR_TI 0x40000000 /* timer interrupt (r2) */ +#define CR_TI_SHIFT 30 +#define CR_CEMASK 0x30000000 /* coprocessor used */ +#define CR_CESHIFT 28 +#define CR_CE_SHIFT 28 +#define CR_CE_BITS 2 +#define CR_DC 0x08000000 /* disable count (r2) */ +#define CR_DC_SHIFT 27 +#define CR_PCI 0x04000000 /* performance counter i/u (r2) */ +#define CR_PCI_SHIFT 26 +#define CR_IV 0x00800000 /* use special i/u vec */ +#define CR_IV_SHIFT 23 +#define CR_WP 0x00400000 /* deferred watchpoint */ +#define CR_WP_SHIFT 22 +#define CR_FDCI 0x00200000 /* fast debug channned i/u (r2) */ +#define CR_FDCI_SHIFT 21 + +#define CR_IMASK 0x0000ff00 /* interrupt pending mask */ +#define CR_IP_MASK 0x0000ff00 +#define CR_IP_SHIFT 8 +#define CR_IP_BITS 8 +#define CR_RIPL 0x0000fc00 +#define CR_RIPL_SHIFT 10 +#define CR_RIPL_BITS 6 + +/* interrupt pending bits */ +#define CR_HINT5 0x00008000 /* h/w interrupt 5 */ +#define CR_HINT4 0x00004000 /* h/w interrupt 4 */ +#define CR_HINT3 0x00002000 /* h/w interrupt 3 */ +#define CR_HINT2 0x00001000 /* h/w interrupt 2 */ +#define CR_HINT1 0x00000800 /* h/w interrupt 1 */ +#define CR_HINT0 0x00000400 /* h/w interrupt 0 */ +#define CR_SINT1 0x00000200 /* s/w interrupt 1 */ +#define CR_SINT0 0x00000100 /* s/w interrupt 0 */ + +/* alternative interrupt pending bit naming */ +#define CR_IP7 0x00008000 +#define CR_IP6 0x00004000 +#define CR_IP5 0x00002000 +#define CR_IP4 0x00001000 +#define CR_IP3 0x00000800 +#define CR_IP2 0x00000400 +#define CR_IP1 0x00000200 +#define CR_IP0 0x00000100 + +#define CR_XMASK 0x0000007c /* exception code mask */ +#define CR_X_MASK 0x0000007c +#define CR_X_SHIFT 2 +#define CR_X_BITS 5 +#define CR_XCPT(x) ((x)<<2) + +/* + * MIPS32 Status Register (CP0 Register 12, Select 0) + */ +#define SR_CU3 0x80000000 /* coprocessor 3 enable */ +#define SR_CU3_SHIFT 31 +#define SR_CU2 0x40000000 /* coprocessor 2 enable */ +#define SR_CU2_SHIFT 30 +#define SR_CU1 0x20000000 /* coprocessor 1 enable */ +#define SR_CU1_SHIFT 29 +#define SR_CU0 0x10000000 /* coprocessor 0 enable */ + +#define SR_RP 0x08000000 /* reduce power */ +#define SR_RP_SHIFT 27 +#define SR_FR 0x04000000 /* 64-bit fpu registers */ +#define SR_FR_SHIFT 26 +#define SR_RE 0x02000000 /* reverse endian (user mode) */ +#define SR_RE_SHIFT 25 +#define SR_MX 0x01000000 /* enable MDMX/DSP ASE */ +#define SR_MX_SHIFT 24 +#define SR_PX 0x00800000 /* user 64-bit reg / 32-bit addr */ +#define SR_PX_SHIFT 23 +#define SR_BEV 0x00400000 /* boot exception vectors */ +#define SR_BEV_SHIFT 22 +#define SR_TS 0x00200000 /* TLB shutdown */ +#define SR_TS_SHIFT 21 +#define SR_SR 0x00100000 /* soft reset occurred */ +#define SR_PE 0x00100000 /* soft reset (clear parity error) */ +#define SR_SR_SHIFT 20 +#define SR_NMI 0x00080000 /* NMI occurred */ +#define SR_NMI_SHIFT 19 +#define SR_MCU 0x00040000 /* MCU ASE implemented */ +#define SR_MCU_SHIFT 18 + +#define SR_IPL_MASK 0x0000fc00 +#define SR_IPL_SHIFT 10 +#define SR_IPL_BITS 6 +#define SR_IMASK 0x0000ff00 + +/* interrupt mask bits */ +#define SR_HINT5 0x00008000 /* enable h/w interrupt 6 */ +#define SR_HINT4 0x00004000 /* enable h/w interrupt 5 */ +#define SR_HINT3 0x00002000 /* enable h/w interrupt 4 */ +#define SR_HINT2 0x00001000 /* enable h/w interrupt 3 */ +#define SR_HINT1 0x00000800 /* enable h/w interrupt 2 */ +#define SR_HINT0 0x00000400 /* enable h/w interrupt 1 */ +#define SR_SINT1 0x00000200 /* enable s/w interrupt 1 */ +#define SR_SINT0 0x00000100 /* enable s/w interrupt 0 */ + +/* alternative interrupt mask naming */ +#define SR_IM9 0x00040000 /* 1st MUCON ASE interrupt */ +#define SR_IM8 0x00010000 /* 2nd MUCON ASE interrupt */ +#define SR_IM7 0x00008000 +#define SR_IM6 0x00004000 +#define SR_IM5 0x00002000 +#define SR_IM4 0x00001000 +#define SR_IM3 0x00000800 +#define SR_IM2 0x00000400 +#define SR_IM1 0x00000200 +#define SR_IM0 0x00000100 + +#define SR_KX 0x00000080 /* 64-bit kernel mode */ +#define SR_KX_SHIFT 7 +#define SR_SX 0x00000040 /* 64-bit supervisor mode */ +#define SR_SX_SHIFT 6 +#define SR_UX 0x00000020 /* 64-bit user mode */ +#define SR_UX_SHIFT 5 + +#define SR_UM 0x00000010 /* user mode */ +#define SR_KSU_MASK 0x00000018 /* ksu mode mask */ +#define SR_KSU_SHIFT 3 +#define SR_KSU_BITS 2 +#define SR_KSU_USER 0x00000010 /* user mode */ +#define SR_KSU_SPVS 0x00000008 /* supervisor mode */ +#define SR_KSU_KERN 0x00000000 /* kernel mode */ + +#define SR_ERL 0x00000004 /* error level */ +#define SR_ERL_SHIFT 2 +#define SR_EXL 0x00000002 /* exception level */ +#define SR_EXL_SHIFT 1 +#define SR_IE 0x00000001 /* interrupt enable */ +#define SR_IE_SHIFT 0 + +/* + * MIPS32r6 VPControl (CP0 Register 0, Select 4) + */ +#define VPCONTROL_DIS 0x00000001 +#define VPCONTROL_SHIFT 0 + +/* + * MIPS32r2 HWREna Register (CP0 Register 7, Select 0) + */ +#define HWRENA_ULR 0x20000000 +#define HWRENA_XNP 0x00000020 +#define HWRENA_PERFCNT 0x00000010 +#define HWRENA_CCRES 0x00000008 +#define HWRENA_CC 0x00000004 +#define HWRENA_SYNCSTEP 0x00000002 +#define HWRENA_CPUNUM 0x00000001 + +/* + * MIPS32r2 IntCtl Register (CP0 Register 12, Select 1) + */ +#define INTCTL_IPTI 0xe0000000 /* timer i/u pending bit */ +#define INTCTL_IPTI_SHIFT 29 +#define INTCTL_IPTI_BITS 3 +#define INTCTL_IPPCI 0x1c000000 /* perfctr i/u pending bit */ +#define INTCTL_IPPCI_SHIFT 26 +#define INTCTL_IPPCI_BITS 3 +#define INTCTL_IPFDC 0x03800000 /* fast debug chan i/u pending bit */ +#define INTCTL_IPFDC_SHIFT 23 +#define INTCTL_IPFDC_BITS 3 +#define INTCTL_VS 0x000003e0 /* vector spacing */ +#define INTCTL_VS_SHIFT 5 +#define INTCTL_VS_BITS 5 +#define INTCTL_VS_0 (0x00 << INTCTL_VS_SHIFT) +#define INTCTL_VS_32 (0x01 << INTCTL_VS_SHIFT) +#define INTCTL_VS_64 (0x02 << INTCTL_VS_SHIFT) +#define INTCTL_VS_128 (0x04 << INTCTL_VS_SHIFT) +#define INTCTL_VS_256 (0x08 << INTCTL_VS_SHIFT) +#define INTCTL_VS_512 (0x10 << INTCTL_VS_SHIFT) + +/* + * MIPS32r2 SRSCtl Register (CP0 Register 12, Select 2) + */ +#define SRSCTL_HSS 0x3c000000 /* highest shadow set */ +#define SRSCTL_HSS_SHIFT 26 +#define SRSCTL_EICSS 0x003c0000 /* EIC shadow set */ +#define SRSCTL_EICSS_SHIFT 18 +#define SRSCTL_ESS 0x0000f000 /* exception shadow set */ +#define SRSCTL_ESS_SHIFT 12 +#define SRSCTL_PSS 0x000003c0 /* previous shadow set */ +#define SRSCTL_PSS_SHIFT 6 +#define SRSCTL_CSS 0x0000000f /* current shadow set */ +#define SRSCTL_CSS_SHIFT 0 + +/* + * MIPS32 BEVVA Register (CP0 Register 15, Select 4) + */ +#define BEVVA_BASE_MASK 0xfffff000 +#define BEVVA_BASE_SHIFT 12 +#define BEVVA_MASK_MASK 0x00000fff +#define BEVVA_MASK_SHIFT 0 + +/* + * MIPS32 Config0 Register (CP0 Register 16, Select 0) + */ +#define CFG0_M 0x80000000 /* Config1 implemented */ +#define CFG0_M_SHIFT 31 +#define CFG0_K23_MASK 0x70000000 /* Fixed MMU kseg2/3 CCA */ +#define CFG0_K23_SHIFT 28 +#define CFG0_KU_MASK 0x0e000000 /* Fixed MMU kuseg CCA */ +#define CFG0_KU_SHIFT 25 +#define CFG0_BE 0x00008000 /* Big Endian */ +#define CFG0_BE_SHIFT 15 +#define CFG0_AT_MASK 0x00006000 /* Architecture type: */ +#define CFG0_ATMASK 0x00006000 +#define CFG0_AT_SHIFT 13 +#define CFG0_AT_BITS 2 +#define CFG0_AT_M32 (0 << CFG0_AT_SHIFT) /* MIPS32 */ +#define CFG0_AT_M64_A32 (1 << CFG0_AT_SHIFT) /* MIPS64, 32-bit addresses */ +#define CFG0_AT_M64_A64 (2 << CFG0_AT_SHIFT) /* MIPS64, 64-bit addresses */ +#define CFG0_AT_RES (3 << CFG0_AT_SHIFT) +#define CFG0_AR_MASK 0x00001c00 +#define CFG0_ARMASK 0x00001c00 +#define CFG0_AR_SHIFT 10 +#define CFG0_ARSHIFT 10 +#define CFG0_AR_BITS 3 +#define CFG0_AR_R1 (0 << CFG0_AR_SHIFT) /* Release 1 */ +#define CFG0_AR_R2 (1 << CFG0_AR_SHIFT) /* Release 2,3,5 */ +#define CFG0_AR_R6 (2 << CFG0_AR_SHIFT) /* Release 6 */ +#define CFG0_MT_MASK 0x00000380 /* MMU Type: */ +#define CFG0_MTMASK 0x00000380 +#define CFG0_MT_SHIFT 7 +#define CFG0_MT_BITS 3 +#define CFG0_MT_NONE (0 << CFG0_MT_SHIFT) /* No MMU */ +#define CFG0_MT_TLB (1 << CFG0_MT_SHIFT) /* Standard TLB */ +#define CFG0_MT_BAT (2 << CFG0_MT_SHIFT) /* BAT */ +#define CFG0_MT_FIXED (3 << CFG0_MT_SHIFT) /* Fixed mapping */ +#define CFG0_MT_NONSTD (3 << CFG0_MT_SHIFT) /* Legacy */ +#define CFG0_MT_DUAL (4 << CFG0_MT_SHIFT) /* Dual VTLB and FTLB */ +#define CFG0_VI 0x00000008 /* Icache is virtual */ +#define CFG0_VI_SHIFT 3 +#define CFG0_K0_MASK 0x00000007 /* KSEG0 coherency algorithm */ +#define CFG0_K0MASK 0x00000007 +#define CFG0_K0_SHIFT 0 +#define CFG0_K0_BITS 3 + +/* + * MIPS32 Config1 Register (CP0 Register 16, Select 1) + */ +#define CFG1_M 0x80000000 /* Config2 implemented */ +#define CFG1_M_SHIFT 31 +#define CFG1_MMUS_MASK 0x7e000000 /* mmu size - 1 */ +#define CFG1_MMUSMASK 0x7e000000 +#define CFG1_MMUS_SHIFT 25 +#define CFG1_MMUSSHIFT 25 +#define CFG1_MMUS_BITS 6 +#define CFG1_IS_MASK 0x01c00000 /* icache lines 64<<n */ +#define CFG1_ISMASK 0x01c00000 +#define CFG1_IS_SHIFT 22 /* Unless n==7, then 32 */ +#define CFG1_ISSHIFT 22 +#define CFG1_IS_BITS 3 +#define CFG1_IL_MASK 0x00380000 /* icache line size 2<<n */ +#define CFG1_ILMASK 0x00380000 +#define CFG1_IL_SHIFT 19 +#define CFG1_ILSHIFT 19 +#define CFG1_IL_BITS 3 +#define CFG1_IA_MASK 0x00070000 /* icache ways - 1 */ +#define CFG1_IAMASK 0x00070000 +#define CFG1_IA_SHIFT 16 +#define CFG1_IASHIFT 16 +#define CFG1_IA_BITS 3 +#define CFG1_DS_MASK 0x0000e000 /* dcache lines 64<<n */ +#define CFG1_DSMASK 0x0000e000 +#define CFG1_DS_SHIFT 13 +#define CFG1_DSSHIFT 13 +#define CFG1_DS_BITS 3 +#define CFG1_DL_MASK 0x00001c00 /* dcache line size 2<<n */ +#define CFG1_DLMASK 0x00001c00 +#define CFG1_DL_SHIFT 10 +#define CFG1_DLSHIFT 10 +#define CFG1_DL_BITS 3 +#define CFG1_DA_MASK 0x00000380 /* dcache ways - 1 */ +#define CFG1_DAMASK 0x00000380 +#define CFG1_DA_SHIFT 7 +#define CFG1_DASHIFT 7 +#define CFG1_DA_BITS 3 +#define CFG1_C2 0x00000040 /* Coprocessor 2 present */ +#define CFG1_C2_SHIFT 6 +#define CFG1_MD 0x00000020 /* MDMX implemented */ +#define CFG1_MD_SHIFT 5 +#define CFG1_PC 0x00000010 /* performance counters implemented */ +#define CFG1_PC_SHIFT 4 +#define CFG1_WR 0x00000008 /* watch registers implemented */ +#define CFG1_WR_SHIFT 3 +#define CFG1_CA 0x00000004 /* compression (mips16) implemented */ +#define CFG1_CA_SHIFT 2 +#define CFG1_EP 0x00000002 /* ejtag implemented */ +#define CFG1_EP_SHIFT 1 +#define CFG1_FP 0x00000001 /* fpu implemented */ +#define CFG1_FP_SHIFT 0 + + +/* + * MIPS32r2 Config2 Register (CP0 Register 16, Select 2) + */ +#define CFG2_M 0x80000000 /* Config3 implemented */ +#define CFG1_M_SHIFT 31 +#define CFG2_TU_MASK 0x70000000 /* tertiary cache control */ +#define CFG2_TUMASK 0x70000000 +#define CFG2_TU_SHIFT 28 +#define CFG2_TUSHIFT 28 +#define CFG2_TU_BITS 3 +#define CFG2_TS_MASK 0x0f000000 /* tcache sets per wway 64<<n */ +#define CFG2_TSMASK 0x0f000000 +#define CFG2_TS_SHIFT 24 +#define CFG2_TSSHIFT 24 +#define CFG2_TS_BITS 4 +#define CFG2_TL_MASK 0x00f00000 /* tcache line size 2<<n */ +#define CFG2_TLMASK 0x00f00000 +#define CFG2_TL_SHIFT 20 +#define CFG2_TLSHIFT 20 +#define CFG2_TL_BITS 4 +#define CFG2_TA_MASK 0x000f0000 /* tcache ways - 1 */ +#define CFG2_TAMASK 0x000f0000 +#define CFG2_TA_SHIFT 16 +#define CFG2_TASHIFT 16 +#define CFG2_TA_BITS 4 +#define CFG2_SU_MASK 0x0000f000 /* secondary cache control */ +#define CFG2_SUMASK 0x0000f000 +#define CFG2_SU_SHIFT 12 +#define CFG2_SUSHIFT 12 +#define CFG2_SU_BITS 4 +#define CFG2_SS_MASK 0x00000f00 /* scache sets per wway 64<<n */ +#define CFG2_SSMASK 0x00000f00 +#define CFG2_SS_SHIFT 8 +#define CFG2_SSSHIFT 8 +#define CFG2_SS_BITS 4 +#define CFG2_SL_MASK 0x000000f0 /* scache line size 2<<n */ +#define CFG2_SLMASK 0x000000f0 +#define CFG2_SL_SHIFT 4 +#define CFG2_SLSHIFT 4 +#define CFG2_SL_BITS 4 +#define CFG2_SA_MASK 0x0000000f /* scache ways - 1 */ +#define CFG2_SAMASK 0x0000000f +#define CFG2_SA_SHIFT 0 +#define CFG2_SASHIFT 0 +#define CFG2_SA_BITS 4 + +/* + * MIPS32r2 Config3 Register (CP0 Register 16, Select 3) + */ +#define CFG3_M 0x80000000 /* Config4 implemented */ +#define CFG3_M_SHIFT 31 +#define CFG3_BPG 0x40000000 /* Big pages implemented */ +#define CFG3_BPG_SHIFT 30 +#define CFG3_CMGCR 0x20000000 /* Coherency manager implemented */ +#define CFG3_CMGCR_SHIFT 29 +#define CFG3_MSAP 0x10000000 /* MSA implemented */ +#define CFG3_MSAP_SHIFT 28 +#define CFG3_BP 0x08000000 /* BadInstrP implemented */ +#define CFG3_BP_SHIFT 27 +#define CFG3_BI 0x04000000 /* BadInstr implemented */ +#define CFG3_BI_SHIFT 26 +#define CFG3_SC 0x02000000 /* Segment control implemented */ +#define CFG3_SC_SHIFT 25 +#define CFG3_PW 0x01000000 /* HW page table walk implemented */ +#define CFG3_PW_SHIFT 24 +#define CFG3_VZ 0x00800000 /* Virtualization module implemented */ +#define CFG3_VZ_SHIFT 23 +#define CFG3_IPLW_MASK 0x00600000 /* IPL field width */ +#define CFG3_IPLW_SHIFT 21 +#define CFG3_IPLW_BITS 2 +#define CFG3_IPLW_6BIT (0 << CFG3_IPLW_SHIFT) /* IPL/RIPL are 6-bits wide */ +#define CFG3_IPLW_8BIT (1 << CFG3_IPLW_SHIFT) /* IPL/RIPL are 8-bits wide */ +#define CFG3_MMAR_MASK 0x001c0000 /* MicroMIPS64 architecture revision */ +#define CFG3_MMAR_SHIFT 18 +#define CFG3_MMAR_BITS 3 +#define CFG3_MMAR_R3 (0 << CFG3_MMAR_SHIFT) /* MicroMIPS64 Release 3 */ +#define CFG3_MCU 0x00020000 /* MCU ASE is implemented */ +#define CFG3_MCU_SHIFT 17 +#define CFG3_IOE 0x00010000 /* MicroMIPS exception entry points */ +#define CFG3_IOE_SHIFT 16 +#define CFG3_ISA_MASK 0x0000c000 /* ISA availability */ +#define CFG3_ISA_SHIFT 14 +#define CFG3_ISA_BITS 2 +#define CFG3_ISA_MIPS (0 << CFG3_ISA_SHIFT) /* MIPS only */ +#define CFG3_ISA_UMIPS (1 << CFG3_ISA_SHIFT) /* MicroMIPS only */ +#define CFG3_ISA_BOTH (2 << CFG3_ISA_SHIFT) /* MIPS (boot) and MicroMIPS */ +#define CFG3_ISA_UBOTH (3 << CFG3_ISA_SHIFT) /* MIPS and MicroMIPS (boot) */ +#define CFG3_ULRI 0x00002000 /* UserLocal register is available */ +#define CFG3_ULRI_SHIFT 13 +#define CFG3_RXI 0x00001000 /* RIE and XIE exist in pagegrain */ +#define CFG3_RXI_SHIFT 12 +#define CFG3_DSP2P 0x00000800 /* DSPR2 ASE present */ +#define CFG3_DSP2P_SHIFT 11 +#define CFG3_DSPP 0x00000400 /* DSP ASE present */ +#define CFG3_DSPP_SHIFT 10 +#define CFG3_CTXTC 0x00000200 /* Context Config regs are present */ +#define CFG3_CTXTC_SHIFT 9 +#define CFG3_ITL 0x00000100 /* IFlowtrace mechanism implemented */ +#define CFG3_ITL_SHIFT 8 +#define CFG3_LPA 0x00000080 /* Large physical addresses */ +#define CFG3_LPA_SHIFT 7 +#define CFG3_VEIC 0x00000040 /* Vectored external i/u controller */ +#define CFG3_VEIC_SHIFT 6 +#define CFG3_VI 0x00000020 /* Vectored i/us */ +#define CFG3_VI_SHIFT 5 +#define CFG3_SP 0x00000010 /* Small page support */ +#define CFG3_SP_SHIFT 4 +#define CFG3_CDMM 0x00000008 /* Common Device Memory Map support */ +#define CFG3_CDMM_SHIFT 3 +#define CFG3_MT 0x00000004 /* MT ASE present */ +#define CFG3_MT_SHIFT 2 +#define CFG3_SM 0x00000002 /* SmartMIPS ASE */ +#define CFG3_SM_SHIFT 1 +#define CFG3_TL 0x00000001 /* Trace Logic */ +#define CFG3_TL_SHIFT 0 + +/* + * MIPS32r2 Config4 Register (CP0 Register 16, Select 4) + */ +#define CFG4_M 0x80000000 /* Config5 implemented */ +#define CFG4_M_SHIFT 31 +#define CFG4_IE_MASK 0x60000000 /* TLB invalidate insn support */ +#define CFG4_IE_SHIFT 29 +#define CFG4_IE_BITS 2 +#define CFG4_IE_NONE (0 << CFG4_IE_SHIFT) /* TLB invalidate not available */ +#define CFG4_IE_EHINV (1 << CFG4_IE_SHIFT) /* TLB invalidate with EHINV */ +#define CFG4_IE_INV (2 << CFG4_IE_SHIFT) /* TLB invalidate per entry */ +#define CFG4_IE_INVALL (3 << CFG4_IE_SHIFT) /* TLB invalidate entire MMU */ +#define CFG4_AE 0x10000000 /* EntryHI.ASID is 10-bits */ +#define CFG4_AE_SHIFT 28 +#define CFG4_VTLBSEXT_MASK 0x0f000000 /* VTLB size extension field */ +#define CFG4_VTLBSEXT_SHIFT 24 +#define CFG4_VTLBSEXT_BITS 4 +#define CFG4_KSCREXIST_MASK 0x00ff0000 /* Indicates presence of KScratch */ +#define CFG4_KSCREXIST_SHIFT 16 +#define CFG4_KSCREXIST_BITS 8 +#define CFG4_MMUED 0x0000c000 /* MMU Extension definition */ +#define CFG4_MMUED_SHIFT 14 +#define CFG4_MMUED_BITS 2 +#define CFG4_MMUED_SIZEEXT (1 << CFG4_MMUED_SHIFT) /* MMUSizeExt */ +#define CFG4_MMUED_FTLB (2 << CFG4_MMUED_SHIFT) /* FTLB fields */ +#define CFG4_MMUED_FTLBVEXT (3 << CFG4_MMUED_SHIFT) /* FTLB and Vext */ +#define CFG4_FTLBPS_MASK 0x00001f00 /* FTLB Page Size */ +#define CFG4_FTLBPS_SHIFT 8 +#define CFG4_FTLBPS_BITS 5 +#define CFG4_FTLBW_MASK 0x000000f0 /* FTLB Ways mask */ +#define CFG4_FTLBW_SHIFT 4 +#define CFG4_FTLBW_BITS 4 +#define CFG4_FTLBS_MASK 0x0000000f /* FTLB Sets mask */ +#define CFG4_FTLBS_SHIFT 0 +#define CFG4_FTLBS_BITS 4 +#define CFG4_MMUSE_MASK 0x000000ff /* MMU size extension */ +#define CFG4_MMUSE_SHIFT 0 +#define CFG4_MMUSE_BITS 8 + +/* + * MIPS32r2 Config5 Register (CP0 Register 16, Select 5) + */ +#define CFG5_M 0x80000000 /* Undefined extension */ +#define CFG5_M_SHIFT 31 +#define CFG5_K 0x40000000 /* Disable CCA control */ +#define CFG5_K_SHIFT 30 +#define CFG5_CV 0x20000000 /* Disable CacheException in KSEG1 */ +#define CFG5_CV_SHIFT 29 +#define CFG5_EVA 0x10000000 /* EVA is implemented */ +#define CFG5_EVA_SHIFT 28 +#define CFG5_MSAEN 0x08000000 /* Enable MSA ASE */ +#define CFG5_MSAEN_SHIFT 27 +#define CFG_XNP 0x00002000 +#define CFG_XNP_SHIFT 13 +#define CFG5_CES 0x00001000 /* Current endian state */ +#define CFG5_CES_SHIFT 12 +#define CFG5_DEC 0x00000800 /* Dual endian control */ +#define CFG5_DEC_SHIFT 11 +#define CFG5_L2C 0x00000400 /* Config 2 is memory mapped */ +#define CFG5_L2C_SHIFT 10 +#define CFG5_UFE 0x00000200 /* Usermode FRE control */ +#define CFG5_LUFE_SHIFT 9 +#define CFG5_FRE 0x00000100 /* Emulation support for FR=0 */ +#define CFG5_FRE_SHIFT 8 +#define CFG5_VP 0x00000080 /* Multiple virtual processors */ +#define CFG5_VP_SHIFT 7 +#define CFG5_SBRI 0x00000040 /* Force RI on SDBBP */ +#define CFG5_SBRI_SHIFT 6 +#define CFG5_MVH 0x00000020 /* XPA instruction support */ +#define CFG5_MVH_SHIFT 5 +#define CFG5_LLB 0x00000010 /* Load-Linked Bit present */ +#define CFG5_LLB_SHIFT 4 +#define CFG5_MRP 0x00000008 /* MAAR and MAARI are present */ +#define CFG5_MRP_SHIFT 3 +#define CFG5_UFR 0x00000004 /* Usermode FR control */ +#define CFG5_UFR_SHIFT 2 +#define CFG5_NF 0x00000001 /* Nested fault support */ +#define CFG5_NF_SHIFT 0 + +/* + * Primary cache mode + */ +#define CFG_CBITS 3 +#define CFG_C_UNCACHED 2 +#define CFG_C_WBACK 3 +#define CFG_C_NONCOHERENT 3 + +#if 0 +/* These cache modes are CPU specific */ +#define CFG_C_WTHRU_NOALLOC 0 +#define CFG_C_WTHRU_ALLOC 1 +#define CFG_C_COHERENTXCL 4 +#define CFG_C_COHERENTXCLW 5 +#define CFG_C_COHERENTUPD 6 +#define CFG_C_UNCACHED_ACCEL 7 +#endif + + +/* + * Primary Cache TagLo (CP0 Register 28, Select 0/2) + */ +#define TAG_PTAG_MASK 0xffffff00 /* Primary Tag */ +#define TAG_PTAG_SHIFT 8 +#define TAG_PSTATE_MASK 0x000000c0 /* Primary Cache State */ +#define TAG_PSTATE_SHIFT 6 +#define TAG_PSTATE_LOCK 0x00000020 +#define TAG_PARITY_MASK 0x00000001 /* Primary Tag Parity */ +#define TAG_PARITY_SHIFT 0 + +/* primary cache state (XXX actually implementation specific) */ +#define PSTATE_INVAL 0 +#define PSTATE_SHARED 1 +#define PSTATE_CLEAN_EXCL 2 +#define PSTATE_DIRTY_EXCL 3 + + +/* + * Cache operations + */ +#define Index_Invalidate_I 0x00 /* 0 0 */ +#define Index_Writeback_Inv_D 0x01 /* 0 1 */ +#define Index_Writeback_Inv_T 0x02 /* 0 2 */ +#define Index_Writeback_Inv_S 0x03 /* 0 3 */ +#define Index_Load_Tag_I 0x04 /* 1 0 */ +#define Index_Load_Tag_D 0x05 /* 1 1 */ +#define Index_Load_Tag_T 0x06 /* 1 2 */ +#define Index_Load_Tag_S 0x07 /* 1 3 */ +#define Index_Store_Tag_I 0x08 /* 2 0 */ +#define Index_Store_Tag_D 0x09 /* 2 1 */ +#define Index_Store_Tag_T 0x0A /* 2 2 */ +#define Index_Store_Tag_S 0x0B /* 2 3 */ +#define Hit_Invalidate_I 0x10 /* 4 0 */ +#define Hit_Invalidate_D 0x11 /* 4 1 */ +#define Hit_Invalidate_T 0x12 /* 4 2 */ +#define Hit_Invalidate_S 0x13 /* 4 3 */ +#define Fill_I 0x14 /* 5 0 */ +#define Hit_Writeback_Inv_D 0x15 /* 5 1 */ +#define Hit_Writeback_Inv_T 0x16 /* 5 2 */ +#define Hit_Writeback_Inv_S 0x17 /* 5 3 */ +#define Hit_Writeback_D 0x19 /* 6 1 */ +#define Hit_Writeback_T 0x1A /* 6 2 */ +#define Hit_Writeback_S 0x1B /* 6 3 */ +#define Fetch_Lock_I 0x1C /* 7 0 */ +#define Fetch_Lock_D 0x1D /* 7 1 */ +#define Fetch_Lock_S 0x1F /* 7 3 */ + +/* MIPS32 WatchLo Register (CP0 Register 18) */ +#define WATCHLO_VA 0xfffffff8 +#define WATCHLO_I 0x00000004 +#define WATCHLO_R 0x00000002 +#define WATCHLO_W 0x00000001 + +/* MIPS32 WatchHi Register (CP0 Register 19) */ +#define WATCHHI_M 0x80000000 +#define WATCHHI_M_SHIFT 31 +#define WATCHHI_G 0x40000000 +#define WATCHHI_G_SHIFT 30 +#define WATCHHI_ASID_MASK 0x00ff0000 +#define WATCHHI_ASIDMASK 0x00ff0000 +#define WATCHHI_ASID_SHIFT 16 +#define WATCHHI_ASIDSHIFT 16 +#define WATCHHI_ASID_BITS 8 +#define WATCHHI_MASK 0x00000ffc +#define WATCHHI_I 0x00000004 +#define WATCHHI_R 0x00000002 +#define WATCHHI_W 0x00000001 + +/* MIPS32 PerfCnt Register (CP0 Register 25) */ +#define PERFCNT_M 0x80000000 +#define PERFCNT_EVENT_MASK 0x000007e0 +#define PERFCNT_EVENTMASK 0x000007e0 +#define PERFCNT_EVENT_SHIFT 5 +#define PERFCNT_EVENTSHIFT 5 +#define PERFCNT_EVENT_BITS 6 +#define PERFCNT_IE 0x00000010 +#define PERFCNT_U 0x00000008 +#define PERFCNT_S 0x00000004 +#define PERFCNT_K 0x00000002 +#define PERFCNT_EXL 0x00000001 + +/* MIPS32r2 PageGrain Register (CP0 Register 5, Select 1) */ +#define PAGEGRAIN_ELPA 0x20000000 /* Enable large physical addresses */ +#define PAGEGRAIN_ELPA_SHIFT 29 +#define PAGEGRAIN_ELPA_BITS 1 + +#define PAGEGRAIN_ESP 0x10000000 /* Enable small (1KB) page support */ + +/* MIPS32r2 EBase Register (CP0 Register 15, Select 1) */ +#define EBASE_BASE 0xfffff000 /* Exception base */ +#define EBASE_WG 0x00000800 /* Write Gate */ +#define EBASE_WG_SHIFT 11 +#define EBASE_CPU 0x000003ff /* CPU number */ +#define EBASE_CPU_SHIFT 0 +#define EBASE_CPU_BITS 10 + +/* MIPS32r2 EntryHi register (CP0 Register 10, Select 0) */ +#define C0_ENTRYHI64_R_MASK 0xC000000000000000 +#define C0_ENTRYHI64_R_BITS 2 +#define C0_ENTRYHI64_R_SHIFT 61 +#define C0_ENTRYHI64_VPN2_MASK 0xFFFFFFE000 +#define C0_ENTRYHI64_VPN2_BITS 27 +#define C0_ENTRYHI64_VPN2_SHIFT 13 +#define C0_ENTRYHI_VPN2_MASK 0xFFFFE000 +#define C0_ENTRYHI_VPN2_BITS 19 +#define C0_ENTRYHI_VPN2_SHIFT 13 +#define C0_ENTRYHI_VPN2X_MASK 0x3 +#define C0_ENTRYHI_VPN2X_BITS 2 +#define C0_ENTRYHI_VPN2X_SHIFT 11 +#define C0_ENTRYHI_EHINV_MASK 0x400 +#define C0_ENTRYHI_EHINV_BITS 1 +#define C0_ENTRYHI_EHINV_SHIFT 10 +#define C0_ENTRYHI_ASIDX_MASK 0x300 +#define C0_ENTRYHI_ASIDX_BITS 2 +#define C0_ENTRYHI_ASIDX_SHIFT 8 +#define C0_ENTRYHI_ASID_MASK 0xFF +#define C0_ENTRYHI_ASID_BITS 8 +#define C0_ENTRYHI_ASID_SHIFT 0 + +/* MIPS32 EntryLo0 register (CP0 Register 2, select 0) */ +#define ENTRYLO064_RI_MASK 0x8000000000000000 +#define ENTRYLO064_RI_BITS 1 +#define ENTRYLO064_RI_SHIFT 63 +#define ENTRYLO064_XI_MASK 0x4000000000000000 +#define ENTRYLO064_XI_BITS 1 +#define ENTRYLO064_XI_SHIFT 62 +#define ENTRYLO064_PFN_MASK 0x3FFFFFFFFFFFFFE0 +#define ENTRYLO064_PFN_BITS 56 +#define ENTRYLO064_PFN_SHIFT 6 +#define ENTRYLO064_RI_SHIFT 63 +#define ENTRYLO064_RI_BITS 1 +#define ENTRYLO064_RI_SHIFT 63 +#define ENTRYLO0_PFNX_MASK 0x7FFFFF +#define ENTRYLO0_PFNX_BITS 23 +#define ENTRYLO0_PFNX_SHIFT 0 +#define ENTRYLO0_RI_MASK 0x80000000 +#define ENTRYLO0_RI_BITS 1 +#define ENTRYLO0_RI_SHIFT 31 +#define ENTRYLO0_XI_MASK 0x40000000 +#define ENTRYLO0_XI_BITS 1 +#define ENTRYLO0_XI_SHIFT 30 +#define ENTRYLO0_PFN_MASK 0x3FFFFFE0 +#define ENTRYLO0_PFN_BITS 23 +#define ENTRYLO0_PFN_SHIFT 6 +#define ENTRYLO0_C_MASK 0x38 +#define ENTRYLO0_C_BITS 3 +#define ENTRYLO0_C_SHIFT 3 +#define ENTRYLO0_D_MASK 0x4 +#define ENTRYLO0_D_BITS 1 +#define ENTRYLO0_D_SHIFT 2 +#define ENTRYLO0_V_MASK 0x2 +#define ENTRYLO0_V_BITS 1 +#define ENTRYLO0_V_SHIFT 1 +#define ENTRYLO0_G_MASK 0x1 +#define ENTRYLO0_G_BITS 1 +#define ENTRYLO0_G_SHIFT 0 + +/* MIPS32 EntryLo1 register (CP0 Register 3, select 0) */ +#define ENTRYLO164_RI_MASK ENTRYLO064_RI_MASK +#define ENTRYLO164_RI_BITS ENTRYLO064_RI_BITS +#define ENTRYLO164_RI_SHIFT ENTRYLO064_RI_SHIFT +#define ENTRYLO164_XI_MASK ENTRYLO064_XI_MASK +#define ENTRYLO164_XI_BITS ENTRYLO064_XI_BITS +#define ENTRYLO164_XI_SHIFT ENTRYLO064_XI_SHIFT +#define ENTRYLO164_PFN_MASK ENTRYLO064_PFN_MASK +#define ENTRYLO164_PFN_BITS ENTRYLO064_PFN_BITS +#define ENTRYLO164_PFN_SHIFT ENTRYLO064_PFN_SHIFT +#define ENTRYLO164_RI_SHIFT ENTRYLO064_RI_SHIFT +#define ENTRYLO164_RI_BITS ENTRYLO064_RI_BITS +#define ENTRYLO164_RI_SHIFT ENTRYLO064_RI_SHIFT +#define ENTRYLO1_PFNX_MASK ENTRYLO0_PFNX_MASK +#define ENTRYLO1_PFNX_BITS ENTRYLO0_PFNX_BITS +#define ENTRYLO1_PFNX_SHIFT ENTRYLO0_PFNX_SHIFT +#define ENTRYLO1_RI_MASK ENTRYLO0_RI_MASK +#define ENTRYLO1_RI_BITS ENTRYLO0_RI_BITS +#define ENTRYLO1_RI_SHIFT ENTRYLO0_RI_SHIFT +#define ENTRYLO1_XI_MASK ENTRYLO0_XI_MASK +#define ENTRYLO1_XI_BITS ENTRYLO0_XI_BITS +#define ENTRYLO1_XI_SHIFT ENTRYLO0_XI_SHIFT +#define ENTRYLO1_PFN_MASK ENTRYLO0_PFN_MASK +#define ENTRYLO1_PFN_BITS ENTRYLO0_PFN_BITS +#define ENTRYLO1_PFN_SHIFT ENTRYLO0_PFN_SHIFT +#define ENTRYLO1_C_MASK ENTRYLO0_C_MASK +#define ENTRYLO1_C_BITS ENTRYLO0_C_BITS +#define ENTRYLO1_C_SHIFT ENTRYLO0_C_SHIFT +#define ENTRYLO1_D_MASK ENTRYLO0_D_MASK +#define ENTRYLO1_D_BITS ENTRYLO0_D_BITS +#define ENTRYLO1_D_SHIFT ENTRYLO0_D_SHIFT +#define ENTRYLO1_V_MASK ENTRYLO0_V_MASK +#define ENTRYLO1_V_BITS ENTRYLO0_V_BITS +#define ENTRYLO1_V_SHIFT ENTRYLO0_V_SHIFT +#define ENTRYLO1_G_MASK ENTRYLO0_G_MASK +#define ENTRYLO1_G_BITS ENTRYLO0_G_BITS +#define ENTRYLO1_G_SHIFT ENTRYLO0_G_SHIFT + +/* MIPS32 TraceControl register (CP0 Register 23, select 1) */ +#define TRACECONTROL_TS_MASK 0x80000000 +#define TRACECONTROL_TS_SHIFT 31 +#define TRACECONTROL_TB_MASK 0x08000000 +#define TRACECONTROL_TB_SHIFT 27 +#define TRACECONTROL_IO_MASK 0x04000000 +#define TRACECONTROL_IO_SHIFT 26 +#define TRACECONTROL_D_MASK 0x02000000 +#define TRACECONTROL_D_SHIFT 25 +#define TRACECONTROL_E_MASK 0x01000000 +#define TRACECONTROL_E_SHIFT 24 +#define TRACECONTROL_K_MASK 0x00800000 +#define TRACECONTROL_K_SHIFT 23 +#define TRACECONTROL_S_MASK 0x00400000 +#define TRACECONTROL_S_SHIFT 22 +#define TRACECONTROL_U_MASK 0x00200000 +#define TRACECONTROL_U_SHIFT 21 +#define TRACECONTROL_ASID_M_MASK 0x001fe000 +#define TRACECONTROL_ASID_M_SHIFT 13 +#define TRACECONTROL_ASID_M_BITS 8 +#define TRACECONTROL_ASID_MASK 0x00001fe0 +#define TRACECONTROL_ASID_SHIFT 5 +#define TRACECONTROL_ASID_BITS 8 +#define TRACECONTROL_G_MASK 0x00000010 +#define TRACECONTROL_G_SHIFT 4 +#define TRACECONTROL_TFCR_MASK 0x00000008 +#define TRACECONTROL_TFCR_SHIFT 3 +#define TRACECONTROL_TLSM_MASK 0x00000004 +#define TRACECONTROL_TLSM_SHIFT 2 +#define TRACECONTROL_TIM_MASK 0x00000002 +#define TRACECONTROL_TIM_SHIFT 1 +#define TRACECONTROL_ON_MASK 0x00000001 +#define TRACECONTROL_ON_SHIFT 0 + +/* MIPS32 TraceControl2 register (CP0 Register 23, select 2) */ +#define TRACECONTROL2_SYPEXT_MASK 0xc0000000 +#define TRACECONTROL2_SYPEXT_SHIFT 30 +#define TRACECONTROL2_SYPEXT_BITS 2 +#define TRACECONTROL2_CPUIDV_MASK 0x20000000 +#define TRACECONTROL2_CPUIDV_SHIFT 29 +#define TRACECONTROL2_CPUID_MASK 0x1fe00000 +#define TRACECONTROL2_CPUID_SHIFT 21 +#define TRACECONTROL2_CPUID_BITS 8 +#define TRACECONTROL2_TCV_MASK 0x00100000 +#define TRACECONTROL2_TCV_SHIFT 20 +#define TRACECONTROL2_TCNUM_MASK 0x000ff000 +#define TRACECONTROL2_TCNUM_SHIFT 12 +#define TRACECONTROL2_TCNUM_BITS 8 +#define TRACECONTROL2_MODE_MASK 0x00000f80 +#define TRACECONTROL2_MODE_SHIFT 7 +#define TRACECONTROL2_MODE_BITS 5 +#define TRACECONTROL2_VMODE_MASK 0x00000060 +#define TRACECONTROL2_VMODE_SHIFT 5 +#define TRACECONTROL2_VMODE_BITS 2 +#define TRACECONTROL2_VMODE_PC (0x0 << TRACECONTROL2_VMODE_SHIFT) +#define TRACECONTROL2_VMODE_PCLSA (0x1 << TRACECONTROL2_VMODE_SHIFT) +#define TRACECONTROL2_VMODE_PCLSAD (0x2 << TRACECONTROL2_VMODE_SHIFT) +#define TRACECONTROL2_TBI_MASK 0x00000010 +#define TRACECONTROL2_TBI_SHIFT 4 +#define TRACECONTROL2_TBU_MASK 0x00000008 +#define TRACECONTROL2_TBU_SHIFT 3 +#define TRACECONTROL2_SYP_MASK 0x00000007 +#define TRACECONTROL2_SYP_SHIFT 0 +#define TRACECONTROL2_SYP_BITS 3 + +/* MIPS32 TraceControl3 register (CP0 Register 24, select 2) */ +#define TRACECONTROL3_TNUD_MASK 0x20000000 +#define TRACECONTROL3_TNUD_SHIFT 29 +#define TRACECONTROL3_MSA_EN_MASK 0x10000000 +#define TRACECONTROL3_MSA_EN_SHIFT 28 +#define TRACECONTROL3_MSA_MASK 0x08000000 +#define TRACECONTROL3_MSA_SHIFT 27 +#define TRACECONTROL3_EASID_M_MASK 0x06000000 +#define TRACECONTROL3_EASID_M_SHIFT 25 +#define TRACECONTROL3_EASID_M_BITS 2 +#define TRACECONTROL3_EASID_MASK 0x01800000 +#define TRACECONTROL3_EASID_SHIFT 23 +#define TRACECONTROL3_EASID_BITS 2 +#define TRACECONTROL3_GV_MASK 0x00400000 +#define TRACECONTROL3_GV_SHIFT 22 +#define TRACECONTROL3_GUESTID_MASK 0x003fc000 +#define TRACECONTROL3_GUESTID_SHIFT 14 +#define TRACECONTROL3_GUESTID_BITS 8 +#define TRACECONTROL3_PECOVF_MASK 0x00000200 +#define TRACECONTROL3_PECOVF_SHIFT 13 +#define TRACECONTROL3_PECFCR_MASK 0x00000100 +#define TRACECONTROL3_PECFCR_SHIFT 12 +#define TRACECONTROL3_PECBP_MASK 0x00000080 +#define TRACECONTROL3_PECBP_SHIFT 11 +#define TRACECONTROL3_PECSYNC_MASK 0x00000040 +#define TRACECONTROL3_PECSYNC_SHIFT 10 +#define TRACECONTROL3_PECE_MASK 0x00000020 +#define TRACECONTROL3_PECE_SHIFT 9 +#define TRACECONTROL3_PEC_MASK 0x00000010 +#define TRACECONTROL3_PEC_SHIFT 8 +#define TRACECONTROL3_TRIDLE_MASK 0x00000004 +#define TRACECONTROL3_TRIDLE_SHIFT 2 +#define TRACECONTROL3_TRPAD_MASK 0x00000002 +#define TRACECONTROL3_TRPAD_SHIFT 1 +#define TRACECONTROL3_FDT_MASK 0x00000001 +#define TRACECONTROL3_FDT_SHIFT 0 + +#ifdef __ASSEMBLER__ + +/* + * MIPS32 Coprocessor 0 register numbers + */ +#define C0_INDEX $0 +#define C0_INX $0 +#define C0_RANDOM $1 +#define C0_RAND $1 +#define C0_ENTRYLO0 $2 +#define C0_TLBLO0 $2 +#define C0_ENTRYLO1 $3 +#define C0_TLBLO1 $3 +#define C0_GLOBAL $3,1 +#define C0_CONTEXT $4 +#define C0_CTXT $4 +#define C0_CONTEXTCONF $4,1 +#define C0_USERLOCAL $4,2 +#define C0_XCONTEXTCONF $4,3 +#define C0_DEBUGCTXTID $4,4 +#define C0_PAGEMASK $5 +#define C0_PAGEGRAIN $5,1 +#define C0_SEGCTL0 $5,2 +#define C0_SEGCTL1 $5,3 +#define C0_SEGCTL2 $5,4 +#define C0_PWBASE $5,5 +#define C0_PWFIELD $5,6 +#define C0_PWSIZE $5,7 +#define C0_WIRED $6 +#define C0_PWCTL $6,6 +#define C0_HWRENA $7 +#define C0_BADVADDR $8 +#define C0_VADDR $8 +#define C0_BADINSTR $8,1 +#define C0_BADPINSTR $8,2 +#define C0_COUNT $9 +#define C0_ENTRYHI $10 +#define C0_TLBHI $10 +#define C0_COMPARE $11 +#define C0_STATUS $12 +#define C0_SR $12 +#define C0_INTCTL $12,1 +#define C0_SRSCTL $12,2 +#define C0_SRSMAP $12,3 +#define C0_CAUSE $13 +#define C0_CR $13 +#define C0_NESTEDEXC $13,5 +#define C0_EPC $14 +#define C0_NEPC $14,2 +#define C0_PRID $15 +#define C0_EBASE $15,1 +#define C0_CDMMBASE $15,2 +#define C0_CMGCRBASE $15,3 +#define C0_BEVVA $15,4 +#define C0_CONFIG $16 +#define C0_CONFIG0 $16,0 +#define C0_CONFIG1 $16,1 +#define C0_CONFIG2 $16,2 +#define C0_CONFIG3 $16,3 +#define C0_CONFIG4 $16,4 +#define C0_CONFIG5 $16,5 +#define C0_LLADDR $17 +#define C0_MAAR $17,1 +#define C0_MAARI $17,2 +#define C0_WATCHLO $18 +#define C0_WATCHHI $19 +#define C0_XCONTEXT $20 +#define C0_DEBUG $23 +#define C0_TRACECONTROL $23,1 +#define C0_TRACECONTROL2 $23,2 +#define C0_USERTRACEDATA1 $23,3 +#define C0_TRACEIBPC $23,4 +#define C0_TRACEDBPC $23,5 +#define C0_DEBUG2 $23,6 +#define C0_DEPC $24 +#define C0_TRACECONTROL3 $24,2 +#define C0_USERTRACEDATA2 $24,3 +#define C0_PERFCNT $25 +#define C0_ERRCTL $26 +#define C0_CACHEERR $27 +#define C0_TAGLO $28 +#define C0_ITAGLO $28 +#define C0_DTAGLO $28,2 +#define C0_TAGLO2 $28,4 +#define C0_DATALO $28,1 +#define C0_IDATALO $28,1 +#define C0_DDATALO $28,3 +#define C0_DATALO2 $28,5 +#define C0_TAGHI $29 +#define C0_ITAGHI $29 +#define C0_DTAGHI $29,2 +#define C0_DATAHI $29,1 +#define C0_IDATAHI $29,1 +#define C0_DDATAHI $29,3 +#define C0_ERRPC $30 +#define C0_DESAVE $31 +#define C0_KSCRATCH1 $31,2 +#define C0_KSCRATCH2 $31,3 +#define C0_KSCRATCH3 $31,4 +#define C0_KSCRATCH4 $31,5 +#define C0_KSCRATCH5 $31,6 +#define C0_KSCRATCH6 $31,7 + +$index = $0 +$random = $1 +$entrylo0 = $2 +$entrylo1 = $3 +$context = $4 +$pagemask = $5 +$wired = $6 +$hwrena = $7 +$vaddr = $8 +$badvaddr = $8 +$count = $9 +$entryhi = $10 +$compare = $11 +$sr = $12 +$cr = $13 +$epc = $14 +$prid = $15 +$config = $16 +$lladdr = $17 +$watchlo = $18 +$watchhi = $19 +$debug = $23 +$depc = $24 +$perfcnt = $25 +$errctl = $26 +$cacheerr = $27 +$taglo = $28 +$taghi = $29 +$errpc = $30 +$desave = $31 + + +#else /* !__ASSEMBLER__ */ + +/* + * Standard types + */ +typedef unsigned int reg32_t; /* a 32-bit register */ +typedef unsigned long long reg64_t; /* a 64-bit register */ +#if _MIPS_SIM==_ABIO32 +typedef unsigned int reg_t; +typedef signed int sreg_t; +#else +typedef unsigned long long reg_t; +typedef signed long long sreg_t; +#endif + +/* + * MIPS32 Coprocessor 0 register encodings for C use. + * These encodings are implementation specific. + */ +#define C0_INDEX 0 +#define C0_INX 0 +#define C0_RANDOM 1 +#define C0_RAND 1 +#define C0_ENTRYLO0 2 +#define C0_TLBLO0 2 +#define C0_ENTRYLO1 3 +#define C0_TLBLO1 3 +#define C0_GLOBAL 0x103 +#define C0_CONTEXT 4 +#define C0_CTXT 4 +#define C0_CONTEXTCONF 0x104 +#define C0_USERLOCAL 0x204 +#define C0_XCONTEXTCONF 0x304 +#define C0_DEBUGCTXTID 0x404 +#define C0_PAGEMASK 5 +#define C0_PAGEGRAIN 0x105 +#define C0_SEGCTL0 0x205 +#define C0_SEGCTL1 0x305 +#define C0_SEGCTL2 0x405 +#define C0_PWBASE 0x505 +#define C0_PWFIELD 0x605 +#define C0_PWSIZE 0x705 +#define C0_WIRED 6 +#define C0_PWCTL 0x606 +#define C0_HWRENA 7 +#define C0_BADVADDR 8 +#define C0_VADDR 8 +#define C0_BADINSTR 0x108 +#define C0_BADINSTRP 0x208 +#define C0_COUNT 9 +#define C0_ENTRYHI 10 +#define C0_TLBHI 10 +#define C0_COMPARE 11 +#define C0_STATUS 12 +#define C0_SR 12 +#define C0_INTCTL 0x10C +#define C0_SRSCTL 0x20C +#define C0_SRSMAP 0x30C +#define C0_CAUSE 13 +#define C0_CR 13 +#define C0_NESTEDEXC 0x50D +#define C0_EPC 14 +#define C0_NEPC 0x20E +#define C0_PRID 15 +#define C0_EBASE 0x10F +#define C0_CDMMBASE 0x20F +#define C0_CMGCRBASE 0x30F +#define C0_BEVVA 0x40F +#define C0_CONFIG 16 +#define C0_CONFIG0 16 +#define C0_CONFIG1 0x110 +#define C0_CONFIG2 0x210 +#define C0_CONFIG3 0x310 +#define C0_CONFIG4 0x410 +#define C0_CONFIG5 0x510 +#define C0_LLADDR 17 +#define C0_MAAR 0x111 +#define C0_MAARI 0x111 +#define C0_WATCHLO 18 +#define C0_WATCHHI 19 +#define C0_XCONTEXT 20 +#define C0_DEBUG 23 +#define C0_TRACECONTROL 0x117 +#define C0_TRACECONTROL2 0x217 +#define C0_USERTRACEDATA1 0x317 +#define C0_TRACEIBPC 0x417 +#define C0_TRACEDBPC 0x517 +#define C0_DEBUG2 0x617 +#define C0_DEPC 24 +#define C0_TRACECONTROL3 0x218 +#define C0_USERTRACEDATA2 0x318 +#define C0_PERFCNT 25 +#define C0_ERRCTL 26 +#define C0_CACHEERR 27 +#define C0_TAGLO 28 +#define C0_ITAGLO 28 +#define C0_DTAGLO 0x21C +#define C0_TAGLO2 0x41C +#define C0_DATALO 0x11C +#define C0_IDATALO 0x11C +#define C0_DDATALO 0x31C +#define C0_DATALO2 0x51C +#define C0_TAGHI 29 +#define C0_ITAGHI 29 +#define C0_DTAGHI 0x21D +#define C0_DATAHI 0x11D +#define C0_IDATAHI 0x11D +#define C0_DDATAHI 0x31D +#define C0_ERRPC 30 +#define C0_DESAVE 31 +#define C0_KSCRATCH1 0x21F +#define C0_KSCRATCH2 0x31F +#define C0_KSCRATCH3 0x41F +#define C0_KSCRATCH4 0x51F +#define C0_KSCRATCH5 0x61F +#define C0_KSCRATCH6 0x71F + +#ifdef __cplusplus +extern "C" { +#endif + +#define _mips_sync() __asm__ __volatile__ ("sync" : : : "memory") + +/* wait for unmasked interrupt */ +#define _mips_wait() \ + __asm__ __volatile ("wait") + +/* + * Define macros for accessing the MIPS32 coprocessor 0 registers. Most apart + * from "set" return the original register value. These macros take an encoded + * (register, select) combination, so they can use the textual names above. + */ + +#define MIPS_C0_REGNAME(regno, sel) ((sel << 8) + regno) + +#define mips32_get_c0(selreg) \ +__extension__ ({ \ + register unsigned long __r; \ + __asm__ __volatile ("mfc0 %0,$%1,%2" \ + : "=d" (__r) \ + : "JK" (selreg & 0x1F), "JK" (selreg >> 8)); \ + __r; \ +}) + +#undef EHB +#if defined (__MIPS_NO_IMPLICIT_EHB) +#define EHB "" +#else +#define EHB "ehb\n" +#endif + +#define mips32_set_c0(selreg, val) \ +do { \ + __asm__ __volatile (".set push \n"\ + ".set noreorder\n"\ + "mtc0 %z0,$%1,%2\n"\ + EHB \ + ".set pop" \ + : \ + : "dJ" ((reg32_t)(val)), "JK" (selreg & 0x1F),\ + "JK" (selreg >> 8) \ + : "memory"); \ +} while (0) + +#define mips32_xch_c0(selreg, val) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = mips32_get_c0 (selreg); \ + mips32_set_c0 (selreg, val); \ + __o; \ +}) + +#define mips32_bc_c0(selreg, clr) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = mips32_get_c0 (selreg); \ + mips32_set_c0 (selreg, __o & ~(clr)); \ + __o; \ +}) + +#define mips32_bs_c0(selreg, set) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = mips32_get_c0 (selreg); \ + mips32_set_c0 (selreg, __o | (set)); \ + __o; \ +}) + +#define mips32_bcs_c0(selreg, clr, set) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = mips32_get_c0 (selreg); \ + mips32_set_c0 (selreg, (__o & ~(clr)) | (set)); \ + __o; \ +}) + +/* MIPS instructions */ +#define mips_sync() \ + ({__asm__ volatile ("\t sync \n");}) + +#define mips_synci(ADDR) \ + ({__asm__ volatile ("\t synci 0(%0) \n" :: "r" (ADDR));}) + +#define mips_synci_step() \ +({ \ + int _step; \ + __asm__ volatile ( \ + "\t rdhwr %0,$1 \n" : "=r" (_step)); \ + _step; \ +}) + +#define mips_ehb() \ + ({__asm__ volatile ("\t ehb \n");}) + +#define mips_tlbwi() \ + ({__asm__ volatile ("\t tlbwi \n");}) + +#define mips_tlbwr() \ + ({__asm__ volatile ("\t tlbwr \n");}) + +#define mips_tlbp() \ + ({__asm__ volatile ("\t tlbp \n");}) + +#define mips_tlbr() \ + ({__asm__ volatile ("\t tlbr \n");}) + +#define mips_eva_tlbinvf() \ +({__asm__ volatile ( \ + "\t .set push \n" \ + "\t .set eva \n" \ + "\t tlbinvf \n" \ + "\t .set pop \n" \ + ); \ +}) + +/* Set upper half of EntryHI */ +#define mips32_sethientryhi(VAL) \ +({__asm__ volatile ( \ + "\t .set push \n" \ + "\t .set xpa \n" \ + "\t mthc0 %0,$10,0 \n" \ + "\t .set pop \n" \ + : :"r" (VAL) \ + ); \ +}) + +#define mips_cache(OP,ADDR) \ + ({__asm__ volatile ("\t cache %0,0(%1) \n" :: "JK" (OP), "r" (ADDR));}) + +/* generic equivalents for mips/cpu.h */ +#define _mips_mfc0(r) mips32_get_c0(r) +#define _mips_mtc0(r,v) mips32_set_c0(r,v) + +/* MIPS32 Entry*, Index, PageMask registers */ +#define mips32_getentryhi() mips32_get_c0(C0_ENTRYHI) +#define mips32_setentryhi(v) mips32_set_c0(C0_ENTRYHI,v) +#define mips32_getentrylo0() mips32_get_c0(C0_ENTRYLO0) +#define mips32_setentrylo0(v) mips32_set_c0(C0_ENTRYLO0,v) +#define mips32_getentrylo1() mips32_get_c0(C0_ENTRYLO1) +#define mips32_setentrylo1(v) mips32_set_c0(C0_ENTRYLO1,v) +#define mips32_getpagemask() mips32_get_c0(C0_PAGEMASK) +#define mips32_setpagemask(v) mips32_set_c0(C0_PAGEMASK,v) +#define mips32_getindex() mips32_get_c0(C0_INDEX) +#define mips32_setindex(v) mips32_set_c0(C0_INDEX,v) + +/* MIPS32 Config0 register */ +#define mips32_getconfig0() mips32_get_c0(C0_CONFIG0) +#define mips32_setconfig0(v) mips32_set_c0(C0_CONFIG0,v) +#define mips32_xchconfig0(v) mips32_xch_c0(C0_CONFIG0,v) +#define mips32_bicconfig0(clr) mips32_bc_c0(C0_CONFIG0,clr) +#define mips32_bisconfig0(set) mips32_bs_c0(C0_CONFIG0,set) +#define mips32_bcsconfig0(c,s) mips32_bcs_c0(C0_CONFIG0,c,s) + +/* MIPS32 Config1, 2, 3, 4, 5 register */ +#define mips32_getconfig1() mips32_get_c0(C0_CONFIG1) +#define mips32_setconfig1(v) mips32_set_c0(C0_CONFIG1,v) +#define mips32_xchconfig1(v) mips32_xch_c0(C0_CONFIG1,v) +#define mips32_bicconfig1(clr) mips32_bc_c0(C0_CONFIG1,clr) +#define mips32_bisconfig1(set) mips32_bs_c0(C0_CONFIG1,set) +#define mips32_bcsconfig1(c,s) mips32_bcs_c0(C0_CONFIG1,c,s) + +#define mips32_getconfig2() mips32_get_c0(C0_CONFIG2) +#define mips32_setconfig2(v) mips32_set_c0(C0_CONFIG2,v) +#define mips32_xchconfig2(v) mips32_xch_c0(C0_CONFIG2,v) +#define mips32_bicconfig2(clr) mips32_bc_c0(C0_CONFIG2,clr) +#define mips32_bisconfig2(set) mips32_bs_c0(C0_CONFIG2,set) +#define mips32_bcsconfig2(c,s) mips32_bcs_c0(C0_CONFIG2,c,s) + +#define mips32_getconfig3() mips32_get_c0(C0_CONFIG3) +#define mips32_setconfig3(v) mips32_set_c0(C0_CONFIG3,v) +#define mips32_xchconfig3(v) mips32_xch_c0(C0_CONFIG3,v) +#define mips32_bicconfig3(clr) mips32_bc_c0(C0_CONFIG3,clr) +#define mips32_bisconfig3(set) mips32_bs_c0(C0_CONFIG3,set) +#define mips32_bcsconfig3(c,s) mips32_bcs_c0(C0_CONFIG3,c,s) + +#define mips32_getconfig4() mips32_get_c0(C0_CONFIG4) +#define mips32_setconfig4(v) mips32_set_c0(C0_CONFIG4,v) +#define mips32_xchconfig4(v) mips32_xch_c0(C0_CONFIG4,v) +#define mips32_bicconfig4(clr) mips32_bc_c0(C0_CONFIG4,clr) +#define mips32_bisconfig4(set) mips32_bs_c0(C0_CONFIG4,set) +#define mips32_bcsconfig4(c,s) mips32_bcs_c0(C0_CONFIG4,c,s) + +#define mips32_getconfig5() mips32_get_c0(C0_CONFIG5) +#define mips32_setconfig5(v) mips32_set_c0(C0_CONFIG5,v) +#define mips32_xchconfig5(v) mips32_xch_c0(C0_CONFIG5,v) +#define mips32_bicconfig5(clr) mips32_bc_c0(C0_CONFIG5,clr) +#define mips32_bisconfig5(set) mips32_bs_c0(C0_CONFIG5,set) +#define mips32_bcsconfig5(c,s) mips32_bcs_c0(C0_CONFIG5,c,s) + +/* MIPS32 Debug register */ +#define mips32_getdebug() mips32_get_c0(C0_DEBUG) +#define mips32_setdebug(v) mips32_set_c0(C0_DEBUG,v) +#define mips32_xchdebug(v) mips32_xch_c0(C0_DEBUG,v) +#define mips32_bicdebug(clr) mips32_bc_c0(C0_DEBUG,clr) +#define mips32_bisdebug(set) mips32_bs_c0(C0_DEBUG,set) +#define mips32_bcsdebug(c,s) mips32_bcs_c0(C0_DEBUG,c,s) + +/* MIPS32 ErrCtl register */ +#define mips32_geterrctl() mips32_get_c0(C0_ERRCTL) +#define mips32_seterrctl(x) mips32_set_c0(C0_ERRCTL,x) +#define mips32_xcherrctl(x) mips32_xch_c0(C0_ERRCTL,x) +#define mips32_bicerrctl(clr) mips32_bc_c0(C0_ERRCTL,clr) +#define mips32_biserrctl(set) mips32_bs_c0(C0_ERRCTL,set) +#define mips32_bcserrctl(c,s) mips32_bcs_c0(C0_ERRCTL,c,s) + +/* MIPS32 TagLo register */ +#define mips32_getitaglo() mips32_get_c0(C0_TAGLO) /* alias define */ +#define mips32_setitaglo(x) mips32_set_c0(C0_TAGLO,x) /* alias define */ +#define mips32_xchitaglo(x) mips32_xch_c0(C0_TAGLO,x) /* alias define */ +#define mips32_getdtaglo() mips32_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 2)) +#define mips32_setdtaglo(x) mips32_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 2),x) +#define mips32_xchdtaglo(x) mips32_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 2),x) +#define mips32_gettaglo2() mips32_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 4)) +#define mips32_settaglo2(x) mips32_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 4),x) +#define mips32_xchtaglo2(x) mips32_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 4),x) + +/* MIPS32 DataLo register */ +#define mips32_getdatalo() mips32_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 1)) +#define mips32_setdatalo(x) mips32_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 1),x) +#define mips32_xchdatalo(x) mips32_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 1),x) +#define mips32_getidatalo() mips32_getdatalo() /* alias define */ +#define mips32_setidatalo(x) mips32_setdatalo(x) /* alias define */ +#define mips32_xchidatalo(x) mips32_xchdatalo(x) /* alias define */ +#define mips32_getddatalo() mips32_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 3)) +#define mips32_setddatalo(x) mips32_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 3),x) +#define mips32_xchddatalo(x) mips32_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 3),x) +#define mips32_getdatalo2() mips32_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 5)) +#define mips32_setdatalo2(x) mips32_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 5),x) +#define mips32_xchdatalo2(x) mips32_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 5),x) + +/* MIPS32r2 IntCtl register */ +#define mips32_getintctl() mips32_get_c0(C0_INTCTL) +#define mips32_setintctl(x) mips32_set_c0(C0_INTCTL,x) +#define mips32_xchintctl(x) mips32_xch_c0(C0_INTCTL,x) + +/* MIPS32r2 SRSCtl register */ +#define mips32_getsrsctl() mips32_get_c0(C0_SRSCTL) +#define mips32_setsrsctl(x) mips32_set_c0(C0_SRSCTL,x) +#define mips32_xchsrsctl(x) mips32_xch_c0(C0_SRSCTL,x) + +/* MIPS32r2 SRSMap register */ +#define mips32_getsrsmapl() mips32_get_c0(C0_SRSMAP) +#define mips32_setsrsmap(x) mips32_set_c0(C0_SRSMAP,x) +#define mips32_xchsrsmap(x) mips32_xch_c0(C0_SRSMAP,x) + +/* MIPS32r2/SmartMIPS PageGrain register */ +#define mips32_getpagegrain() mips32_get_c0(C0_PAGEGRAIN) +#define mips32_setpagegrain(x) mips32_set_c0(C0_PAGEGRAIN,x) +#define mips32_xchpagegrain(x) mips32_xch_c0(C0_PAGEGRAIN,x) + +/* MIPS32r2 HWREna register */ +#define mips32_gethwrena() mips32_get_c0(C0_HWRENA) +#define mips32_sethwrena(v) mips32_set_c0(C0_HWRENA,v) +#define mips32_xchhwrena(v) mips32_xch_c0(C0_HWRENA,v) +#define mips32_bichwrena(clr) mips32_bc_c0(C0_HWRENA,clr) +#define mips32_bishwrena(set) mips32_bs_c0(C0_HWRENA,set) +#define mips32_bcshwrena(c,s) mips32_bcs_c0(C0_HWRENA,c,s) + +/* MIPS32r2 EBase register */ +#define mips32_getebase() mips32_get_c0(C0_EBASE) +#define mips32_setebase(x) mips32_set_c0(C0_EBASE,x) +#define mips32_xchebase(x) mips32_xch_c0(C0_EBASE,x) + +/* CP0 Status register (NOTE: not atomic operations) */ +#define mips32_getsr() mips32_get_c0(C0_SR) +#define mips32_setsr(v) mips32_set_c0(C0_SR,v) +#define mips32_xchsr(v) mips32_xch_c0(C0_SR,v) +#define mips32_bicsr(clr) mips32_bc_c0(C0_SR,clr) +#define mips32_bissr(set) mips32_bs_c0(C0_SR,set) +#define mips32_bcssr(c,s) mips32_bcs_c0(C0_SR,c,s) + +/* CP0 Cause register (NOTE: not atomic operations) */ +#define mips32_getcr() mips32_get_c0(C0_CR) +#define mips32_setcr(v) mips32_set_c0(C0_CR,v) +#define mips32_xchcr(v) mips32_xch_c0(C0_CR,v) +#define mips32_biccr(clr) mips32_bc_c0(C0_CR,clr) +#define mips32_biscr(set) mips32_bs_c0(C0_CR,set) +#define mips32_bcscr(c,s) mips32_bcs_c0(C0_CR,c,s) + +/* CP0 PrID register */ +#define mips32_getprid() mips32_get_c0(C0_PRID) + +#ifdef C0_COUNT +/* CP0 Count register */ +#define mips32_getcount() mips32_get_c0(C0_COUNT) +#define mips32_setcount(v) mips32_set_c0(C0_COUNT,v) +#define mips32_xchcount(v) mips32_xch_c0(C0_COUNT,v) +#endif + +#ifdef C0_COMPARE +/* CP0 Compare register*/ +#define mips32_getcompare() mips32_get_c0(C0_COMPARE) +#define mips32_setcompare(v) mips32_set_c0(C0_COMPARE,v) +#define mips32_xchcompare(v) mips32_xch_c0(C0_COMPARE,v) +#endif + +#ifdef C0_CONFIG +/* CP0 Config register */ +#define mips32_getconfig() mips32_get_c0(C0_CONFIG) +#define mips32_setconfig(v) mips32_set_c0(C0_CONFIG,v) +#define mips32_xchconfig(v) mips32_xch_c0(C0_CONFIG,v) +#define mips32_bicconfig(c) mips32_bc_c0(C0_CONFIG,c) +#define mips32_bisconfig(s) mips32_bs_c0(C0_CONFIG,s) +#define mips32_bcsconfig(c,s) mips32_bcs_c0(C0_CONFIG,c,s) +#endif + +#ifdef C0_ECC +/* CP0 ECC register */ +#define mips32_getecc() mips32_get_c0(C0_ECC) +#define mips32_setecc(x) mips32_set_c0(C0_ECC, x) +#define mips32_xchecc(x) mips32_xch_c0(C0_ECC, x) +#endif + +#ifdef C0_TAGHI +/* CP0 TagHi register */ +#define mips32_gettaghi() mips32_get_c0(C0_TAGHI) +#define mips32_settaghi(x) mips32_set_c0(C0_TAGHI, x) +#define mips32_xchtaghi(x) mips32_xch_c0(C0_TAGHI, x) +#endif + +#ifdef C0_WATCHLO +/* CP0 WatchLo register */ +#define mips32_getwatchlo() mips32_get_c0(C0_WATCHLO) +#define mips32_setwatchlo(x) mips32_set_c0(C0_WATCHLO, x) +#define mips32_xchwatchlo(x) mips32_xch_c0(C0_WATCHLO, x) +#endif + +#ifdef C0_WATCHHI +/* CP0 WatchHi register */ +#define mips32_getwatchhi() mips32_get_c0(C0_WATCHHI) +#define mips32_setwatchhi(x) mips32_set_c0(C0_WATCHHI, x) +#define mips32_xchwatchhi(x) mips32_xch_c0(C0_WATCHHI, x) +#endif + +#ifdef C0_USERTRACE1 +/* PDTRACE usertrace registers */ +#define mips32_usertrace1(x) mips32_set_c0(C0_USERTRACE1, x) +#define mips32_usertrace2(x) mips32_set_c0(C0_USERTRACE2, x) +#endif + +/* + * Define macros for accessing the MIPS32 coprocessor 0 registers. Most + * apart from "set" return the original register value. These particular + * macros take (reg, sel) as separate paramters, so they can't be used with + * the coprocessor 0 register names above. + */ +#define _m32c0_mfc0(reg, sel) \ +__extension__ ({ \ + register unsigned long __r; \ + __asm__ __volatile ("mfc0 %0,$%1,%2" \ + : "=d" (__r) \ + : "JK" (reg), "JK" (sel)); \ + __r; \ +}) + +#define _m32c0_mtc0(reg, sel, val) \ +do { \ + __asm__ __volatile (".set push \n"\ + ".set noreorder\n"\ + "mtc0 %z0,$%1,%2\n"\ + "ehb\n" \ + ".set pop" \ + : \ + : "dJ" ((reg32_t)(val)), "JK" (reg), "JK" (sel) \ + : "memory"); \ +} while (0) + +#define _m32c0_mxc0(reg, sel, val) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _m32c0_mfc0 (reg, sel); \ + _m32c0_mtc0 (reg, sel, val); \ + __o; \ +}) + +#define _m32c0_bcc0(reg, sel, clr) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _m32c0_mfc0 (reg, sel); \ + _m32c0_mtc0 (reg, sel, __o & ~(clr)); \ + __o; \ +}) + +#define _m32c0_bsc0(reg, sel, set) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _m32c0_mfc0 (reg, sel); \ + _m32c0_mtc0 (reg, sel, __o | (set)); \ + __o; \ +}) + +#define _m32c0_bcsc0(reg, sel, clr, set) \ +__extension__ ({ \ + register reg32_t __o; \ + __o = _m32c0_mfc0 (reg, sel); \ + _m32c0_mtc0 (reg, sel, (__o & ~(clr)) | (set)); \ + __o; \ +}) + +#ifdef __cplusplus +} +#endif + +/* Define MIPS32 user-level intrinsics */ +#include <mips/mips32.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* CP0 intrinsics */ + +/* MIPS32r2 atomic interrupt disable */ +#define _mips_intdisable() __extension__({ \ + unsigned int __v; \ + __asm__ __volatile__ ("di %0; ehb" : "=d" (__v)); \ + __v; \ +}) + +/* MIPS32r2 atomic interrupt disable */ +#define _mips_intenable() __extension__({ \ + unsigned int __v; \ + __asm__ __volatile__ ("ei %0; ehb" : "=d" (__v)); \ + __v; \ +}) + +/* MIPS32r2 atomic interrupt restore */ +#define _mips_intrestore(x) \ + mips_setsr (x) + +/* MIPS32r2 set SRSCtl.PSS (previous shadow set), returning old value */ +extern unsigned int _mips32r2_xchsrspss (unsigned int); + +/* MIPS32r2 write previous gpr */ +#define _mips32r2_wrpgpr(regno, val) \ +do { \ + __asm __volatile ("wrpgpr $%0,%z1" \ + : /* no outputs */ \ + : "JK" (regno), "dJ" (val)); \ +} while (0) + +/* MIPS32r2 read previous gpr */ +#define _mips32r2_rdpgpr(regno) \ +__extension__({ \ + reg_t __val; \ + __asm __volatile ("rdpgpr %0,$%1" \ + : "=d" (__val) \ + : "JK" (regno)); \ + __val; \ +}) + +#endif /* __ASSEMBLER__ */ + +/* MIPS32 PREF instruction hint codes */ +#define PREF_LOAD 0 +#define PREF_STORE 1 +#define PREF_LOAD_STREAMED 4 +#define PREF_STORE_STREAMED 5 +#define PREF_LOAD_RETAINED 6 +#define PREF_STORE_RETAINED 7 +#define PREF_WRITEBACK_INVAL 25 +#define PREF_PREPAREFORSTORE 30 + +#ifdef __cplusplus +} +#endif +#endif /* _M32C0_H_ */ diff --git a/libgloss/mips/include/mips/m32c1.h b/libgloss/mips/include/mips/m32c1.h new file mode 100644 index 0000000..a4524ec --- /dev/null +++ b/libgloss/mips/include/mips/m32c1.h @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _M32C1_H_ +#define _M32C1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __ASSEMBLER__ + +unsigned fpa_getrid(void); /* get fpa revision id */ +unsigned fpa_getsr(void); /* get fpa status register */ +void fpa_setsr(unsigned); +unsigned fpa_xchsr(unsigned); +unsigned fpa_bicsr(unsigned); +unsigned fpa_bissr(unsigned); + +unsigned msa_getmir(void); /* get msa revision id */ +unsigned msa_getsr(void); /* get msa status register */ +void msa_setsr(unsigned); +unsigned msa_xchsr(unsigned); +unsigned msa_bicsr(unsigned); +unsigned msa_bissr(unsigned); + +/* + * Define macros to accessing the Coprocessor 1 control registers. + * Most apart from "set" return the original register value. + */ + +#define fpa_getrid() \ +__extension__({ \ + register unsigned __r; \ + __asm__ __volatile ("cfc1 %0,$0" : "=d" (__r)); \ + __r; \ +}) + +#define fpa_getfir() fpa_getrid() + +#define fpa_getsr() \ +__extension__({ \ + register unsigned __r; \ + __asm__ __volatile ("cfc1 %0,$31" : "=d" (__r)); \ + __r; \ +}) + +#define fpa_setsr(val) \ +__extension__({ \ + register unsigned __r = (val); \ + __asm__ __volatile ("ctc1 %0,$31" : : "d" (__r)); \ + __r; \ +}) + +#define fpa_xchsr(val) \ +__extension__({ \ + register unsigned __o, __n = (val); \ + __asm__ __volatile ("cfc1 %0,$31" : "=d" (__o)); \ + __asm__ __volatile ("ctc1 %0,$31" : : "d" (__n)); \ + __o; \ +}) + +#define fpa_bissr(val) \ +__extension__({ \ + register unsigned __o, __n; \ + __asm__ __volatile ("cfc1 %0,$31" : "=d" (__o)); \ + __n = __o | (val); \ + __asm__ __volatile ("ctc1 %0,$31" : : "d" (__n)); \ + __o; \ +}) + +#define fpa_bicsr(val) \ +__extension__({ \ + register unsigned __o, __n; \ + __asm__ __volatile ("cfc1 %0,$31" : "=d" (__o)); \ + __n = __o &~ (val); \ + __asm__ __volatile ("ctc1 %0,$31" : : "d" (__n)); \ + __o; \ +}) + + +#define msa_getmir() \ +__extension__({ \ + register unsigned __r; \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "cfcmsa %0,$0\n" \ + ".set pop": "=d" (__r)); \ + __r; \ +}) + +#define msa_getsr() \ +__extension__({ \ + register unsigned __r; \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "cfcmsa %0,$1\n" \ + ".set pop": "=d" (__r)); \ + __r; \ +}) + +#define msa_setsr(val) \ +__extension__({ \ + register unsigned __r = (val); \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "ctcmsa $1,%0\n" \ + ".set pop": : "d" (__r)); \ + __r; \ +}) + +#define msa_xchsr(val) \ +__extension__({ \ + register unsigned __o, __n = (val); \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "cfcmsa %0,$1\n" \ + ".set pop": "=d" (__o)); \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "ctcmsa $1,%0\n" \ + ".set pop": : "d" (__n)); \ + __o; \ +}) + +#define msa_bissr(val) \ +__extension__({ \ + register unsigned __o, __n; \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "cfcmsa %0,$1\n" \ + ".set pop": "=d" (__o)); \ + __n = __o | (val); \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "ctcmsa $1,%0\n" \ + ".set pop": : "d" (__n)); \ + __o; \ +}) + +#define msa_bicsr(val) \ +__extension__({ \ + register unsigned __o, __n; \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "cfcmsa %0,$1\n" \ + ".set pop": "=d" (__o)); \ + __n = __o &~ (val); \ + __asm__ __volatile (".set push\n" \ + ".set fp=64\n" \ + ".set msa\n" \ + "ctcmsa $1,%0\n" \ + ".set pop": : "d" (__n)); \ + __o; \ +}) + +#endif /* !ASSEMBLER */ + +#ifdef __cplusplus +} +#endif + +/* + * FCSR - FPU Control & Status Register + */ +#define FPA_CSR_MD0 0x00200000 /* machine dependent */ +#define FPA_CSR_MD1 0x00400000 /* machine dependent */ +#define FPA_CSR_COND 0x00800000 /* $fcc0 */ +#define FPA_CSR_COND0 0x00800000 /* $fcc0 */ +#define FPA_CSR_FLUSH 0x01000000 /* flush to 0 */ +#define FPA_CSR_FS 0x01000000 /* flush to 0 */ +#define FPA_CSR_COND1 0x02000000 /* $fcc1 */ +#define FPA_CSR_COND2 0x04000000 /* $fcc2 */ +#define FPA_CSR_COND3 0x08000000 /* $fcc3 */ +#define FPA_CSR_COND4 0x10000000 /* $fcc4 */ +#define FPA_CSR_COND5 0x20000000 /* $fcc5 */ +#define FPA_CSR_COND6 0x40000000 /* $fcc6 */ +#define FPA_CSR_COND7 0x80000000 /* $fcc7 */ + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPA_CSR_ALL_X 0x0003f000 +#define FPA_CSR_UNI_X 0x00020000 +#define FPA_CSR_INV_X 0x00010000 +#define FPA_CSR_DIV_X 0x00008000 +#define FPA_CSR_OVF_X 0x00004000 +#define FPA_CSR_UDF_X 0x00002000 +#define FPA_CSR_INE_X 0x00001000 + +#define FPA_CSR_ALL_E 0x00000f80 +#define FPA_CSR_INV_E 0x00000800 +#define FPA_CSR_DIV_E 0x00000400 +#define FPA_CSR_OVF_E 0x00000200 +#define FPA_CSR_UDF_E 0x00000100 +#define FPA_CSR_INE_E 0x00000080 + +#define FPA_CSR_ALL_S 0x0000007c +#define FPA_CSR_INV_S 0x00000040 +#define FPA_CSR_DIV_S 0x00000020 +#define FPA_CSR_OVF_S 0x00000010 +#define FPA_CSR_UDF_S 0x00000008 +#define FPA_CSR_INE_S 0x00000004 + +/* rounding mode */ +#define FPA_CSR_RN 0x0 /* nearest */ +#define FPA_CSR_RZ 0x1 /* towards zero */ +#define FPA_CSR_RU 0x2 /* towards +Infinity */ +#define FPA_CSR_RD 0x3 /* towards -Infinity */ + +/* FPU Implementation Register */ +#define FPA_FIR_F64 0x00400000 /* implements 64-bits registers */ +#define FPA_FIR_L 0x00200000 /* implements long fixed point */ +#define FPA_FIR_W 0x00100000 /* implements word fixed point */ +#define FPA_FIR_3D 0x00080000 /* implements MIPS-3D ASE */ +#define FPA_FIR_PS 0x00040000 /* implements paired-single format */ +#define FPA_FIR_D 0x00020000 /* implements double format */ +#define FPA_FIR_S 0x00010000 /* implements single format */ +#define FPA_FIR_PRID 0x0000ff00 /* ProcessorID */ +#define FPA_FIR_REV 0x000000ff /* Revision */ + +#ifdef __ASSEMBLER__ + + .previous + +/* control regs */ + $fir = $0 + $fccr = $25 + $fexr = $26 + $fenr = $28 + $fcsr = $31 + +/* backwards compat */ + $fpa_rid = $0 + $fpa_sr = $31 +#endif + + +#endif /*_M32C1_H_*/ diff --git a/libgloss/mips/include/mips/m32tlb.h b/libgloss/mips/include/mips/m32tlb.h new file mode 100644 index 0000000..83d781e --- /dev/null +++ b/libgloss/mips/include/mips/m32tlb.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + + /* + * m32tlb.h: MIPS32 TLB support functions + */ + +#ifndef _M32TLB_H_ +#define _M32TLB_H_ + +#if __mips != 32 && __mips != 64 +#error use -mips32 or -mips64 option with this file +#endif + +#include <mips/notlb.h> +#ifndef __ASSEMBLER__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __mips16 +# define _MIPS_M32TLB_NOMIPS16 __attribute__((nomips16)) +#else +# define _MIPS_M32TLB_NOMIPS16 +#endif + +typedef unsigned int tlbhi_t; +typedef unsigned int tlblo_t; + +// Returns the size of the TLB. +_MIPS_M32TLB_NOMIPS16 +int mips_tlb_size (void); + // Probes the TLB for an entry matching hi, and if present invalidates it. +_MIPS_M32TLB_NOMIPS16 +void mips_tlbinval (tlbhi_t hi); + +// Invalidate the whole TLB. +_MIPS_M32TLB_NOMIPS16 +void mips_tlbinvalall (void); + +// Reads the TLB entry with specified by index, and returns the EntryHi, +// EntryLo0, EntryLo1 and PageMask parts in *phi, *plo0, *plo1 and *pmsk +// respectively. +_MIPS_M32TLB_NOMIPS16 +void mips_tlbri2 (tlbhi_t *phi, tlblo_t *plo0, tlblo_t *plo1, unsigned *pmsk, + int index); + +// Writes hi, lo0, lo1 and msk into the TLB entry specified by index. +_MIPS_M32TLB_NOMIPS16 +void mips_tlbwi2 (tlbhi_t hi, tlblo_t lo0, tlblo_t lo1, unsigned msk, + int index); + +// Writes hi, lo0, lo1 and msk into the TLB entry specified by the +// Random register. +_MIPS_M32TLB_NOMIPS16 +void mips_tlbwr2 (tlbhi_t hi, tlblo_t lo0, tlblo_t lo1, unsigned msk); + +// Probes the TLB for an entry matching hi and returns its index, or -1 if +// not found. If found, then the EntryLo0, EntryLo1 and PageMask parts of the +// entry are also returned in *plo0, *plo1 and *pmsk respectively +_MIPS_M32TLB_NOMIPS16 +int mips_tlbprobe2 (tlbhi_t hi, tlblo_t *plo0, tlblo_t *plo1, unsigned *pmsk); + +// Probes the TLB for an entry matching hi and if present rewrites that entry, +// otherwise updates a random entry. A safe way to update the TLB. +_MIPS_M32TLB_NOMIPS16 +int mips_tlbrwr2 (tlbhi_t hi, tlblo_t lo0, tlblo_t lo1, unsigned msk); + +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* _M32TLB_H_ */ diff --git a/libgloss/mips/include/mips/m64c0.h b/libgloss/mips/include/mips/m64c0.h new file mode 100644 index 0000000..2f4a340 --- /dev/null +++ b/libgloss/mips/include/mips/m64c0.h @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _M64C0_H_ +#define _M64C0_H_ + +/* Superset of MIPS32 */ +#include <mips/m32c0.h> + +#ifndef __ASSEMBLER__ +typedef union { + unsigned long long ll; + struct { +#if defined(_MIPSEB) || defined(MIPSEB) + unsigned int hi; + unsigned int lo; +#else + unsigned int lo; + unsigned int hi; +#endif + } s; +} __ll_shape_type; +#endif + +/* + * Define macros for accessing the MIPS coprocessor 0 registers which are + * 64 bits wide. + * Most apart from "set" return the original register value. + */ + +#if (_MIPS_SIM == _ABIO32) +#define mips64_get_c0(selreg) \ +__extension__ ({ \ + __ll_shape_type __r; \ + __asm__ __volatile ("mfc0 %0,$%2,%3\n" \ + ".set push\n"\ + ".set xpa\n"\ + "mfhc0 %1,$%2,%3\n" \ + ".set pop\n" \ + : "=r" (__r.s.lo), \ + "=r" (__r.s.hi) \ + : "JK" (selreg & 0x1F), "JK" (selreg >> 8)); \ + __r.ll; \ +}) +#else /* _MIPS_SIM==N32 || _MIPS_SIM==N64 */ +#define mips64_get_c0(selreg) \ +__extension__ ({ \ + register unsigned long __r; \ + __asm__ __volatile ("dmfc0 %0,$%1,%2" \ + : "=d" (__r) \ + : "JK" (selreg & 0x1F), "JK" (selreg >> 8)); \ + __r; \ +}) +#endif + +#undef EHB +#if defined (__MIPS_NO_IMPLICIT_EHB) +#define EHB "" +#else +#define EHB "ehb\n" +#endif + +#if (_MIPS_SIM == _ABIO32) +#define mips64_set_c0(selreg, val) \ +do { \ + __ll_shape_type __ll; \ + __ll.ll = (val); \ + __asm__ __volatile (".set push \n"\ + ".set noreorder\n"\ + "mtc0 %z0,$%2,%3\n"\ + ".set xpa\n"\ + "mthc0 %z1,$%2,%3\n"\ + EHB \ + ".set pop" \ + : \ + : "dJ" ((reg32_t)(__ll.s.lo)),\ + "dJ" ((reg32_t)(__ll.s.hi)),\ + "JK" (selreg & 0x1F),\ + "JK" (selreg >> 8)\ + : "memory"); \ +} while (0) +#else /* _MIPS_SIM==N32 || _MIPS_SIM==N64 */ +#define mips64_set_c0(selreg, val) \ +do { \ + __asm__ __volatile (".set push \n"\ + ".set noreorder\n"\ + "dmtc0 %z0,$%1,%2\n"\ + EHB \ + ".set pop" \ + : \ + : "dJ" ((reg64_t)(val)), "JK" (selreg & 0x1F),\ + "JK" (selreg >> 8) \ + : "memory"); \ +} while (0) +#endif + +#define mips64_xch_c0(selreg, val) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = mips64_get_c0 (selreg); \ + mips64_set_c0 (selreg, val); \ + __o; \ +}) + +#define mips64_bc_c0(selreg, clr) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = mips64_get_c0 (selreg); \ + mips64_set_c0 (selreg, __o & ~(clr)); \ + __o; \ +}) + +#define mips64_bs_c0(selreg, set) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = mips64_get_c0 (selreg); \ + mips64_set_c0 (selreg, __o | (set)); \ + __o; \ +}) + +#define mips64_bcs_c0(selreg, clr, set) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = mips64_get_c0 (selreg); \ + mips64_set_c0 (selreg, (__o & ~(clr)) | (set)); \ + __o; \ +}) + +/* MIPS64 Entry*, Index, PageMask registers */ +#define mips64_setentryhi(x) mips64_set_c0(C0_ENTRYHI,x) +#define mips64_getentryhi() mips64_get_c0(C0_ENTRYHI) +#define mips64_setentrylo0(x) mips64_set_c0(C0_ENTRYLO0,x) +#define mips64_getentrylo0() mips64_get_c0(C0_ENTRYLO0) +#define mips64_setentrylo1(x) mips64_set_c0(C0_ENTRYLO1,x) +#define mips64_getentrylo1() mips64_get_c0(C0_ENTRYLO1) +#define mips64_setpagemask(x) mips64_set_c0(C0_PAGEMASK,x) +#define mips64_getpagemask() mips64_get_c0(C0_PAGEMASK) +#define mips64_setindex(x) mips32_set_c0(C0_INDEX,x) +#define mips64_getindex(x) mips32_get_c0(C0_INDEX) + +/* MIPS64 Config3 and Config4 registers */ +#define mips64_getconfig3() mips32_get_c0(C0_CONFIG3) +#define mips64_setconfig3(x) mips32_set_c0(C0_CONFIG3,x) +#define mips64_getconfig4() mips32_get_c0(C0_CONFIG4) +#define mips64_setconfig4(x) mips32_set_c0(C0_CONFIG4,x) + +/* MIPS64 TagLo register */ +#define mips64_getitaglo() mips64_get_c0(C0_TAGLO) /* alias define */ +#define mips64_setitaglo(x) mips64_set_c0(C0_TAGLO,x) /* alias define */ +#define mips64_xchitaglo(x) mips64_xch_c0(C0_TAGLO,x) /* alias define */ +#define mips64_getdtaglo() mips64_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 2)) +#define mips64_setdtaglo(x) mips64_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 2),x) +#define mips64_xchdtaglo(x) mips64_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 2),x) +#define mips64_gettaglo2() mips64_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 4)) +#define mips64_settaglo2(x) mips64_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 4),x) +#define mips64_xchtaglo2(x) mips64_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 4),x) + +/* MIPS64 DataLo register */ +#define mips64_getdatalo() mips64_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 1)) +#define mips64_setdatalo(x) mips64_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 1),x) +#define mips64_xchdatalo(x) mips64_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 1),x) +#define mips64_getidatalo() mips64_getdatalo() /* alias define */ +#define mips64_setidatalo(x) mips64_setdatalo(x) /* alias define */ +#define mips64_xchidatalo(x) mips64_xchdatalo(x) /* alias define */ +#define mips64_getddatalo() mips64_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 3)) +#define mips64_setddatalo(x) mips64_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 3),x) +#define mips64_xchddatalo(x) mips64_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 3),x) +#define mips64_getdatalo2() mips64_get_c0(MIPS_C0_REGNAME(C0_TAGLO, 5)) +#define mips64_setdatalo2(x) mips64_set_c0(MIPS_C0_REGNAME(C0_TAGLO, 5),x) +#define mips64_xchdatalo2(x) mips64_xch_c0(MIPS_C0_REGNAME(C0_TAGLO, 5),x) + +/* CP0 TagHi register */ +#define mips64_gettaghi() mips64_get_c0(C0_TAGHI) +#define mips64_settaghi(x) mips64_set_c0(C0_TAGHI, x) +#define mips64_xchtaghi(x) mips64_xch_c0(C0_TAGHI, x) + +/* CP0 WatchLo register */ +#define mips64_getwatchlo() mips64_get_c0(C0_WATCHLO) +#define mips64_setwatchlo(x) mips64_set_c0(C0_WATCHLO, x) +#define mips64_xchwatchlo(x) mips64_xch_c0(C0_WATCHLO, x) + +#define _m64c0_mfc0(reg, sel) \ +__extension__ ({ \ + register unsigned long __r; \ + __asm__ __volatile ("dmfc0 %0,$%1,%2" \ + : "=d" (__r) \ + : "JK" (reg), "JK" (sel)); \ + __r; \ +}) + +#define _m64c0_mtc0(reg, sel, val) \ +do { \ + __asm__ __volatile (".set push \n"\ + ".set noreorder\n"\ + "dmtc0 %z0,$%1,%2\n"\ + "ehb\n" \ + ".set pop" \ + : \ + : "dJ" ((reg64_t)(val)), "JK" (reg), "JK" (sel) \ + : "memory"); \ +} while (0) + +#define _m64c0_mxc0(reg, sel, val) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = _m64c0_mfc0 (reg, sel); \ + _m64c0_mtc0 (reg, sel, val); \ + __o; \ +}) + +#define _m64c0_bcc0(reg, sel, clr) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = _m64c0_mfc0 (reg, sel); \ + _m64c0_mtc0 (reg, sel, __o & ~(clr)); \ + __o; \ +}) + +#define _m64c0_bsc0(reg, sel, set) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = _m64c0_mfc0 (reg, sel); \ + _m64c0_mtc0 (reg, sel, __o | (set)); \ + __o; \ +}) + +#define _m64c0_bcsc0(reg, sel, clr, set) \ +__extension__ ({ \ + register reg64_t __o; \ + __o = _m64c0_mfc0 (reg, sel); \ + _m64c0_mtc0 (reg, sel, (__o & ~(clr)) | (set)); \ + __o; \ +}) + +/* Define MIPS64 user-level intrinsics */ +#include <mips/mips64.h> + +/* MIPS64-specific MMU interface */ +#include <mips/m64tlb.h> + +#endif /* _M64C0_H_ */ diff --git a/libgloss/mips/include/mips/m64tlb.h b/libgloss/mips/include/mips/m64tlb.h new file mode 100644 index 0000000..4894d25 --- /dev/null +++ b/libgloss/mips/include/mips/m64tlb.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2015-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * m64tlb.h: MIPS64 / XPA TLB support functions +*/ +#ifndef _M64TLB_H_ +#define _M64TLB_H_ + +#if __mips != 32 && __mips != 64 +#error use -mips32 or -mips64 option with this file +#endif + +#include <mips/notlb.h> + +#ifndef __ASSEMBLER__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __mips16 +# define _MIPS_M64TLB_NOMIPS16 __attribute__((nomips16)) +#else +# define _MIPS_M64TLB_NOMIPS16 +#endif + +typedef unsigned long long tlbhi64_t; +typedef unsigned long long tlblo64_t; +// Returns the size of the TLB. +_MIPS_M64TLB_NOMIPS16 +int m64_tlb_size (void); + +// Probes the TLB for an entry matching hi, and if present invalidates it. +_MIPS_M64TLB_NOMIPS16 +void m64_tlbinval (tlbhi64_t hi); + +// Invalidate the whole TLB. +_MIPS_M64TLB_NOMIPS16 +void m64_tlbinvalall (void); + +// Reads the TLB entry with specified by index, and returns the EntryHi, +// EntryLo0, EntryLo1 and PageMask parts in *phi, *plo0, *plo1 and *pmsk +// respectively. +_MIPS_M64TLB_NOMIPS16 +void m64_tlbri2 (tlbhi64_t *phi, tlblo64_t *plo0, tlblo64_t *plo1, + unsigned long long *pmsk, int index); + +// Writes hi, lo0, lo1 and msk into the TLB entry specified by index. +_MIPS_M64TLB_NOMIPS16 +void m64_tlbwi2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1, + unsigned long long msk, int index); + +// Writes hi, lo0, lo1 and msk into the TLB entry specified by the +// Random register. +_MIPS_M64TLB_NOMIPS16 +void m64_tlbwr2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1, + unsigned long long msk); + +// Probes the TLB for an entry matching hi and returns its index, or -1 if +// not found. If found, then the EntryLo0, EntryLo1 and PageMask parts of the +// entry are also returned in *plo0, *plo1 and *pmsk respectively +_MIPS_M64TLB_NOMIPS16 +int m64_tlbprobe2 (tlbhi64_t hi, tlblo64_t *plo0, tlblo64_t *plo1, + unsigned long long *pmsk); + +// Probes the TLB for an entry matching hi and if present rewrites that entry, +// otherwise updates a random entry. A safe way to update the TLB. +_MIPS_M64TLB_NOMIPS16 +int m64_tlbrwr2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1, + unsigned long long msk); + +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* _M64TLB_H_ */ diff --git a/libgloss/mips/include/mips/mips32.h b/libgloss/mips/include/mips/mips32.h new file mode 100644 index 0000000..ccd9482 --- /dev/null +++ b/libgloss/mips/include/mips/mips32.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS32_H_ +#define _MIPS32_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __ASSEMBLER__ + +#if ! __mips16 + +/* C interface to clz/clo instructions */ + +/* count leading zeros */ +# define mips_clz(x) __builtin_clz (x) + +/* count trailing zeros */ +# define mips_ctz(x) __builtin_ctz (x) + +#define mips_clo(x) __extension__({ \ + unsigned int __x = (x); \ + unsigned int __v; \ + __asm__ ("clo %0,%1" : "=d" (__v) : "d" (__x)); \ + __v; \ +}) + +#ifndef __mips64 + +/* Simulate 64-bit count leading zeroes */ +#if !defined(mips_dclz) +#define mips_dclz(x) __extension__({ \ + unsigned long long __x = (x); \ + unsigned int __hx = (__x >> 32); \ + __hx ? mips_clz(__hx) : 32 + mips_clz(__x); \ +}) +#endif + +/* Simulate 64-bit count leading ones */ +#if !defined(mips_dclo) +#define mips_dclo(x) __extension__({ \ + unsigned long long __x = (x); \ + unsigned int __hx = (__x >> 32); \ + (~__hx) ? mips_clo(__hx) : 32 + mips_clo(__x); \ +}) +#endif + +/* Simulate 64-bit count trailing zeroes */ +#if !defined(mips_dctz) +#define mips_dctz(x) __extension__({ \ + unsigned long long __dx = (x); \ + unsigned int __ldx = __dx; \ + unsigned int __hdx = __dx >> 32; \ + __ldx ? mips_ctz(__ldx) : (63 ^ mips_clz(__hdx & -__hdx)); \ + }) +#endif + +#endif + +/* MIPS32r2 wsbh opcode */ +#define _mips32r2_wsbh(x) __extension__({ \ + unsigned int __x = (x), __v; \ + __asm__ ("wsbh %0,%1" \ + : "=d" (__v) \ + : "d" (__x)); \ + __v; \ +}) + +/* MIPS32r2 byte-swap word */ +#define _mips32r2_bswapw(x) __extension__({ \ + unsigned int __x = (x), __v; \ + __asm__ ("wsbh %0,%1; rotr %0,16" \ + : "=d" (__v) \ + : "d" (__x)); \ + __v; \ +}) + +/* MIPS32r2 insert bits */ +#define _mips32r2_ins(tgt,val,pos,sz) __extension__({ \ + unsigned int __t = (tgt), __v = (val); \ + __asm__ ("ins %0,%z1,%2,%3" \ + : "+d" (__t) \ + : "dJ" (__v), "I" (pos), "I" (sz)); \ + __t; \ +}) + +/* MIPS32r2 extract bits */ +#define _mips32r2_ext(x,pos,sz) __extension__({ \ + unsigned int __x = (x), __v; \ + __asm__ ("ext %0,%z1,%2,%3" \ + : "=d" (__v) \ + : "dJ" (__x), "I" (pos), "I" (sz)); \ + __v; \ +}) + +#if __mips_isa_rev < 6 + +/* MIPS32r2 jr.hb */ +#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32 +#define mips32_jr_hb() __asm__ __volatile__( \ + "bltzal $0,0f\n" \ +"0: addiu $31,1f-0b\n" \ +" jr.hb $31\n" \ +"1:" \ + : : : "$31") +#elif _MIPS_SIM == _ABI64 +#define mips32_jr_hb() __asm__ __volatile__( \ + "bltzal $0,0f\n" \ +"0: daddiu $31,1f-0b\n" \ +" jr.hb $31\n" \ +"1:" \ + : : : "$31") +#else +#error Unknown ABI +#endif + +#else /* __mips_isa_rev < 6 */ + +/* MIP32r6 jr.hb */ +#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32 +#define mips32_jr_hb() __asm__ __volatile__( \ + "auipc $24,%pcrel_hi(1f)\n" \ + "addiu $24,%pcrel_lo(1f + 4)\n" \ + "jr.hb $24\n" \ +"1:" \ + : : : "$24") +#elif _MIPS_SIM == _ABI64 +#define mips32_jr_hb() __asm__ __volatile__( \ + "auipc $24,%pcrel_hi(1f)\n" \ + "daddiu $24,%pcrel_lo(1f + 4)\n" \ + "jr.hb $24\n" \ +"1:" \ + : : : "$24") +#else +#error Unknown ABI +#endif + +#endif /* __mips_isa_rev < 6 */ + +#endif /* ! __mips16 */ + +#endif /* __ASSEMBLER__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _MIPS32_H_ */ diff --git a/libgloss/mips/include/mips/mips64.h b/libgloss/mips/include/mips/mips64.h new file mode 100644 index 0000000..2602a35 --- /dev/null +++ b/libgloss/mips/include/mips/mips64.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS64_H_ +#define _MIPS64_H_ + +#include <mips/mips32.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __ASSEMBLER__ + +#if __mips == 64 && ! __mips16 + +/* 64-bit count leading zeroes */ +#if !defined(mips_dclz) +# define mips_dclz(x) __builtin_clzll (x) +#endif + +/* 64-bit count trailing zeroes */ +#if !defined(mips_dctz) +# define mips_dctz(x) __builtin_ctzll (x) +#endif + +#if !defined(mips_dclo) +#define mips_dclo(x) __extension__({ \ + unsigned long long __x = (x); \ + unsigned int __v; \ + __asm__ ("dclo %0,%1" : "=d" (__v) : "d" (__x)); \ + __v; \ +}) +#endif + +/* MIPS64r2 dshd opcode */ +#define _mips64r2_dshd(x) __extension__({ \ + unsigned long long __x = (x), __v; \ + __asm__ ("dshd %0,%1" \ + : "=d" (__v) \ + : "d" (__x)); \ + __v; \ +}) + +/* MIPS64r2 dsbh opcode */ +#define _mips64r2_dsbh(x) __extension__({ \ + unsigned long long __x = (x), __v; \ + __asm__ ("dsbh %0,%1" \ + : "=d" (__v) \ + : "d" (__x)); \ + __v; \ +}) + +/* MIPS64r2 byte-swap doubleword */ +#define _mips64r2_bswapd(x) __extension__({ \ + unsigned long long __x = (x), __v; \ + __asm__ ("dsbh %0,%1; dshd %0,%0" \ + : "=d" (__v) \ + : "d" (__x)); \ + __v; \ +}) + +/* MIPS64r2 insert bits */ +#define _mips64r2_dins(tgt,val,pos,sz) __extension__({ \ + unsigned long long __t = (tgt), __v = (val); \ + __asm__ ("dins %0,%z1,%2,%3" \ + : "+d" (__t) \ + : "dJ" (__v), "I" (pos), "I" (sz)); \ + __t; \ +}) + +/* MIPS64r2 extract bits */ +#define _mips64r2_dext(x,pos,sz) __extension__({ \ + unsigned long long __x = (x), __v; \ + __asm__ ("dext %0,%z1,%2,%3" \ + : "=d" (__v) \ + : "dJ" (__x), "I" (pos), "I" (sz)); \ + __v; \ +}) + +#endif /* __mips == 64 && ! __mips16 */ + +#endif /* !__ASSEMBLER__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _MIPS64_H_ */ diff --git a/libgloss/mips/include/mips/mt.h b/libgloss/mips/include/mips/mt.h new file mode 100644 index 0000000..10bed4c --- /dev/null +++ b/libgloss/mips/include/mips/mt.h @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS_MT_H_ +#define _MIPS_MT_H_ + +#include <mips/m32c0.h> +#include <mips/mips32.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MIPS32 MVPControl Register (CP0 Register 0, Select 1) + */ +#define MVPCONTROL_EVP 0x00000001 /* Enable Virtual Processors */ +#define MVPCONTROL_VPC 0x00000002 /* VPE Configuration State */ +#define MVPCONTROL_STLB 0x00000004 /* Share TLBS */ +#define MVPCONTROL_CPA 0x00000008 /* Cache Partitioning Active */ + +/* + * MIPS32 MVPConf0 Register (CP0 Register 0, Select 2) + */ +#define MVPCONF0_PTC 0x000000ff +#define MVPCONF0_PTC_SHIFT 0 +#define MVPCONF0_PVPE 0x00003c00 +#define MVPCONF0_PVPE_SHIFT 10 +#define MVPCONF0_TCA 0x00008000 +#define MVPCONF0_PTLBE 0x03ff0000 +#define MVPCONF0_PTLBE_SHIFT 16 +#define MVPCONF0_TLBS 0x20000000 +#define MVPCONF0_M 0x80000000 + +/* + * MIPS32 MVPConf1 Register (CP0 Register 0, Select 3) + */ +#define MVPCONF1_PCP1 0x000000ff +#define MVPCONF1_PCP1_SHIFT 0 +#define MVPCONF1_PCP2 0x0003fc00 +#define MVPCONF1_PCP2_SHIFT 10 +#define MVPCONF1_PCX 0x0ff00000 +#define MVPCONF1_PCX_SHIFT 20 +#define MVPCONF1_C1F 0x40000000 +#define MVPCONF1_C1M 0x80000000 + +/* + * MIPS32 VPEControl Register (CP0 Register 1, Select 1) + */ +#define VPECONTROL_TARGTC 0x000000ff +#define VPECONTROL_TARGTC_SHIFT 0 +#define VPECONTROL_TARGVPE 0x00003c00 +#define VPECONTROL_TARGVPE_SHIFT 10 +#define VPECONTROL_TE 0x00008000 +#define VPECONTROL_EXCPT 0x00070000 +#define VPECONTROL_EXCPT_SHIFT 16 +#define VPECONTROL_GSI 0x00100000 +#define VPECONTROL_YSI 0x00200000 + +/* + * MIPS32 VPEConf0 Register (CP0 Register 1, Select 2) + */ +#define VPECONF0_VPA 0x00000001 +#define VPECONF0_MVP 0x00000002 +#define VPECONF0_XTC 0x1fe00000 +#define VPECONF0_XTC_SHIFT 21 +#define VPECONF0_M 0x80000000 + +/* + * MIPS32 VPEConf1 Register (CP0 Register 1, Select 3) + */ +#define VPECONF1_NCP1 0x000000ff +#define VPECONF1_NCP1_SHIFT 0 +#define VPECONF1_NCP2 0x0003fc00 +#define VPECONF1_NCP2_SHIFT 10 +#define VPECONF1_NCX 0x0ff00000 +#define VPECONF1_NCX_SHIFT 20 + +/* + * MIPS32 YQMask Register (CP0 Register 1, Select 4) + */ +#define YQMASK_MASK 0x7fffffff +#define YQMASK_MASK_SHIFT 0 + +/* + * MIPS32 VPEOpt Register (CP0 Register 1, Select 7) + */ +#define VPEOPT_DWX0 0x00000001 +#define VPEOPT_DWX1 0x00000002 +#define VPEOPT_DWX2 0x00000004 +#define VPEOPT_DWX3 0x00000008 +#define VPEOPT_DWX4 0x00000010 +#define VPEOPT_DWX5 0x00000020 +#define VPEOPT_DWX6 0x00000040 +#define VPEOPT_DWX7 0x00000080 +#define VPEOPT_DWX 0x000000ff +#define VPEOPT_DWX_SHIFT 0 +#define VPEOPT_IWX0 0x00000100 +#define VPEOPT_IWX1 0x00000200 +#define VPEOPT_IWX2 0x00000400 +#define VPEOPT_IWX3 0x00000800 +#define VPEOPT_IWX4 0x00001000 +#define VPEOPT_IWX5 0x00002000 +#define VPEOPT_IWX6 0x00004000 +#define VPEOPT_IWX7 0x00008000 +#define VPEOPT_IWX 0x0000ff00 +#define VPEOPT_IWX_SHIFT 8 + +/* + * MIPS32 TCStatus Register (CP0 Register 2, Select 1) + */ +#define TCSTATUS_TASID 0x000000ff +#define TCSTATUS_TASID_SHIFT 0 +#define TCSTATUS_IXMT 0x00000400 +#define TCSTATUS_TKSU 0x00001800 +#define TCSTATUS_TKSU_SHIFT 11 +#define TCSTATUS_A 0x00002000 +#define TCSTATUS_DA 0x00008000 +#define TCSTATUS_IMPL 0x000f0000 +#define TCSTATUS_IMPL_SHIFT 16 +#define TCSTATUS_DT 0x00100000 +#define TCSTATUS_TDS 0x00200000 +#define TCSTATUS_TSST 0x00400000 +#define TCSTATUS_RNST 0x01800000 +#define TCSTATUS_RNST_SHIFT 23 +#define TCSTATUS_TCU0 0x10000000 +#define TCSTATUS_TCU1 0x20000000 +#define TCSTATUS_TCU2 0x40000000 +#define TCSTATUS_TCU3 0x80000000 + +/* + * MIPS32 TCBind Register (CP0 Register 2, Select 2) + */ +#define TCBIND_CURVPE 0x0000000f +#define TCBIND_CURVPE_SHIFT 0 +#define TCBIND_CURTC 0x1fe00000 +#define TCBIND_CURTC_SHIFT 21 + +/* + * MIPS32 TCHalt Register (CP0 Register 2, Select 4) + */ +#define TCHALT_H 0x00000001 + +/* + * MIPS32 SRSConf0 Register (CP0 Register 6, Select 1) + */ +#define SRSCONF0_SRS1 0x000003ff +#define SRSCONF0_SRS1_SHIFT 0 +#define SRSCONF0_SRS2 0x000ffc00 +#define SRSCONF0_SRS2_SHIFT 10 +#define SRSCONF0_SRS3 0x3ff00000 +#define SRSCONF0_SRS3_SHIFT 20 +#define SRSCONF0_M 0x80000000 + +/* + * MIPS32 SRSConf1 Register (CP0 Register 6, Select 2) + */ +#define SRSCONF1_SRS4 0x000003ff +#define SRSCONF1_SRS4_SHIFT 0 +#define SRSCONF1_SRS5 0x000ffc00 +#define SRSCONF1_SRS5_SHIFT 10 +#define SRSCONF1_SRS6 0x3ff00000 +#define SRSCONF1_SRS6_SHIFT 20 +#define SRSCONF1_M 0x80000000 + +/* + * MIPS32 SRSConf2 Register (CP0 Register 6, Select 3) + */ +#define SRSCONF2_SRS7 0x000003ff +#define SRSCONF2_SRS7_SHIFT 0 +#define SRSCONF2_SRS8 0x000ffc00 +#define SRSCONF2_SRS8_SHIFT 10 +#define SRSCONF2_SRS9 0x3ff00000 +#define SRSCONF2_SRS9_SHIFT 20 +#define SRSCONF2_M 0x80000000 + +/* + * MIPS32 SRSConf3 Register (CP0 Register 6, Select 4) + */ +#define SRSCONF3_SRS10 0x000003ff +#define SRSCONF3_SRS10_SHIFT 0 +#define SRSCONF3_SRS11 0x000ffc00 +#define SRSCONF3_SRS11_SHIFT 10 +#define SRSCONF3_SRS12 0x3ff00000 +#define SRSCONF3_SRS12_SHIFT 20 +#define SRSCONF3_M 0x80000000 + +/* + * MIPS32 SRSConf4 Register (CP0 Register 6, Select 5) + */ +#define SRSCONF4_SRS13 0x000003ff +#define SRSCONF4_SRS13_SHIFT 0 +#define SRSCONF4_SRS14 0x000ffc00 +#define SRSCONF4_SRS14_SHIFT 10 +#define SRSCONF4_SRS15 0x3ff00000 +#define SRSCONF4_SRS15_SHIFT 20 + +/* + * MIPS32 Config3 Register (CP0 Register 16, Select 3) + * New fields for MT + */ +#define CFG3_MT 0x00000004 + +#ifdef __ASSEMBLER__ + +/* + * MT Coprocessor 0 register numbers + */ +#define C0_MVPCONTROL $0,1 +#define C0_MVPCONF0 $0,2 +#define C0_MVPCONF1 $0,3 +#define C0_VPECONTROL $1,1 +#define C0_VPECONF0 $1,2 +#define C0_VPECONF1 $1,3 +#define C0_YQMASK $1,4 +#define C0_VPESCHEDULE $1,5 +#define C0_VPESCHEFBACK $1,6 +#define C0_VPEOPT $1,7 +#define C0_TCSTATUS $2,1 +#define C0_TCBIND $2,2 +#define C0_TCRESTART $2,3 +#define C0_TCHALT $2,4 +#define C0_TCCONTEXT $2,5 +#define C0_TCSCHEDULE $2,6 +#define C0_TCSCHEFBACK $2,7 +#define C0_SRSCONF0 $6,1 +#define C0_SRSCONF1 $6,2 +#define C0_SRSCONF2 $6,3 +#define C0_SRSCONF3 $6,4 +#define C0_SRSCONF4 $6,5 + +#else + +#define mips32_getmvpcontrol() _m32c0_mfc0(0,1) +#define mips32_setmvpcontrol(x) _m32c0_mtc0(0,1,x) +#define mips32_xchmvpcontrol(x) _m32c0_mxc0(0,1,x) + +#define mips32_getmvpconf0() _m32c0_mfc0(0,2) +#define mips32_setmvpconf0(x) _m32c0_mtc0(0,2,x) +#define mips32_xchmvpconf0(x) _m32c0_mxc0(0,2,x) + +#define mips32_getmvpconf1() _m32c0_mfc0(0,3) +#define mips32_setmvpconf1(x) _m32c0_mtc0(0,3,x) +#define mips32_xchmvpconf1(x) _m32c0_mxc0(0,3,x) + +#define mips32_getvpecontrol() _m32c0_mfc0(1,1) +#define mips32_setvpecontrol(x) _m32c0_mtc0(1,1,x) +#define mips32_xchvpecontrol(x) _m32c0_mxc0(1,1,x) + +#define mips32_getvpeconf0() _m32c0_mfc0(1,2) +#define mips32_setvpeconf0(x) _m32c0_mtc0(1,2,x) +#define mips32_xchvpeconf0(x) _m32c0_mxc0(1,2,x) + +#define mips32_getvpeconf1() _m32c0_mfc0(1,3) +#define mips32_setvpeconf1(x) _m32c0_mtc0(1,3,x) +#define mips32_xchvpeconf1(x) _m32c0_mxc0(1,3,x) + +#define mips32_getyqmask() _m32c0_mfc0(1,4) +#define mips32_setyqmask(x) _m32c0_mtc0(1,4,x) +#define mips32_xchyqmask(x) _m32c0_mxc0(1,4,x) + +#define mips32_getvpeschedule() _m32c0_mfc0(1,5) +#define mips32_setvpeschedule(x) _m32c0_mtc0(1,5,x) +#define mips32_xchvpeschedule(x) _m32c0_mxc0(1,5,x) + +#define mips32_getvpeschefback() _m32c0_mfc0(1,6) +#define mips32_setvpeschefback(x) _m32c0_mtc0(1,6,x) +#define mips32_xchvpeschefback(x) _m32c0_mxc0(1,6,x) + +#define mips32_getvpeopt() _m32c0_mfc0(1,7) +#define mips32_setvpeopt(x) _m32c0_mtc0(1,7,x) +#define mips32_xchvpeopt(x) _m32c0_mxc0(1,7,x) + +#define mips32_gettcstatus() _m32c0_mfc0(2,1) +#define mips32_settcstatus(x) _m32c0_mtc0(2,1,x) +#define mips32_xchtcstatus(x) _m32c0_mxc0(2,1,x) + +#define mips32_gettcbind() _m32c0_mfc0(2,2) +#define mips32_settcbind(x) _m32c0_mtc0(2,2,x) +#define mips32_xchtcbind(x) _m32c0_mxc0(2,2,x) + +#define mips32_gettcrestart() _m32c0_mfc0(2,3) +#define mips32_settcrestart(x) _m32c0_mtc0(2,3,x) +#define mips32_xchtcrestart(x) _m32c0_mxc0(2,3,x) + +#define mips32_gettchalt() _m32c0_mfc0(2,4) +#define mips32_settchalt(x) _m32c0_mtc0(2,4,x) +#define mips32_xchtchalt(x) _m32c0_mxc0(2,4,x) + +#define mips32_gettccontext() _m32c0_mfc0(2,5) +#define mips32_settccontext(x) _m32c0_mtc0(2,5,x) +#define mips32_xchtccontext(x) _m32c0_mxc0(2,5,x) + +#define mips32_gettcschedule() _m32c0_mfc0(2,6) +#define mips32_settcschedule(x) _m32c0_mtc0(2,6,x) +#define mips32_xchtcschedule(x) _m32c0_mxc0(2,6,x) + +#define mips32_gettcschefback() _m32c0_mfc0(2,7) +#define mips32_settcschefback(x) _m32c0_mtc0(2,7,x) +#define mips32_xchtcschefback(x) _m32c0_mxc0(2,7,x) + +#define mips32_getsrsconf0() _m32c0_mfc0(6,1) +#define mips32_setsrsconf0(x) _m32c0_mtc0(6,1,x) +#define mips32_xchsrsconf0(x) _m32c0_mxc0(6,1,x) + +#define mips32_getsrsconf1() _m32c0_mfc0(6,2) +#define mips32_setsrsconf1(x) _m32c0_mtc0(6,2,x) +#define mips32_xchsrsconf1(x) _m32c0_mxc0(6,2,x) + +#define mips32_getsrsconf2() _m32c0_mfc0(6,3) +#define mips32_setsrsconf2(x) _m32c0_mtc0(6,3,x) +#define mips32_xchsrsconf2(x) _m32c0_mxc0(6,3,x) + +#define mips32_getsrsconf3() _m32c0_mfc0(6,4) +#define mips32_setsrsconf3(x) _m32c0_mtc0(6,4,x) +#define mips32_xchsrsconf3(x) _m32c0_mxc0(6,4,x) + +#define mips32_getsrsconf4() _m32c0_mfc0(6,5) +#define mips32_setsrsconf4(x) _m32c0_mtc0(6,5,x) +#define mips32_xchsrsconf4(x) _m32c0_mxc0(6,5,x) + +#if !__mips16 +/* Access to other VPE/TC registers */ + +/* move from gpr */ +#define _m32c0_mftgpr(rt) \ +__extension__ ({ \ + unsigned long __res; \ + __asm__ __volatile__( \ + ".set push\n" \ + ".set noat\n" \ + "mftgpr\t%0,$" #rt "\n" \ + ".set pop\n" \ + : "=d" (__res)); \ + __res; \ +}) + +/* move to gpr */ +#define _m32c0_mttgpr(rd,v) \ +do { \ + __asm__ __volatile__( \ + ".set push\n" \ + ".set noat\n" \ + "mttgpr\t%z0,$" #rd "\n" \ + ".set pop\n" \ + : : "dJ" (v)); \ +} while (0) + +/* move from cp0 */ +#define _m32c0_mftc0(rt,sel) \ +__extension__ ({ \ + unsigned long __res; \ + __asm__ __volatile__( \ + "mftc0\t%0,$" #rt "," #sel \ + : "=d" (__res)); \ + __res; \ +}) + +/* move to cp0 */ +#define _m32c0_mttc0(rd,sel,v) \ +do { \ + __asm__ __volatile__( \ + "%(mttc0\t %z0,$" #rd "," #sel "; ehb%)" \ + : : "dJ" (v)); \ +} while (0) +#endif /* ! __mips16 */ + +/* + * targeted VPE register macros + */ +#define mips32_mt_settarget(tc) \ + mips32_setvpecontrol ( \ + (mips32_getvpecontrol () & ~(VPECONTROL_TARGTC)) \ + | ((tc) << VPECONTROL_TARGTC_SHIFT)) + +#define mips32_mt_gettarget() \ + ((mips32_getvpecontrol () & (VPECONTROL_TARGTC)) \ + >> VPECONTROL_TARGTC_SHIFT) + +/* + * Before using any mips32_mt_ macros you should ensure the + * destination VPE and TC are set with a call to mips32_mt_settarget() + */ + +/* + * Non-MT CP0 registers + */ +#define mips32_mt_getc0status() _m32c0_mftc0(12, 0) +#define mips32_mt_setc0status(val) _m32c0_mttc0(12, 0, val) +#define mips32_mt_getc0cause() _m32c0_mftc0(13, 0) +#define mips32_mt_setc0cause(val) _m32c0_mttc0(13, 0, val) +#define mips32_mt_getc0config() _m32c0_mftc0(16, 0) +#define mips32_mt_setc0config(val) _m32c0_mttc0(16, 0, val) +#define mips32_mt_getc0config1() _m32c0_mftc0(16, 1) +#define mips32_mt_setc0config1(val) _m32c0_mttc0(16, 1, val) +#define mips32_mt_getc0ebase() _m32c0_mftc0(15, 1) +#define mips32_mt_setc0ebase(val) _m32c0_mttc0(15, 1, val) + +/* + * Non-MT GPR registers + */ +#define mips32_mt_getsp() _m32c0_mftgpr(29) +#define mips32_mt_setsp(val) _m32c0_mttgpr(29, val) +#define mips32_mt_getgp() _m32c0_mftgpr(28) +#define mips32_mt_setgp(val) _m32c0_mttgpr(28, val) + +/* + * VPE + */ +#define mips32_mt_getvpecontrol() _m32c0_mftc0(1, 1) +#define mips32_mt_setvpecontrol(val) _m32c0_mttc0(1, 1, val) +#define mips32_mt_getvpeconf0() _m32c0_mftc0(1, 2) +#define mips32_mt_setvpeconf0(val) _m32c0_mttc0(1, 2, val) + +/* + * TC + */ +#define mips32_mt_gettcstatus() _m32c0_mftc0(2, 1) +#define mips32_mt_settcstatus(val) _m32c0_mttc0(2, 1, val) +#define mips32_mt_gettcbind() _m32c0_mftc0(2, 2) +#define mips32_mt_settcbind(val) _m32c0_mttc0(2, 2, val) +#define mips32_mt_gettcrestart() _m32c0_mftc0(2, 3) +#define mips32_mt_settcrestart(val) _m32c0_mttc0(2, 3, val) +#define mips32_mt_gettchalt() _m32c0_mftc0(2, 4) +#define mips32_mt_settchalt(val) _m32c0_mttc0(2, 4, val) +#define mips32_mt_gettccontext() _m32c0_mftc0(2, 5) +#define mips32_mt_settccontext(val) _m32c0_mttc0(2, 5, val) + + +/* + * MT Intrinsics + */ +#define mips_mt_fork(a, pv, cv) \ +__extension__ ({ \ + void * __a = (a); \ + unsigned int __cv = (cv); \ + unsigned int __res = (pv); \ + __asm__ __volatile (".set push; .set mt; fork %0,%1,%z2; .set pop" \ + : "+d" (__res) \ + : "d" (__a), "dJ" (__cv)); \ + __res; \ +}) + +#define mips_mt_yield(yq) \ +__extension__ ({ \ + unsigned int __yq = (yq); \ + unsigned int __res; \ + __asm__ __volatile (".set push; .set mt; yield %0,%z1; .set pop" \ + : "=d" (__res) \ + : "dJ" (__yq)); \ + __res; \ +}) + +#define mips_mt_dmt() \ +__extension__ ({ \ + unsigned int __res; \ + __asm__ __volatile (".set push; .set mt; dmt %0; .set pop" \ + : "=d" (__res)); \ + mips32_jr_hb(); \ + __res & VPECONTROL_TE; \ +}) + +#define mips_mt_emt() \ +__extension__ ({ \ + unsigned int __res; \ + __asm__ __volatile (".set push; .set mt; emt %0; ehb; .set pop" \ + : "=d" (__res)); \ + __res & VPECONTROL_TE; \ +}) + +#define mips_mt_dvpe() \ +__extension__ ({ \ + unsigned int __res; \ + __asm__ __volatile (".set push; .set mt; dvpe %0; .set pop" \ + : "=d" (__res)); \ + mips32_jr_hb(); \ + __res & MVPCONTROL_EVP; \ +}) + +#define mips_mt_evpe() \ +__extension__ ({ \ + unsigned int __res; \ + __asm__ __volatile (".set push; .set mt; evpe %0; ehb; .set pop" \ + : "=d" (__res)); \ + __res & MVPCONTROL_EVP; \ +}) + +#endif /* __ASSEMBLER__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _MIPS_MT_H_ */ diff --git a/libgloss/mips/include/mips/notlb.h b/libgloss/mips/include/mips/notlb.h new file mode 100644 index 0000000..53565a1 --- /dev/null +++ b/libgloss/mips/include/mips/notlb.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _NOTLB_H_ +#define _NOTLB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ROM_BASE +#define ROM_BASE 0xbfc00000 /* standard ROM base address */ +#endif + +#ifdef __ASSEMBLER__ + +/* + * Stub 32-bit memory regions + */ +#define KSEG0_BASE 0x80000000 +#define KSEG1_BASE 0xa0000000 +#define KSEG0_SIZE 0x20000000 +#define KSEG1_SIZE 0x20000000 +#define RVEC_BASE ROM_BASE + +/* + * Translate a kernel address in KSEG0 or KSEG1 to a real + * physical address and back. + */ +#define KVA_TO_PA(v) ((v) & 0x1fffffff) +#define PA_TO_KVA0(pa) ((pa) | 0x80000000) +#define PA_TO_KVA1(pa) ((pa) | 0xa0000000) + +/* translate between KSEG0 and KSEG1 addresses */ +#define KVA0_TO_KVA1(v) ((v) | 0x20000000) +#define KVA1_TO_KVA0(v) ((v) & ~0x20000000) + +#else /* __ASSEMBLER__ */ +/* + * Standard address types + */ +#ifndef _PADDR_T_DEFINED_ +typedef unsigned long paddr_t; /* a physical address */ +#define _PADDR_T_DEFINED_ +#endif +#ifndef _VADDR_T_DEFINED_ +typedef unsigned long vaddr_t; /* a virtual address */ +#define _VADDR_T_DEFINED_ +#endif + +/* + * Stub 32-bit memory regions + */ +#define KSEG0_BASE ((void *)0x80000000) +#define KSEG1_BASE ((void *)0xa0000000) +#define KSEG0_SIZE 0x20000000u +#define KSEG1_SIZE 0x20000000u + +#define RVEC_BASE ((void *)ROM_BASE) /* reset vector base */ + +/* + * Translate a kernel virtual address in KSEG0 or KSEG1 to a real + * physical address and back. + */ +#define KVA_TO_PA(v) ((paddr_t)(v) & 0x1fffffff) +#define PA_TO_KVA0(pa) ((void *) ((pa) | 0x80000000)) +#define PA_TO_KVA1(pa) ((void *) ((pa) | 0xa0000000)) + +/* translate between KSEG0 and KSEG1 virtual addresses */ +#define KVA0_TO_KVA1(v) ((void *) ((unsigned)(v) | 0x20000000)) +#define KVA1_TO_KVA0(v) ((void *) ((unsigned)(v) & ~0x20000000)) + +/* Test for KSEGS */ +#define IS_KVA(v) ((int)(v) < 0) +#define IS_KVA0(v) (((unsigned)(v) >> 29) == 0x4) +#define IS_KVA1(v) (((unsigned)(v) >> 29) == 0x5) +#define IS_KVA01(v) (((unsigned)(v) >> 30) == 0x2) + +/* convert register type to address and back */ +#define VA_TO_REG(v) ((long)(v)) /* sign-extend 32->64 */ +#define REG_TO_VA(v) ((void *)(long)(v)) /* truncate 64->32 */ + +#endif /* __ASSEMBLER__ */ + +#ifdef __cplusplus +} +#endif +#endif /* _NOTLB_H_*/ diff --git a/libgloss/mips/include/mips/prid.h b/libgloss/mips/include/mips/prid.h new file mode 100644 index 0000000..96ae397 --- /dev/null +++ b/libgloss/mips/include/mips/prid.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS_PRID_H_ +#define _MIPS_PRID_H_ + +/* + * MIPS CPU types + */ +#define PRID_R2000 0x01 /* MIPS R2000 CPU ISA I */ +#define PRID_R3000 0x02 /* MIPS R3000 CPU ISA I */ +#define PRID_R6000 0x03 /* MIPS R6000 CPU ISA II */ +#define PRID_R4000 0x04 /* MIPS R4000/4400 CPU ISA III */ +#define PRID_LR33K 0x05 /* LSI Logic R3000 derivate ISA I */ +#define PRID_R6000A 0x06 /* MIPS R6000A CPU ISA II */ +#define PRID_R3IDT 0x07 /* IDT R3000 derivates ISA I */ +#define PRID_R3IDT_R3041 0x07 /* R3041 (cp_rev field) */ +#define PRID_R3IDT_R36100 0x10 /* R36100 (cp_rev field) */ +#define PRID_R10000 0x09 /* MIPS R10000/T5 CPU ISA IV */ +#define PRID_R4200 0x0a /* MIPS R4200 CPU (ICE) ISA III */ +#define PRID_R4300 0x0b /* NEC VR4300 CPU ISA III */ +#define PRID_R4100 0x0c /* NEC VR4100 CPU ISA III */ +#define PRID_R8000 0x10 /* MIPS R8000 Blackbird/TFP ISA IV */ +#define PRID_RC6457X 0x15 /* IDT RC6457X CPU ISA IV */ +#define PRID_RC3233X 0x18 /* IDT RC3233X CPU ISA MIPS32 */ +#define PRID_R4600 0x20 /* QED R4600 Orion ISA III */ +#define PRID_R4700 0x21 /* QED R4700 Orion ISA III */ +#define PRID_R3900 0x22 /* Toshiba/Philips R3900 CPU ISA I */ +#define PRID_R4650 0x22 /* QED R4650/R4640 CPU ISA III */ +#define PRID_R5000 0x23 /* MIPS R5000 CPU ISA IV */ +#define PRID_RC3236X 0x26 /* IDT RC3236X CPU ISA MIPS32 */ +#define PRID_RM7000 0x27 /* QED RM7000 CPU ISA IV */ +#define PRID_RM52XX 0x28 /* QED RM52XX CPU ISA IV */ +#define PRID_RC6447X 0x30 /* IDT RC6447X CPU ISA III */ +#define PRID_R5400 0x54 /* NEC Vr5400 CPU ISA IV */ +#define PRID_R5500 0x55 /* NEC Vr5500 CPU ISA IV */ +#define PRID_JADE 0x80 /* MIPS Jade (obsolete name) ISA MIPS32 */ +#define PRID_4KC 0x80 /* MIPS 4Kc (TLB) ISA MIPS32 */ +#define PRID_5KC 0x81 /* MIPS 5Kc ISA MIPS64 */ +#define PRID_20KC 0x82 /* MIPS 20Kc ISA MIPS64 */ +#define PRID_4KMP 0x83 /* MIPS 4Kp/4Km (FM) ISA MIPS32 */ +#define PRID_4KEC 0x84 /* MIPS 4KEc (TLB) ISA MIPS32 */ +#define PRID_4KEMP 0x85 /* MIPS 4KEm/4KEp (FM) ISA MIPS32 */ +#define PRID_4KSC 0x86 /* MIPS 4KSc ISA MIPS32 */ +#define PRID_M4K 0x87 /* MIPS M4K ISA MIPS32r2 */ +#define PRID_25KF 0x88 /* MIPS 25Kf ISA MIPS64 */ +#define PRID_5KE 0x89 /* MIPS 5KE ISA MIPS64r2 */ +#define PRID_4KEC_R2 0x90 /* MIPS 4KEc (TLB) ISA MIPS32r2 */ +#define PRID_4KEMP_R2 0x91 /* MIPS 4KEm/4KEp (FM) ISA MIPS32r2 */ +#define PRID_4KSD 0x92 /* MIPS 4KSd ISA MIPS32r2 */ +#define PRID_24K 0x93 /* MIPS 24K ISA MIPS32r2 */ +#define PRID_34K 0x95 /* MIPS 34K ISA MIPS32r2 */ +#define PRID_24KE 0x96 /* MIPS 24KE ISA MIPS32r2 */ +#define PRID_74K 0x97 /* MIPS 74K ISA MIPS32r2 */ +#define PRID_1004K 0x99 /* MIPS 1004K ISA MIPS32r2 */ +#define PRID_1074K 0x9A /* MIPS 1074K ISA MIPS32r2 */ +#define PRID_M14K 0x9B /* MIPS M14K ISA MIPS32r2 */ +#define PRID_M14KC 0x9C /* MIPS M14KC ISA MIPS32r2 */ +#define PRID_M14KE 0x9D /* MIPS M14KE ISA MIPS32r2 */ +#define PRID_M14KEC 0x9E /* MIPS M14KEC ISA MIPS32r2 */ +#define PRID_INTERAPTIV_UP 0xA0 /* MIPS INTERAPTIV UP ISA MIPS32r2 */ +#define PRID_INTERAPTIV_MP 0xA1 /* MIPS INTERAPTIV MP ISA MIPS32r2 */ +#define PRID_PROAPTIV_UP 0xA2 /* MIPS PROAPTIV UP ISA MIPS32r2 */ +#define PRID_PROAPTIV_MP 0xA3 /* MIPS PROAPTIV MP ISA MIPS32r2 */ +#define PRID_M5100 0xA6 /* MIPS WARRIOR M5100 ISA MIPS32r2 */ +#define PRID_M5150 0xA7 /* MIPS WARRIOR M5150 ISA MIPS32r2 */ +#define PRID_P5600 0xA8 /* MIPS WARRIOR P5600 ISA MIPS32r2 */ +#define PRID_I6400 0xA9 /* MIPS I6400 ISA MIPS64r6 */ + +/* + * MIPS FPU types + */ +#define PRID_SOFT 0x00 /* Software emulation ISA I */ +#define PRID_R2360 0x01 /* MIPS R2360 FPC ISA I */ +#define PRID_R2010 0x02 /* MIPS R2010 FPC ISA I */ +#define PRID_R3010 0x03 /* MIPS R3010 FPC ISA I */ +#define PRID_R6010 0x04 /* MIPS R6010 FPC ISA II */ +#define PRID_R4010 0x05 /* MIPS R4000/R4400 FPC ISA II */ +#define PRID_LR33010 0x06 /* LSI Logic derivate ISA I */ +#define PRID_R10010 0x09 /* MIPS R10000/T5 FPU ISA IV */ +#define PRID_R4210 0x0a /* MIPS R4200 FPC (ICE) ISA III */ +#define PRID_UNKF1 0x0b /* unnanounced product cpu ISA III */ +#define PRID_R8010 0x10 /* MIPS R8000 Blackbird/TFP ISA IV */ +#define PRID_RC6457XF 0x15 /* IDT RC6457X FPU ISA IV */ +#define PRID_R4610 0x20 /* QED R4600 Orion ISA III */ +#define PRID_R3SONY 0x21 /* Sony R3000 based FPU ISA I */ +#define PRID_R3910 0x22 /* Toshiba/Philips R3900 FPU ISA I */ +#define PRID_R5010 0x23 /* MIPS R5000 FPU ISA IV */ +#define PRID_RM7000F 0x27 /* QED RM7000 FPU ISA IV */ +#define PRID_RM52XXF 0x28 /* QED RM52X FPU ISA IV */ +#define PRID_RC6447XF 0x30 /* IDT RC6447X FPU ISA III */ +#define PRID_R5400F 0x54 /* NEC Vr5400 FPU ISA IV */ +#define PRID_R5500F 0x55 /* NEC Vr5500 FPU ISA IV */ +#define PRID_20KCF 0x82 /* MIPS 20Kc FPU ISA MIPS64 */ +#define PRID_5KF 0x81 /* MIPS 5Kf FPU ISA MIPS64 */ +#define PRID_25KFF 0x88 /* MIPS 25Kf FPU ISA MIPS64 */ +#define PRID_5KEF 0x89 /* MIPS 5KEf FPU ISA MIPS64r2 */ +#define PRID_24KF 0x93 /* MIPS 24Kf FPU ISA MIPS32r2 */ +#define PRID_34KF 0x95 /* MIPS 34K FPU ISA MIPS32r2 */ +#define PRID_24KEF 0x96 /* MIPS 24KE FPU ISA MIPS32r2 */ +#define PRID_74KF 0x97 /* MIPS 74K FPU ISA MIPS32r2 */ + +#endif /* _MIPS_PRID_H_ */ diff --git a/libgloss/mips/include/mips/regdef.h b/libgloss/mips/include/mips/regdef.h new file mode 100644 index 0000000..4e4f004 --- /dev/null +++ b/libgloss/mips/include/mips/regdef.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MIPS_REGDEF_H_ +#define _MIPS_REGDEF_H_ + +#define zero $0 + +#define AT $1 + +#define v0 $2 +#define v1 $3 +#define va0 $2 +#define va1 $3 + +#define vt0 $2 +#define vt1 $3 + +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 + +#if _MIPS_SIM==_ABIN32 || _MIPS_SIM==_ABI64 || _MIPS_SIM==_ABIEABI +#define a4 $8 +#define a5 $9 +#define a6 $10 +#define a7 $11 +#define t0 $12 +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define ta0 $8 /* alias for $a4 */ +#define ta1 $9 /* alias for $a5 */ +#define ta2 $10 /* alias for $a6 */ +#define ta3 $11 /* alias for $a7 */ +#else +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define ta0 $12 /* alias for $t4 */ +#define ta1 $13 /* alias for $t5 */ +#define ta2 $14 /* alias for $t6 */ +#define ta3 $15 /* alias for $t7 */ +#endif + +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define s8 $30 /* == fp */ + +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 + +#define gp $28 + +#define sp $29 +#define fp $30 +#define ra $31 + +#define r0 $0 +#define r1 $1 +#define r2 $2 +#define r3 $3 +#define r4 $4 +#define r5 $5 +#define r6 $6 +#define r7 $7 +#define r8 $8 +#define r9 $9 +#define r10 $10 +#define r11 $11 +#define r12 $12 +#define r13 $13 +#define r14 $14 +#define r15 $15 +#define r16 $16 +#define r17 $17 +#define r18 $18 +#define r19 $19 +#define r20 $20 +#define r21 $21 +#define r22 $22 +#define r23 $23 +#define r24 $24 +#define r25 $25 +#define r26 $26 +#define r27 $27 +#define r28 $28 +#define r29 $29 +#define r30 $30 +#define r31 $31 + +#endif /*_MIPS_REGDEF_H_*/ diff --git a/libgloss/mips/include/mips/uhi_syscalls.h b/libgloss/mips/include/mips/uhi_syscalls.h new file mode 100644 index 0000000..e4bb6cc --- /dev/null +++ b/libgloss/mips/include/mips/uhi_syscalls.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _UHI_SYSCALLS_ +#define _UHI_SYSCALLS_ + +#define __MIPS_UHI_EXIT 1 +#define __MIPS_UHI_OPEN 2 +#define __MIPS_UHI_CLOSE 3 +#define __MIPS_UHI_READ 4 +#define __MIPS_UHI_WRITE 5 +#define __MIPS_UHI_LSEEK 6 +#define __MIPS_UHI_UNLINK 7 +#define __MIPS_UHI_FSTAT 8 +#define __MIPS_UHI_ARGC 9 +#define __MIPS_UHI_ARGLEN 10 +#define __MIPS_UHI_ARGN 11 +#define __MIPS_UHI_RAMRANGE 12 +#define __MIPS_UHI_LOG 13 +#define __MIPS_UHI_ASSERT 14 +#define __MIPS_UHI_EXCEPTION 15 +#define __MIPS_UHI_PREAD 19 +#define __MIPS_UHI_PWRITE 20 +#define __MIPS_UHI_LINK 22 +#define __MIPS_UHI_BOOTFAIL 23 +#define __MIPS_UHI_BREAK 24 + +#define __MIPS_UHI_BF_CACHE 1 + +#define __xstr(s) __str(s) +#define __str(s) #s +#define __MIPS_UHI_SYSCALL_NUM 1 + +#ifdef __MIPS_SDBBP__ + #define SYSCALL(NUM) "\tsdbbp " __xstr (NUM) + #define ASM_SYSCALL(NUM) sdbbp NUM +#else + #define SYSCALL(NUM) "\tsyscall " __xstr (NUM) + #define ASM_SYSCALL(NUM) syscall NUM +#endif + +#endif // _UHI_SYSCALLS_ diff --git a/libgloss/mips/include/mips/version.h b/libgloss/mips/include/mips/version.h new file mode 100644 index 0000000..d2ca567 --- /dev/null +++ b/libgloss/mips/include/mips/version.h @@ -0,0 +1,4 @@ +/* This file just defines the current version number of MIPS HAL library. */ + +#define __MIPS_HAL_VERSION__ "3.0.0" + diff --git a/libgloss/mips/malta32-yamon.ld b/libgloss/mips/malta32-yamon.ld new file mode 100644 index 0000000..31e0778 --- /dev/null +++ b/libgloss/mips/malta32-yamon.ld @@ -0,0 +1,316 @@ +/* + * A malta based target independent link script to produce UHI + * compliant binaries with varying levels of system initialization + * support. + */ + +__entry = DEFINED(__reset_vector) ? 0xbfc00000 : _start; +ENTRY(__entry) +OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips") +GROUP(-lc -lyamon -luhi -lgcc -lhal) +SEARCH_DIR(.) + +/* Define where the yamon entry point table is */ +__yamon_functions = 0x9fc00500; + +__DYNAMIC = 0; +STARTUP(crt0.o) +/* Force the exception handler to be registered */ +EXTERN(__register_excpt_handler) +/* Force the exception handler to be included in the link */ +EXTERN(__exception_entry) +/* + * Require verbose exceptions. This can be changed to pull in + * __exception_handle_quiet to reduce code size but be less + * informative + */ +EXTERN(__exception_handle_verbose) +/* Force ISRs 0-7 to be included in the link */ +EXTERN(_isr_vec_7) +/* Require the UHI getargs support */ +EXTERN(__getargs) +/* Include the breakpoint exception handler. */ +EXTERN (__uhi_break); + +/* + * Set the location of the top of the stack. A value of 0 means + * that it will be automatically placed at the highest address + * available as described by the __memory_* setttings + */ +PROVIDE (__stack = 0); + +/* Size of the memory returned by _get_ram_range */ +PROVIDE (__memory_size = 3M); + +/* Base of the memory returned by _get_ram_range */ +PROVIDE (__memory_base = 0x80000000); + +/* Stride length for tlb software invalidate for tlbinvf + * (mipsXXr3+). Some MIPS implementations may layout the sets/ways + * differently in the index register. Either sets LSB or ways LSB. + * + * By setting this to 1 we presume that sets come first. The default boot + * code will decrement this value from the Number of TLB entries. + */ +PROVIDE (__tlb_stride_length = 1); + +/* By default, XPA is not used even if available. To enable XPA, + * __enable_xpa should be 1. + */ +PROVIDE (__enable_xpa = 0); + +/* + * 0 = Do not use exception handler present in boot for UHI + * 1 = Use exception handler present in boot for UHI if BEV is 0 at + * startup + * 2 = Always use exception handler present in boot for UHI + */ +PROVIDE (__use_excpt_boot = 0); +/* + * Include the code to be able to return to boot context. This is + * necessary if __use_excpt_boot != 0. + */ +EXTERN (__register_excpt_boot); + +ASSERT (DEFINED(__register_excpt_boot) || __use_excpt_boot == 0, + "Registration for boot context is required for UHI chaining") + +/* Control if subnormal floating-point values are flushed to zero in + hardware. This applies to both FPU and MSA operations. */ +PROVIDE (__flush_to_zero = 1); + +/* Set up the public symbols depending on whether the user has chosen + quiet or verbose exception handling above */ +EXTERN (__exception_handle); +PROVIDE(__exception_handle = (DEFINED(__exception_handle_quiet) + ? __exception_handle_quiet + : __exception_handle_verbose)); +PROVIDE(_mips_handle_exception = __exception_handle); + +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we multiple object file + * formats, as some prepend an underscore. + */ +PROVIDE (hardware_exit_hook = 0); +PROVIDE (hardware_hazard_hook = 0); +PROVIDE (hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); + +/* The default base address for application code is 0x80200000 which + leaves 2M of space at the start of KSEG0 for a bootloader. */ +PROVIDE (__app_start = DEFINED(__reset_vector) ? 0x80000000 : 0x80200000); +/* Set default vector spacing to 32 bytes. */ +PROVIDE (__isr_vec_space = 32); +/* Leave space for 9 vector entries by default. 8 entry points and one + fallback handler. */ +PROVIDE (__isr_vec_count = 9); +/* + * The start of flash must be set if including boot code. By default + * the use of boot code will mean that application code is copied + * from flash to RAM at runtime before being executed. + */ +PROVIDE (__flash_start = DEFINED(__reset_vector) ? 0xbfc00000 : __app_start); + +SECTIONS +{ + /* Start of bootrom */ + .bootrom 0x9fc00000 : /* Runs uncached (from 0x9fc00000) until I$ is + initialized. */ + AT (__flash_start) + { + *(.reset) /* Reset entry point. */ + *(.boot) /* Boot code. */ + . = ALIGN(8); + } = 0 + + PROVIDE (__flash_app_start = SIZEOF(.bootrom) + __flash_start); + + /* Start of the application */ + .exception_vector ALIGN(__app_start, 0x1000) : + AT (__flash_app_start) + { + __excpt_ebase = ABSOLUTE(.); + __base = .; + KEEP(* (.text.__exception_entry)) + . = __base + 0x200; + KEEP(* (SORT(.text.__isr_vec*))) + /* Leave space for all the vector entries */ + . = __base + 0x200 + (__isr_vec_space * __isr_vec_count); + ASSERT(__isr_vec_space == (DEFINED(__isr_vec_sw1) + ? __isr_vec_sw1 - __isr_vec_sw0 + : __isr_vec_space), + "Actual ISR vector spacing does not match __isr_vec_space"); + ASSERT(__base + 0x200 == (DEFINED(__isr_vec_sw0) + ? __isr_vec_sw0 & 0xfffffffe : __base + 0x200), + "__isr_vec_sw0 is not placed at EBASE + 0x200"); + . = ALIGN(8); + } = 0 + + .text : { + _ftext = . ; + PROVIDE (eprol = .); + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.mips16.fn.*) + *(.mips16.call.*) + } + .init : { + KEEP (*(.init)) + } + .fini : { + KEEP (*(.fini)) + } + .rel.sdata : { + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + } + PROVIDE (etext = .); + _etext = .; + + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } + .jcr : { KEEP (*(.jcr)) } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + + KEEP (*crtbegin.o(.ctors)) + + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + + . = .; + .MIPS.abiflags : { + __MIPS_abiflags_start = .; + *(.MIPS.abiflags) + __MIPS_abiflags_end = .; + } + .rodata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + . = ALIGN(16); + _fdata = .; + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + . = ALIGN(8); + MIPS_REVISION = DEFINED (__mips_isa_rev) ? ABSOLUTE(__mips_isa_rev) : 0; + GP_OFFSET = (MIPS_REVISION < 7) ? 0x8000 : 0; + _gp = . + GP_OFFSET; + __global = _gp; + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + . = ALIGN(4); + PROVIDE (edata = .); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + . = ALIGN(4); + PROVIDE (end = .); + _end = .; + /* Now place the data that is only needed within start.S and can be + overwritten by the heap. */ + .startdata : { + *(.startdata) + } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to + the beginning of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_ranges 0 : { *(.debug_ranges) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /* Special sections generated by gcc */ + /* Newer GNU linkers strip by default */ + .mdebug.abi32 0 : { KEEP(*(.mdebug.abi32)) } + .mdebug.abiN32 0 : { KEEP(*(.mdebug.abiN32)) } + .mdebug.abi64 0 : { KEEP(*(.mdebug.abi64)) } + .mdebug.abiO64 0 : { KEEP(*(.mdebug.abiO64)) } + .mdebug.eabi32 0 : { KEEP(*(.mdebug.eabi32)) } + .mdebug.eabi64 0 : { KEEP(*(.mdebug.eabi64)) } + .gcc_compiled_long32 0 : { KEEP(*(.gcc_compiled_long32)) } + .gcc_compiled_long64 0 : { KEEP(*(.gcc_compiled_long64)) } +} diff --git a/libgloss/mips/mti32.ld b/libgloss/mips/mti32.ld index 3c8daf6..f54fdac 100644 --- a/libgloss/mips/mti32.ld +++ b/libgloss/mips/mti32.ld @@ -3,7 +3,6 @@ the simulator. */ ENTRY(_start) -OUTPUT_ARCH("mips:isa32r2") OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips") GROUP(-lc -lidt -lgcc) SEARCH_DIR(.) @@ -56,15 +55,30 @@ SECTIONS PROVIDE (etext = .); _etext = .; - .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } .eh_frame : { /* The .eh_frame section from the crtend file contains the end of eh_frame marker and it must be last. */ KEEP (*(EXCLUDE_FILE (*crtend.o) .eh_frame)) KEEP (*(.eh_frame)) } - .gcc_except_table : { *(.gcc_except_table) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : { *(.gnu_extab .gnu_extab.*) } .jcr : { KEEP (*(.jcr)) } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } .ctors : { /* gcc uses crtbegin.o to find the start of diff --git a/libgloss/mips/mti64.ld b/libgloss/mips/mti64.ld index 74d7784..af35af5 100644 --- a/libgloss/mips/mti64.ld +++ b/libgloss/mips/mti64.ld @@ -5,7 +5,6 @@ each other (e.g., MIPS32r2 and MIPS64). */ ENTRY(_start) -OUTPUT_ARCH("mips:isa64r2") OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips") GROUP(-lc -lidt -lgcc) SEARCH_DIR(.) diff --git a/libgloss/mips/mti64_n32.ld b/libgloss/mips/mti64_n32.ld index 5098a88..47b26f8 100644 --- a/libgloss/mips/mti64_n32.ld +++ b/libgloss/mips/mti64_n32.ld @@ -8,7 +8,6 @@ o32 ABI targets in OUTPUT_FORMAT. */ ENTRY(_start) -OUTPUT_ARCH("mips:isa64r2") OUTPUT_FORMAT("elf32-ntradlittlemips", "elf32-ntradbigmips", "elf32-ntradlittlemips") GROUP(-lc -lidt -lgcc) SEARCH_DIR(.) diff --git a/libgloss/mips/regs.S b/libgloss/mips/regs.S index e4b1343..ac29354 100644 --- a/libgloss/mips/regs.S +++ b/libgloss/mips/regs.S @@ -98,7 +98,10 @@ #define SR_SX 0x00000040 /* Supervisor extended addressing enabled */ #define SR_UX 0x00000020 /* User extended addressing enabled */ -#define SR_MSA 0x08000000 /* MSA ASE */ +#define SR_IE 0x00000001 /* Interrupt enable */ + +#define SR_MX 0x01000000 /* MDMX or DSP ASE */ +#define CFG5_MSAEN 0x08000000 /* MSA ASE */ /* Standard (R4000) cache operations. Taken from "MIPS R4000 Microprocessor User's Manual" 2nd edition: */ diff --git a/libgloss/mips/rules/mipshal.mk b/libgloss/mips/rules/mipshal.mk new file mode 100644 index 0000000..7d7f099 --- /dev/null +++ b/libgloss/mips/rules/mipshal.mk @@ -0,0 +1,135 @@ +# Copyright 2015, Imagination Technologies Limited and/or its +# affiliated group companies. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# Usage: +# +# "include mipshal.mk" should be included in the top level makefile of the +# project seeking to use this file. The variables CC and LD will be defined +# by this file. The variables CFLAGS and LDFLAGS will be extended by this +# file. +# +# Symbols that are to be overwridden should be defined in the the makefile +# before "include mipshal.mk" or passed to make on the command line in the +# form 'make STACK=0x1000' or 'make FLASH_START=0xBFC00000'. +# +# Care should be taken to ensure that no pre-existing environment variables +# collide with the set of variables that this file inspects as unintended +# results may happen. + +# Portable 'lowercase' func. +lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1)))))))))))))))))))))))))) + +# Default values for the linker script symbols listed below are +# defined in the linker script. + +# These are linker script symbols that are prefixed with '__" +priv_symbols = MEMORY_BASE MEMORY_SIZE STACK +priv_symbols += BEV_OVERRIDE +priv_symbols += ENABLE_XPA +priv_symbols += FLUSH_TO_ZERO +priv_symbols += FLASH_START APP_START FLASH_APP_START +priv_symbols += ISR_VEC_SPACE ISR_VECTOR_COUNT + +comma := , + +# A bit of makefile magic: +# foreach symbol in overridable ld-symbols : +# If symbol has a value, produce a linker argument for that symbol. +MIPS_HAL_LDFLAGS = $(foreach a,$(priv_symbols),$(if $($a),-Wl$(comma)--defsym$(comma)__$(call lc,$(a))=$($a))) + +# Linker scripts for 32 & 64bit and ABI flags. +LDSCRIPT32 ?= uhi32.ld +LDSCRIPT64 ?= uhi64_64.ld +LDSCRIPTN32 ?= uhi64_n32.ld + +ifdef ENDIAN + ifeq ($(ENDIAN), EL) + ENDIANF = -EL + else + ifeq ($(ENDIAN), EB) + ENDIANF = -EB + else + $(error Endian must be either EL, EB or undefined for default) + endif + endif +endif + +# Pick the appropiate flags based on $(ABI) +ifeq ($(ABI), 32) + MIPS_TOOLCHAIN ?= mips-mti-elf + LDSCRIPT ?= $(LDSCRIPT32) +else + ifeq ($(ABI), 64) + MIPS_TOOLCHAIN ?= mips-img-elf + LDSCRIPT ?= $(LDSCRIPT64) + else + ifeq ($(ABI), n32) + MIPS_TOOLCHAIN ?= mips-img-elf + LDSCRIPT ?= $(LDSCRIPTN32) + else + $(error ABI must one of 32,64,n32) + endif + endif +endif + +ifeq ($(ROMABLE),1) + MIPS_HAL_LDFLAGS += -T bootcode.ld +endif + +ifdef ELF_ENTRY + MIPS_HAL_LDFLAGS += -Wl,--entry,$(ELF_ENTRY) +endif + +ifndef MIPS_ELF_ROOT + $(error MIPS_ELF_ROOT must be set to point to toolkit installation root) +endif + +ifeq ($(OS),Windows_NT) + CROSS_COMPILE=$(subst \,/,$(MIPS_ELF_ROOT))/bin/$(MIPS_TOOLCHAIN)- + SREC2HEX=$(subst \,/,$(MIPS_ELF_ROOT))/share/mips/rules/srec2hex.pl +else + CROSS_COMPILE=$(MIPS_ELF_ROOT)/bin/$(MIPS_TOOLCHAIN)- + SREC2HEX=$(MIPS_ELF_ROOT)/share/mips/rules/srec2hex.pl +endif + +CC = $(CROSS_COMPILE)gcc +CFLAGS += -mabi=$(ABI) $(ENDIANF) +LD = $(CC) +LDFLAGS += $(MIPS_HAL_LDFLAGS) -mabi=$(ABI) $(ENDIANF) -T $(LDSCRIPT) + +OBJDUMP = $(CROSS_COMPILE)objdump +OBJCOPY = $(CROSS_COMPILE)objcopy +READELF = $(CROSS_COMPILE)readelf +NM = $(CROSS_COMPILE)nm +STRIP = $(CROSS_COMPILE)strip + +%.rec: %.elf + $(OBJCOPY) -O srec $^ $@ + +%.hex: %.rec + $(SREC2HEX) -EL $^ > $@ diff --git a/libgloss/mips/rules/srec2hex.pl b/libgloss/mips/rules/srec2hex.pl new file mode 100755 index 0000000..59ce1bf --- /dev/null +++ b/libgloss/mips/rules/srec2hex.pl @@ -0,0 +1,196 @@ +#!/bin/env perl + +# Copyright (C) 2018 MIPS Tech, LLC +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# File: srec2hex.pl +# +# Description: +# This script converts an S-record file to a MIPS HEX file useful for +# some simulation environments +# +# Usage: +# srec2hex.pl -EL|-EB inputfile [outputfile] +# + +use File::Basename; +use Cwd; + +# Init global variables +$Endian = ""; +$Debug = 0; +$Verbose = 0; +$IFile = ""; +$IFH = "STDIN"; +$OFile = ""; +$OFH = "STDOUT"; + +# Parse command line for switches +$Errors = 0; +while (@ARGV && ($ARGV[0] =~ /^-./)) # Check for switches +{ + $ARGV[0] =~ /^-help$/ && ($Errors++, shift(@ARGV), next); + $ARGV[0] =~ /^-verbose$/ && ($Verbose = 1, shift(@ARGV), next); + $ARGV[0] =~ /^-EL$/ && ($Endian = $ARGV[0], shift(@ARGV), next); + $ARGV[0] =~ /^-EB$/ && ($Endian = $ARGV[0], shift(@ARGV), next); + print STDERR "\n$0: Unknown qualifier: $ARGV[0]\n"; + $Errors++; + last; +} + +$Errors++ if ($Endian eq ""); +if ($#ARGV > 1) { + $Errors++; +} else { + $IFile = $ARGV[0] if ($#ARGV >= 0); + $OFile = $ARGV[1] if ($#ARGV == 1); + if ($IFile ne "") { + if (! -f $IFile) { + print STDERR "\n$0: ERROR: Input file $IFile does not exist\n"; + $Errors++; + } else { + if (! open (IFILE, "< $IFile")) { + printf "\n$0: ERROR: Failed to open input file $IFile - $!\n"; + $Errors++; + } + } + $IFH = "IFILE"; + } + if ($OFile ne "") { + if (! open (OFILE, "> $OFile")) { + printf "\n$0: ERROR: Failed to open output file $OFile - $!\n"; + close(IFILE); + $Errors++; + } + $OFH = "OFILE"; + } +} + +if ($Errors > 0) { + $usage = +"Usage: $0 -E{B|L} [qualifiers] [input-file] [[output-file]] + -EB Convert big-endian S-Record file + -EL Convert little-endian S-Record file + -help Output this message and exit + -verbose Emit verbose messages +"; + printf STDERR $usage; + exit(1); +} + +printf $OFH "\# Endian %s\n", ($Endian eq "-EB") ? "Big" : "Little"; + +my $word = ""; +my $start; +my $incr; + +if ($Endian eq "-EL") { + $start = 6; + $incr = -2; + $word = "00000000"; +} else { + $start = 0; + $incr = 2; +} +my $byteno = $start; +my $tofill = 4; +my $waddr = ""; +my $naddr = ""; + +while (<$IFH>) { + my $line = $_; + my $dbindex; + my $addr; + my $datablock; + chomp $line; + + last if $line =~ /^S[7-9]/ ; + next if $line =~ /^S0/ || $line =~ /^S[4-6]/ ; + + my $reclen = hex(substr $line, 2, 2); + + if ( $line =~ /^S1/ ) { + $addr = hex(substr $line, 4, 4); + $datablock = substr $line, 8; + $reclen -= 2; + } elsif ( $line =~ /^S2/ ) { + $addr = hex(substr $line, 4, 6); + $datablock = substr $line, 10; + $reclen -= 3; + } elsif ( $line =~ /^S3/ ) { + $addr = hex(substr $line, 4, 8); + $datablock = substr $line, 12; + $reclen -= 4; + } else { + printf STDERR "Bad s-record found: %s\n", $line; + exit(1); + } + $dbindex = 0; + # snip checksum byte + $reclen -= 1; + + unless ($addr == $naddr) { + if ($tofill != 4) { + while ($tofill--) { + substr($word, $byteno, 2) = "00"; + $byteno += $incr; + } + $word =~ tr/A-Z/a-z/; + printf $OFH "%x %s\n", $waddr / 4, $word; + $tofill = 4; + $byteno = $start; + $waddr = $waddr+4; + } + if (($addr & 0x3) != 0) { + $naddr = $addr & ~0x3; + $byteno = $start; + $tofill = 4; + while($naddr != $addr) { + substr($word, $byteno, 2) = "00"; + $byteno += $incr; + $naddr += 1; + $tofill -=1; + } + } + } + $naddr = $addr; + $waddr = $naddr; + while($reclen > 0) { + substr ($word, $byteno, 2) = substr ($datablock, $dbindex, 2); + $byteno += $incr; + $dbindex += 2; + $tofill -=1; + if ($tofill == 0) { + $word =~ tr/A-Z/a-z/; + printf $OFH "%x %s\n", $waddr / 4, $word; + $byteno = $start; + $tofill = 4; + $waddr = $waddr+4; + } + $reclen = $reclen - 1; + $naddr = $naddr + 1; + } +} diff --git a/libgloss/mips/syscalls.c b/libgloss/mips/syscalls.c deleted file mode 100644 index b502ac4..0000000 --- a/libgloss/mips/syscalls.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <_ansi.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "regs.S" - -struct s_mem { - unsigned int size; - unsigned int icsize; - unsigned int dcsize; -}; - -void *get_mem_info (struct s_mem *); - -extern char _end[]; - -/* FIXME: This is not ideal, since we do a get_mem_info() call for - every sbrk() call. */ -char * -sbrk (int nbytes) -{ - static char *heap_ptr = _end; - static char *heap_start = _end; - char *base; - struct s_mem mem; - ptrdiff_t avail = 0; - - /* The sizeof (s_mem.size) must be 4 bytes. The compiler should be - able to eliminate this check */ - if (sizeof (unsigned int) != 4) - return (char *)-1; - - get_mem_info(&mem); - /* NOTE: The value returned from the get_mem_info call is the amount - of memory, and not the address of the (last byte + 1) */ - - if (((uintptr_t)heap_ptr >= heap_start) && ((uintptr_t)heap_ptr < (heap_start + mem.size))) { - avail = (heap_start + mem.size) - heap_ptr; - base = heap_ptr; - } /* else will fail since "nbytes" will be greater than zeroed "avail" value */ - - if ((nbytes > avail) || (heap_ptr + nbytes < _end)) - base = (char *)-1; - else - heap_ptr += nbytes; - - return base; -} diff --git a/libgloss/mips/uhi/uhi_assert.c b/libgloss/mips/uhi/uhi_assert.c new file mode 100644 index 0000000..ff414a9 --- /dev/null +++ b/libgloss/mips/uhi/uhi_assert.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis void __assert_func (const char *filename, int32_t line_num, + * const char *func, const char *expr); + * + * Parameters: + * filename - Name of the file + * line_num - Line number + * func - Name of the function + * expr - Expression + * + * Return: + * None + * + * Arguments to syscall: + * $25 - Operation code for __assert_func + * $4 - Name of the file + * $5 - Line number + * $6 - Name of the function + * $7 - Expression + * + * Return from syscall: + * None + * + * @Description Assert +*/ + +#include <stdint.h> +#include <mips/hal.h> +#include <mips/uhi_syscalls.h> + +void _MIPS_HAL_NOMIPS16 +__uhi_assert (const char *message, const char *filename, int32_t line_num) +{ + register const char *arg1 asm ("$4") = message; + register const char *arg2 asm ("$5") = filename; + register int32_t arg3 asm ("$6") = line_num; + register int32_t op asm ("$25") = __MIPS_UHI_ASSERT; + register int32_t ret1 asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t ret2 asm ("$3") = 0; + + __asm__ __volatile__ (" # __assert_func(%0, %1, %2, %3, %4, %5) op=%6\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret1), "+r" (ret2), "+r" (arg1), "+r" (arg2) + : "r" (arg3), "r" (op)); +} diff --git a/libgloss/mips/uhi/uhi_break.c b/libgloss/mips/uhi/uhi_break.c new file mode 100644 index 0000000..305825c --- /dev/null +++ b/libgloss/mips/uhi/uhi_break.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int __uhi_break (struct gp_ctx *ctx); + * + * Parameters: + * $4 - GP context + * + * Arguments to break: + * $25 - Operation code for __uhi_break + * $4 - GP context + * + * Return from break: + * $2 - Return 1 if breakpoint exception is handled else 0 + * + * @Description Handle a breakpoint exception +*/ + +#include <stdint.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +/* Forward a breakpoint exception to boot. */ +int _MIPS_HAL_NOMIPS16 +__uhi_break (struct gpctx *ctx) +{ + register struct gpctx *arg1 asm ("$4") = ctx; + register int32_t op asm ("$25") = __MIPS_UHI_BREAK; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + + __asm__ __volatile__ (" # %0 = __uhi_break(%1) op=%2\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret) + : "r" (arg1), "r" (op)); + return ret; +} diff --git a/libgloss/mips/uhi/uhi_close.c b/libgloss/mips/uhi/uhi_close.c new file mode 100644 index 0000000..a95b399 --- /dev/null +++ b/libgloss/mips/uhi/uhi_close.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis close + * + * Arguments to syscall: + * $25 - Operation code for close + * $4 - File handle + * + * Return from syscall: + * $2 - 0 on success else -1 + * $3 - errno + * + * @Description File close +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int _MIPS_HAL_NOMIPS16 +close (int fd) +{ + register int32_t arg1 asm ("$4") = fd; + register int32_t op asm ("$25") = __MIPS_UHI_CLOSE; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = close(%2) op=%3\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1) + : "r" (op) + : "$5"); + + if (ret != 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_exception.c b/libgloss/mips/uhi/uhi_exception.c new file mode 100644 index 0000000..857442c --- /dev/null +++ b/libgloss/mips/uhi/uhi_exception.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int __uhi_exception (struct gp_ctx *ctx); + * + * Parameters: + * $4 - GP context + * + * Arguments to syscall: + * $25 - Operation code for __uhi_exception + * $4 - GP context + * + * Return from syscall: + * $2 - + * + * @Description Handle an unhandled exception +*/ + +#include <stdint.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int32_t _MIPS_HAL_NOMIPS16 +__uhi_exception (struct gpctx *ctx, int32_t abi) +{ + register struct gpctx *arg1 asm ("$4") = ctx; + register int32_t arg2 asm ("$5") = abi; + register int32_t op asm ("$25") = __MIPS_UHI_EXCEPTION; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + + __asm__ __volatile__ (" # %0 = __uhi_exception(%1, %2) op=%3\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret) + : "r" (arg1), "r" (arg2), "r" (op) + : "$3"); + return ret; +} diff --git a/libgloss/mips/uhi/uhi_exit.c b/libgloss/mips/uhi/uhi_exit.c new file mode 100644 index 0000000..5d4384e --- /dev/null +++ b/libgloss/mips/uhi/uhi_exit.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis void __exit (int32_t exit_code); + * + * Parameters: + * exit_code - Exit code + * + * Return: + * None + * + * Arguments to syscall: + * $25 - Operation code for exit + * $4 - Exit code + * + * @Description Transfer control to the debug port +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +void __return_to_boot (int32_t exit_code) __attribute__((noreturn)) + __attribute__((weak)); + +/* Defined in .ld file */ +extern char __use_excpt_boot[]; + +/* _exit has been declared weak to allow its defination in the application */ +int _MIPS_HAL_NOMIPS16 +__exit (int exit_code) +{ + register int32_t arg1 asm ("$4") = exit_code; + register int32_t op asm ("$25") = __MIPS_UHI_EXIT; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + + __asm__ __volatile__ (" # _exit(%0 %1) op=%2\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "+r" (arg1) + : "r" (op) + : "$3", "$5"); + + /* exit wasn't handled, return to caller of _start + * __use_excpt_boot has following values + * 0 = Do not use exception handler present in boot + * 1 = Use exception handler present in boot if BEV + is 0 at startup + * 2 = Always use exception handler present in boot + */ + if (((long) __use_excpt_boot == 2 + || ((long) __use_excpt_boot == 1 + && __get_startup_BEV + && __get_startup_BEV () == 0)) + && __return_to_boot) + __return_to_boot (exit_code); + + /* Infinite loop if control returns. */ + __exit (exit_code); + return exit_code; +} diff --git a/libgloss/mips/uhi/uhi_fstat.c b/libgloss/mips/uhi/uhi_fstat.c new file mode 100644 index 0000000..6bbe53a --- /dev/null +++ b/libgloss/mips/uhi/uhi_fstat.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t fstat (int32_t file, struct stat *sbuf); + * + * Parameters: + * file - File handle + * sbuf - Pointer to dst buffer + * + * Return: + * 0 on success else -1 + * + * Arguments to syscall: + * $25 - Operation code for fstat + * $4 - File handle + * $5 - Pointer to dst buffer (struct stat *) + * + * Return from syscall: + * $2 - 0 on success else -1 + * $3 - errno + * + * @Description File statistics +*/ + +#include <stdio.h> +#include <stdint.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stddef.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> +#include "uhi_stat.h" + +/* This macro declares a dummy type with -ve size if CONDITION is false */ +#define __paste(STR1, STR2) STR1##STR2 +#define __check(LINE, CONDITION) typedef char __paste(assertion_failed_at_line_, LINE) [(int)(CONDITION)-1] + +int _MIPS_HAL_NOMIPS16 +fstat (int file, struct stat *sbuf) +{ + struct uhi_stat hbuf = {0,}; + register int32_t arg1 asm ("$4") = file; + register struct uhi_stat *arg2 asm ("$5") = &hbuf; + register int32_t op asm ("$25") = __MIPS_UHI_FSTAT; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + /* + * We assume that NewLib has following 'struct stat'. Any change in + * this structure (either offset or size) would generate a compile + * time error. + */ +#if defined (_LP64) + __check (__LINE__, sizeof (struct stat) == 104); + __check (__LINE__, offsetof (struct stat, st_dev) == 0); + __check (__LINE__, offsetof (struct stat, st_ino) == 2); + __check (__LINE__, offsetof (struct stat, st_mode) == 4); + __check (__LINE__, offsetof (struct stat, st_nlink) == 8); + __check (__LINE__, offsetof (struct stat, st_uid) == 10); + __check (__LINE__, offsetof (struct stat, st_gid) == 12); + __check (__LINE__, offsetof (struct stat, st_rdev) == 14); + __check (__LINE__, offsetof (struct stat, st_size) == 16); + __check (__LINE__, offsetof (struct stat, st_atime) == 24); + __check (__LINE__, offsetof (struct stat, st_spare1) == 32); + __check (__LINE__, offsetof (struct stat, st_mtime) == 40); + __check (__LINE__, offsetof (struct stat, st_spare2) == 48); + __check (__LINE__, offsetof (struct stat, st_ctime) == 56); + __check (__LINE__, offsetof (struct stat, st_spare3) == 64); + __check (__LINE__, offsetof (struct stat, st_blksize) == 72); + __check (__LINE__, offsetof (struct stat, st_blocks) == 80); + __check (__LINE__, offsetof (struct stat, st_spare4) == 88); +#else + __check (__LINE__, sizeof (struct stat) == 60); + __check (__LINE__, offsetof (struct stat, st_dev) == 0); + __check (__LINE__, offsetof (struct stat, st_ino) == 2); + __check (__LINE__, offsetof (struct stat, st_mode) == 4); + __check (__LINE__, offsetof (struct stat, st_nlink) == 8); + __check (__LINE__, offsetof (struct stat, st_uid) == 10); + __check (__LINE__, offsetof (struct stat, st_gid) == 12); + __check (__LINE__, offsetof (struct stat, st_rdev) == 14); + __check (__LINE__, offsetof (struct stat, st_size) == 16); + __check (__LINE__, offsetof (struct stat, st_atime) == 20); + __check (__LINE__, offsetof (struct stat, st_spare1) == 24); + __check (__LINE__, offsetof (struct stat, st_mtime) == 28); + __check (__LINE__, offsetof (struct stat, st_spare2) == 32); + __check (__LINE__, offsetof (struct stat, st_ctime) == 36); + __check (__LINE__, offsetof (struct stat, st_spare3) == 40); + __check (__LINE__, offsetof (struct stat, st_blksize) == 44); + __check (__LINE__, offsetof (struct stat, st_blocks) == 48); + __check (__LINE__, offsetof (struct stat, st_spare4) == 52); +#endif + + __asm__ __volatile__ (" # %0,%1 = fstat(%2, %3) op=%4\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), + "+r" (arg2) + : "r" (op)); + + if (ret != 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + else + { + sbuf->st_dev = hbuf.st_dev; + sbuf->st_ino = hbuf.st_ino; + sbuf->st_mode = hbuf.st_mode; + sbuf->st_nlink = hbuf.st_nlink; + sbuf->st_uid = hbuf.st_uid; + sbuf->st_gid = hbuf.st_gid; + sbuf->st_rdev = hbuf.st_rdev; + sbuf->st_size = (long) hbuf.st_size; + sbuf->st_atime = (time_t) hbuf.st_atime; + sbuf->st_spare1 = (long) hbuf.st_spare1; + sbuf->st_mtime = (time_t) hbuf.st_mtime; + sbuf->st_spare2 = (long) hbuf.st_spare2; + sbuf->st_ctime = (time_t) hbuf.st_ctime; + sbuf->st_spare3 = (long) hbuf.st_spare3; + sbuf->st_blksize = (long) hbuf.st_blksize; + sbuf->st_blocks = (long) hbuf.st_blocks; + sbuf->st_spare4[0] = (long) hbuf.st_spare4[0]; + sbuf->st_spare4[1] = (long) hbuf.st_spare4[1]; + } + + return ret; +} + +#undef __paste +#undef __check diff --git a/libgloss/mips/uhi/uhi_get_ram_range.c b/libgloss/mips/uhi/uhi_get_ram_range.c new file mode 100644 index 0000000..b8d86d1 --- /dev/null +++ b/libgloss/mips/uhi/uhi_get_ram_range.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +extern char __attribute__((weak)) __memory_size[]; +extern char __attribute__((weak)) __memory_base[]; + +void _MIPS_HAL_NOMIPS16 +_get_ram_range (void **ram_base, void **ram_extent) +{ + register int32_t op asm ("$25") = __MIPS_UHI_RAMRANGE; + register void* r_base asm ("$2") = (void*)__MIPS_UHI_SYSCALL_NUM; + register void* r_extent asm ("$3") = NULL; + + if (__memory_size != NULL) + { + if (ram_base) + *ram_base = (void*)(unsigned long)__memory_base; + *ram_extent = (void*)((unsigned long)__memory_base + + (unsigned long)__memory_size); + return; + } + + __asm__ __volatile__ (" # %0,%1 = ramrange() op=%2\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (r_base), "=r" (r_extent) + : "r" (op) + : "$4", "$5"); + + if (ram_base) + *ram_base = r_base; + *ram_extent = r_extent; +} diff --git a/libgloss/mips/uhi/uhi_getargs.S b/libgloss/mips/uhi/uhi_getargs.S new file mode 100644 index 0000000..e27e7ff --- /dev/null +++ b/libgloss/mips/uhi/uhi_getargs.S @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/asm.h> +#include <mips/regdef.h> +#include <mips/cpu.h> +#include <mips/uhi_syscalls.h> + +MIPS_NOMIPS16 + + .text + .align 2 + .globl __getargs + .ent __getargs + .type __getargs, @function +__getargs: + + move t0, zero /* argc */ + move t1, zero /* argv */ + + li t9, __MIPS_UHI_ARGC + li vt0, __MIPS_UHI_SYSCALL_NUM + + ASM_SYSCALL (__MIPS_UHI_SYSCALL_NUM) + + /* return on error (-1) */ + blez vt0, .Lreturn + + move t0, vt0 /* argc: number of arguments */ + sll t3, t0, LOG2_SZPTR /* Multiply by size of pointer */ + addiu t3, t3, ALSZ /* Round to stack alignment */ + and t3, t3, ALMASK + PTR_SUBU sp, sp, t3 /* make room for argv */ + move t1, sp /* argv */ + move t2, zero + +.Lloop: + + li t9, __MIPS_UHI_ARGLEN + li vt0, __MIPS_UHI_SYSCALL_NUM + move a0, t2 /* argument number */ + + ASM_SYSCALL (__MIPS_UHI_SYSCALL_NUM) /* get length of arg N */ + + blez vt0, .Lreturn /* return on error */ + + addiu vt0, vt0, 1 + addiu vt0, vt0, ALSZ + and vt0, vt0, ALMASK + PTR_SUBU sp, sp, vt0 + sll t3, t2, LOG2_SZPTR + PTR_ADDU t3, t3, t1 + PTR_S sp, 0(t3) /* argv[i] */ + + li t9, __MIPS_UHI_ARGN + li vt0, __MIPS_UHI_SYSCALL_NUM + move a0, t2 /* argument number */ + move a1, sp /* argument buffer */ + + ASM_SYSCALL (__MIPS_UHI_SYSCALL_NUM) + + bltz vt0, .Lreturn /* return on error */ + + addiu t2, t2, 1 + slt vt0, t2, t0 + bnez vt0, .Lloop + +.Lreturn: + move a0, t0 + move a1, t1 + + /* Leave 16-bytes for register arguments and up to 8 bytes for + a null envp. Round up to 32 for alignment. */ + PTR_SUBU sp, sp, 16+(NARGSAVE*SZARG) + PTR_ADDU a2, sp, (NARGSAVE*SZARG) + PTR_S zero, 0(a2) + + jr $31 + + .end __getargs + .size __getargs, .-__getargs diff --git a/libgloss/mips/uhi/uhi_indirect.c b/libgloss/mips/uhi/uhi_indirect.c new file mode 100644 index 0000000..c3feac2 --- /dev/null +++ b/libgloss/mips/uhi/uhi_indirect.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <mips/hal.h> + +/* Forward a UHI SYSCALL operation to SDBPP interface. */ +int _MIPS_HAL_NOMIPS16 +__uhi_indirect (struct gpctx *ctx) +{ + register reg_t arg1 asm ("$4") = ctx->r[C_CTX_REGNO(4)]; + register reg_t arg2 asm ("$5") = ctx->r[C_CTX_REGNO(5)]; + register reg_t arg3 asm ("$6") = ctx->r[C_CTX_REGNO(6)]; + register reg_t arg4 asm ("$7") = ctx->r[C_CTX_REGNO(7)]; + register reg_t op asm ("$25") = ctx->r[C_CTX_REGNO(25)]; + register reg_t ret1 asm ("$2") = 1; + register reg_t ret2 asm ("$3"); + + __asm__ __volatile__(" # UHI indirect\n" + "\tsdbbp 1" + : "+r" (ret1), "=r" (ret2), "+r" (arg1), "+r" (arg2) + : "r" (arg3), "r" (arg4), "r" (op)); + + ctx->r[C_CTX_REGNO(2)] = ret1; + ctx->r[C_CTX_REGNO(3)] = ret2; + ctx->r[C_CTX_REGNO(4)] = arg1; + ctx->r[C_CTX_REGNO(5)] = arg2; + /* Handled, move on. SYSCALL is 4-bytes in all ISAs. */ + ctx->epc += 4; + + return 1; /* exception handled */ +} diff --git a/libgloss/mips/uhi/uhi_link.c b/libgloss/mips/uhi/uhi_link.c new file mode 100644 index 0000000..7eddc06 --- /dev/null +++ b/libgloss/mips/uhi/uhi_link.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t link (const char *oldname, const char *newname); + * + * Parameters: + * oldname - Name of the file to rename + * newname - New file name + * + * Return: + * $2 - Zero on success or -1 in case of error + * + * Arguments to syscall: + * $25 - Operation code for rename + * $4 - Name of the file to rename + * $5 - New file name + * + * Return from syscall: + * $2 - Zero on success or -1 in case of error + * $3 - errno + * + * @Description Rename a file +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int _MIPS_HAL_NOMIPS16 +link (const char *oldname, const char *newname) +{ + register const char *arg1 asm ("$4") = oldname; + register const char *arg2 asm ("$5") = newname; + register int32_t op asm ("$25") = __MIPS_UHI_LINK; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = link(%2, %3) op=%4\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), + "+r" (arg2) + : "r" (op)); + + if (ret != 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_lseek.c b/libgloss/mips/uhi/uhi_lseek.c new file mode 100644 index 0000000..0146843 --- /dev/null +++ b/libgloss/mips/uhi/uhi_lseek.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis lseek + * + * Arguments to syscall: + * $25 - Operation code for seek + * $4 - File handle + * $5 - Offset + * $6 - Direction + * + * Return from syscall: + * $2 - New offset + * $3 - errno + * + * @Description File seek +*/ + +#include <sys/types.h> +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +off_t _MIPS_HAL_NOMIPS16 +lseek (int fd, off_t offset, int whence) +{ + register int32_t arg1 asm ("$4") = fd; + register int32_t arg2 asm ("$5") = offset; + register int32_t arg3 asm ("$6") = whence; + register int32_t op asm ("$25") = __MIPS_UHI_LSEEK; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = lseek(%2, %3, %4) op=%5\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), + "+r" (arg2) + : "r" (arg3), "r" (op)); + + if (ret == -1) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_open.c b/libgloss/mips/uhi/uhi_open.c new file mode 100644 index 0000000..38bc229 --- /dev/null +++ b/libgloss/mips/uhi/uhi_open.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis open + * + * Arguments to syscall: + * $25 - Operation code for open + * $4 - Name of the file + * $5 - Read/Write etc. flags + * $6 - Privileges + * + * Return from syscall: + * $2 - File handle + * $3 - errno + * + * @Description File open +*/ + +#include <sys/types.h> +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int _MIPS_HAL_NOMIPS16 +open (const char *file_name, int flags, mode_t mode) +{ + register const char * arg1 asm ("$4") = file_name; + register int32_t arg2 asm ("$5") = flags; + register int32_t arg3 asm ("$6") = mode; + register int32_t op asm ("$25") = __MIPS_UHI_OPEN; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = open(%2, %3, %4) op=%5\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), "+r" (arg2) + : "r" (arg3), "r" (op)); + + if (ret == -1) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_plog.c b/libgloss/mips/uhi/uhi_plog.c new file mode 100644 index 0000000..c0376c0 --- /dev/null +++ b/libgloss/mips/uhi/uhi_plog.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t plog (int8_t *fmt, int32_t num); + * + * Parameters: + * fmt - Format string + * num - The only int argument + * + * Return: + * Number of chars written + * + * Arguments to syscall: + * $25 - Operation code for __plog + * $4 - Format string + * $5 - The only int argument + * + * Return from syscall: + * $2 - Number of chars written + * $3 - errno + * + * @Description Print information +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/hal.h> +#include <mips/uhi_syscalls.h> + +int32_t _MIPS_HAL_NOMIPS16 +__plog (int8_t *fmt, int32_t num) +{ + register int8_t *arg1 asm ("$4") = fmt; + register int32_t arg2 asm ("$5") = num; + register int32_t op asm ("$25") = __MIPS_UHI_LOG; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = __plog(%2, %3) op=%4\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), "+r" (arg2) + : "r" (op)); + + if (ret != 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_pread.c b/libgloss/mips/uhi/uhi_pread.c new file mode 100644 index 0000000..814de03 --- /dev/null +++ b/libgloss/mips/uhi/uhi_pread.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis pread + * + * Arguments to syscall: + * $25 - Operation code for pread + * $4 - File handle + * $5 - Destination buffer + * $6 - Max number of bytes to read + * $7 - Offset in file from which bytes to be read + * + * Return from syscall: + * $2 - Number of bytes read or -1 in case of error + * $3 - errno + * + * @Description File read from a given offset +*/ + +#include <sys/types.h> +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +ssize_t _MIPS_HAL_NOMIPS16 +pread (int fd, void *buf, size_t count, off_t offset) +{ + register int32_t arg1 asm ("$4") = fd; + register void *arg2 asm ("$5") = buf; + register int32_t arg3 asm ("$6") = count; + register int32_t arg4 asm ("$7") = offset; + register int32_t op asm ("$25") = __MIPS_UHI_PREAD; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = pread(%2, %3, %4, %5) op=%6\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), + "+r" (arg2) + : "r" (arg3), "r" (arg4), "r" (op)); + + if (ret == -1) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_pwrite.c b/libgloss/mips/uhi/uhi_pwrite.c new file mode 100644 index 0000000..8a1529a --- /dev/null +++ b/libgloss/mips/uhi/uhi_pwrite.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis pwrite + * + * Arguments to syscall: + * $25 - Operation code for pwrite + * $4 - File handle + * $5 - Buffer to write + * $6 - Length of the buffer + * $7 - Offset in file at which bytes to be written + * + * Return from syscall: + * $2 - Number of bytes written + * $3 - errno + * + * @Description Write to a file at a given offset +*/ + +#include <sys/types.h> +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +ssize_t _MIPS_HAL_NOMIPS16 +pwrite (int fd, const void *buf, size_t count, off_t offset) +{ + register int32_t arg1 asm ("$4") = fd; + register const void *arg2 asm ("$5") = buf; + register int32_t arg3 asm ("$6") = count; + register int32_t arg4 asm ("$7") = offset; + register int32_t op asm ("$25") = __MIPS_UHI_PWRITE; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = pwrite(%2, %3, %4 %5) op=%6\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), + "+r" (arg2) + : "r" (arg3), "r" (arg4), "r" (op)); + + if (ret == -1) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_read.c b/libgloss/mips/uhi/uhi_read.c new file mode 100644 index 0000000..ffc017e --- /dev/null +++ b/libgloss/mips/uhi/uhi_read.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis read + * + * Arguments to syscall: + * $25 - Operation code for read + * $4 - File handle + * $5 - Destination buffer + * $6 - Max number of bytes to read + * + * Return from syscall: + * $2 - Number of bytes read + * $3 - errno + * + * @Description File read +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int _MIPS_HAL_NOMIPS16 +read (int fd, void *buffer, size_t len) +{ + register int32_t arg1 asm ("$4") = fd; + register void *arg2 asm ("$5") = buffer; + register int32_t arg3 asm ("$6") = len; + register int32_t op asm ("$25") = __MIPS_UHI_READ; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = read(%2, %3, %4) op=%5\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), + "+r" (arg2) + : "r" (arg3), "r" (op)); + + if (ret == -1) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_stat.c b/libgloss/mips/uhi/uhi_stat.c new file mode 100644 index 0000000..fd66368 --- /dev/null +++ b/libgloss/mips/uhi/uhi_stat.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis stat + * + * @Description File statistics +*/ + +#include <stdint.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> +#include "uhi_stat.h" + +int +stat (const char *filename, struct stat *buf) +{ + int32_t fid, ret = -1; + + fid = open (filename, 0, 0666); /* open in read mode */ + + if (fid >= 0) + { + ret = fstat (fid, buf); + close (fid); + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_stat.h b/libgloss/mips/uhi/uhi_stat.h new file mode 100644 index 0000000..0bbba83 --- /dev/null +++ b/libgloss/mips/uhi/uhi_stat.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdio.h> +#include <time.h> + +struct uhi_stat +{ + short st_dev; + unsigned short st_ino; + unsigned int st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + short st_rdev; + unsigned long long st_size; + unsigned long long st_atime; + unsigned long long st_spare1; + unsigned long long st_mtime; + unsigned long long st_spare2; + unsigned long long st_ctime; + unsigned long long st_spare3; + unsigned long long st_blksize; + unsigned long long st_blocks; + unsigned long long st_spare4[2]; +}; diff --git a/libgloss/mips/uhi/uhi_unlink.c b/libgloss/mips/uhi/uhi_unlink.c new file mode 100644 index 0000000..2fc323c --- /dev/null +++ b/libgloss/mips/uhi/uhi_unlink.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t unlink (const char *file); + * + * Parameters: + * file - Name of the file + * + * Return: + * 0 on success else -1 + * + * Arguments to syscall: + * $25 - Operation code for unlink + * $4 - Name of the file + * + * Return from syscall: + * $2 - 0 on success else -1 + * $3 - errno + * + * @Description Unlink a file +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int _MIPS_HAL_NOMIPS16 +unlink (const char *file) +{ + register const char *arg1 asm ("$4") = file; + register int32_t op asm ("$25") = __MIPS_UHI_UNLINK; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = unlink(%2) op=%3\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1) + : "r" (op) + : "$5"); + + if (ret != 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/uhi_write.c b/libgloss/mips/uhi/uhi_write.c new file mode 100644 index 0000000..c30202d --- /dev/null +++ b/libgloss/mips/uhi/uhi_write.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis write + * + * Arguments to syscall: + * $25 - Operation code for write + * $4 - File handle + * $5 - Buffer to write + * $6 - Length of the buffer + * + * Return from syscall: + * $2 - Number of bytes written + * $3 - errno + * + * @Description File write +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int _MIPS_HAL_NOMIPS16 +write (int fd, const void *buf, size_t count) +{ + register int32_t arg1 asm ("$4") = fd; + register const void *arg2 asm ("$5") = buf; + register int32_t arg3 asm ("$6") = count; + register int32_t op asm ("$25") = __MIPS_UHI_WRITE; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + __asm__ __volatile__ (" # %0,%1 = write(%2, %3, %4) op=%5\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), + "+r" (arg2) + : "r" (arg3), "r" (op)); + + if (ret == -1) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} diff --git a/libgloss/mips/uhi/yamon_close.c b/libgloss/mips/uhi/yamon_close.c new file mode 100644 index 0000000..c08bd14 --- /dev/null +++ b/libgloss/mips/uhi/yamon_close.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t close (int32_t fd); + * + * Parameters: + * $4 - File handle + * + * Return: + * $2 - 0 on success else -1 + * + * Arguments to syscall: + * $25 - Operation code for close + * $4 - File handle + * + * Return from syscall: + * $2 - 0 on success else -1 + * $3 - errno + * + * @Description File close +*/ + +#include <stdint.h> +#include <errno.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int32_t _MIPS_HAL_NOMIPS16 +close (int32_t fd) +{ + register int32_t arg1 asm ("$4") = fd; + register int32_t op asm ("$25") = __MIPS_UHI_CLOSE; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + if (fd == 0 || fd == 1 || fd == 2) + return 0; + + __asm__ __volatile__(" # %0,%1 = close(%2) op=%3\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1) + : "r" (op) + : "$5"); + + if (ret != 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} + diff --git a/libgloss/mips/uhi/yamon_exception.c b/libgloss/mips/uhi/yamon_exception.c new file mode 100644 index 0000000..f4d9a64 --- /dev/null +++ b/libgloss/mips/uhi/yamon_exception.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int __uhi_exception (struct gp_ctx *ctx); + * + * Parameters: + * $4 - GP context + * + * Arguments to syscall: + * $25 - Operation code for __uhi_exception + * $4 - GP context + * + * Return from syscall: + * $2 - + * + * @Description Handle an unhandled exception +*/ + +#include <stdint.h> +#include <mips/hal.h> + +int32_t _MIPS_HAL_NOMIPS16 +__uhi_exception (struct gpctx *ctx, int32_t abi) +{ + return -1; +} diff --git a/libgloss/mips/uhi/yamon_exit.c b/libgloss/mips/uhi/yamon_exit.c new file mode 100644 index 0000000..e288118 --- /dev/null +++ b/libgloss/mips/uhi/yamon_exit.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis void __exit (int32_t exit_code); + * + * Parameters: + * $4 - Exit code + * + * Return: + * None + * + * @Description Transfer control to the debug port +*/ + +#include <stdint.h> +#include <errno.h> +#include "yamon_syscalls.h" +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +__attribute__ ((weak)) int _MIPS_HAL_NOMIPS16 +__exit (int exit_code) +{ + typedef void (*funcptr) (int32_t); + extern funcptr __yamon_functions[]; + funcptr yamonexit; + + yamonexit = (funcptr)__yamon_functions[__YAMON_EXIT]; + (yamonexit) (exit_code); + + __exit (exit_code); /* just to avoide the warning */ + return exit_code; +} + diff --git a/libgloss/mips/uhi/yamon_fstat.c b/libgloss/mips/uhi/yamon_fstat.c new file mode 100644 index 0000000..e1f8d1a --- /dev/null +++ b/libgloss/mips/uhi/yamon_fstat.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t fstat (int32_t file, struct stat *sbuf); + * + * Parameters: + * $4 - File handle + * $5 - Pointer to dst buffer (struct stat *) + * + * Return: + * $2 - 0 on success else -1 + * + * Arguments to syscall: + * $25 - Operation code for fstat + * $4 - File handle + * $5 - Pointer to dst buffer (struct stat *) + * + * Return from syscall: + * $2 - 0 on success else -1 + * $3 - errno + * + * @Description File statistics +*/ + +#include <stdio.h> +#include <stdint.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stddef.h> +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> +#include "uhi_stat.h" + +/* This macro declares a dummy type with -ve size if CONDITION is false */ +#define __paste(STR1, STR2) STR1##STR2 +#define __check(LINE, CONDITION) typedef char __paste(assertion_failed_at_line_, LINE) [(int)(CONDITION)-1] + +int _MIPS_HAL_NOMIPS16 +fstat (int file, struct stat *sbuf) +{ + struct uhi_stat hbuf = {0,}; + register int32_t arg1 asm ("$4") = file; + register struct uhi_stat *arg2 asm ("$5") = &hbuf; + register int32_t op asm ("$25") = __MIPS_UHI_FSTAT; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + /* + * We assume that NewLib has following 'struct stat'. Any change in + * this structure (either offset or size) would generate a compile + * time error. + */ +#if defined (_LP64) + __check (__LINE__, sizeof (struct stat) == 104); + __check (__LINE__, offsetof (struct stat, st_dev) == 0); + __check (__LINE__, offsetof (struct stat, st_ino) == 2); + __check (__LINE__, offsetof (struct stat, st_mode) == 4); + __check (__LINE__, offsetof (struct stat, st_nlink) == 8); + __check (__LINE__, offsetof (struct stat, st_uid) == 10); + __check (__LINE__, offsetof (struct stat, st_gid) == 12); + __check (__LINE__, offsetof (struct stat, st_rdev) == 14); + __check (__LINE__, offsetof (struct stat, st_size) == 16); + __check (__LINE__, offsetof (struct stat, st_atime) == 24); + __check (__LINE__, offsetof (struct stat, st_spare1) == 32); + __check (__LINE__, offsetof (struct stat, st_mtime) == 40); + __check (__LINE__, offsetof (struct stat, st_spare2) == 48); + __check (__LINE__, offsetof (struct stat, st_ctime) == 56); + __check (__LINE__, offsetof (struct stat, st_spare3) == 64); + __check (__LINE__, offsetof (struct stat, st_blksize) == 72); + __check (__LINE__, offsetof (struct stat, st_blocks) == 80); + __check (__LINE__, offsetof (struct stat, st_spare4) == 88); +#else + __check (__LINE__, sizeof (struct stat) == 60); + __check (__LINE__, offsetof (struct stat, st_dev) == 0); + __check (__LINE__, offsetof (struct stat, st_ino) == 2); + __check (__LINE__, offsetof (struct stat, st_mode) == 4); + __check (__LINE__, offsetof (struct stat, st_nlink) == 8); + __check (__LINE__, offsetof (struct stat, st_uid) == 10); + __check (__LINE__, offsetof (struct stat, st_gid) == 12); + __check (__LINE__, offsetof (struct stat, st_rdev) == 14); + __check (__LINE__, offsetof (struct stat, st_size) == 16); + __check (__LINE__, offsetof (struct stat, st_atime) == 20); + __check (__LINE__, offsetof (struct stat, st_spare1) == 24); + __check (__LINE__, offsetof (struct stat, st_mtime) == 28); + __check (__LINE__, offsetof (struct stat, st_spare2) == 32); + __check (__LINE__, offsetof (struct stat, st_ctime) == 36); + __check (__LINE__, offsetof (struct stat, st_spare3) == 40); + __check (__LINE__, offsetof (struct stat, st_blksize) == 44); + __check (__LINE__, offsetof (struct stat, st_blocks) == 48); + __check (__LINE__, offsetof (struct stat, st_spare4) == 52); +#endif + + if (file == 0 || file == 1 || file == 2) + { + sbuf->st_mode = S_IRUSR | S_IWUSR | S_IWGRP; + sbuf->st_blksize = BUFSIZ; + sbuf->st_dev = 0; + sbuf->st_ino = 0; + sbuf->st_nlink = 0; + sbuf->st_uid = 0; + sbuf->st_gid = 0; + sbuf->st_rdev = 0; + sbuf->st_size = 0; + sbuf->st_atime = (time_t) 0; + sbuf->st_spare1 = 0; + sbuf->st_mtime = (time_t) 0; + sbuf->st_spare2 = 0; + sbuf->st_ctime = (time_t) 0; + sbuf->st_spare3 = 0; + sbuf->st_blocks = 0; + sbuf->st_spare4[0] = 0; + sbuf->st_spare4[1] = 0; + return 0; + } + + __asm__ __volatile__(" # %0,%1 = fstat(%2, %3) op=%4\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), "+r" (arg2) + : "r" (op)); + + if (ret != 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + else + { + sbuf->st_dev = hbuf.st_dev; + sbuf->st_ino = hbuf.st_ino; + sbuf->st_mode = hbuf.st_mode; + sbuf->st_nlink = hbuf.st_nlink; + sbuf->st_uid = hbuf.st_uid; + sbuf->st_gid = hbuf.st_gid; + sbuf->st_rdev = hbuf.st_rdev; + sbuf->st_size = (long) hbuf.st_size; + sbuf->st_atime = (time_t) hbuf.st_atime; + sbuf->st_spare1 = (long) hbuf.st_spare1; + sbuf->st_mtime = (time_t) hbuf.st_mtime; + sbuf->st_spare2 = (long) hbuf.st_spare2; + sbuf->st_ctime = (time_t) hbuf.st_ctime; + sbuf->st_spare3 = (long) hbuf.st_spare3; + sbuf->st_blksize = (long) hbuf.st_blksize; + sbuf->st_blocks = (long) hbuf.st_blocks; + sbuf->st_spare4[0] = (long) hbuf.st_spare4[0]; + sbuf->st_spare4[1] = (long) hbuf.st_spare4[1]; + } + + return ret; +} + +#undef __paste +#undef __check + diff --git a/libgloss/mips/uhi/yamon_read.c b/libgloss/mips/uhi/yamon_read.c new file mode 100644 index 0000000..1e365ce --- /dev/null +++ b/libgloss/mips/uhi/yamon_read.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t read (int32_t fd, void *buffer, int32_t len); + * + * Parameters: + * $4 - File handle + * $5 - Destination buffer + * $6 - Max number of bytes to read + * + * Return: + * $2 - Number of bytes read + * + * Arguments to syscall: + * $25 - Operation code for read + * $4 - File handle + * $5 - Destination buffer + * $6 - Max number of bytes to read + * + * Return from syscall: + * $2 - Number of bytes read + * $3 - errno + * + * @Description File read +*/ + +#include <stdint.h> +#include <errno.h> +#include "yamon_syscalls.h" +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + + +int32_t _MIPS_HAL_NOMIPS16 +read (int32_t fd, void *buffer, int32_t len) +{ + register int32_t arg1 asm ("$4") = fd; + register void *arg2 asm ("$5") = buffer; + register int32_t arg3 asm ("$6") = len; + register int32_t op asm ("$25") = __MIPS_UHI_READ; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + /* yamon getchar always reads from stdin */ + if (fd == 0) + { + typedef int32_t (*funcptr) (int32_t, char *); + extern funcptr __yamon_functions[]; + funcptr yamonread; + int32_t i; + yamonread = (funcptr)__yamon_functions[__YAMON_GETCHAR]; + + for (i=0; i<=len; i++) + ret += (yamonread) (fd, (char*)buffer+i); + } + else + { + /* Use UHI read when reading from source other than stdin */ + __asm__ __volatile__(" # %0,%1 = read (%2, %3, %4) op=%5\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), "+r" (arg2) + : "r" (arg3), "r" (op)); + } + + if (ret < 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} + diff --git a/libgloss/mips/uhi/yamon_syscalls.h b/libgloss/mips/uhi/yamon_syscalls.h new file mode 100644 index 0000000..038012e --- /dev/null +++ b/libgloss/mips/uhi/yamon_syscalls.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* These defines are used as array indices in c code */ +#define __YAMON_PRINT_COUNT 0x01 /* At location 0x04 in vector table */ +#define __YAMON_GETCHAR 0x14 /* At location 0x50 in vector table */ +#define __YAMON_EXIT 0x08 /* At location 0x20 in vector table */ + diff --git a/libgloss/mips/uhi/yamon_write.c b/libgloss/mips/uhi/yamon_write.c new file mode 100644 index 0000000..f42bb65 --- /dev/null +++ b/libgloss/mips/uhi/yamon_write.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2014-2018 MIPS Tech, LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * @Synopsis int32_t write (int32_t fd, void *buffer, int32_t count); + * + * Parameters: + * $4 - File handle + * $5 - Buffer to write + * $6 - Length of the buffer + * + * Return: + * $2 - Number of bytes written + * + * Arguments to syscall: + * $25 - Operation code for write + * $4 - File handle + * $5 - Buffer to write + * $6 - Length of the buffer + * + * Return from syscall: + * $2 - Number of bytes written + * $3 - errno + * + * @Description File write +*/ + +#include <stdint.h> +#include <errno.h> +#include "yamon_syscalls.h" +#include <mips/uhi_syscalls.h> +#include <mips/hal.h> + +int32_t _MIPS_HAL_NOMIPS16 +write (int32_t fd, void *buffer, int32_t count) +{ + register int32_t arg1 asm ("$4") = fd; + register void *arg2 asm ("$5") = buffer; + register int32_t arg3 asm ("$6") = count; + register int32_t op asm ("$25") = __MIPS_UHI_WRITE; + register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM; + register int32_t new_errno asm ("$3") = 0; + + /* yamon print_count always writes to stdout */ + if (fd == 1 || fd == 2) + { + typedef int32_t (*funcptr) (int32_t, char *, int32_t); + extern funcptr __yamon_functions[]; + funcptr yamonwrite; + + yamonwrite = (funcptr)__yamon_functions[__YAMON_PRINT_COUNT]; + + ret = (yamonwrite) (0, buffer, count); + } + else + { + /* Use UHI write when writing to destination other than stdout */ + __asm__ __volatile__(" # %0,%1 = write(%2, %3, %4) op=%5\n" + SYSCALL (__MIPS_UHI_SYSCALL_NUM) + : "+r" (ret), "=r" (new_errno), "+r" (arg1), "+r" (arg2) + : "r" (arg3), "r" (op)); + } + if (ret < 0) + { + /* Do a dance to set errno, errno is a function call that can + clobber $3. */ + volatile uint32_t errno_tmp = new_errno; + errno = errno_tmp; + } + + return ret; +} + diff --git a/libgloss/mips/uhi32.ld b/libgloss/mips/uhi32.ld new file mode 100644 index 0000000..320880d --- /dev/null +++ b/libgloss/mips/uhi32.ld @@ -0,0 +1,346 @@ +/* + * A platform and target independent link script to produce UHI + * compliant binaries with varying levels of system initialization + * support. + */ + +__entry = DEFINED(__reset_vector) ? 0xbfc00000 : _start; +ENTRY(__entry) +OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips") +GROUP(-lc -luhi -lgcc -lhal) +SEARCH_DIR(.) +__DYNAMIC = 0; +STARTUP(crt0.o) +/* Force the exception handler to be registered */ +EXTERN(__register_excpt_handler) +/* Force the exception handler to be included in the link */ +EXTERN(__exception_entry) +/* + * Require verbose exceptions. This can be changed to pull in + * __exception_handle_quiet to reduce code size but be less + * informative + */ +EXTERN(__exception_handle_verbose) +/* Force ISRs to be included in the link */ +EXTERN(__isr_vec_) +/* Require the UHI getargs support */ +EXTERN(__getargs) +/* Include the breakpoint exception handler. */ +EXTERN (__uhi_break); + +/* + * Set the location of the top of the stack. A value of 0 means + * that it will be automatically placed at the highest address + * available as described by the __memory_* setttings + */ +PROVIDE (__stack = 0); + +/* Size of the memory returned by _get_ram_range */ +PROVIDE (__memory_size = 3M); + +/* Base of the memory returned by _get_ram_range */ +PROVIDE (__memory_base = 0x80000000); + +/* Stride length for tlb software invalidate for tlbinvf + * (mipsXXr3+). Some MIPS implementations may layout the sets/ways + * differently in the index register. Either sets LSB or ways LSB. + * + * By setting this to 1 we presume that sets come first. The default boot + * code will decrement this value from the Number of TLB entries. + */ +PROVIDE (__tlb_stride_length = 1); + +/* By default, XPA is not used even if available. To enable XPA, + * __enable_xpa should be 1. + */ +PROVIDE (__enable_xpa = 0); + +/* + * 0 = Do not use exception handler present in boot for UHI + * 1 = Use exception handler present in boot for UHI if BEV is 0 at + * startup + * 2 = Always use exception handler present in boot for UHI + */ +PROVIDE (__use_excpt_boot = 1); +/* + * Include the code to be able to return to boot context. This is + * necessary if __use_excpt_boot != 0. + */ +EXTERN (__register_excpt_boot); + +ASSERT (DEFINED(__register_excpt_boot) || __use_excpt_boot == 0, + "Registration for boot context is required for UHI chaining") + +/* Control if subnormal floating-point values are flushed to zero in + hardware. This applies to both FPU and MSA operations. */ +PROVIDE (__flush_to_zero = 1); + +/* Set up the public symbols depending on whether the user has chosen + quiet or verbose exception handling above */ +EXTERN (__exception_handle); +PROVIDE(__exception_handle = (DEFINED(__exception_handle_quiet) + ? __exception_handle_quiet + : __exception_handle_verbose)); +PROVIDE(_mips_handle_exception = __exception_handle); + +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we multiple object file + * formats, as some prepend an underscore. + */ +PROVIDE (hardware_exit_hook = 0); +PROVIDE (hardware_hazard_hook = 0); +PROVIDE (hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); + +/* The default base address for application code is 0x80200000 which + leaves 2M of space at the start of KSEG0 for a bootloader. */ +PROVIDE (__app_start = DEFINED(__reset_vector) ? 0x80000000 : 0x80200000); +/* Set default vector spacing to 32 bytes. */ +PROVIDE (__isr_vec_space = 32); +/* Leave space for 9 vector entries by default. 8 entry points and one + fallback handler. */ +PROVIDE (__isr_vec_count = 9); +/* + * The start of flash must be set if including boot code. By default + * the use of boot code will mean that application code is copied + * from flash to RAM at runtime before being executed. + */ +PROVIDE (__flash_start = DEFINED(__reset_vector) ? 0xbfc00000 : __app_start); +/* Set the default execution address for boot code. */ +PROVIDE (__bev_override = 0x9fc00000); + +SECTIONS +{ + /* Start of bootrom */ + .bootrom __bev_override : /* Runs uncached (from 0x9fc00000) until I$ is + initialized. */ + AT (__flash_start) + { + *(.reset) /* Reset entry point. */ + *(.boot) /* Boot code. */ + . = ALIGN(8); + } = 0 + + PROVIDE (__flash_app_start = DEFINED(__xip) + ? ALIGN(__flash_start + SIZEOF(.bootrom), 0x1000) + : __flash_start + SIZEOF(.bootrom)); + + __aligned_app_start = DEFINED(__xip) + ? ALIGN(__bev_override + SIZEOF(.bootrom), 0x1000) + : ALIGN(__app_start, 0x1000); + + PROVIDE (__ebase_size = 0x200); + + /* Start of the application */ + .exception_vector __aligned_app_start : + AT (__flash_app_start) + { + PROVIDE (__excpt_ebase = ABSOLUTE(.)); + __base = .; + KEEP(* (.text.__exception_entry)) + . = __base + __ebase_size; + KEEP(* (SORT(.text.__isr_vec*))) + /* Leave space for all the vector entries */ + . = __base + __ebase_size + (__isr_vec_space * __isr_vec_count); + ASSERT(__isr_vec_space == (DEFINED(__isr_vec_sw1) + ? __isr_vec_sw1 - __isr_vec_sw0 + : __isr_vec_space), + "Actual ISR vector spacing does not match __isr_vec_space"); + ASSERT(__base + __ebase_size == (DEFINED(__isr_vec_sw0) + ? __isr_vec_sw0 & 0xfffffffe + : __base + __ebase_size), + "__isr_vec_sw0 is not placed at EBASE + 0x200"); + . = ALIGN(8); + } = 0 + + .text : { + _ftext = . ; + PROVIDE (eprol = .); + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.mips16.fn.*) + *(.mips16.call.*) + } + .init : { + KEEP (*(.init)) + } + .fini : { + KEEP (*(.fini)) + } + .rel.sdata : { + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + } + PROVIDE (etext = .); + _etext = .; + + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : + { + /* The .eh_frame section from the crtend file contains the + end of eh_frame marker and it must be last. */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .eh_frame)) + KEEP (*(.eh_frame)) + } + + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : { *(.gnu_extab .gnu_extab.*) } + .jcr : { KEEP (*(.jcr)) } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + + KEEP (*crtbegin.o(.ctors)) + + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + + . = .; + .MIPS.abiflags : { + __MIPS_abiflags_start = .; + *(.MIPS.abiflags) + __MIPS_abiflags_end = .; + } + .rodata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + . = ALIGN(16); + _fdata = .; + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + . = ALIGN(8); + _gp = . + 0x8000; + __global = _gp; + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + . = ALIGN(4); + PROVIDE (edata = .); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + . = ALIGN(4); + PROVIDE (end = .); + _end = .; + /* Now place the data that is only needed within start.S and can be + overwritten by the heap. */ + .startdata : { + *(.startdata) + } + + /* We do not support any runtime relocation handling with this script. */ + /DISCARD/ : { *(.rel.dyn) *(.rela.dyn) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to + the beginning of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_ranges 0 : { *(.debug_ranges) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /* Special sections generated by gcc */ + /* Newer GNU linkers strip by default */ + .mdebug.abi32 0 : { KEEP(*(.mdebug.abi32)) } + .mdebug.abiN32 0 : { KEEP(*(.mdebug.abiN32)) } + .mdebug.abi64 0 : { KEEP(*(.mdebug.abi64)) } + .mdebug.abiO64 0 : { KEEP(*(.mdebug.abiO64)) } + .mdebug.eabi32 0 : { KEEP(*(.mdebug.eabi32)) } + .mdebug.eabi64 0 : { KEEP(*(.mdebug.eabi64)) } + .gcc_compiled_long32 0 : { KEEP(*(.gcc_compiled_long32)) } + .gcc_compiled_long64 0 : { KEEP(*(.gcc_compiled_long64)) } +} diff --git a/libgloss/mips/uhi64_64.ld b/libgloss/mips/uhi64_64.ld new file mode 100644 index 0000000..ce34f72 --- /dev/null +++ b/libgloss/mips/uhi64_64.ld @@ -0,0 +1,345 @@ +/* + * A platform and target independent link script to produce UHI + * compliant binaries with varying levels of system initialization + * support. + */ + +__entry = DEFINED(__reset_vector) ? 0xffffffffbfc00000 : _start; +ENTRY(__entry) +OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips") +GROUP(-lc -luhi -lgcc -lhal) +SEARCH_DIR(.) +__DYNAMIC = 0; +STARTUP(crt0.o) +/* Force the exception handler to be registered */ +EXTERN(__register_excpt_handler) +/* Force the exception handler to be included in the link */ +EXTERN(__exception_entry) +/* + * Require verbose exceptions. This can be changed to pull in + * __exception_handle_quiet to reduce code size but be less + * informative + */ +EXTERN(__exception_handle_verbose) +/* Force ISRs to be included in the link */ +EXTERN(__isr_vec) +/* Require the UHI getargs support */ +EXTERN(__getargs) +/* Include the breakpoint exception handler. */ +EXTERN (__uhi_break); + +/* + * Set the location of the top of the stack. A value of 0 means + * that it will be automatically placed at the highest address + * available as described by the __memory_* setttings + */ +PROVIDE (__stack = 0); + +/* Size of the memory returned by _get_ram_range */ +PROVIDE (__memory_size = 3M); + +/* Base of the memory returned by _get_ram_range */ +PROVIDE (__memory_base = 0xffffffff80000000); + +/* Stride length for tlb software invalidate for tlbinvf + * (mipsXXr3+). Some MIPS implementations may layout the sets/ways + * differently in the index register. Either sets LSB or ways LSB. + * + * By setting this to 1 we presume that sets come first. The default boot + * code will decrement this value from the Number of TLB entries. + */ +PROVIDE (__tlb_stride_length = 1); + +/* By default, XPA is not used even if available. To enable XPA, + * __enable_xpa should be 1. + */ +PROVIDE (__enable_xpa = 0); + +/* + * 0 = Do not use exception handler present in boot for UHI + * 1 = Use exception handler present in boot for UHI if BEV is 0 at + * startup + * 2 = Always use exception handler present in boot for UHI + */ +PROVIDE (__use_excpt_boot = 1); +/* + * Include the code to be able to return to boot context. This is + * necessary if __use_excpt_boot != 0. + */ +EXTERN (__register_excpt_boot); + +ASSERT (DEFINED(__register_excpt_boot) || __use_excpt_boot == 0, + "Registration for boot context is required for UHI chaining") + +/* Control if subnormal floating-point values are flushed to zero in + hardware. This applies to both FPU and MSA operations. */ +PROVIDE (__flush_to_zero = 1); + +/* Set up the public symbols depending on whether the user has chosen + quiet or verbose exception handling above */ +EXTERN (__exception_handle); +PROVIDE(__exception_handle = (DEFINED(__exception_handle_quiet) + ? __exception_handle_quiet + : __exception_handle_verbose)); +PROVIDE(_mips_handle_exception = __exception_handle); + +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we multiple object file + * formats, as some prepend an underscore. + */ +PROVIDE (hardware_exit_hook = 0); +PROVIDE (hardware_hazard_hook = 0); +PROVIDE (hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); + +/* The default base address for application code is 0x80200000 which + leaves 2M of space at the start of KSEG0 for a bootloader. */ +PROVIDE (__app_start = DEFINED(__reset_vector) ? 0xffffffff80000000 :0xffffffff80200000); +/* Set default vector spacing to 64 bytes. */ +PROVIDE (__isr_vec_space = 64); +/* Leave space for 9 vector entries by default. 8 entry points and one + fallback handler. */ +PROVIDE (__isr_vec_count = 9); +/* + * The start of flash must be set if including boot code. By default + * the use of boot code will mean that application code is copied + * from flash to RAM at runtime before being executed. + */ +PROVIDE (__flash_start = DEFINED(__reset_vector) ? 0xffffffffbfc00000 : __app_start); +/* Set the default execution address for boot code. */ +PROVIDE (__bev_override = 0xffffffff9fc00000); + +SECTIONS +{ + /* Start of bootrom */ + .bootrom __bev_override : /* Runs uncached (from 0x9fc00000) until I$ is + initialized. */ + AT (__flash_start) + { + *(.reset) /* Reset entry point. */ + *(.boot) /* Boot code. */ + . = ALIGN(8); + } = 0 + + PROVIDE (__flash_app_start = DEFINED(__xip) + ? ALIGN(__flash_start + SIZEOF(.bootrom), 0x1000) + : __flash_start + SIZEOF(.bootrom)); + + __aligned_app_start = DEFINED(__xip) + ? ALIGN(__bev_override + SIZEOF(.bootrom), 0x1000) + : ALIGN(__app_start, 0x1000); + + PROVIDE (__ebase_size = 0x200); + + /* Start of the application */ + .exception_vector __aligned_app_start : + AT (__flash_app_start) + { + PROVIDE (__excpt_ebase = ABSOLUTE(.)); + __base = .; + KEEP(* (.text.__exception_entry)) + . = __base + __ebase_size; + KEEP(* (SORT(.text.__isr_vec*))) + /* Leave space for all the vector entries */ + . = __base + __ebase_size + (__isr_vec_space * __isr_vec_count); + ASSERT(__isr_vec_space == (DEFINED(__isr_vec_sw1) + ? __isr_vec_sw1 - __isr_vec_sw0 + : __isr_vec_space), + "Actual ISR vector spacing does not match __isr_vec_space"); + ASSERT(__base + __ebase_size == (DEFINED(__isr_vec_sw0) + ? __isr_vec_sw0 + : __base + __ebase_size), + "__isr_vec_sw0 is not placed at EBASE + 0x200"); + . = ALIGN(8); + } = 0 + + .text : { + _ftext = . ; + PROVIDE (eprol = .); + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.mips16.fn.*) + *(.mips16.call.*) + } + .init : { + KEEP (*(.init)) + } + .fini : { + KEEP (*(.fini)) + } + .rel.sdata : { + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + } + PROVIDE (etext = .); + _etext = .; + + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : + { + /* The .eh_frame section from the crtend file contains the + end of eh_frame marker and it must be last. */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .eh_frame)) + KEEP (*(.eh_frame)) + } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : { *(.gnu_extab .gnu_extab.*) } + .jcr : { KEEP (*(.jcr)) } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + + KEEP (*crtbegin.o(.ctors)) + + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + + . = .; + .MIPS.abiflags : { + __MIPS_abiflags_start = .; + *(.MIPS.abiflags) + __MIPS_abiflags_end = .; + } + .rodata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + . = ALIGN(16); + _fdata = .; + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + . = ALIGN(8); + _gp = . + 0x8000; + __global = _gp; + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + . = ALIGN(4); + PROVIDE (edata = .); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + . = ALIGN(4); + PROVIDE (end = .); + _end = .; + /* Now place the data that is only needed within start.S and can be + overwritten by the heap. */ + .startdata : { + *(.startdata) + } + + /* We do not support any runtime relocation handling with this script. */ + /DISCARD/ : { *(.rel.dyn) *(.rela.dyn) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to + the beginning of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_ranges 0 : { *(.debug_ranges) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /* Special sections generated by gcc */ + /* Newer GNU linkers strip by default */ + .mdebug.abi32 0 : { KEEP(*(.mdebug.abi32)) } + .mdebug.abiN32 0 : { KEEP(*(.mdebug.abiN32)) } + .mdebug.abi64 0 : { KEEP(*(.mdebug.abi64)) } + .mdebug.abiO64 0 : { KEEP(*(.mdebug.abiO64)) } + .mdebug.eabi32 0 : { KEEP(*(.mdebug.eabi32)) } + .mdebug.eabi64 0 : { KEEP(*(.mdebug.eabi64)) } + .gcc_compiled_long32 0 : { KEEP(*(.gcc_compiled_long32)) } + .gcc_compiled_long64 0 : { KEEP(*(.gcc_compiled_long64)) } +} diff --git a/libgloss/mips/uhi64_n32.ld b/libgloss/mips/uhi64_n32.ld new file mode 100644 index 0000000..e604fb4 --- /dev/null +++ b/libgloss/mips/uhi64_n32.ld @@ -0,0 +1,345 @@ +/* + * A platform and target independent link script to produce UHI + * compliant binaries with varying levels of system initialization + * support. + */ + +__entry = DEFINED(__reset_vector) ? 0xbfc00000 : _start; +ENTRY(__entry) +OUTPUT_FORMAT("elf32-ntradlittlemips", "elf32-ntradbigmips", "elf32-ntradlittlemips") +GROUP(-lc -luhi -lgcc -lhal) +SEARCH_DIR(.) +__DYNAMIC = 0; +STARTUP(crt0.o) +/* Force the exception handler to be registered */ +EXTERN(__register_excpt_handler) +/* Force the exception handler to be included in the link */ +EXTERN(__exception_entry) +/* + * Require verbose exceptions. This can be changed to pull in + * __exception_handle_quiet to reduce code size but be less + * informative + */ +EXTERN(__exception_handle_verbose) +/* Force ISRs to be included in the link */ +EXTERN(__isr_vec) +/* Require the UHI getargs support */ +EXTERN(__getargs) +/* Include the breakpoint exception handler. */ +EXTERN (__uhi_break); + +/* + * Set the location of the top of the stack. A value of 0 means + * that it will be automatically placed at the highest address + * available as described by the __memory_* setttings + */ +PROVIDE (__stack = 0); + +/* Size of the memory returned by _get_ram_range */ +PROVIDE (__memory_size = 3M); + +/* Base of the memory returned by _get_ram_range */ +PROVIDE (__memory_base = 0x80000000); + +/* Stride length for tlb software invalidate for tlbinvf + * (mipsXXr3+). Some MIPS implementations may layout the sets/ways + * differently in the index register. Either sets LSB or ways LSB. + * + * By setting this to 1 we presume that sets come first. The default boot + * code will decrement this value from the Number of TLB entries. + */ +PROVIDE (__tlb_stride_length = 1); + +/* By default, XPA is not used even if available. To enable XPA, + * __enable_xpa should be 1. + */ +PROVIDE (__enable_xpa = 0); + +/* + * 0 = Do not use exception handler present in boot for UHI + * 1 = Use exception handler present in boot for UHI if BEV is 0 at + * startup + * 2 = Always use exception handler present in boot for UHI + */ +PROVIDE (__use_excpt_boot = 1); +/* + * Include the code to be able to return to boot context. This is + * necessary if __use_excpt_boot != 0. + */ +EXTERN (__register_excpt_boot); + +ASSERT (DEFINED(__register_excpt_boot) || __use_excpt_boot == 0, + "Registration for boot context is required for UHI chaining") + +/* Control if subnormal floating-point values are flushed to zero in + hardware. This applies to both FPU and MSA operations. */ +PROVIDE (__flush_to_zero = 1); + +/* Set up the public symbols depending on whether the user has chosen + quiet or verbose exception handling above */ +EXTERN (__exception_handle); +PROVIDE(__exception_handle = (DEFINED(__exception_handle_quiet) + ? __exception_handle_quiet + : __exception_handle_verbose)); +PROVIDE(_mips_handle_exception = __exception_handle); + +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we multiple object file + * formats, as some prepend an underscore. + */ +PROVIDE (hardware_exit_hook = 0); +PROVIDE (hardware_hazard_hook = 0); +PROVIDE (hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); + +/* The default base address for application code is 0x80200000 which + leaves 2M of space at the start of KSEG0 for a bootloader. */ +PROVIDE (__app_start = DEFINED(__reset_vector) ? 0x80000000 : 0x80200000); +/* Set default vector spacing to 32 bytes. */ +PROVIDE (__isr_vec_space = 32); +/* Leave space for 9 vector entries by default. 8 entry points and one + fallback handler. */ +PROVIDE (__isr_vec_count = 9); +/* + * The start of flash must be set if including boot code. By default + * the use of boot code will mean that application code is copied + * from flash to RAM at runtime before being executed. + */ +PROVIDE (__flash_start = DEFINED(__reset_vector) ? 0xbfc00000 : __app_start); +/* Set the default execution address for boot code. */ +PROVIDE (__bev_override = 0x9fc00000); + +SECTIONS +{ + /* Start of bootrom */ + .bootrom __bev_override : /* Runs uncached (from 0x9fc00000) until I$ is + initialized. */ + AT (__flash_start) + { + *(.reset) /* Reset entry point. */ + *(.boot) /* Boot code. */ + . = ALIGN(8); + } = 0 + + PROVIDE (__flash_app_start = DEFINED(__xip) + ? ALIGN(__flash_start + SIZEOF(.bootrom), 0x1000) + : __flash_start + SIZEOF(.bootrom)); + + __aligned_app_start = DEFINED(__xip) + ? ALIGN(__bev_override + SIZEOF(.bootrom), 0x1000) + : ALIGN(__app_start, 0x1000); + + PROVIDE (__ebase_size = 0x200); + + /* Start of the application */ + .exception_vector __aligned_app_start : + AT (__flash_app_start) + { + PROVIDE (__excpt_ebase = ABSOLUTE(.)); + __base = .; + KEEP(* (.text.__exception_entry)) + . = __base + __ebase_size; + KEEP(* (SORT(.text.__isr_vec*))) + /* Leave space for all the vector entries */ + . = __base + __ebase_size + (__isr_vec_space * __isr_vec_count); + ASSERT(__isr_vec_space == (DEFINED(__isr_vec_sw1) + ? __isr_vec_sw1 - __isr_vec_sw0 + : __isr_vec_space), + "Actual ISR vector spacing does not match __isr_vec_space"); + ASSERT(__base + __ebase_size == (DEFINED(__isr_vec_sw0) + ? __isr_vec_sw0 + : __base + __ebase_size), + "__isr_vec_sw0 is not placed at EBASE + 0x200"); + . = ALIGN(8); + } = 0 + + .text : { + _ftext = . ; + PROVIDE (eprol = .); + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.mips16.fn.*) + *(.mips16.call.*) + } + .init : { + KEEP (*(.init)) + } + .fini : { + KEEP (*(.fini)) + } + .rel.sdata : { + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + } + PROVIDE (etext = .); + _etext = .; + + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : + { + /* The .eh_frame section from the crtend file contains the + end of eh_frame marker and it must be last. */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .eh_frame)) + KEEP (*(.eh_frame)) + } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : { *(.gnu_extab .gnu_extab.*) } + .jcr : { KEEP (*(.jcr)) } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + + KEEP (*crtbegin.o(.ctors)) + + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + + . = .; + .MIPS.abiflags : { + __MIPS_abiflags_start = .; + *(.MIPS.abiflags) + __MIPS_abiflags_end = .; + } + .rodata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + . = ALIGN(16); + _fdata = .; + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + . = ALIGN(8); + _gp = . + 0x8000; + __global = _gp; + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + . = ALIGN(4); + PROVIDE (edata = .); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + . = ALIGN(4); + PROVIDE (end = .); + _end = .; + /* Now place the data that is only needed within start.S and can be + overwritten by the heap. */ + .startdata : { + *(.startdata) + } + + /* We do not support any runtime relocation handling with this script. */ + /DISCARD/ : { *(.rel.dyn) *(.rela.dyn) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to + the beginning of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_ranges 0 : { *(.debug_ranges) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /* Special sections generated by gcc */ + /* Newer GNU linkers strip by default */ + .mdebug.abi32 0 : { KEEP(*(.mdebug.abi32)) } + .mdebug.abiN32 0 : { KEEP(*(.mdebug.abiN32)) } + .mdebug.abi64 0 : { KEEP(*(.mdebug.abi64)) } + .mdebug.abiO64 0 : { KEEP(*(.mdebug.abiO64)) } + .mdebug.eabi32 0 : { KEEP(*(.mdebug.eabi32)) } + .mdebug.eabi64 0 : { KEEP(*(.mdebug.eabi64)) } + .gcc_compiled_long32 0 : { KEEP(*(.gcc_compiled_long32)) } + .gcc_compiled_long64 0 : { KEEP(*(.gcc_compiled_long64)) } +} |