diff options
289 files changed, 33124 insertions, 1700 deletions
diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml index 53dd06d..3c3cd93 100644 --- a/.github/workflows/cygwin.yml +++ b/.github/workflows/cygwin.yml @@ -29,7 +29,7 @@ jobs: # install build tools - name: Install build tools run: | - dnf install -y autoconf automake make patch perl mingw${{ matrix.pkgarch }}-gcc-c++ mingw${{ matrix.pkgarch }}-winpthreads-static mingw${{ matrix.pkgarch }}-zlib-static + dnf install -y autoconf automake gawk make patch perl mingw${{ matrix.pkgarch }}-gcc-c++ mingw${{ matrix.pkgarch }}-winpthreads-static mingw${{ matrix.pkgarch }}-zlib-static # enable 'dnf copr' - name: Enable 'dnf copr' @@ -107,7 +107,10 @@ jobs: - run: git config --global core.autocrlf input # remove inheritable permissions since they break assumptions testsuite # makes about file modes - - run: icacls . /inheritance:r + - name: adjust permissions + run: | + icacls . /inheritance:r + icacls . /grant Administrators:F - uses: actions/checkout@v3 # install cygwin and build tools @@ -148,16 +151,35 @@ jobs: - name: Build Cygwin run: >- export PATH=/usr/bin:$(cygpath ${SYSTEMROOT})/system32 && + export DESTDIR=$(realpath $(pwd)/install) && mkdir build install && (cd winsup; ./autogen.sh) && cd build && - ../configure --prefix=$(realpath $(pwd)/../install) -v && + ../configure --prefix=/usr -v && export MAKEFLAGS=-j$(nproc) && make && - make install && + export CYGWIN=winsymlinks:sys && + make install -j1 tooldir=/usr gcc_tooldir=/usr DESTDIR=${DESTDIR} && (cd */newlib; make info man) && - (cd */newlib; make install-info install-man) - shell: C:\cygwin\bin\bash.exe --noprofile --norc -eo pipefail '{0}' + (cd */newlib; make install-info install-man tooldir=/usr gcc_tooldir=/usr DESTDIR=${DESTDIR}) + shell: bash --noprofile --norc -eo pipefail '{0}' + + # adjust install so it matches the physical arrangement of directories when + # unpacked by setup + - name: Rearrange for default mountpoints + run: | + mv -v install/usr/bin install/bin + mv -v install/usr/lib install/lib + shell: bash --noprofile --norc -o igncr -eo pipefail '{0}' + + # upload installed cygwin as an artifact, for subsequent use in + # test job(s) + - name: Make Cygwin installation artifact + uses: actions/upload-artifact@v4 + with: + name: cygwin-install-${{ matrix.pkgarch }} + path: | + install # test - name: Test Cygwin @@ -167,7 +189,7 @@ jobs: cd build && (export PATH=${{ matrix.target }}/winsup/testsuite/testinst/bin:${PATH} && cmd /c $(cygpath -wa ${{ matrix.target }}/winsup/cygserver/cygserver) &) && (cd ${{ matrix.target }}/winsup; make check AM_COLOR_TESTS=always) - shell: C:\cygwin\bin\bash.exe --noprofile --norc -eo pipefail '{0}' + shell: bash --noprofile --norc -eo pipefail '{0}' # upload test logs to facilitate investigation of problems - name: Upload test logs @@ -182,3 +204,143 @@ jobs: # workaround problems with actions/checkout post-run step using cygwin git - name: Avoid actions/checkout post-run step using Cygwin git run: bash -c 'rm /usr/bin/git.exe' + + windows-stress-test: + needs: windows-build + + strategy: + fail-fast: false + matrix: + include: + - pkgarch: x86_64 + runarch: x86_64 + runner: windows-latest + - pkgarch: x86_64 + runarch: arm64 + runner: windows-11-arm + runs-on: ${{ matrix.runner }} + name: stress tests ${{ matrix.pkgarch }} on ${{ matrix.runarch }} Windows + + steps: + - run: git config --global core.autocrlf input + - uses: actions/checkout@v3 + + # install cygwin + - name: Install Cygwin + id: cygwin-install + uses: cygwin/cygwin-install-action@master + with: + platform: ${{ matrix.pkgarch }} + packages: | + procps-ng + stress-ng + + # fetch the just-built cygwin installation artifact + - name: Unpack just-built Cygwin artifact + uses: actions/download-artifact@v4 + with: + name: cygwin-install-${{ matrix.pkgarch }} + # use the install-dir of cygwin-install-action above, so we unpack the + # artifact over it + path: ${{ steps.cygwin-install.outputs.root }} + + # This isn't quite right, as it just overwrites existing files, it doesn't + # remove anything which is no longer provided. Ideally, we'd make a cygwin + # package of the just-built cygwin version and install it here, but tools + # don't exist (yet) to let us do that... + + # run stress-test + - name: Run stress tests + run: | + export PATH=/usr/bin:$(cygpath ${SYSTEMROOT})/system32 + uname -a + export LOGDIR=$(cygpath -a logs) + winsup/testsuite/stress/cygstress CI + shell: bash --noprofile --norc -o igncr -eo pipefail '{0}' + continue-on-error: ${{ matrix.runarch == 'arm64' }} + + # upload logs artifact + - name: Capture logs artifact + uses: actions/upload-artifact@v4 + with: + name: stress-logs-${{ matrix.pkgarch }}-on-${{ matrix.runarch }} + path: | + logs + if: ${{ !cancelled() }} + + windows-stc-regression-test: + needs: windows-build + + strategy: + fail-fast: false + matrix: + include: + - pkgarch: x86_64 + runarch: x86_64 + runner: windows-latest + - pkgarch: x86_64 + runarch: arm64 + runner: windows-11-arm + runs-on: ${{ matrix.runner }} + name: stc tests ${{ matrix.pkgarch }} on ${{ matrix.runarch }} Windows + + steps: + # install cygwin + - name: Install Cygwin + id: cygwin-install + uses: cygwin/cygwin-install-action@master + with: + platform: ${{ matrix.pkgarch }} + packages: | + gcc-core + git + meson + ninja + + # The download-artifact action currently seems to fail with EPERM when it + # tries to unpack over a symlink. Remove the only such instance. + - name: Workaround download-artifact issue + run: | + cd /d ${{ steps.cygwin-install.outputs.root }}\lib + bash -c 'rm libg.a' + shell: cmd + + # fetch the just-built cygwin installation artifact + - name: Unpack just-built Cygwin artifact + uses: actions/download-artifact@v4 + with: + name: cygwin-install-${{ matrix.pkgarch }} + # use the install-dir of cygwin-install-action above, so we unpack the + # artifact over it + path: ${{ steps.cygwin-install.outputs.root }} + + # This isn't quite right, as it just overwrites existing files, it doesn't + # remove anything which is no longer provided. Ideally, we'd make a cygwin + # package of the just-built cygwin version and install it here, but tools + # don't exist (yet) to let us do that... + + # fetch and build stc test + - name: Fetch and build stc tests + run: | + export PATH=/usr/bin:$(cygpath ${SYSTEMROOT})/system32 + uname -a + git clone https://cygwin.com/git/cygwin-apps/stc.git --depth 1 + meson setup _build stc + ninja -C _build + shell: bash --noprofile --norc -o igncr -eo pipefail '{0}' + + # run stc test + - name: Run stc tests + run: | + export PATH=/usr/bin:$(cygpath ${SYSTEMROOT})/system32 + meson test -C _build + shell: bash --noprofile --norc -o igncr -eo pipefail '{0}' + + # upload logs artifact + - name: Capture logs artifact + uses: actions/upload-artifact@v4 + with: + name: stc-logs-${{ matrix.pkgarch }}-on-${{ matrix.runarch }} + path: | + _build/meson-logs + if: ${{ !cancelled() }} diff --git a/libgloss/config/mips.mt b/libgloss/config/mips.mt index 6ae84b4..7be62dc 100644 --- a/libgloss/config/mips.mt +++ b/libgloss/config/mips.mt @@ -4,28 +4,62 @@ # are mentioned here, they are not used for all targets. # close.o: ${srcdir}/../close.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? fstat.o: ${srcdir}/../fstat.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? getpid.o: ${srcdir}/../getpid.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? isatty.o: ${srcdir}/../isatty.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? kill.o: ${srcdir}/../kill.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? lseek.o: ${srcdir}/../lseek.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? open.o: ${srcdir}/../open.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? print.o: ${srcdir}/../print.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? putnum.o: ${srcdir}/../putnum.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? read.o: ${srcdir}/../read.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? stat.o: ${srcdir}/../stat.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? unlink.o: ${srcdir}/../unlink.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? write.o: ${srcdir}/../write.c - $(CC) $(CFLAGS_FOR_TARGET) -O2 $(INCLUDES) -c $(CFLAGS) $? + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? +get_ram_range.o: ${srcdir}/hal/get_ram_range.c + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? +link.o: $(srcdir)/hal/link.c + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $? + +# These are the UHI implementations of semi-hosting functions + +uhi_getargs.o: $(srcdir)/uhi/uhi_getargs.S + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $< +uhi_%.o: $(srcdir)/uhi/uhi_%.c + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $< + +# These are the YAMON specific versions of semi-hosting which fall +# back to UHI for operations not supported natively on YAMON +yamon_%.o: $(srcdir)/uhi/yamon_%.c + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $< + +# Exception and interrupt handling support +mips_excpt_handler.o: $(srcdir)/hal/mips_excpt_handler.c + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) -DVERBOSE_EXCEPTIONS=1 $(INCLUDES) -c $(CFLAGS) $< +mips_excpt_handler_quiet.o: $(srcdir)/hal/mips_excpt_handler.c + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $< -o $@ +%.o: $(srcdir)/hal/%.S + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $< -o $@ +%.o: $(srcdir)/hal/%.c + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $< -o $@ +mips_excpt_isr_000.o: + $(CC) $(CFLAGS_FOR_TARGET) $(HALCFLAGS) $(INCLUDES) $(CFLAGS) -c -DDEF=__isr_vec_000 -DREF=__isr_vec_000 -DISR=_mips_isr_000 -DZERO ${srcdir}/hal/mips_excpt_isr_fragment.S -o $@ +mips_excpt_isr_%.o: + $(CC) $(CFLAGS_FOR_TARGET) $(HALCFLAGS) $(INCLUDES) $(CFLAGS) -c -DDEF=__isr_vec_$* -DREF=__isr_vec_$(shell printf '%03d' `expr $* - 1`) -DISR=_mips_isr_$* ${srcdir}/hal/mips_excpt_isr_fragment.S -o $@ + +# Boot code +%.o: $(srcdir)/boot/%.S + $(CC) $(CFLAGS_FOR_TARGET) -O2 $(HALCFLAGS) $(INCLUDES) -c $(CFLAGS) $< diff --git a/libgloss/configure b/libgloss/configure index a0cc8b5..3eb4c27 100755 --- a/libgloss/configure +++ b/libgloss/configure @@ -5461,18 +5461,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 @@ -5484,6 +5482,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/doc/porting.texi b/libgloss/doc/porting.texi index 1f68757..dd5e29e 100644 --- a/libgloss/doc/porting.texi +++ b/libgloss/doc/porting.texi @@ -50,9 +50,7 @@ into another language, under the above conditions for modified versions. @end titlepage @direntry -START-INFO-DIR-ENTRY * Embed with GNU: (porting-). Embed with GNU -END-INFO-DIR-ENTRY @end direntry @ifnottex diff --git a/libgloss/kill.c b/libgloss/kill.c index 4b9b736..fd52bd6 100644 --- a/libgloss/kill.c +++ b/libgloss/kill.c @@ -13,6 +13,7 @@ * they apply. */ #include "glue.h" +void _exit(int); extern void _exit (int) __attribute__((__noreturn__)); 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)) } +} diff --git a/libgloss/or1k/impure.c b/libgloss/or1k/impure.c index e94fd63..7780c91 100644 --- a/libgloss/or1k/impure.c +++ b/libgloss/or1k/impure.c @@ -108,7 +108,7 @@ _or1k_libc_getreent(void) { } #ifdef __OR1K_MULTICORE__ -struct _or1k_reent (*_or1k_reent)[]; +struct _or1k_reent *_or1k_reent; #else struct _or1k_reent _or1k_reent; #endif diff --git a/libgloss/or1k/or1k-internals.h b/libgloss/or1k/or1k-internals.h index 3aabdb0..d92c166 100644 --- a/libgloss/or1k/or1k-internals.h +++ b/libgloss/or1k/or1k-internals.h @@ -55,8 +55,8 @@ struct _or1k_reent { #ifdef __OR1K_MULTICORE__ -extern struct _or1k_reent (*_or1k_reent)[]; -#define OR1K_REENT (*_or1k_reent)[or1k_coreid()] +extern struct _or1k_reent *_or1k_reent; +#define OR1K_REENT _or1k_reent[or1k_coreid()] #else extern struct _or1k_reent _or1k_reent; #define OR1K_REENT _or1k_reent diff --git a/libgloss/riscv/crt0.S b/libgloss/riscv/crt0.S index 54443e4..aa5ac36 100644 --- a/libgloss/riscv/crt0.S +++ b/libgloss/riscv/crt0.S @@ -27,8 +27,13 @@ _start: .option pop /* Initialize jvt CSR (reg addr: 0x0017) */ +#ifndef __riscv_cmodel_large .weak __jvt_base$ lla a0, __jvt_base$ +#else + la a0, .Laddr_jvt_base + ld a0, 0(a0) +#endif beqz a0, .Ljvt_init_end .option push .option norelax @@ -38,21 +43,38 @@ _start: .Ljvt_init_end: # Clear the bss segment +#ifndef __riscv_cmodel_large la a0, __bss_start la a2, _end +#else + la a0, .Laddr_bss_start + ld a0, 0(a0) + la a2, .Laddr_end + ld a2, 0(a2) +#endif sub a2, a2, a0 li a1, 0 call memset #ifdef _LITE_EXIT # Make reference to atexit weak to avoid unconditionally pulling in # support code. Refer to comments in __atexit.c for more details. +#ifndef __riscv_cmodel_large .weak atexit la a0, atexit +#else + la a0, .Laddr_atexit + ld a0, 0(a0) +#endif beqz a0, .Lweak_atexit .weak __libc_fini_array #endif +#ifndef __riscv_cmodel_large la a0, __libc_fini_array # Register global termination functions +#else + la a0, .Laddr_libc_fini_array + ld a0, 0(a0) +#endif call atexit # to be called upon exit #ifdef _LITE_EXIT .Lweak_atexit: @@ -66,4 +88,21 @@ _start: add a2, a2, a1 # a2 = envp call main tail exit +#ifdef __riscv_cmodel_large +.Laddr_gp: + .dword __global_pointer$ +.Laddr_jvt_base: + .weak __jvt_base$ + .dword __jvt_base$ +.Laddr_bss_start: + .dword __bss_start +.Laddr_end: + .dword _end +.Laddr_atexit: + .weak atexit + .dword atexit +.Laddr_libc_fini_array: + .weak __libc_fini_array + .dword __libc_fini_array +#endif .size _start, .-_start diff --git a/libgloss/riscv/internal_syscall.h b/libgloss/riscv/internal_syscall.h index 080c8c8..254880b 100644 --- a/libgloss/riscv/internal_syscall.h +++ b/libgloss/riscv/internal_syscall.h @@ -24,7 +24,7 @@ __syscall_error(long a0) static inline long __internal_syscall(long n, int argc, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5) { -#ifdef __riscv_32e +#ifdef __riscv_abi_rve register long syscall_id asm("t0") = n; #else register long syscall_id asm("a7") = n; diff --git a/libgloss/rs6000/mbx-print.c b/libgloss/rs6000/mbx-print.c index 64472ee..591ca2d 100644 --- a/libgloss/rs6000/mbx-print.c +++ b/libgloss/rs6000/mbx-print.c @@ -13,6 +13,8 @@ * they apply. */ +extern int write(int fd, const void *buf, unsigned int count); + /* * print -- do a raw print of a string */ diff --git a/libgloss/rs6000/mvme-print.c b/libgloss/rs6000/mvme-print.c index 8d19542..d8f4c50 100644 --- a/libgloss/rs6000/mvme-print.c +++ b/libgloss/rs6000/mvme-print.c @@ -12,6 +12,9 @@ * the new terms are clearly indicated on the first page of each file where * they apply. */ +extern void __pcrlf(void); +extern void __outln(char *, char *); +extern void __outstr(char *, char *); /* * write -- write some bytes to the output device. diff --git a/libgloss/rs6000/mvme-read.c b/libgloss/rs6000/mvme-read.c index 1c823b4..9d1e7d3 100644 --- a/libgloss/rs6000/mvme-read.c +++ b/libgloss/rs6000/mvme-read.c @@ -14,7 +14,7 @@ */ extern int inbyte (); -extern char * __inln (); +extern char * __inln (char *); /* * read -- read bytes from the serial port. Ignore fd, since diff --git a/libgloss/rs6000/sim-abort.c b/libgloss/rs6000/sim-abort.c index e1b59cf..931f886 100644 --- a/libgloss/rs6000/sim-abort.c +++ b/libgloss/rs6000/sim-abort.c @@ -14,6 +14,9 @@ * they apply. */ +extern int write(int fd, const void *buf, unsigned int count); +extern void exit(int status); + void abort(void) { write (2, "Abort called.\n", sizeof("Abort called.\n")-1); diff --git a/libgloss/rs6000/sim-inbyte.c b/libgloss/rs6000/sim-inbyte.c index 787b689..fe1ac2a 100644 --- a/libgloss/rs6000/sim-inbyte.c +++ b/libgloss/rs6000/sim-inbyte.c @@ -13,6 +13,7 @@ * the new terms are clearly indicated on the first page of each file where * they apply. */ +extern int read(int fd, void *buf, unsigned int count); int inbyte () diff --git a/libgloss/rs6000/sim-print.c b/libgloss/rs6000/sim-print.c index c0b9adc..49596af 100644 --- a/libgloss/rs6000/sim-print.c +++ b/libgloss/rs6000/sim-print.c @@ -13,6 +13,8 @@ * they apply. */ +extern int write(int fd, const void *buf, unsigned int count); + /* * print -- do a raw print of a string */ diff --git a/libgloss/rs6000/sim-sbrk.c b/libgloss/rs6000/sim-sbrk.c index 5c8bd65..0bbfe33 100644 --- a/libgloss/rs6000/sim-sbrk.c +++ b/libgloss/rs6000/sim-sbrk.c @@ -13,6 +13,7 @@ * the new terms are clearly indicated on the first page of each file where * they apply. */ +extern int brk(void *addr); extern char _end[]; static char *curbrk = _end; diff --git a/newlib/MAINTAINERS b/newlib/MAINTAINERS index 4dfef27..499791e 100644 --- a/newlib/MAINTAINERS +++ b/newlib/MAINTAINERS @@ -41,7 +41,6 @@ mn10300 Nick Clifton nickc@redhat.com moxie Anthony Green green@moxielogic.com risc-v Kito Cheng kito.cheng@gmail.com aarch64 Richard Earnshaw richard.earnshaw@arm.com - Marcus Shawcroft marcus.shawcroft@arm.com msp430 Nick Clifton nickc@redhat.com pru Dimitar Dimitrov dimitar@dinux.eu diff --git a/newlib/Makefile.in b/newlib/Makefile.in index 52b5d80..af520ac 100644 --- a/newlib/Makefile.in +++ b/newlib/Makefile.in @@ -856,7 +856,7 @@ check_PROGRAMS = @HAVE_LIBC_MACHINE_PRU_TRUE@am__append_113 = libc/machine/pru/setjmp.s @HAVE_LIBC_MACHINE_RISCV_TRUE@am__append_114 = \ @HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/memmove.S libc/machine/riscv/memmove-stub.c libc/machine/riscv/memset.S libc/machine/riscv/memcpy-asm.S libc/machine/riscv/memcpy.c libc/machine/riscv/strlen.c \ -@HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/strcpy.c libc/machine/riscv/stpcpy.c libc/machine/riscv/strcmp.S libc/machine/riscv/setjmp.S libc/machine/riscv/ieeefp.c libc/machine/riscv/ffs.c +@HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/strcpy.c libc/machine/riscv/stpcpy.c libc/machine/riscv/strcmp.S libc/machine/riscv/memchr.c libc/machine/riscv/memrchr.c libc/machine/riscv/setjmp.S libc/machine/riscv/ieeefp.c libc/machine/riscv/ffs.c @HAVE_LIBC_MACHINE_RL78_TRUE@am__append_115 = libc/machine/rl78/setjmp.S @HAVE_LIBC_MACHINE_RX_TRUE@am__append_116 = \ @@ -2185,6 +2185,8 @@ am__objects_51 = libc/ssp/libc_a-chk_fail.$(OBJEXT) \ @HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-strcpy.$(OBJEXT) \ @HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-stpcpy.$(OBJEXT) \ @HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-strcmp.$(OBJEXT) \ +@HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-memchr.$(OBJEXT) \ +@HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-memrchr.$(OBJEXT) \ @HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-setjmp.$(OBJEXT) \ @HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-ieeefp.$(OBJEXT) \ @HAVE_LIBC_MACHINE_RISCV_TRUE@ libc/machine/riscv/libc_a-ffs.$(OBJEXT) @@ -4002,7 +4004,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ shared_machine_dir = @shared_machine_dir@ sharedstatedir = @sharedstatedir@ @@ -9185,6 +9186,12 @@ libc/machine/riscv/libc_a-stpcpy.$(OBJEXT): \ libc/machine/riscv/libc_a-strcmp.$(OBJEXT): \ libc/machine/riscv/$(am__dirstamp) \ libc/machine/riscv/$(DEPDIR)/$(am__dirstamp) +libc/machine/riscv/libc_a-memchr.$(OBJEXT): \ + libc/machine/riscv/$(am__dirstamp) \ + libc/machine/riscv/$(DEPDIR)/$(am__dirstamp) +libc/machine/riscv/libc_a-memrchr.$(OBJEXT): \ + libc/machine/riscv/$(am__dirstamp) \ + libc/machine/riscv/$(DEPDIR)/$(am__dirstamp) libc/machine/riscv/libc_a-setjmp.$(OBJEXT): \ libc/machine/riscv/$(am__dirstamp) \ libc/machine/riscv/$(DEPDIR)/$(am__dirstamp) @@ -13139,10 +13146,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/powerpc/$(DEPDIR)/libc_a-vfscanf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-ffs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-ieeefp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-memchr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-memcpy-asm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-memcpy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-memmove-stub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-memmove.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-memrchr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-memset.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-setjmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/machine/riscv/$(DEPDIR)/libc_a-stpcpy.Po@am__quote@ @@ -18832,28 +18841,28 @@ libc/machine/mips/libc_a-strcmp.obj: libc/machine/mips/strcmp.S libc/machine/mips/libc_a-memset.o: libc/machine/mips/memset.S @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -MT libc/machine/mips/libc_a-memset.o -MD -MP -MF libc/machine/mips/$(DEPDIR)/libc_a-memset.Tpo -c -o libc/machine/mips/libc_a-memset.o `test -f 'libc/machine/mips/memset.S' || echo '$(srcdir)/'`libc/machine/mips/memset.S @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) libc/machine/mips/$(DEPDIR)/libc_a-memset.Tpo libc/machine/mips/$(DEPDIR)/libc_a-memset.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memset.S' object='libc/machine/mips/libc_a-memset.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memset.c' object='libc/machine/mips/libc_a-memset.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -c -o libc/machine/mips/libc_a-memset.o `test -f 'libc/machine/mips/memset.S' || echo '$(srcdir)/'`libc/machine/mips/memset.S libc/machine/mips/libc_a-memset.obj: libc/machine/mips/memset.S @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -MT libc/machine/mips/libc_a-memset.obj -MD -MP -MF libc/machine/mips/$(DEPDIR)/libc_a-memset.Tpo -c -o libc/machine/mips/libc_a-memset.obj `if test -f 'libc/machine/mips/memset.S'; then $(CYGPATH_W) 'libc/machine/mips/memset.S'; else $(CYGPATH_W) '$(srcdir)/libc/machine/mips/memset.S'; fi` @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) libc/machine/mips/$(DEPDIR)/libc_a-memset.Tpo libc/machine/mips/$(DEPDIR)/libc_a-memset.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memset.S' object='libc/machine/mips/libc_a-memset.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memset.c' object='libc/machine/mips/libc_a-memset.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -c -o libc/machine/mips/libc_a-memset.obj `if test -f 'libc/machine/mips/memset.S'; then $(CYGPATH_W) 'libc/machine/mips/memset.S'; else $(CYGPATH_W) '$(srcdir)/libc/machine/mips/memset.S'; fi` libc/machine/mips/libc_a-memcpy.o: libc/machine/mips/memcpy.S @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -MT libc/machine/mips/libc_a-memcpy.o -MD -MP -MF libc/machine/mips/$(DEPDIR)/libc_a-memcpy.Tpo -c -o libc/machine/mips/libc_a-memcpy.o `test -f 'libc/machine/mips/memcpy.S' || echo '$(srcdir)/'`libc/machine/mips/memcpy.S @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) libc/machine/mips/$(DEPDIR)/libc_a-memcpy.Tpo libc/machine/mips/$(DEPDIR)/libc_a-memcpy.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memcpy.S' object='libc/machine/mips/libc_a-memcpy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memcpy.c' object='libc/machine/mips/libc_a-memcpy.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -c -o libc/machine/mips/libc_a-memcpy.o `test -f 'libc/machine/mips/memcpy.S' || echo '$(srcdir)/'`libc/machine/mips/memcpy.S libc/machine/mips/libc_a-memcpy.obj: libc/machine/mips/memcpy.S @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -MT libc/machine/mips/libc_a-memcpy.obj -MD -MP -MF libc/machine/mips/$(DEPDIR)/libc_a-memcpy.Tpo -c -o libc/machine/mips/libc_a-memcpy.obj `if test -f 'libc/machine/mips/memcpy.S'; then $(CYGPATH_W) 'libc/machine/mips/memcpy.S'; else $(CYGPATH_W) '$(srcdir)/libc/machine/mips/memcpy.S'; fi` @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) libc/machine/mips/$(DEPDIR)/libc_a-memcpy.Tpo libc/machine/mips/$(DEPDIR)/libc_a-memcpy.Po -@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memcpy.S' object='libc/machine/mips/libc_a-memcpy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='libc/machine/mips/memcpy.c' object='libc/machine/mips/libc_a-memcpy.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CCASFLAGS) $(CCASFLAGS) -c -o libc/machine/mips/libc_a-memcpy.obj `if test -f 'libc/machine/mips/memcpy.S'; then $(CYGPATH_W) 'libc/machine/mips/memcpy.S'; else $(CYGPATH_W) '$(srcdir)/libc/machine/mips/memcpy.S'; fi` @@ -34819,6 +34828,34 @@ libc/machine/riscv/libc_a-stpcpy.obj: libc/machine/riscv/stpcpy.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/machine/riscv/libc_a-stpcpy.obj `if test -f 'libc/machine/riscv/stpcpy.c'; then $(CYGPATH_W) 'libc/machine/riscv/stpcpy.c'; else $(CYGPATH_W) '$(srcdir)/libc/machine/riscv/stpcpy.c'; fi` +libc/machine/riscv/libc_a-memchr.o: libc/machine/riscv/memchr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/machine/riscv/libc_a-memchr.o -MD -MP -MF libc/machine/riscv/$(DEPDIR)/libc_a-memchr.Tpo -c -o libc/machine/riscv/libc_a-memchr.o `test -f 'libc/machine/riscv/memchr.c' || echo '$(srcdir)/'`libc/machine/riscv/memchr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/machine/riscv/$(DEPDIR)/libc_a-memchr.Tpo libc/machine/riscv/$(DEPDIR)/libc_a-memchr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/machine/riscv/memchr.c' object='libc/machine/riscv/libc_a-memchr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/machine/riscv/libc_a-memchr.o `test -f 'libc/machine/riscv/memchr.c' || echo '$(srcdir)/'`libc/machine/riscv/memchr.c + +libc/machine/riscv/libc_a-memchr.obj: libc/machine/riscv/memchr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/machine/riscv/libc_a-memchr.obj -MD -MP -MF libc/machine/riscv/$(DEPDIR)/libc_a-memchr.Tpo -c -o libc/machine/riscv/libc_a-memchr.obj `if test -f 'libc/machine/riscv/memchr.c'; then $(CYGPATH_W) 'libc/machine/riscv/memchr.c'; else $(CYGPATH_W) '$(srcdir)/libc/machine/riscv/memchr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/machine/riscv/$(DEPDIR)/libc_a-memchr.Tpo libc/machine/riscv/$(DEPDIR)/libc_a-memchr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/machine/riscv/memchr.c' object='libc/machine/riscv/libc_a-memchr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/machine/riscv/libc_a-memchr.obj `if test -f 'libc/machine/riscv/memchr.c'; then $(CYGPATH_W) 'libc/machine/riscv/memchr.c'; else $(CYGPATH_W) '$(srcdir)/libc/machine/riscv/memchr.c'; fi` + +libc/machine/riscv/libc_a-memrchr.o: libc/machine/riscv/memrchr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/machine/riscv/libc_a-memrchr.o -MD -MP -MF libc/machine/riscv/$(DEPDIR)/libc_a-memrchr.Tpo -c -o libc/machine/riscv/libc_a-memrchr.o `test -f 'libc/machine/riscv/memrchr.c' || echo '$(srcdir)/'`libc/machine/riscv/memrchr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/machine/riscv/$(DEPDIR)/libc_a-memrchr.Tpo libc/machine/riscv/$(DEPDIR)/libc_a-memrchr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/machine/riscv/memrchr.c' object='libc/machine/riscv/libc_a-memrchr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/machine/riscv/libc_a-memrchr.o `test -f 'libc/machine/riscv/memrchr.c' || echo '$(srcdir)/'`libc/machine/riscv/memrchr.c + +libc/machine/riscv/libc_a-memrchr.obj: libc/machine/riscv/memrchr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/machine/riscv/libc_a-memrchr.obj -MD -MP -MF libc/machine/riscv/$(DEPDIR)/libc_a-memrchr.Tpo -c -o libc/machine/riscv/libc_a-memrchr.obj `if test -f 'libc/machine/riscv/memrchr.c'; then $(CYGPATH_W) 'libc/machine/riscv/memrchr.c'; else $(CYGPATH_W) '$(srcdir)/libc/machine/riscv/memrchr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/machine/riscv/$(DEPDIR)/libc_a-memrchr.Tpo libc/machine/riscv/$(DEPDIR)/libc_a-memrchr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/machine/riscv/memrchr.c' object='libc/machine/riscv/libc_a-memrchr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/machine/riscv/libc_a-memrchr.obj `if test -f 'libc/machine/riscv/memrchr.c'; then $(CYGPATH_W) 'libc/machine/riscv/memrchr.c'; else $(CYGPATH_W) '$(srcdir)/libc/machine/riscv/memrchr.c'; fi` + libc/machine/riscv/libc_a-ieeefp.o: libc/machine/riscv/ieeefp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/machine/riscv/libc_a-ieeefp.o -MD -MP -MF libc/machine/riscv/$(DEPDIR)/libc_a-ieeefp.Tpo -c -o libc/machine/riscv/libc_a-ieeefp.o `test -f 'libc/machine/riscv/ieeefp.c' || echo '$(srcdir)/'`libc/machine/riscv/ieeefp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/machine/riscv/$(DEPDIR)/libc_a-ieeefp.Tpo libc/machine/riscv/$(DEPDIR)/libc_a-ieeefp.Po diff --git a/newlib/configure.host b/newlib/configure.host index c43cfcf..89564c0 100644 --- a/newlib/configure.host +++ b/newlib/configure.host @@ -252,6 +252,7 @@ case "${host_cpu}" in mips*) machine_dir=mips libm_machine_dir=mips + newlib_cflags="${newlib_cflags}" ;; mmix) ;; diff --git a/newlib/doc/makedocbook.py b/newlib/doc/makedocbook.py index 9c5615f..b5ef596 100755 --- a/newlib/doc/makedocbook.py +++ b/newlib/doc/makedocbook.py @@ -198,7 +198,7 @@ def function(c, l): descr = line_markup_convert(', '.join(descrlist)) # fpclassify includes an 'and' we need to discard - namelist = map(lambda v: re.sub(r'^and ', r'', v.strip(), 1), namelist) + namelist = map(lambda v: re.sub(r'^and ', r'', v.strip(), count=1), namelist) # strip off << >> surrounding name namelist = map(lambda v: v.strip().lstrip('<').rstrip('>'), namelist) # instantiate list to make it subscriptable @@ -563,7 +563,7 @@ def t_TABLEEND(t): def t_ITEM(t): r'o\s.*\n' - t.value = re.sub(r'o\s', r'', lexer.lexmatch.group(0), 1) + t.value = re.sub(r'o\s', r'', lexer.lexmatch.group(0), count=1) t.value = line_markup_convert(t.value) return t diff --git a/newlib/libc/ctype/ctype_.c b/newlib/libc/ctype/ctype_.c index 32ce4f3..869945f 100644 --- a/newlib/libc/ctype/ctype_.c +++ b/newlib/libc/ctype/ctype_.c @@ -95,21 +95,12 @@ char _ctype_b[128 + 256] = { /* For backward compatibility */ char __EXPORT *__ctype_ptr__ = DEFAULT_CTYPE_PTR; -# ifdef __x86_64__ __asm__ (" \n\ .data \n\ .globl _ctype_ \n\ .set _ctype_,_ctype_b+127 \n\ .text \n\ "); -# else -__asm__ (" \n\ - .data \n\ - .globl __ctype_ \n\ - .set __ctype_,__ctype_b+127 \n\ - .text \n\ -"); -# endif # else /* !__CYGWIN__ */ const char _ctype_[1 + 256] = { diff --git a/newlib/libc/include/machine/ieeefp.h b/newlib/libc/include/machine/ieeefp.h index f99577b..c5fafcf 100644 --- a/newlib/libc/include/machine/ieeefp.h +++ b/newlib/libc/include/machine/ieeefp.h @@ -263,9 +263,15 @@ #ifdef __MIPSEL__ #define __IEEE_LITTLE_ENDIAN +#if __SIZEOF_DOUBLE__ == 4 +#define _DOUBLE_IS_32BITS +#endif #endif #ifdef __MIPSEB__ #define __IEEE_BIG_ENDIAN +#if __SIZEOF_DOUBLE__ == 4 +#define _DOUBLE_IS_32BITS +#endif #endif #ifdef __MMIX__ diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h index 102582c..ab820ed 100644 --- a/newlib/libc/include/machine/setjmp.h +++ b/newlib/libc/include/machine/setjmp.h @@ -22,7 +22,16 @@ _BEGIN_STD_C #endif #if defined(__aarch64__) -#define _JBLEN 22 +# if defined(__CYGWIN__) +/* + * Windows Arm64 ABI requires saving x19-x28, FP, LR, SP, FPCR, FPSR, d8-d15 + * and jump address to jmp_buf. On top of that, Cygwin requires saving + * TLS stack pointer. + */ +# define _JBLEN 25 +# else +# define _JBLEN 22 +# endif #define _JBTYPE long long #endif diff --git a/newlib/libc/include/pthread.h b/newlib/libc/include/pthread.h index c99ad39..05ff315 100644 --- a/newlib/libc/include/pthread.h +++ b/newlib/libc/include/pthread.h @@ -87,11 +87,11 @@ int pthread_mutex_timedlock (pthread_mutex_t *__mutex, #endif /* _POSIX_TIMEOUTS */ -#if __GNU_VISIBLE +#if (__GNU_VISIBLE || __POSIX_VISIBLE >= 202405) /* The Issue 8 standard adds pthread_mutex_clocklock() */ int pthread_mutex_clocklock(pthread_mutex_t *__restrict, clockid_t, const struct timespec *__restrict); -#endif /* __GNU_VISIBLE */ +#endif /* __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 */ /* Condition Variable Initialization Attributes, P1003.1c/Draft 10, p. 96 */ @@ -133,12 +133,12 @@ int pthread_cond_timedwait (pthread_cond_t *__cond, pthread_mutex_t *__mutex, const struct timespec *__abstime); -#if __GNU_VISIBLE +#if (__GNU_VISIBLE || __POSIX_VISIBLE >= 202405) /* The Issue 8 standard adds pthread_cond_clockwait() */ int pthread_cond_clockwait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict, clockid_t, const struct timespec *__restrict); -#endif /* __GNU_VISIBLE */ +#endif /* __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 */ #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) @@ -436,14 +436,14 @@ int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); int pthread_rwlock_timedwrlock (pthread_rwlock_t *__rwlock, const struct timespec *__abstime); -#if __GNU_VISIBLE +#if (__GNU_VISIBLE || __POSIX_VISIBLE >= 202405) /* The Issue 8 standard adds pthread_rwlock_clockrdlock() * and pthread_rwlock_clockwrlock()*/ int pthread_rwlock_clockrdlock(pthread_rwlock_t *__restrict, clockid_t, const struct timespec *__restrict); int pthread_rwlock_clockwrlock(pthread_rwlock_t *__restrict, clockid_t, const struct timespec *__restrict); -#endif /* __GNU_VISIBLE */ +#endif /* __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 */ #endif /* defined(_POSIX_READER_WRITER_LOCKS) */ diff --git a/newlib/libc/include/search.h b/newlib/libc/include/search.h index ed321b0..70a1a20 100644 --- a/newlib/libc/include/search.h +++ b/newlib/libc/include/search.h @@ -36,6 +36,8 @@ typedef struct node { } node_t; #endif +typedef void posix_tnode; + struct hsearch_data { struct internal_head *htable; @@ -54,11 +56,11 @@ ENTRY *hsearch(ENTRY, ACTION); int hcreate_r(size_t, struct hsearch_data *); void hdestroy_r(struct hsearch_data *); int hsearch_r(ENTRY, ACTION, ENTRY **, struct hsearch_data *); -void *tdelete(const void *__restrict, void **__restrict, __compar_fn_t); +void *tdelete(const void *__restrict, posix_tnode **__restrict, __compar_fn_t); void tdestroy (void *, void (*)(void *)); -void *tfind(const void *, void **, __compar_fn_t); -void *tsearch(const void *, void **, __compar_fn_t); -void twalk(const void *, void (*)(const void *, VISIT, int)); +posix_tnode *tfind(const void *, posix_tnode *const *, __compar_fn_t); +posix_tnode *tsearch(const void *, posix_tnode **, __compar_fn_t); +void twalk(const posix_tnode *, void (*)(const posix_tnode *, VISIT, int)); __END_DECLS #endif /* !_SEARCH_H_ */ diff --git a/newlib/libc/include/stdlib.h b/newlib/libc/include/stdlib.h index 0690a03..55b20fa 100644 --- a/newlib/libc/include/stdlib.h +++ b/newlib/libc/include/stdlib.h @@ -333,10 +333,13 @@ extern long double strtold (const char *__restrict, char **__restrict); #if __ISO_C_VISIBLE >= 2011 void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) __alloc_size(2) __result_use_check; +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#if (__ISO_C_VISIBLE >= 2011 || __POSIX_VISIBLE >= 202405) int at_quick_exit(void (*)(void)); _Noreturn void quick_exit(int); -#endif /* __ISO_C_VISIBLE >= 2011 */ +#endif /* __ISO_C_VISIBLE >= 2011 || __POSIX_VISIBLE >= 202405 */ _END_STD_C diff --git a/newlib/libc/include/sys/config.h b/newlib/libc/include/sys/config.h index 5dcc77a..4c9acc5 100644 --- a/newlib/libc/include/sys/config.h +++ b/newlib/libc/include/sys/config.h @@ -4,7 +4,7 @@ #include <machine/ieeefp.h> /* floating point macros */ #include <sys/features.h> /* POSIX defs */ -#ifdef __aarch64__ +#if defined(__aarch64__) || defined(__mips__) #define MALLOC_ALIGNMENT 16 #endif diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h index 5ce5387..eafac96 100644 --- a/newlib/libc/include/sys/reent.h +++ b/newlib/libc/include/sys/reent.h @@ -709,7 +709,8 @@ struct _reent {0, {0}}, \ {0, {0}}, \ {0, {0}}, \ - {0, {0}} \ + {0, {0}}, \ + 0 \ } \ }, \ _REENT_INIT_RESERVED_6_7 \ diff --git a/newlib/libc/include/sys/stat.h b/newlib/libc/include/sys/stat.h index b4e27f2..7edfe34 100644 --- a/newlib/libc/include/sys/stat.h +++ b/newlib/libc/include/sys/stat.h @@ -38,6 +38,16 @@ struct stat time_t st_atime; time_t st_mtime; time_t st_ctime; +#elif defined(__mips__) + time_t st_atime; + long st_spare1; + time_t st_mtime; + long st_spare2; + time_t st_ctime; + long st_spare3; + blksize_t st_blksize; + blkcnt_t st_blocks; + long st_spare4[2]; #else struct timespec st_atim; struct timespec st_mtim; @@ -50,7 +60,7 @@ struct stat #endif }; -#if !(defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)) +#if !((defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)) || defined(__mips__)) #define st_atime st_atim.tv_sec #define st_ctime st_ctim.tv_sec #define st_mtime st_mtim.tv_sec @@ -136,7 +146,11 @@ struct stat int chmod (const char *__path, mode_t __mode ); int fchmod (int __fd, mode_t __mode); +#if defined(__mips__) && defined(__mips16) +int __attribute__((nomips16)) fstat (int __fd, struct stat *__sbuf ); +#else int fstat (int __fd, struct stat *__sbuf ); +#endif // __mips__ int mkdir (const char *_path, mode_t __mode ); int mkfifo (const char *__path, mode_t __mode ); int stat (const char *__restrict __path, struct stat *__restrict __sbuf ); diff --git a/newlib/libc/include/sys/unistd.h b/newlib/libc/include/sys/unistd.h index 771a4bd..4cf9f06 100644 --- a/newlib/libc/include/sys/unistd.h +++ b/newlib/libc/include/sys/unistd.h @@ -215,7 +215,7 @@ int setpgrp (void); #if defined(__CYGWIN__) && __BSD_VISIBLE /* Stub for Linux libbsd compatibility. */ #define initsetproctitle(c, a, e) setproctitle_init((c), (a), (e)) -static inline void setproctitle_init (int _c, char *_a[], char *_e[]) {} +static __inline void setproctitle_init (int _c, char *_a[], char *_e[]) {} void setproctitle (const char *, ...) _ATTRIBUTE ((__format__ (__printf__, 1, 2))); diff --git a/newlib/libc/include/time.h b/newlib/libc/include/time.h index ab34913..a2df4f7 100644 --- a/newlib/libc/include/time.h +++ b/newlib/libc/include/time.h @@ -57,6 +57,11 @@ clock_t clock (void); double difftime (time_t _time2, time_t _time1); time_t mktime (struct tm *_timeptr); time_t time (time_t *_timer); +#if (__ISO_C_VISIBLE >= 2011 || __POSIX_VISIBLE >= 202405) +#define TIME_UTC 1 + +int timespec_get(struct timespec *ts, int base); +#endif #ifndef _REENT_ONLY char *asctime (const struct tm *_tblock); char *ctime (const time_t *_time); diff --git a/newlib/libc/machine/aarch64/sys/fenv.h b/newlib/libc/machine/aarch64/sys/fenv.h index 6b08792..1f97791 100644 --- a/newlib/libc/machine/aarch64/sys/fenv.h +++ b/newlib/libc/machine/aarch64/sys/fenv.h @@ -80,9 +80,17 @@ extern const fenv_t *_fe_dfl_env; #if __BSD_VISIBLE -/* We currently provide no external definitions of the functions below. */ +/* We currently provide no external definitions of the functions below + except of for Cygwin where those functions are exported by + winsup/cygwin/cygwin.din. */ + +#ifdef __CYGWIN__ +#define __cygwin_fenv_static __fenv_static +#else +#define __cygwin_fenv_static static +#endif -static inline int +__cygwin_fenv_static inline int feenableexcept(int __mask) { fenv_t __old_r, __new_r; @@ -93,7 +101,7 @@ feenableexcept(int __mask) return ((__old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); } -static inline int +__cygwin_fenv_static inline int fedisableexcept(int __mask) { fenv_t __old_r, __new_r; @@ -104,7 +112,7 @@ fedisableexcept(int __mask) return ((__old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); } -static inline int +__cygwin_fenv_static inline int fegetexcept(void) { fenv_t __r; diff --git a/newlib/libc/machine/mips/Makefile.inc b/newlib/libc/machine/mips/Makefile.inc index 22f0c6e..3686beb 100644 --- a/newlib/libc/machine/mips/Makefile.inc +++ b/newlib/libc/machine/mips/Makefile.inc @@ -1 +1 @@ -libc_a_SOURCES += %D%/setjmp.S %D%/strlen.c %D%/strcmp.S %D%/strncpy.c %D%/memset.S %D%/memcpy.S +libc_a_SOURCES += %D%/setjmp.S %D%/strlen.c %D%/strcmp.S %D%/strncpy.c %D%/memset.c %D%/memcpy.c diff --git a/newlib/libc/machine/mips/machine/regdef.h b/newlib/libc/machine/mips/machine/regdef.h index 0164164..5d19f90 100644 --- a/newlib/libc/machine/mips/machine/regdef.h +++ b/newlib/libc/machine/mips/machine/regdef.h @@ -45,6 +45,11 @@ #define v0 $2 #define v1 $3 +#define va0 $2 +#define va1 $3 + +#define vt0 $2 +#define vt1 $3 #define a0 $4 #define a1 $5 @@ -100,4 +105,37 @@ #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 diff --git a/newlib/libc/machine/mips/memcpy.c b/newlib/libc/machine/mips/memcpy.c new file mode 100644 index 0000000..03ef299 --- /dev/null +++ b/newlib/libc/machine/mips/memcpy.c @@ -0,0 +1,449 @@ +/* + * 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. +*/ + +/* Typical observed latency in cycles in fetching from DRAM. */ +#ifndef LATENCY_CYCLES + #define LATENCY_CYCLES 63 +#endif + +/* Pre-fetch performance is subject to accurate prefetch ahead, + which in turn depends on both the cache-line size and the amount + of look-ahead. Since cache-line size is not nominally fixed in + a typically library built for multiple platforms, we make conservative + assumptions in the default case. This code will typically operate + on such conservative assumptions, but if compiled with the correct + -mtune=xx options, will perform even better on those specific + platforms. */ +#if defined(_MIPS_TUNE_OCTEON2) || defined(_MIPS_TUNE_OCTEON3) + #define CACHE_LINE 128 + #define BLOCK_CYCLES 30 + #undef LATENCY_CYCLES + #define LATENCY_CYCLES 150 +#elif defined(_MIPS_TUNE_I6400) || defined(_MIPS_TUNE_I6500) + #define CACHE_LINE 64 + #define BLOCK_CYCLES 15 +#elif defined(_MIPS_TUNE_P6600) + #define CACHE_LINE 32 + #define BLOCK_CYCLES 15 +#elif defined(_MIPS_TUNE_INTERAPTIV) || defined(_MIPS_TUNE_INTERAPTIV_MR2) + #define CACHE_LINE 32 + #define BLOCK_CYCLES 30 +#else + #ifndef CACHE_LINE + #define CACHE_LINE 32 + #endif + #ifndef BLOCK_CYCLES + #ifdef __nanomips__ + #define BLOCK_CYCLES 20 + #else + #define BLOCK_CYCLES 11 + #endif + #endif +#endif + +/* Pre-fetch look ahead = ceil (latency / block-cycles) */ +#define PREF_AHEAD (LATENCY_CYCLES / BLOCK_CYCLES \ + + ((LATENCY_CYCLES % BLOCK_CYCLES) == 0 ? 0 : 1)) + +/* The unroll-factor controls how many words at a time in the core loop. */ +#ifndef BLOCK_SIZE + #define BLOCK_SIZE (CACHE_LINE == 128 ? 16 : 8) +#elif BLOCK_SIZE != 8 && BLOCK_SIZE != 16 + #error "BLOCK_SIZE must be 8 or 16" +#endif + +#define __overloadable +#if !defined(UNALIGNED_INSTR_SUPPORT) +/* does target have unaligned lw/ld/ualw/uald instructions? */ + #define UNALIGNED_INSTR_SUPPORT 0 +#if (__mips_isa_rev < 6 && !defined(__mips1)) || defined(__nanomips__) + #undef UNALIGNED_INSTR_SUPPORT + #define UNALIGNED_INSTR_SUPPORT 1 + #endif +#endif +#if !defined(HW_UNALIGNED_SUPPORT) +/* Does target have hardware support for unaligned accesses? */ + #define HW_UNALIGNED_SUPPORT 0 + #if __mips_isa_rev >= 6 && !defined(__nanomips__) + #undef HW_UNALIGNED_SUPPORT + #define HW_UNALIGNED_SUPPORT 1 + #endif +#endif + +#ifndef ENABLE_PREFETCH + #define ENABLE_PREFETCH 1 +#endif + +#ifndef ENABLE_PREFETCH_CHECK + #define ENABLE_PREFETCH_CHECK 0 +#endif + +#if ENABLE_PREFETCH + #if ENABLE_PREFETCH_CHECK +#include <assert.h> +static char *limit; +#define PREFETCH(addr) \ + do { \ + assert ((char *)(addr) < limit); \ + __builtin_prefetch ((addr), 0, 1); \ + } while (0) +#else /* ENABLE_PREFETCH_CHECK */ + #define PREFETCH(addr) __builtin_prefetch (addr, 0, 1) + #endif /* ENABLE_PREFETCH_CHECK */ +#else /* ENABLE_PREFETCH */ + #define PREFETCH(addr) +#endif /* ENABLE_PREFETCH */ + +#include <string.h> + +#ifdef __mips64 +typedef unsigned long long reg_t; +typedef struct +{ + reg_t B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8; +} bits_t; +#else /* __mips64 */ +typedef unsigned long reg_t; +typedef struct +{ + reg_t B0:8, B1:8, B2:8, B3:8; +} bits_t; +#endif /* __mips64 */ + +#define CACHE_LINES_PER_BLOCK \ + ((BLOCK_SIZE * sizeof (reg_t) > CACHE_LINE) \ + ? (BLOCK_SIZE * sizeof (reg_t) / CACHE_LINE) \ + : 1) + +typedef union +{ + reg_t v; + bits_t b; +} bitfields_t; + +#define DO_BYTE(a, i) \ + a[i] = bw.b.B##i; \ + len--; \ + if (!len) return ret; \ + +/* This code is called when aligning a pointer, there are remaining bytes + after doing word compares, or architecture does not have some form + of unaligned support. */ +static inline void * __attribute__ ((always_inline)) +do_bytes (void *a, const void *b, unsigned long len, void *ret) +{ + unsigned char *x = (unsigned char *) a; + unsigned char *y = (unsigned char *) b; + unsigned long i; + /* 'len' might be zero here, so preloading the first two values + before the loop may access unallocated memory. */ + for (i = 0; i < len; i++) + { + *x = *y; + x++; + y++; + } + return ret; +} + +/* This code is called to copy only remaining bytes within word or doubleword */ +static inline void * __attribute__ ((always_inline)) +do_bytes_remaining (void *a, const void *b, unsigned long len, void *ret) +{ + unsigned char *x = (unsigned char *) a; + bitfields_t bw; + if (len > 0) + { + bw.v = *(reg_t *)b; + DO_BYTE(x, 0); + DO_BYTE(x, 1); + DO_BYTE(x, 2); +#ifdef __mips64 + DO_BYTE(x, 3); + DO_BYTE(x, 4); + DO_BYTE(x, 5); + DO_BYTE(x, 6); +#endif /* __mips64 */ + } + return ret; +} + +static inline void * __attribute__ ((always_inline)) +do_words_remaining (reg_t *a, const reg_t *b, unsigned long words, + unsigned long bytes, void *ret) +{ + /* Use a set-back so that load/stores have incremented addresses in + order to promote bonding. */ + int off = (BLOCK_SIZE - words); + a -= off; + b -= off; + switch (off) + { + case 1: a[1] = b[1]; + case 2: a[2] = b[2]; + case 3: a[3] = b[3]; + case 4: a[4] = b[4]; + case 5: a[5] = b[5]; + case 6: a[6] = b[6]; + case 7: a[7] = b[7]; +#if BLOCK_SIZE==16 + case 8: a[8] = b[8]; + case 9: a[9] = b[9]; + case 10: a[10] = b[10]; + case 11: a[11] = b[11]; + case 12: a[12] = b[12]; + case 13: a[13] = b[13]; + case 14: a[14] = b[14]; + case 15: a[15] = b[15]; +#endif /* BLOCK_SIZE==16 */ + } + return do_bytes_remaining (a + BLOCK_SIZE, b + BLOCK_SIZE, bytes, ret); +} + +#if !HW_UNALIGNED_SUPPORT +#if UNALIGNED_INSTR_SUPPORT +/* For MIPS GCC, there are no unaligned builtins - so this struct forces + the compiler to treat the pointer access as unaligned. */ +struct ulw +{ + reg_t uli; +} __attribute__ ((packed)); +static inline void * __attribute__ ((always_inline)) +do_uwords_remaining (struct ulw *a, const reg_t *b, unsigned long words, + unsigned long bytes, void *ret) +{ + /* Use a set-back so that load/stores have incremented addresses in + order to promote bonding. */ + int off = (BLOCK_SIZE - words); + a -= off; + b -= off; + switch (off) + { + case 1: a[1].uli = b[1]; + case 2: a[2].uli = b[2]; + case 3: a[3].uli = b[3]; + case 4: a[4].uli = b[4]; + case 5: a[5].uli = b[5]; + case 6: a[6].uli = b[6]; + case 7: a[7].uli = b[7]; +#if BLOCK_SIZE==16 + case 8: a[8].uli = b[8]; + case 9: a[9].uli = b[9]; + case 10: a[10].uli = b[10]; + case 11: a[11].uli = b[11]; + case 12: a[12].uli = b[12]; + case 13: a[13].uli = b[13]; + case 14: a[14].uli = b[14]; + case 15: a[15].uli = b[15]; +#endif /* BLOCK_SIZE==16 */ + } + return do_bytes_remaining (a + BLOCK_SIZE, b + BLOCK_SIZE, bytes, ret); +} + +/* The first pointer is not aligned while second pointer is. */ +static void * +unaligned_words (struct ulw *a, const reg_t * b, + unsigned long words, unsigned long bytes, void *ret) +{ + unsigned long i, words_by_block, words_by_1; + words_by_1 = words % BLOCK_SIZE; + words_by_block = words / BLOCK_SIZE; + + for (; words_by_block > 0; words_by_block--) + { + /* This condition is deliberately conservative. One could theoretically + pre-fetch another time around in some cases without crossing the page + boundary at the limit, but checking for the right conditions here is + too expensive to be worth it. */ + if (words_by_block > PREF_AHEAD) + for (i = 0; i < CACHE_LINES_PER_BLOCK; i++) + PREFETCH (b + ((BLOCK_SIZE / CACHE_LINES_PER_BLOCK) + * (PREF_AHEAD + i))); + + reg_t y0 = b[0], y1 = b[1], y2 = b[2], y3 = b[3]; + reg_t y4 = b[4], y5 = b[5], y6 = b[6], y7 = b[7]; + a[0].uli = y0; + a[1].uli = y1; + a[2].uli = y2; + a[3].uli = y3; + a[4].uli = y4; + a[5].uli = y5; + a[6].uli = y6; + a[7].uli = y7; +#if BLOCK_SIZE==16 + y0 = b[8], y1 = b[9], y2 = b[10], y3 = b[11]; + y4 = b[12], y5 = b[13], y6 = b[14], y7 = b[15]; + a[8].uli = y0; + a[9].uli = y1; + a[10].uli = y2; + a[11].uli = y3; + a[12].uli = y4; + a[13].uli = y5; + a[14].uli = y6; + a[15].uli = y7; +#endif /* BLOCK_SIZE==16 */ + a += BLOCK_SIZE; + b += BLOCK_SIZE; + } + + /* Mop up any remaining bytes. */ + return do_uwords_remaining (a, b, words_by_1, bytes, ret); +} + +#else /* !UNALIGNED_INSTR_SUPPORT */ + +/* No HW support or unaligned lw/ld/ualw/uald instructions. */ +static void * +unaligned_words (reg_t * a, const reg_t * b, + unsigned long words, unsigned long bytes, void *ret) +{ + unsigned long i; + unsigned char *x; + for (i = 0; i < words; i++) + { + bitfields_t bw; + bw.v = *((reg_t*) b); + x = (unsigned char *) a; + x[0] = bw.b.B0; + x[1] = bw.b.B1; + x[2] = bw.b.B2; + x[3] = bw.b.B3; +#ifdef __mips64 + x[4] = bw.b.B4; + x[5] = bw.b.B5; + x[6] = bw.b.B6; + x[7] = bw.b.B7; +#endif + a += 1; + b += 1; + } + /* Mop up any remaining bytes. */ + return do_bytes_remaining (a, b, bytes, ret); +} + +#endif /* UNALIGNED_INSTR_SUPPORT */ +#endif /* HW_UNALIGNED_SUPPORT */ + +/* both pointers are aligned, or first isn't and HW support for unaligned. */ +static void * +aligned_words (reg_t * a, const reg_t * b, + unsigned long words, unsigned long bytes, void *ret) +{ + unsigned long i, words_by_block, words_by_1; + words_by_1 = words % BLOCK_SIZE; + words_by_block = words / BLOCK_SIZE; + + for (; words_by_block > 0; words_by_block--) + { + if (words_by_block > PREF_AHEAD) + for (i = 0; i < CACHE_LINES_PER_BLOCK; i++) + PREFETCH (b + ((BLOCK_SIZE / CACHE_LINES_PER_BLOCK) + * (PREF_AHEAD + i))); + + reg_t x0 = b[0], x1 = b[1], x2 = b[2], x3 = b[3]; + reg_t x4 = b[4], x5 = b[5], x6 = b[6], x7 = b[7]; + a[0] = x0; + a[1] = x1; + a[2] = x2; + a[3] = x3; + a[4] = x4; + a[5] = x5; + a[6] = x6; + a[7] = x7; +#if BLOCK_SIZE==16 + x0 = b[8], x1 = b[9], x2 = b[10], x3 = b[11]; + x4 = b[12], x5 = b[13], x6 = b[14], x7 = b[15]; + a[8] = x0; + a[9] = x1; + a[10] = x2; + a[11] = x3; + a[12] = x4; + a[13] = x5; + a[14] = x6; + a[15] = x7; +#endif /* BLOCK_SIZE==16 */ + a += BLOCK_SIZE; + b += BLOCK_SIZE; + } + + /* mop up any remaining bytes. */ + return do_words_remaining (a, b, words_by_1, bytes, ret); +} + +void * +memcpy (void *a, const void *b, size_t len) __overloadable +{ + unsigned long bytes, words, i; + void *ret = a; +#if ENABLE_PREFETCH_CHECK + limit = (char *)b + len; +#endif /* ENABLE_PREFETCH_CHECK */ + /* shouldn't hit that often. */ + if (len <= 8) + return do_bytes (a, b, len, a); + + /* Start pre-fetches ahead of time. */ + if (len > CACHE_LINE * PREF_AHEAD) + for (i = 1; i < PREF_AHEAD; i++) + PREFETCH ((char *)b + CACHE_LINE * i); + else + for (i = 1; i < len / CACHE_LINE; i++) + PREFETCH ((char *)b + CACHE_LINE * i); + + /* Align the second pointer to word/dword alignment. + Note that the pointer is only 32-bits for o32/n32 ABIs. For + n32, loads are done as 64-bit while address remains 32-bit. */ + bytes = ((unsigned long) b) % (sizeof (reg_t)); + + if (bytes) + { + bytes = (sizeof (reg_t)) - bytes; + if (bytes > len) + bytes = len; + do_bytes (a, b, bytes, ret); + if (len == bytes) + return ret; + len -= bytes; + a = (void *) (((unsigned char *) a) + bytes); + b = (const void *) (((unsigned char *) b) + bytes); + } + + /* Second pointer now aligned. */ + words = len / sizeof (reg_t); + bytes = len % sizeof (reg_t); + +#if HW_UNALIGNED_SUPPORT + /* treat possible unaligned first pointer as aligned. */ + return aligned_words (a, b, words, bytes, ret); +#else /* !HW_UNALIGNED_SUPPORT */ + if (((unsigned long) a) % sizeof (reg_t) == 0) + return aligned_words (a, b, words, bytes, ret); + /* need to use unaligned instructions on first pointer. */ + return unaligned_words (a, b, words, bytes, ret); +#endif /* HW_UNALIGNED_SUPPORT */ +} diff --git a/newlib/libc/machine/mips/memset.c b/newlib/libc/machine/mips/memset.c new file mode 100644 index 0000000..9f07ef5 --- /dev/null +++ b/newlib/libc/machine/mips/memset.c @@ -0,0 +1,176 @@ +/* + * 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. +*/ + +#include <string.h> + +#if _MIPS_SIM == _ABIO32 +#define SIZEOF_reg_t 4 +typedef unsigned long reg_t; +#else +#define SIZEOF_reg_t 8 +typedef unsigned long long reg_t; +#endif + +typedef struct bits8 +{ + reg_t B0:8, B1:8, B2:8, B3:8; +#if SIZEOF_reg_t == 8 + reg_t B4:8, B5:8, B6:8, B7:8; +#endif +} bits8_t; +typedef struct bits16 +{ + reg_t B0:16, B1:16; +#if SIZEOF_reg_t == 8 + reg_t B2:16, B3:16; +#endif +} bits16_t; +typedef struct bits32 +{ + reg_t B0:32; +#if SIZEOF_reg_t == 8 + reg_t B1:32; +#endif +} bits32_t; + +/* This union assumes that small structures can be in registers. If + not, then memory accesses will be done - not optimal, but ok. */ +typedef union +{ + reg_t v; + bits8_t b8; + bits16_t b16; + bits32_t b32; +} bitfields_t; + +/* This code is called when aligning a pointer or there are remaining bytes + after doing word sets. */ +static inline void * __attribute__ ((always_inline)) +do_bytes (void *a, void *retval, unsigned char fill, const unsigned long len) +{ + unsigned char *x = ((unsigned char *) a); + unsigned long i; + + for (i = 0; i < len; i++) + *x++ = fill; + + return retval; +} + +/* Pointer is aligned. */ +static void * +do_aligned_words (reg_t * a, void * retval, reg_t fill, + unsigned long words, unsigned long bytes) +{ + unsigned long i, words_by_1, words_by_16; + + words_by_1 = words % 16; + words_by_16 = words / 16; + + /* + * Note: prefetching the store memory is not beneficial on most + * cores since the ls/st unit has store buffers that will be filled + * before the cache line is actually needed. + * + * Also, using prepare-for-store cache op is problematic since we + * don't know the implementation-defined cache line length and we + * don't want to touch unintended memory. + */ + for (i = 0; i < words_by_16; i++) + { + a[0] = fill; + a[1] = fill; + a[2] = fill; + a[3] = fill; + a[4] = fill; + a[5] = fill; + a[6] = fill; + a[7] = fill; + a[8] = fill; + a[9] = fill; + a[10] = fill; + a[11] = fill; + a[12] = fill; + a[13] = fill; + a[14] = fill; + a[15] = fill; + a += 16; + } + + /* do remaining words. */ + for (i = 0; i < words_by_1; i++) + *a++ = fill; + + /* mop up any remaining bytes. */ + return do_bytes (a, retval, fill, bytes); +} + +void * +memset (void *a, int ifill, size_t len) +{ + unsigned long bytes, words; + bitfields_t fill; + void *retval = (void *) a; + + /* shouldn't hit that often. */ + if (len < 16) + return do_bytes (a, retval, ifill, len); + + /* Align the pointer to word/dword alignment. + Note that the pointer is only 32-bits for o32/n32 ABIs. For + n32, loads are done as 64-bit while address remains 32-bit. */ + bytes = ((unsigned long) a) % (sizeof (reg_t) * 2); + if (bytes) + { + bytes = (sizeof (reg_t) * 2 - bytes); + if (bytes > len) + bytes = len; + do_bytes (a, retval, ifill, bytes); + if (len == bytes) + return retval; + len -= bytes; + a = (void *) (((unsigned char *) a) + bytes); + } + + /* Create correct fill value for reg_t sized variable. */ + if (ifill != 0) + { + fill.b8.B0 = (unsigned char) ifill; + fill.b8.B1 = fill.b8.B0; + fill.b16.B1 = fill.b16.B0; +#if SIZEOF_reg_t == 8 + fill.b32.B1 = fill.b32.B0; +#endif + } + else + fill.v = 0; + + words = len / sizeof (reg_t); + bytes = len % sizeof (reg_t); + return do_aligned_words (a, retval, fill.v, words, bytes); +} diff --git a/newlib/libc/machine/mips/setjmp.S b/newlib/libc/machine/mips/setjmp.S index cfc1d51..1e3ee0d 100644 --- a/newlib/libc/machine/mips/setjmp.S +++ b/newlib/libc/machine/mips/setjmp.S @@ -67,7 +67,7 @@ regardless of whether the realignment happened or not. */ #define FPR_LAYOUT \ - and $8, $4, 4; \ + andi $8, $4, 4; \ beq $8, $0, 1f; \ GPR_OFFSET ($31, 22); \ addiu $4, $4, -4; \ @@ -133,7 +133,7 @@ setjmp: #undef FPR_OFFSET move $2,$0 - j $31 + jr $31 .end setjmp @@ -154,6 +154,6 @@ longjmp: li $5,1 1: move $2,$5 - j $31 + jr $31 .end longjmp diff --git a/newlib/libc/machine/mips/strcmp.S b/newlib/libc/machine/mips/strcmp.S index 9d33a4e..07b988a 100644 --- a/newlib/libc/machine/mips/strcmp.S +++ b/newlib/libc/machine/mips/strcmp.S @@ -1,31 +1,30 @@ /* - * Copyright (c) 2014 - * Imagination Technologies Limited. + * 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 MIPS Technologies, Inc., nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * modification, are permitted provided that the following conditions are met: * - * THIS SOFTWARE IS PROVIDED BY IMAGINATION TECHNOLOGIES LIMITED ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * 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 IMAGINATION TECHNOLOGIES LIMITED 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. - */ + * 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. +*/ #ifdef ANDROID_CHANGES # include "machine/asm.h" @@ -38,22 +37,14 @@ # include <sys/asm.h> #endif -/* Technically strcmp should not read past the end of the strings being - compared. We will read a full word that may contain excess bits beyond - the NULL string terminator but unless ENABLE_READAHEAD is set, we will not - read the next word after the end of string. Setting ENABLE_READAHEAD will - improve performance but is technically illegal based on the definition of - strcmp. */ -#ifdef ENABLE_READAHEAD -# define DELAY_READ -#else -# define DELAY_READ nop -#endif - /* Testing on a little endian machine showed using CLZ was a performance loss, so we are not turning it on by default. */ #if defined(ENABLE_CLZ) && (__mips_isa_rev > 1) # define USE_CLZ +#elif (__mips_isa_rev >= 2) +# define USE_EXT 1 +#else +# define USE_EXT 0 #endif /* Some asm.h files do not have the L macro definition. */ @@ -74,6 +65,10 @@ # endif #endif +/* Haven't yet found a configuration where DSP code outperforms + normal assembly. */ +#define __mips_using_dsp 0 + /* Allow the routine to be named something else if desired. */ #ifndef STRCMP_NAME # define STRCMP_NAME strcmp @@ -85,148 +80,184 @@ LEAF(STRCMP_NAME, 0) LEAF(STRCMP_NAME) #endif .set nomips16 - .set noreorder - or t0, a0, a1 - andi t0,0x3 + andi t0, t0, 0x3 bne t0, zero, L(byteloop) /* Both strings are 4 byte aligned at this point. */ - lui t8, 0x0101 - ori t8, t8, 0x0101 - lui t9, 0x7f7f - ori t9, 0x7f7f - -#define STRCMP32(OFFSET) \ - lw v0, OFFSET(a0); \ - lw v1, OFFSET(a1); \ - subu t0, v0, t8; \ - bne v0, v1, L(worddiff); \ - nor t1, v0, t9; \ - and t0, t0, t1; \ + li t8, 0x01010101 +#if !__mips_using_dsp + li t9, 0x7f7f7f7f +#endif + +#if __mips_using_dsp +# define STRCMP32(OFFSET) \ + lw a2, OFFSET(a0); \ + lw a3, OFFSET(a1); \ + subu_s.qb t0, t8, a2; \ + bne a2, a3, L(worddiff); \ bne t0, zero, L(returnzero) +#else /* !__mips_using_dsp */ +# define STRCMP32(OFFSET) \ + lw a2, OFFSET(a0); \ + lw a3, OFFSET(a1); \ + subu t0, a2, t8; \ + nor t1, a2, t9; \ + bne a2, a3, L(worddiff); \ + and t1, t0, t1; \ + bne t1, zero, L(returnzero) +#endif /* __mips_using_dsp */ + .align 2 L(wordloop): STRCMP32(0) - DELAY_READ STRCMP32(4) - DELAY_READ STRCMP32(8) - DELAY_READ STRCMP32(12) - DELAY_READ STRCMP32(16) - DELAY_READ STRCMP32(20) - DELAY_READ STRCMP32(24) - DELAY_READ - STRCMP32(28) + lw a2, 28(a0) + lw a3, 28(a1) +#if __mips_using_dsp + subu_s.qb t0, t8, a2 +#else + subu t0, a2, t8 + nor t1, a2, t9 + and t1, t0, t1 +#endif + PTR_ADDIU a0, a0, 32 - b L(wordloop) + bne a2, a3, L(worddiff) PTR_ADDIU a1, a1, 32 + beq t1, zero, L(wordloop) L(returnzero): - j ra - move v0, zero + move va0, zero + jr ra + .align 2 L(worddiff): #ifdef USE_CLZ - subu t0, v0, t8 - nor t1, v0, t9 - and t1, t0, t1 - xor t0, v0, v1 + xor t0, a2, a3 or t0, t0, t1 # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ wsbh t0, t0 rotr t0, t0, 16 -# endif +# endif /* LITTLE_ENDIAN */ clz t1, t0 - and t1, 0xf8 -# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - neg t1 - addu t1, 24 + or t0, t1, 24 /* Only care about multiples of 8. */ + xor t1, t1, t0 /* {0,8,16,24} => {24,16,8,0} */ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + sllv a2,a2,t1 + sllv a3,a3,t1 +# else + srlv a2,a2,t1 + srlv a3,a3,t1 # endif - rotrv v0, v0, t1 - rotrv v1, v1, t1 - and v0, v0, 0xff - and v1, v1, 0xff - j ra - subu v0, v0, v1 + subu va0, a2, a3 + jr ra #else /* USE_CLZ */ # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - andi t0, v0, 0xff - beq t0, zero, L(wexit01) - andi t1, v1, 0xff - bne t0, t1, L(wexit01) - - srl t8, v0, 8 - srl t9, v1, 8 - andi t8, t8, 0xff + andi a0, a2, 0xff /* abcd => d */ + andi a1, a3, 0xff + beq a0, zero, L(wexit01) +# if USE_EXT + ext t8, a2, 8, 8 + bne a0, a1, L(wexit01) + ext t9, a3, 8, 8 beq t8, zero, L(wexit89) + ext a0, a2, 16, 8 + bne t8, t9, L(wexit89) + ext a1, a3, 16, 8 +# else /* !USE_EXT */ + srl t8, a2, 8 + bne a0, a1, L(wexit01) + srl t9, a3, 8 + andi t8, t8, 0xff andi t9, t9, 0xff + beq t8, zero, L(wexit89) + srl a0, a2, 16 bne t8, t9, L(wexit89) + srl a1, a3, 16 + andi a0, a0, 0xff + andi a1, a1, 0xff +# endif /* !USE_EXT */ - srl t0, v0, 16 - srl t1, v1, 16 - andi t0, t0, 0xff - beq t0, zero, L(wexit01) - andi t1, t1, 0xff - bne t0, t1, L(wexit01) - - srl t8, v0, 24 - srl t9, v1, 24 # else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ - srl t0, v0, 24 - beq t0, zero, L(wexit01) - srl t1, v1, 24 - bne t0, t1, L(wexit01) + srl a0, a2, 24 /* abcd => a */ + srl a1, a3, 24 + beq a0, zero, L(wexit01) - srl t8, v0, 16 - srl t9, v1, 16 - andi t8, t8, 0xff +# if USE_EXT + ext t8, a2, 16, 8 + bne a0, a1, L(wexit01) + ext t9, a3, 16, 8 beq t8, zero, L(wexit89) + ext a0, a2, 8, 8 + bne t8, t9, L(wexit89) + ext a1, a3, 8, 8 +# else /* ! USE_EXT */ + srl t8, a2, 16 + bne a0, a1, L(wexit01) + srl t9, a3, 16 + andi t8, t8, 0xff andi t9, t9, 0xff + beq t8, zero, L(wexit89) + srl a0, a2, 8 bne t8, t9, L(wexit89) + srl a1, a3, 8 + andi a0, a0, 0xff + andi a1, a1, 0xff +# endif /* USE_EXT */ + +# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ - srl t0, v0, 8 - srl t1, v1, 8 - andi t0, t0, 0xff - beq t0, zero, L(wexit01) - andi t1, t1, 0xff - bne t0, t1, L(wexit01) + beq a0, zero, L(wexit01) + bne a0, a1, L(wexit01) - andi t8, v0, 0xff - andi t9, v1, 0xff +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + srl a0, a2, 24 + srl a1, a3, 24 +# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ + move a0, a2 + move a1, a3 # endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ -L(wexit89): - j ra - subu v0, t8, t9 L(wexit01): - j ra - subu v0, t0, t1 + subu va0, a0, a1 + jr ra + +L(wexit89): + subu va0, t8, t9 + jr ra + #endif /* USE_CLZ */ +#define DELAY_NOP nop + /* It might seem better to do the 'beq' instruction between the two 'lbu' instructions so that the nop is not needed but testing showed that this code is actually faster (based on glibc strcmp test). */ + #define BYTECMP01(OFFSET) \ - lbu v0, OFFSET(a0); \ - lbu v1, OFFSET(a1); \ - beq v0, zero, L(bexit01); \ - nop; \ - bne v0, v1, L(bexit01) + lbu a3, OFFSET(a1); \ + DELAY_NOP; \ + beq a2, zero, L(bexit01); \ + lbu t8, OFFSET+1(a0); \ + bne a2, a3, L(bexit01) #define BYTECMP89(OFFSET) \ - lbu t8, OFFSET(a0); \ lbu t9, OFFSET(a1); \ + DELAY_NOP; \ beq t8, zero, L(bexit89); \ - nop; \ + lbu a2, OFFSET+1(a0); \ bne t8, t9, L(bexit89) + .align 2 L(byteloop): + lbu a2, 0(a0) BYTECMP01(0) BYTECMP89(1) BYTECMP01(2) @@ -234,19 +265,21 @@ L(byteloop): BYTECMP01(4) BYTECMP89(5) BYTECMP01(6) - BYTECMP89(7) + lbu t9, 7(a1) + PTR_ADDIU a0, a0, 8 - b L(byteloop) + beq t8, zero, L(bexit89) PTR_ADDIU a1, a1, 8 + beq t8, t9, L(byteloop) -L(bexit01): - j ra - subu v0, v0, v1 L(bexit89): - j ra - subu v0, t8, t9 + subu va0, t8, t9 + jr ra + +L(bexit01): + subu va0, a2, a3 + jr ra .set at - .set reorder END(STRCMP_NAME) diff --git a/newlib/libc/machine/mips/strlen.c b/newlib/libc/machine/mips/strlen.c index a87bddd..65cbaf3 100644 --- a/newlib/libc/machine/mips/strlen.c +++ b/newlib/libc/machine/mips/strlen.c @@ -33,27 +33,21 @@ strlen (const char *str) } #elif defined(__mips64) __asm__("" /* 64-bit MIPS targets */ - " .set noreorder\n" - " .set nomacro\n" " .globl strlen\n" " .ent strlen\n" "strlen:\n" " daddiu $2,$4,1\n" "\n" "1: lbu $3,0($4)\n" - " bnez $3,1b\n" " daddiu $4,$4,1\n" + " bnez $3,1b\n" "\n" - " jr $31\n" " dsubu $2,$4,$2\n" - " .end strlen\n" - " .set macro\n" - " .set reorder\n"); + " jr $31\n" + " .end strlen\n"); #else __asm__("" /* 32-bit MIPS targets */ - " .set noreorder\n" - " .set nomacro\n" " .globl strlen\n" " .ent strlen\n" "strlen:\n" @@ -63,12 +57,10 @@ __asm__("" /* 32-bit MIPS targets */ #if defined(_R3000) " nop \n" #endif - " bnez $3,1b\n" " addiu $4,$4,1\n" + " bnez $3,1b\n" "\n" - " jr $31\n" " subu $2,$4,$2\n" - " .end strlen\n" - " .set macro\n" - " .set reorder\n"); + " jr $31\n" + " .end strlen\n"); #endif diff --git a/newlib/libc/machine/riscv/Makefile.inc b/newlib/libc/machine/riscv/Makefile.inc index 4d6c046..85bed91 100644 --- a/newlib/libc/machine/riscv/Makefile.inc +++ b/newlib/libc/machine/riscv/Makefile.inc @@ -1,3 +1,3 @@ libc_a_SOURCES += \ %D%/memmove.S %D%/memmove-stub.c %D%/memset.S %D%/memcpy-asm.S %D%/memcpy.c %D%/strlen.c \ - %D%/strcpy.c %D%/stpcpy.c %D%/strcmp.S %D%/setjmp.S %D%/ieeefp.c %D%/ffs.c + %D%/strcpy.c %D%/stpcpy.c %D%/strcmp.S %D%/memchr.c %D%/memrchr.c %D%/setjmp.S %D%/ieeefp.c %D%/ffs.c diff --git a/newlib/libc/machine/riscv/memchr.c b/newlib/libc/machine/riscv/memchr.c new file mode 100644 index 0000000..62a7d19 --- /dev/null +++ b/newlib/libc/machine/riscv/memchr.c @@ -0,0 +1,152 @@ +/* +FUNCTION + <<memchr>>---find character in memory + +INDEX + memchr + +SYNOPSIS + #include <string.h> + void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); + +DESCRIPTION + This function searches memory starting at <<*<[src]>>> for the + character <[c]>. The search only ends with the first + occurrence of <[c]>, or after <[length]> characters; in + particular, <<NUL>> does not terminate the search. + +RETURNS + If the character <[c]> is found within <[length]> characters + of <<*<[src]>>>, a pointer to the character is returned. If + <[c]> is not found, then <<NULL>> is returned. + +PORTABILITY +<<memchr>> is ANSI C. + +<<memchr>> requires no supporting OS subroutines. + +QUICKREF + memchr ansi pure +*/ + +#include <sys/asm.h> +#include <stddef.h> +#include "rv_string.h" + +// Move size +#if __riscv_zilsd +#define MV_SZ 8 +#else +#define MV_SZ SZREG +#endif + + +void * +memchr (const void *src_void, + int c, + size_t length) +{ + const unsigned char *src = (const unsigned char *) src_void; + unsigned char d = c; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + size_t align = (uintptr_t) src & (MV_SZ - 1); + + if (align) + { + align = MV_SZ - align; + + if (length < align) align = length; + + switch (align) + { +#if MV_SZ == 8 + case 7: + if (*src++ == d) return (void *) (src - 1); + case 6: + if (*src++ == d) return (void *) (src - 1); + case 5: + if (*src++ == d) return (void *) (src - 1); + case 4: + if (*src++ == d) return (void *) (src - 1); +#endif /* MV_SZ == 8 */ + case 3: + if (*src++ == d) return (void *) (src - 1); + case 2: + if (*src++ == d) return (void *) (src - 1); + case 1: + if (*src++ == d) return (void *) (src - 1); + } + + length -= align; + } + + const unsigned char *end_addr = src + (length & ~(MV_SZ - 1)); + + if (src < end_addr) + { + uintxlen_t mask = __libc_splat_byte(d); + + do + { + uintlslen_t val = *(uintlslen_t*) src; + uintxlen_t word1 = val ^ mask; + + if (__libc_detect_null(word1)) + { +#if __riscv_zbb + word1 = ~__LIBC_RISCV_ZBB_ORC_B(word1); + word1 = __LIBC_RISCV_ZBB_CNT_Z(word1); + + return (void *) (src + (word1 >> 3)); +#else /* not __riscv_zbb */ + if (*src++ == d) return (void *) (src - 1); + if (*src++ == d) return (void *) (src - 1); + if (*src++ == d) return (void *) (src - 1); +#if __riscv_xlen == 64 + if (*src++ == d) return (void *) (src - 1); + if (*src++ == d) return (void *) (src - 1); + if (*src++ == d) return (void *) (src - 1); + if (*src++ == d) return (void *) (src - 1); +#endif /* __riscv_xlen == 64 */ + return (void *) src; +#endif /* __riscv_zbb */ + } +#if __riscv_zilsd + uintxlen_t word2 = (val >> 32); + word2 ^= mask; + + if (__libc_detect_null(word2)) + { + src += MV_SZ / 2; +#if __riscv_zbb + word2 = ~__LIBC_RISCV_ZBB_ORC_B(word2); + word2 = __LIBC_RISCV_ZBB_CNT_Z(word2); + + return (void *) (src + (word2 >> 3)); +#else /* not __riscv_zbb */ + if (*src++ == d) return (void *) (src - 1); + if (*src++ == d) return (void *) (src - 1); + if (*src++ == d) return (void *) (src - 1); + return (void *) src; +#endif /* __riscv_zbb */ + } +#endif /* __riscv_zilsd */ + + src += MV_SZ; + } while (src < end_addr); + + length &= MV_SZ - 1; + } + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (length--) + { + if (*src == d) + return (void *) src; + src++; + } + + return NULL; +} diff --git a/newlib/libc/machine/riscv/memcpy-asm.S b/newlib/libc/machine/riscv/memcpy-asm.S index 5571e47..2771285 100644 --- a/newlib/libc/machine/riscv/memcpy-asm.S +++ b/newlib/libc/machine/riscv/memcpy-asm.S @@ -14,15 +14,15 @@ .global memcpy .type memcpy, @function memcpy: - mv t1, a0 + mv a3, a0 beqz a2, 2f 1: - lb t2, 0(a1) - sb t2, 0(t1) - add a2, a2, -1 - add t1, t1, 1 - add a1, a1, 1 + lbu a4, 0(a1) + sb a4, 0(a3) + addi a2, a2, -1 + addi a3, a3, 1 + addi a1, a1, 1 bnez a2, 1b 2: diff --git a/newlib/libc/machine/riscv/memcpy.c b/newlib/libc/machine/riscv/memcpy.c index e1a34a8..a27e0ec 100644 --- a/newlib/libc/machine/riscv/memcpy.c +++ b/newlib/libc/machine/riscv/memcpy.c @@ -1,4 +1,5 @@ /* Copyright (c) 2017 SiFive Inc. All rights reserved. + Copyright (c) 2025 Mahmoud Abumandour <ma.mandourr@gmail.com> This copyrighted material is made available to anyone wishing to use, modify, copy, or redistribute it subject to the terms and conditions @@ -10,83 +11,137 @@ */ #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) -//memcpy defined in memcpy-asm.S +// memcpy defined in memcpy-asm.S #else -#include <string.h> -#include <stdint.h> #include "../../string/local.h" +#include "xlenint.h" +#include <string.h> +#include <sys/asm.h> #define unlikely(X) __builtin_expect (!!(X), 0) -void * -__inhibit_loop_to_libcall -memcpy(void *__restrict aa, const void *__restrict bb, size_t n) +static inline void +__libc_memcpy_bytewise (unsigned char *dst, const unsigned char *src, + const size_t sz) { - #define BODY(a, b, t) { \ - t tt = *b; \ - a++, b++; \ - *(a - 1) = tt; \ - } + const unsigned char *end = dst + sz; + while (dst < end) + *dst++ = *src++; +} - char *a = (char *)aa; - const char *b = (const char *)bb; - char *end = a + n; - uintptr_t msk = sizeof (long) - 1; -#if __riscv_misaligned_slow || __riscv_misaligned_fast - if (n < sizeof (long)) -#else - if (unlikely ((((uintptr_t)a & msk) != ((uintptr_t)b & msk)) - || n < sizeof (long))) +#ifndef __riscv_misaligned_fast +static uintxlen_t +__libc_load_xlen (const void *src) +{ + const unsigned char *p = (const unsigned char *)src; + uintxlen_t ret = 0; + unsigned char b0 = *p++; + unsigned char b1 = *p++; + unsigned char b2 = *p++; + unsigned char b3 = *p++; + ret = (uintxlen_t)b0 | ((uintxlen_t)b1 << 8) | ((uintxlen_t)b2 << 16) + | ((uintxlen_t)b3 << 24); +#if __riscv_xlen == 64 + unsigned char b4 = *p++; + unsigned char b5 = *p++; + unsigned char b6 = *p++; + unsigned char b7 = *p++; + ret |= ((uintxlen_t)b4 << 32) | ((uintxlen_t)b5 << 40) + | ((uintxlen_t)b6 << 48) | ((uintxlen_t)b7 << 56); +#endif + return ret; +} #endif + +void * +__inhibit_loop_to_libcall +memcpy (void *__restrict aa, const void *__restrict bb, size_t n) +{ + unsigned char *a = (unsigned char *)aa; + const unsigned char *b = (const unsigned char *)bb; + unsigned char *end = a + n; + uintptr_t msk = SZREG - 1; + if (n < SZREG) { -small: if (__builtin_expect (a < end, 1)) - while (a < end) - BODY (a, b, char); + __libc_memcpy_bytewise (a, b, n); return aa; } +/* + * If misaligned access is slow or prohibited, and the alignments of the source + * and destination are different, we align the destination to do XLEN stores. + * This uses only one aligned store for every four (or eight for XLEN == 64) + * bytes of data. + */ +#ifndef __riscv_misaligned_fast + if (unlikely ((((uintptr_t)a & msk) != ((uintptr_t)b & msk)))) + { + size_t dst_pad = (uintptr_t)a & msk; + dst_pad = (SZREG - dst_pad) & msk; + __libc_memcpy_bytewise (a, b, dst_pad); + a += dst_pad; + b += dst_pad; + + uintxlen_t *la = (uintxlen_t *)a; + const unsigned char *cb = (const unsigned char *)b; + uintxlen_t *lend = (uintxlen_t *)((uintptr_t)end & ~msk); + + while (la < lend) + { + *la++ = __libc_load_xlen (cb); + cb += SZREG; + } + a = (unsigned char *)la; + b = (const unsigned char *)cb; + if (unlikely (a < end)) + __libc_memcpy_bytewise (a, b, end - a); + return aa; + } +#endif + if (unlikely (((uintptr_t)a & msk) != 0)) - while ((uintptr_t)a & msk) - BODY (a, b, char); + { + size_t pad = SZREG - ((uintptr_t)a & msk); + __libc_memcpy_bytewise (a, b, pad); + a += pad; + b += pad; + } - long *la = (long *)a; - const long *lb = (const long *)b; - long *lend = (long *)((uintptr_t)end & ~msk); + uintxlen_t *la = (uintxlen_t *)a; + const uintxlen_t *lb = (const uintxlen_t *)b; + uintxlen_t *lend = (uintxlen_t *)((uintptr_t)end & ~msk); if (unlikely (lend - la > 8)) { while (lend - la > 8) - { - long b0 = *lb++; - long b1 = *lb++; - long b2 = *lb++; - long b3 = *lb++; - long b4 = *lb++; - long b5 = *lb++; - long b6 = *lb++; - long b7 = *lb++; - long b8 = *lb++; - *la++ = b0; - *la++ = b1; - *la++ = b2; - *la++ = b3; - *la++ = b4; - *la++ = b5; - *la++ = b6; - *la++ = b7; - *la++ = b8; - } + { + uintxlen_t b0 = *lb++; + uintxlen_t b1 = *lb++; + uintxlen_t b2 = *lb++; + uintxlen_t b3 = *lb++; + uintxlen_t b4 = *lb++; + uintxlen_t b5 = *lb++; + uintxlen_t b6 = *lb++; + uintxlen_t b7 = *lb++; + uintxlen_t b8 = *lb++; + *la++ = b0; + *la++ = b1; + *la++ = b2; + *la++ = b3; + *la++ = b4; + *la++ = b5; + *la++ = b6; + *la++ = b7; + *la++ = b8; + } } - while (la < lend) - BODY (la, lb, long); - - a = (char *)la; - b = (const char *)lb; + a = (unsigned char *)la; + b = (const unsigned char *)lb; if (unlikely (a < end)) - goto small; + __libc_memcpy_bytewise (a, b, end - a); return aa; } #endif diff --git a/newlib/libc/machine/riscv/memmove.S b/newlib/libc/machine/riscv/memmove.S index 66d9cd4..061472c 100644 --- a/newlib/libc/machine/riscv/memmove.S +++ b/newlib/libc/machine/riscv/memmove.S @@ -14,26 +14,26 @@ .global memmove .type memmove, @function memmove: - beqz a2, 2f + beqz a2, .Ldone /* in case there are 0 bytes to be copied, return immediately */ - mv t1, a0 + mv a4, a0 /* copy the destination address over to a4, since memmove should return that address in a0 at the end */ li a3, 1 - bgtu a1, a0, 1f + bgtu a1, a0, .Lcopy /* in case of source address > destination address, copy from start to end of the specified memory area */ - li a3, -1 - addi a4, a2 , -1 - add t1, t1, a4 - add a1, a1, a4 + li a3, -1 /* otherwhise, start copying from the end of the specified memory area in order to prevent data loss in case of overlapping memory areas.*/ + add a4, a4, a2 /* add the number of bytes to be copied to both addresses. this gives us the address one byte past the end of the memory area we want to copy, */ + add a1, a1, a2 /* therefore we need to subtract 1 from both addresses in the next step before starting the copying process. */ -1: - lb t2, 0(a1) - sb t2, 0(t1) - add a2, a2, -1 - add t1, t1, a3 +.Lincrement: + add a4, a4, a3 /* in case of source address < destination address, increment both addresses by -1 before copying any data to obtain the correct start addresses */ add a1, a1, a3 - bnez a2, 1b +.Lcopy: + lbu a5, 0(a1) + addi a2, a2, -1 /* copy bytes as long as a2 (= the number of bytes to be copied) > 0. the increment is done here to relax the RAW dependency between load and store */ + sb a5, 0(a4) + bnez a2, .Lincrement -2: +.Ldone: ret .size memmove, .-memmove diff --git a/newlib/libc/machine/riscv/memrchr.c b/newlib/libc/machine/riscv/memrchr.c new file mode 100644 index 0000000..47e1023 --- /dev/null +++ b/newlib/libc/machine/riscv/memrchr.c @@ -0,0 +1,172 @@ +/* +FUNCTION + <<memrchr>>---reverse search for character in memory + +INDEX + memrchr + +SYNOPSIS + #include <string.h> + void *memrchr(const void *<[src]>, int <[c]>, size_t <[length]>); + +DESCRIPTION + This function searches memory starting at <[length]> bytes + beyond <<*<[src]>>> backwards for the character <[c]>. + The search only ends with the first occurrence of <[c]>; in + particular, <<NUL>> does not terminate the search. + +RETURNS + If the character <[c]> is found within <[length]> characters + of <<*<[src]>>>, a pointer to the character is returned. If + <[c]> is not found, then <<NULL>> is returned. + +PORTABILITY +<<memrchr>> is a GNU extension. + +<<memrchr>> requires no supporting OS subroutines. + +QUICKREF + memrchr +*/ + +#include <sys/asm.h> +#include <stddef.h> +#include "rv_string.h" + +// Move size +#if __riscv_zilsd +#define MV_SZ 8 + +// Offset is only 4 bytes for Zilsd/Zclsd since each register is 32 bits +#define OFFSET 4 +#else +#define MV_SZ SZREG +#define OFFSET SZREG +#endif + + +void * +memrchr (const void *src_void, + int c, + size_t length) +{ + const unsigned char *src = (const unsigned char *) src_void; + unsigned char d = c; + + if (length) src += length - 1; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + + /* + We add one to the address because even if an address is already aligned, + when loading words the bytes preceding this address are read, so check + the single byte. + + If the address has all the least significant bits set equaling MV_SZ - 1, + and has a length of at least MV_SZ, we can read a word starting from + src & ~(MV_SZ - 1) because no alignment is actually required + */ + size_t align = (uintptr_t) (src + 1) & (MV_SZ - 1); + + if (align) + { + if (length < align) align = length; + + switch (align) + { +#if MV_SZ == 8 + case 7: + if (*src-- == d) return (void *) (src + 1); + case 6: + if (*src-- == d) return (void *) (src + 1); + case 5: + if (*src-- == d) return (void *) (src + 1); + case 4: + if (*src-- == d) return (void *) (src + 1); +#endif /* MV_SZ == 8 */ + case 3: + if (*src-- == d) return (void *) (src + 1); + case 2: + if (*src-- == d) return (void *) (src + 1); + case 1: + if (*src-- == d) return (void *) (src + 1); + } + + length -= align; + } + + const unsigned char *end_addr = src - (length & ~(MV_SZ - 1)); + + if (src > end_addr) + { + src -= MV_SZ - 1; + + uintxlen_t mask = __libc_splat_byte(d); + + do + { + uintlslen_t val = *(uintlslen_t*) src; + +#if __riscv_zilsd + uintxlen_t word2 = val >> 32; + word2 ^= mask; + + if (__libc_detect_null(word2)) + { +#if __riscv_zbb + src += OFFSET; + word2 = ~__LIBC_RISCV_ZBB_ORC_B(word2); + word2 = __LIBC_RISCV_ZBB_CNT_Z_REV(word2); + + return (void *) (src + OFFSET - 1 - (word2 >> 3)); +#else /* not __riscv_zbb */ + src += MV_SZ - 1; + if (*src-- == d) return (void *) (src + 1); + if (*src-- == d) return (void *) (src + 1); + if (*src-- == d) return (void *) (src + 1); + return (void *) src; +#endif /* __riscv_zbb */ + } +#endif /* __riscv_zilsd */ + uintxlen_t word1 = val ^ mask; + + if (__libc_detect_null(word1)) + { +#if __riscv_zbb + word1 = ~__LIBC_RISCV_ZBB_ORC_B(word1); + word1 = __LIBC_RISCV_ZBB_CNT_Z_REV(word1); + + return (void *) (src + OFFSET - 1 - (word1 >> 3)); +#else /* not __riscv_zbb */ + src += OFFSET - 1; + if (*src-- == d) return (void *) (src + 1); + if (*src-- == d) return (void *) (src + 1); + if (*src-- == d) return (void *) (src + 1); +#if __riscv_xlen == 64 + if (*src-- == d) return (void *) (src + 1); + if (*src-- == d) return (void *) (src + 1); + if (*src-- == d) return (void *) (src + 1); + if (*src-- == d) return (void *) (src + 1); +#endif /* __riscv_xlen == 64 */ + return (void *) src; +#endif /* __riscv_zbb */ + } + + src -= MV_SZ; + } while (src > end_addr); + + length &= MV_SZ - 1; + src = end_addr; + } + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (length--) + { + if (*src == d) + return (void *) src; + src--; + } + + return NULL; +} diff --git a/newlib/libc/machine/riscv/memset.S b/newlib/libc/machine/riscv/memset.S index a717ae7..533f667 100644 --- a/newlib/libc/machine/riscv/memset.S +++ b/newlib/libc/machine/riscv/memset.S @@ -9,105 +9,296 @@ http://www.opensource.org/licenses. */ +#include <sys/asm.h> + + +#define BYTE_TBL_SZ 31 +#define WORD_TBL_SZ 32 + +#if __riscv_zilsd +/* Move size */ +#define MV_SZ 8 + +/* Store instruction */ +#define RG_ST sd + +/* Zilsd and Zclsd require an even numbered register */ +#define REG_SPLAT a4 +#else +#define MV_SZ SZREG +#define RG_ST REG_S +#define REG_SPLAT a1 +#endif + +/* + Use an extended register for Zilsd and Zclsd if available + since a5 is used for the odd numbered register, in order + to eliminate an li instruction +*/ +#if __riscv_zilsd && !__riscv_abi_rve +#define REG_TABLE a6 +#else +#define REG_TABLE a5 +#endif + + .text .global memset -.type memset, @function +.type memset, @function + +/* void *memset(void *s, int c, size_t n); */ + + memset: #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) - mv t1, a0 - beqz a2, 2f + mv a3, a0 + beqz a2, .Ldone -1: - sb a1, 0(t1) - add a2, a2, -1 - add t1, t1, 1 - bnez a2, 1b +.Lset: + sb a1, 0(a3) + addi a2, a2, -1 + addi a3, a3, 1 + bnez a2, .Lset -2: +.Ldone: ret #else - li t1, 15 - move a4, a0 - bleu a2, t1, .Ltiny - and a5, a4, 15 - bnez a5, .Lmisaligned + li REG_TABLE, BYTE_TBL_SZ + mv a3, a0 + + /* If there aren't many bytes, copy them individually to reduce overhead */ + bleu a2, REG_TABLE, .Lcopy_bytes + + and a4, a3, MV_SZ - 1 + beqz a4, .Lword_check + + /* + Jump into the byte table depending on the number of bytes that need to be + written + */ +1: + auipc t0, %pcrel_hi(.Ltable_misaligned) + + /* + Instructions in the tables are forced to be four bytes, so scale count + by 4 + */ +#if __riscv_zba + sh2add t0, a4, t0 +#else + sll t1, a4, 2 + add t0, t0, t1 +#endif -.Laligned: - bnez a1, .Lwordify + /* Save the return address because we aren't exiting the function yet */ + mv t1, ra + jalr t0, %pcrel_lo(1b) -.Lwordified: - and a3, a2, ~15 - and a2, a2, 15 - add a3, a3, a4 + /* Update pointer and count by what was written */ + mv ra, t1 + add a4, a4, -MV_SZ + add a2, a2, a4 + sub a3, a3, a4 + /* Access is now aligned. Check we can copy words. */ + bleu a2, REG_TABLE, .Lcopy_bytes + +.Lword_check: + /* Don't need to splat special case of zero */ + bnez a1, .Lsplat_byte +#if __riscv_zilsd + mv REG_SPLAT, a1 +#endif + j .Lcopy_words_init + +/* + Align labels to four bytes after unconditional jumps to avoid any + penalties when jumping to 32-bit instructions that aren't 4-byte + aligned +*/ +.p2align 2 +.Lsplat_byte: +#if __riscv_zbkb + packh REG_SPLAT, a1, a1 #if __riscv_xlen == 64 -1:sd a1, 0(a4) - sd a1, 8(a4) + packw REG_SPLAT, REG_SPLAT, REG_SPLAT +#endif + pack REG_SPLAT, REG_SPLAT, REG_SPLAT #else -1:sw a1, 0(a4) - sw a1, 4(a4) - sw a1, 8(a4) - sw a1, 12(a4) + and a1, a1, 0xFF + sll t0, a1, 8 + or a1, a1, t0 + sll t0, a1, 16 + or REG_SPLAT, a1, t0 +#if __riscv_xlen == 64 + sll t0, REG_SPLAT, 32 + or REG_SPLAT, REG_SPLAT, t0 +#endif #endif - add a4, a4, 16 - bltu a4, a3, 1b - bnez a2, .Ltiny - ret +.Lcopy_words_init: +#if __riscv_zilsd + /* Odd register of even-odd pair */ + mv a5, REG_SPLAT +#endif + + /* Calculate end address */ + and t0, a2, ~(MV_SZ - 1) + add t1, a3, t0 + + /* + The idea behind the table of word copies is that first we calculate any + remainder of bytes that need to be copied by the table that aren't an + entire table length. That's copied first. After that, runs of the entire + table are performed. + */ + and t0, t0, (WORD_TBL_SZ - 1) * MV_SZ + + /* Skip if there's no remainder */ + beqz t0, .Ltable_bigly + neg t0, t0 + add t0, t0, WORD_TBL_SZ * MV_SZ + + /* Adjust start address with offset */ + sub a3, a3, t0 + +1: + auipc t2, %pcrel_hi(.Ltable_bigly) + +#if MV_SZ == 8 + /* + If eight bytes are being copied with each store, we need to divide + the table offset in half + */ + srl t0, t0, 1 +#endif + + add t2, t2, t0 + jr t2, %pcrel_lo(1b) -.Ltiny: - sub a3, t1, a2 - sll a3, a3, 2 -1:auipc t0, %pcrel_hi(.Ltable) - add a3, a3, t0 +.p2align 2 +.Ltable_bigly: +/* + Force the instructions to be four bytes to avoid an extra instruction + that would be needed to halve the offset for sw +*/ .option push .option norvc -.Ltable_misaligned: - jr a3, %pcrel_lo(1b) -.Ltable: - sb a1,14(a4) - sb a1,13(a4) - sb a1,12(a4) - sb a1,11(a4) - sb a1,10(a4) - sb a1, 9(a4) - sb a1, 8(a4) - sb a1, 7(a4) - sb a1, 6(a4) - sb a1, 5(a4) - sb a1, 4(a4) - sb a1, 3(a4) - sb a1, 2(a4) - sb a1, 1(a4) - sb a1, 0(a4) + RG_ST REG_SPLAT, MV_SZ*0(a3) + RG_ST REG_SPLAT, MV_SZ*1(a3) + RG_ST REG_SPLAT, MV_SZ*2(a3) + RG_ST REG_SPLAT, MV_SZ*3(a3) + RG_ST REG_SPLAT, MV_SZ*4(a3) + RG_ST REG_SPLAT, MV_SZ*5(a3) + RG_ST REG_SPLAT, MV_SZ*6(a3) + RG_ST REG_SPLAT, MV_SZ*7(a3) + RG_ST REG_SPLAT, MV_SZ*8(a3) + RG_ST REG_SPLAT, MV_SZ*9(a3) + RG_ST REG_SPLAT, MV_SZ*10(a3) + RG_ST REG_SPLAT, MV_SZ*11(a3) + RG_ST REG_SPLAT, MV_SZ*12(a3) + RG_ST REG_SPLAT, MV_SZ*13(a3) + RG_ST REG_SPLAT, MV_SZ*14(a3) + RG_ST REG_SPLAT, MV_SZ*15(a3) + RG_ST REG_SPLAT, MV_SZ*16(a3) + RG_ST REG_SPLAT, MV_SZ*17(a3) + RG_ST REG_SPLAT, MV_SZ*18(a3) + RG_ST REG_SPLAT, MV_SZ*19(a3) + RG_ST REG_SPLAT, MV_SZ*20(a3) + RG_ST REG_SPLAT, MV_SZ*21(a3) + RG_ST REG_SPLAT, MV_SZ*22(a3) + RG_ST REG_SPLAT, MV_SZ*23(a3) + RG_ST REG_SPLAT, MV_SZ*24(a3) + RG_ST REG_SPLAT, MV_SZ*25(a3) + RG_ST REG_SPLAT, MV_SZ*26(a3) + RG_ST REG_SPLAT, MV_SZ*27(a3) + RG_ST REG_SPLAT, MV_SZ*28(a3) + RG_ST REG_SPLAT, MV_SZ*29(a3) + RG_ST REG_SPLAT, MV_SZ*30(a3) + RG_ST REG_SPLAT, MV_SZ*31(a3) .option pop - ret -.Lwordify: - and a1, a1, 0xFF - sll a3, a1, 8 - or a1, a1, a3 - sll a3, a1, 16 - or a1, a1, a3 -#if __riscv_xlen == 64 - sll a3, a1, 32 - or a1, a1, a3 + /* Update the pointer and copy data if needed */ + add a3, a3, MV_SZ * WORD_TBL_SZ + bltu a3, t1, .Ltable_bigly + + /* Copy any remaining bytes */ + and a2, a2, MV_SZ - 1 + beqz a2, .Lexit + +#if __riscv_zilsd && __riscv_abi_rve + /* Restore table size if necessary */ + li REG_TABLE, BYTE_TBL_SZ #endif - j .Lwordified - -.Lmisaligned: - sll a3, a5, 2 -1:auipc t0, %pcrel_hi(.Ltable_misaligned) - add a3, a3, t0 - mv t0, ra - jalr a3, %pcrel_lo(1b) - mv ra, t0 - - add a5, a5, -16 - sub a4, a4, a5 - add a2, a2, a5 - bleu a2, t1, .Ltiny - j .Laligned + +.Lcopy_bytes: + auipc t0, %pcrel_hi(.Ltable_tiny) + + sub a2, REG_TABLE, a2 + + /* + Instructions in the tables are forced to be four bytes, so scale count + by 4 + */ +#if __riscv_zba + sh2add t0, a2, t0 +#else + sll a2, a2, 2 + add t0, t0, a2 +#endif + + /* Don't save the return address because we're exiting after the jump */ + jr t0, %pcrel_lo(.Lcopy_bytes) + +.p2align 2 +.Ltable_tiny: +/* + norvc is needed because the immediate is only two bits in size for c.sb, + and without it the table would have a mix of 2- and 4-byte instructions + when Zcb is available +*/ +.option push +.option norvc + sb a1, 30(a3) + sb a1, 29(a3) + sb a1, 28(a3) + sb a1, 27(a3) + sb a1, 26(a3) + sb a1, 25(a3) + sb a1, 24(a3) + sb a1, 23(a3) + sb a1, 22(a3) + sb a1, 21(a3) + sb a1, 20(a3) + sb a1, 19(a3) + sb a1, 18(a3) + sb a1, 17(a3) + sb a1, 16(a3) + sb a1, 15(a3) + sb a1, 14(a3) + sb a1, 13(a3) + sb a1, 12(a3) + sb a1, 11(a3) + sb a1, 10(a3) + sb a1, 9(a3) + sb a1, 8(a3) +#if MV_SZ == 8 +.Ltable_misaligned: +#endif + sb a1, 7(a3) + sb a1, 6(a3) + sb a1, 5(a3) + sb a1, 4(a3) +#if MV_SZ == 4 +.Ltable_misaligned: +#endif + sb a1, 3(a3) + sb a1, 2(a3) + sb a1, 1(a3) + sb a1, 0(a3) +.option pop +.Lexit: + ret #endif - .size memset, .-memset +.size memset, .-memset diff --git a/newlib/libc/machine/riscv/sys/string.h b/newlib/libc/machine/riscv/rv_string.h index b65635c..dc2a26d 100644 --- a/newlib/libc/machine/riscv/sys/string.h +++ b/newlib/libc/machine/riscv/rv_string.h @@ -9,31 +9,35 @@ http://www.opensource.org/licenses. */ -#ifndef _SYS_STRING_H -#define _SYS_STRING_H +#ifndef _RV_STRING_H +#define _RV_STRING_H #include <stdbool.h> -#include "asm.h" +#include "xlenint.h" #if __riscv_zbb #include <riscv_bitmanip.h> // Determine which intrinsics to use based on XLEN and endianness #if __riscv_xlen == 64 - #define __LIBC_RISCV_ZBB_ORC_B(x) __riscv_orc_b_64(x) + #define __LIBC_RISCV_ZBB_ORC_B(x) __riscv_orc_b_64(x) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_ctz_64(x) + #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_ctz_64(x) + #define __LIBC_RISCV_ZBB_CNT_Z_REV(x) __riscv_clz_64(x) #else - #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_clz_64(x) + #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_clz_64(x) + #define __LIBC_RISCV_ZBB_CNT_Z_REV(x) __riscv_ctz_64(x) #endif #else - #define __LIBC_RISCV_ZBB_ORC_B(x) __riscv_orc_b_32(x) + #define __LIBC_RISCV_ZBB_ORC_B(x) __riscv_orc_b_32(x) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_ctz_32(x) + #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_ctz_32(x) + #define __LIBC_RISCV_ZBB_CNT_Z_REV(x) __riscv_clz_32(x) #else - #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_clz_32(x) + #define __LIBC_RISCV_ZBB_CNT_Z(x) __riscv_clz_32(x) + #define __LIBC_RISCV_ZBB_CNT_Z_REV(x) __riscv_ctz_32(x) #endif #endif #endif @@ -82,8 +86,8 @@ static __inline char *__libc_strcpy(char *dst, const char *src, bool ret_start) if (!(*dst++ = src[0])) return dst0; if (!(*dst++ = src[1])) return dst0; if (!(*dst++ = src[2])) return dst0; - if (!(*dst++ = src[3])) return dst0; #if __riscv_xlen == 64 + if (!(*dst++ = src[3])) return dst0; if (!(*dst++ = src[4])) return dst0; if (!(*dst++ = src[5])) return dst0; if (!(*dst++ = src[6])) return dst0; @@ -94,13 +98,13 @@ static __inline char *__libc_strcpy(char *dst, const char *src, bool ret_start) if (!(*dst++ = src[0])) return dst - 1; if (!(*dst++ = src[1])) return dst - 1; if (!(*dst++ = src[2])) return dst - 1; - if (!(*dst++ = src[3])) return dst - 1; #if __riscv_xlen == 64 + if (!(*dst++ = src[3])) return dst - 1; if (!(*dst++ = src[4])) return dst - 1; if (!(*dst++ = src[5])) return dst - 1; if (!(*dst++ = src[6])) return dst - 1; - dst0 = dst; #endif + dst0 = dst; } *dst = 0; @@ -121,4 +125,33 @@ static __inline char *__libc_strcpy(char *dst, const char *src, bool ret_start) } -#endif +static __inline uintxlen_t __libc_splat_byte(unsigned char c) +{ + uintxlen_t val; + +#if __riscv_zbkb + asm volatile ("packh %0, %1, %1" + : "=r" (val) + : "r" (c) + ); +#if __riscv_xlen == 64 + asm volatile ("packw %0, %0, %0" + : "+r" (val) + ); +#endif /* __riscv_xlen == 64 */ + asm volatile ("pack %0, %0, %0" + : "+r" (val) + ); +#else /* not __riscv_zbkb */ + val = (c << 8) | c; + val = (val << 16) | val; +#if __riscv_xlen == 64 + val = (val << 32) | val; +#endif /* __riscv_xlen == 64 */ +#endif /* __riscv_zbkb */ + + return val; +} + + +#endif /* _RV_STRING_H */ diff --git a/newlib/libc/machine/riscv/setjmp.S b/newlib/libc/machine/riscv/setjmp.S index eef242e..f2b5053 100644 --- a/newlib/libc/machine/riscv/setjmp.S +++ b/newlib/libc/machine/riscv/setjmp.S @@ -16,21 +16,33 @@ .type setjmp, @function setjmp: REG_S ra, 0*SZREG(a0) - REG_S s0, 1*SZREG(a0) - REG_S s1, 2*SZREG(a0) + #if __riscv_xlen == 32 && (__riscv_zilsd) && (__riscv_misaligned_fast) + sd s0, 1*SZREG(a0) + #else + REG_S s0, 1*SZREG(a0) + REG_S s1, 2*SZREG(a0) + #endif -#ifndef __riscv_32e - REG_S s2, 3*SZREG(a0) - REG_S s3, 4*SZREG(a0) - REG_S s4, 5*SZREG(a0) - REG_S s5, 6*SZREG(a0) - REG_S s6, 7*SZREG(a0) - REG_S s7, 8*SZREG(a0) - REG_S s8, 9*SZREG(a0) - REG_S s9, 10*SZREG(a0) - REG_S s10,11*SZREG(a0) - REG_S s11,12*SZREG(a0) - REG_S sp, 13*SZREG(a0) +#ifndef __riscv_abi_rve + #if __riscv_xlen == 32 && (__riscv_zilsd) && (__riscv_misaligned_fast) + sd s2, 3*SZREG(a0) + sd s4, 5*SZREG(a0) + sd s6, 7*SZREG(a0) + sd s8, 9*SZREG(a0) + sd s10,11*SZREG(a0) + #else + REG_S s2, 3*SZREG(a0) + REG_S s3, 4*SZREG(a0) + REG_S s4, 5*SZREG(a0) + REG_S s5, 6*SZREG(a0) + REG_S s6, 7*SZREG(a0) + REG_S s7, 8*SZREG(a0) + REG_S s8, 9*SZREG(a0) + REG_S s9, 10*SZREG(a0) + REG_S s10,11*SZREG(a0) + REG_S s11,12*SZREG(a0) + #endif + REG_S sp, 13*SZREG(a0) #else REG_S sp, 3*SZREG(a0) #endif @@ -59,19 +71,31 @@ setjmp: .type longjmp, @function longjmp: REG_L ra, 0*SZREG(a0) - REG_L s0, 1*SZREG(a0) - REG_L s1, 2*SZREG(a0) -#ifndef __riscv_32e - REG_L s2, 3*SZREG(a0) - REG_L s3, 4*SZREG(a0) - REG_L s4, 5*SZREG(a0) - REG_L s5, 6*SZREG(a0) - REG_L s6, 7*SZREG(a0) - REG_L s7, 8*SZREG(a0) - REG_L s8, 9*SZREG(a0) - REG_L s9, 10*SZREG(a0) - REG_L s10,11*SZREG(a0) - REG_L s11,12*SZREG(a0) + #if __riscv_xlen == 32 && (__riscv_zilsd) && (__riscv_misaligned_fast) + ld s0, 1*SZREG(a0) + #else + REG_L s0, 1*SZREG(a0) + REG_L s1, 2*SZREG(a0) + #endif +#ifndef __riscv_abi_rve + #if __riscv_xlen == 32 && (__riscv_zilsd) && (__riscv_misaligned_fast) + ld s2, 3*SZREG(a0) + ld s4, 5*SZREG(a0) + ld s6, 7*SZREG(a0) + ld s8, 9*SZREG(a0) + ld s10,11*SZREG(a0) + #else + REG_L s2, 3*SZREG(a0) + REG_L s3, 4*SZREG(a0) + REG_L s4, 5*SZREG(a0) + REG_L s5, 6*SZREG(a0) + REG_L s6, 7*SZREG(a0) + REG_L s7, 8*SZREG(a0) + REG_L s8, 9*SZREG(a0) + REG_L s9, 10*SZREG(a0) + REG_L s10,11*SZREG(a0) + REG_L s11,12*SZREG(a0) + #endif REG_L sp, 13*SZREG(a0) #else REG_L sp, 3*SZREG(a0) diff --git a/newlib/libc/machine/riscv/stpcpy.c b/newlib/libc/machine/riscv/stpcpy.c index 9243457..14c3222 100644 --- a/newlib/libc/machine/riscv/stpcpy.c +++ b/newlib/libc/machine/riscv/stpcpy.c @@ -1,5 +1,5 @@ -#include <string.h> #include <stdbool.h> +#include "rv_string.h" char *stpcpy(char *dst, const char *src) { diff --git a/newlib/libc/machine/riscv/strcmp.S b/newlib/libc/machine/riscv/strcmp.S index 12c39db..0b1dfc4 100644 --- a/newlib/libc/machine/riscv/strcmp.S +++ b/newlib/libc/machine/riscv/strcmp.S @@ -16,15 +16,15 @@ .type strcmp, @function strcmp: #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) -1: +.Lcompare: lbu a2, 0(a0) lbu a3, 0(a1) - add a0, a0, 1 - add a1, a1, 1 - bne a2, a3, 2f - bnez a2, 1b + addi a0, a0, 1 + addi a1, a1, 1 + bne a2, a3, .Lreturn_diff + bnez a2, .Lcompare -2: +.Lreturn_diff: sub a0, a2, a3 ret @@ -48,12 +48,16 @@ strcmp: REG_L a2, \i*SZREG(a0) REG_L a3, \i*SZREG(a1) - and t0, a2, a5 - or t1, a2, a5 - add t0, t0, a5 - or t0, t0, t1 + #if __riscv_zbb + orc.b a4, a2 + #else + and a4, a2, a5 + or t1, a2, a5 + add a4, a4, a5 + or a4, a4, t1 + #endif - bne t0, t2, .Lnull\i + bne a4, t2, .Lnull\i .if \i+1-\n bne a2, a3, .Lmismatch .else @@ -95,73 +99,109 @@ strcmp: .Lmismatch: # words don't match, but a2 has no null byte. + #if __riscv_zbb + xor a4, a2, a3 # find differing bits + + # Check system endianness + # If little-endian, use Count Trailing Zeros (ctz) + # If big-endian, use Count Leading Zeros (clz) + # This helps identify the position of the first differing byte between a2 and a3. + + # For example, in little-endian, least significant byte comes first. + # So trailing zeros help find which byte position differs. + + # In big-endian, most significant byte comes first, so leading zeros are used. + # The position will then be used to extract the differing byte. + + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + ctz a5, a4 + #else + clz a5, a4 + #endif + + andi a5, a5, -8 # find position of bit offset to the start of the byte where the first difference occurs + + + # Shift a2 and a3 right by a5 bits to bring the target byte to the LSB, and isolate the byte of interest + srl a2, a2, a5 + and a2, a2, 0xff + + srl a3, a3, a5 + and a3, a3, 0xff + + + sub a0, a2, a3 # Calculate and return the difference in the isolated bytes + ret + + #else + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #if __riscv_xlen == 64 + sll a4, a2, 48 + sll a5, a3, 48 + bne a4, a5, .Lmismatch_upper + sll a4, a2, 32 + sll a5, a3, 32 + bne a4, a5, .Lmismatch_upper + #endif + sll a4, a2, 16 + sll a5, a3, 16 + bne a4, a5, .Lmismatch_upper + + srl a4, a2, 8*SZREG-16 + srl a5, a3, 8*SZREG-16 + sub a0, a4, a5 + and a1, a0, 0xff + bnez a1, .Lfinal_upper_diff + ret -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - -#if __riscv_xlen == 64 - sll a4, a2, 48 - sll a5, a3, 48 - bne a4, a5, .Lmismatch_upper - sll a4, a2, 32 - sll a5, a3, 32 - bne a4, a5, .Lmismatch_upper -#endif - sll a4, a2, 16 - sll a5, a3, 16 - bne a4, a5, .Lmismatch_upper - - srl a4, a2, 8*SZREG-16 - srl a5, a3, 8*SZREG-16 - sub a0, a4, a5 - and a1, a0, 0xff - bnez a1, 1f - ret - -.Lmismatch_upper: - srl a4, a4, 8*SZREG-16 - srl a5, a5, 8*SZREG-16 - sub a0, a4, a5 - and a1, a0, 0xff - bnez a1, 1f - ret - -1:and a4, a4, 0xff - and a5, a5, 0xff - sub a0, a4, a5 - ret - -#else - -#if __riscv_xlen == 64 - srl a4, a2, 48 - srl a5, a3, 48 - bne a4, a5, .Lmismatch_lower - srl a4, a2, 32 - srl a5, a3, 32 - bne a4, a5, .Lmismatch_lower -#endif - srl a4, a2, 16 - srl a5, a3, 16 - bne a4, a5, .Lmismatch_lower - - srl a4, a2, 8 - srl a5, a3, 8 - bne a4, a5, 1f - and a4, a2, 0xff - and a5, a3, 0xff -1:sub a0, a4, a5 - ret - -.Lmismatch_lower: - srl a2, a4, 8 - srl a3, a5, 8 - bne a2, a3, 1f - and a2, a4, 0xff - and a3, a5, 0xff -1:sub a0, a2, a3 - ret - -#endif + .Lmismatch_upper: + srl a4, a4, 8*SZREG-16 + srl a5, a5, 8*SZREG-16 + sub a0, a4, a5 + and a1, a0, 0xff + bnez a1, .Lfinal_upper_diff + ret + + .Lfinal_upper_diff: + and a4, a4, 0xff + and a5, a5, 0xff + sub a0, a4, a5 + ret + #else + #if __riscv_xlen == 64 + srl a4, a2, 48 + srl a5, a3, 48 + bne a4, a5, .Lmismatch_lower + srl a4, a2, 32 + srl a5, a3, 32 + bne a4, a5, .Lmismatch_lower + #endif + srl a4, a2, 16 + srl a5, a3, 16 + bne a4, a5, .Lmismatch_lower + + srl a4, a2, 8 + srl a5, a3, 8 + bne a4, a5, .Lbyte_diff + and a4, a2, 0xff + and a5, a3, 0xff + + .Lbyte_diff: + sub a0, a4, a5 + ret + + .Lmismatch_lower: + srl a2, a4, 8 + srl a3, a5, 8 + bne a2, a3, .Lfinal_lower_diff + and a2, a4, 0xff + and a3, a5, 0xff + + .Lfinal_lower_diff: + sub a0, a2, a3 + ret + #endif + #endif .Lmisaligned: # misaligned @@ -169,10 +209,10 @@ strcmp: lbu a3, 0(a1) add a0, a0, 1 add a1, a1, 1 - bne a2, a3, 1f + bne a2, a3, .Lmisaligned_diff bnez a2, .Lmisaligned -1: +.Lmisaligned_diff: sub a0, a2, a3 ret @@ -188,9 +228,16 @@ strcmp: foundnull 1 3 foundnull 2 3 #endif +#ifdef __riscv_cmodel_large + # Put the data within the funciton for large code model to prevent + # the data put too far. +.align 3 +mask: +.dword 0x7f7f7f7f7f7f7f7f +#endif .size strcmp, .-strcmp -#if SZREG == 8 +#if SZREG == 8 && !defined(__riscv_cmodel_large) .section .srodata.cst8,"aM",@progbits,8 .align 3 mask: diff --git a/newlib/libc/machine/riscv/strcpy.c b/newlib/libc/machine/riscv/strcpy.c index f770493..a05ec1c 100644 --- a/newlib/libc/machine/riscv/strcpy.c +++ b/newlib/libc/machine/riscv/strcpy.c @@ -9,8 +9,8 @@ http://www.opensource.org/licenses. */ -#include <string.h> #include <stdbool.h> +#include "rv_string.h" char *strcpy(char *dst, const char *src) { diff --git a/newlib/libc/machine/riscv/strlen.c b/newlib/libc/machine/riscv/strlen.c index 7e5d416..8ab5ce5 100644 --- a/newlib/libc/machine/riscv/strlen.c +++ b/newlib/libc/machine/riscv/strlen.c @@ -9,9 +9,10 @@ http://www.opensource.org/licenses. */ +#include <sys/types.h> #include <string.h> #include <stdint.h> -#include "sys/asm.h" +#include "rv_string.h" size_t strlen(const char *str) { @@ -38,7 +39,9 @@ size_t strlen(const char *str) asm volatile ("" : "+r"(ps)); /* prevent "optimization" */ str = (const char *)ps; - size_t ret = str - start, sp = sizeof (*ps); + + size_t ret = str - start; + ssize_t sp = sizeof (*ps); #if __riscv_zbb psval = ~__LIBC_RISCV_ZBB_ORC_B(psval); @@ -47,16 +50,16 @@ size_t strlen(const char *str) return ret + (psval >> 3) - sp; #else char c0 = str[0 - sp], c1 = str[1 - sp], c2 = str[2 - sp], c3 = str[3 - sp]; - if (c0 == 0) return ret + 0 - sp; - if (c1 == 0) return ret + 1 - sp; - if (c2 == 0) return ret + 2 - sp; - if (c3 == 0) return ret + 3 - sp; + if (c0 == 0) return ret + 0 - sp; + if (c1 == 0) return ret + 1 - sp; + if (c2 == 0) return ret + 2 - sp; + if (__riscv_xlen == 32 || c3 == 0) return ret + 3 - sp; #if __riscv_xlen == 64 c0 = str[4 - sp], c1 = str[5 - sp], c2 = str[6 - sp]; - if (c0 == 0) return ret + 4 - sp; - if (c1 == 0) return ret + 5 - sp; - if (c2 == 0) return ret + 6 - sp; + if (c0 == 0) return ret + 4 - sp; + if (c1 == 0) return ret + 5 - sp; + if (c2 == 0) return ret + 6 - sp; #endif return ret + 7 - sp; diff --git a/newlib/libc/machine/riscv/sys/asm.h b/newlib/libc/machine/riscv/sys/asm.h index 0a354b2..8c8aeb3 100644 --- a/newlib/libc/machine/riscv/sys/asm.h +++ b/newlib/libc/machine/riscv/sys/asm.h @@ -12,8 +12,6 @@ #ifndef _SYS_ASM_H #define _SYS_ASM_H -#include <stdint.h> - /* * Macros to handle different pointer/register sizes for 32/64-bit code */ @@ -22,13 +20,11 @@ # define SZREG 8 # define REG_S sd # define REG_L ld -typedef uint64_t uintxlen_t; #elif __riscv_xlen == 32 # define PTRLOG 2 # define SZREG 4 # define REG_S sw # define REG_L lw -typedef uint32_t uintxlen_t; #else # error __riscv_xlen must equal 32 or 64 #endif diff --git a/newlib/libc/machine/riscv/xlenint.h b/newlib/libc/machine/riscv/xlenint.h new file mode 100644 index 0000000..2d444ff --- /dev/null +++ b/newlib/libc/machine/riscv/xlenint.h @@ -0,0 +1,21 @@ +#ifndef _XLENINT_H +#define _XLENINT_H + +#include <stdint.h> + +#if __riscv_xlen == 64 +typedef uint64_t uintxlen_t; +#elif __riscv_xlen == 32 +typedef uint32_t uintxlen_t; +#else +# error __riscv_xlen must equal 32 or 64 +#endif + +/* Load/Store length */ +#if __riscv_zilsd +typedef uint64_t uintlslen_t; +#else +typedef uintxlen_t uintlslen_t; +#endif + +#endif /* _XLENINT_H */ diff --git a/newlib/libc/posix/ftw.c b/newlib/libc/posix/ftw.c index 79e6358..e3ca85c 100644 --- a/newlib/libc/posix/ftw.c +++ b/newlib/libc/posix/ftw.c @@ -30,7 +30,9 @@ int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int /* The following cast assumes that calling a function with one * argument more than it needs behaves as expected. This is * actually undefined, but works on all real-world machines. */ - return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS); + return nftw(path, + (int (*)(const char *, const struct stat *, int, struct FTW *))fn, + fd_limit, FTW_PHYS); } #endif /* ! HAVE_OPENDIR */ diff --git a/newlib/libc/posix/glob.c b/newlib/libc/posix/glob.c index 20eec02..fe7359b 100644 --- a/newlib/libc/posix/glob.c +++ b/newlib/libc/posix/glob.c @@ -157,10 +157,8 @@ static void qprintf(const char *, Char *); #endif int -glob(pattern, flags, errfunc, pglob) - const char *__restrict pattern; - int flags, (*errfunc)(const char *, int); - glob_t *__restrict pglob; +glob(const char *__restrict pattern, int flags, + int (*errfunc)(const char *, int), glob_t *__restrict pglob) { const u_char *patnext; int c, limit; @@ -215,10 +213,7 @@ glob(pattern, flags, errfunc, pglob) * characters */ static int -globexp1(pattern, pglob, limit) - const Char *pattern; - glob_t *pglob; - int *limit; +globexp1(const Char *pattern, glob_t *pglob, int *limit) { const Char* ptr = pattern; int rv; @@ -241,10 +236,8 @@ globexp1(pattern, pglob, limit) * If it fails then it tries to glob the rest of the pattern and returns. */ static int -globexp2(ptr, pattern, pglob, rv, limit) - const Char *ptr, *pattern; - glob_t *pglob; - int *rv, *limit; +globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, + int *limit) { int i; Char *lm, *ls; @@ -348,11 +341,7 @@ globexp2(ptr, pattern, pglob, rv, limit) * expand tilde from the passwd file. */ static const Char * -globtilde(pattern, patbuf, patbuf_len, pglob) - const Char *pattern; - Char *patbuf; - size_t patbuf_len; - glob_t *pglob; +globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) { struct passwd *pwd; char *h; @@ -428,10 +417,7 @@ globtilde(pattern, patbuf, patbuf_len, pglob) * to find no matches. */ static int -glob0(pattern, pglob, limit) - const Char *pattern; - glob_t *pglob; - int *limit; +glob0(const Char *pattern, glob_t *pglob, int *limit) { const Char *qpatnext; int c, err, oldpathc; @@ -517,17 +503,13 @@ glob0(pattern, pglob, limit) } static int -compare(p, q) - const void *p, *q; +compare(const void *p, const void *q) { return(strcmp(*(char **)p, *(char **)q)); } static int -glob1(pattern, pglob, limit) - Char *pattern; - glob_t *pglob; - int *limit; +glob1(Char *pattern, glob_t *pglob, int *limit) { Char pathbuf[MAXPATHLEN]; @@ -544,10 +526,8 @@ glob1(pattern, pglob, limit) * meta characters. */ static int -glob2(pathbuf, pathend, pathend_last, pattern, pglob, limit) - Char *pathbuf, *pathend, *pathend_last, *pattern; - glob_t *pglob; - int *limit; +glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern, + glob_t *pglob, int *limit) { struct stat sb; Char *p, *q; @@ -604,10 +584,8 @@ glob2(pathbuf, pathend, pathend_last, pattern, pglob, limit) } static int -glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit) - Char *pathbuf, *pathend, *pathend_last, *pattern, *restpattern; - glob_t *pglob; - int *limit; +glob3(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern, + Char *restpattern, glob_t *pglob, int *limit) { struct dirent *dp; DIR *dirp; @@ -620,7 +598,7 @@ glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit) * and dirent.h as taking pointers to differently typed opaque * structures. */ - struct dirent *(*readdirfunc)(); + struct dirent *(*readdirfunc)(void *); if (pathend > pathend_last) return (1); @@ -645,7 +623,7 @@ glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit) if (pglob->gl_flags & GLOB_ALTDIRFUNC) readdirfunc = pglob->gl_readdir; else - readdirfunc = readdir; + readdirfunc = (struct dirent *(*)(void *))readdir; while ((dp = (*readdirfunc)(dirp))) { u_char *sc; Char *dc; @@ -690,10 +668,7 @@ glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit) * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ static int -globextend(path, pglob, limit) - const Char *path; - glob_t *pglob; - int *limit; +globextend(const Char *path, glob_t *pglob, int *limit) { char **pathv; int i; @@ -745,8 +720,7 @@ globextend(path, pglob, limit) * pattern causes a recursion level. */ static int -match(name, pat, patend) - Char *name, *pat, *patend; +match(Char *name, Char *pat, Char *patend) { int ok, negate_range; Char c, k; @@ -797,8 +771,7 @@ match(name, pat, patend) /* Free allocated data belonging to a glob_t structure. */ void -globfree(pglob) - glob_t *pglob; +globfree(glob_t *pglob) { int i; char **pp; @@ -814,9 +787,7 @@ globfree(pglob) } static DIR * -g_opendir(str, pglob) - Char *str; - glob_t *pglob; +g_opendir(Char *str, glob_t *pglob) { char buf[MAXPATHLEN]; @@ -834,10 +805,7 @@ g_opendir(str, pglob) } static int -g_lstat(fn, sb, pglob) - Char *fn; - struct stat *sb; - glob_t *pglob; +g_lstat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[MAXPATHLEN]; @@ -851,10 +819,7 @@ g_lstat(fn, sb, pglob) } static int -g_stat(fn, sb, pglob) - Char *fn; - struct stat *sb; - glob_t *pglob; +g_stat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[MAXPATHLEN]; @@ -868,9 +833,7 @@ g_stat(fn, sb, pglob) } static Char * -g_strchr(str, ch) - Char *str; - int ch; +g_strchr(Char *str, int ch) { do { if (*str == ch) @@ -880,10 +843,7 @@ g_strchr(str, ch) } static int -g_Ctoc(str, buf, len) - const Char *str; - char *buf; - u_int len; +g_Ctoc(const Char *str, char *buf, u_int len) { while (len--) { @@ -895,9 +855,7 @@ g_Ctoc(str, buf, len) #ifdef DEBUG static void -qprintf(str, s) - const char *str; - Char *s; +qprintf(const char *str, Char *s) { Char *p; diff --git a/newlib/libc/posix/posix_spawn.c b/newlib/libc/posix/posix_spawn.c index 46e4e53..51ad23f 100644 --- a/newlib/libc/posix/posix_spawn.c +++ b/newlib/libc/posix/posix_spawn.c @@ -102,56 +102,13 @@ Supporting OS subroutines required: <<_close>>, <<dup2>>, <<_fcntl>>, #include <stdlib.h> #include <string.h> #include <unistd.h> +#include "posix_spawn.h" /* Only deal with a pointer to environ, to work around subtle bugs with shared libraries and/or small data systems where the user declares his own 'environ'. */ static char ***p_environ = &environ; -struct __posix_spawnattr { - short sa_flags; - pid_t sa_pgroup; - struct sched_param sa_schedparam; - int sa_schedpolicy; - sigset_t sa_sigdefault; - sigset_t sa_sigmask; -}; - -struct __posix_spawn_file_actions { - STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; -}; - -typedef struct __posix_spawn_file_actions_entry { - STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; - enum { - FAE_OPEN, - FAE_DUP2, - FAE_CLOSE, - FAE_CHDIR, - FAE_FCHDIR - } fae_action; - - int fae_fildes; - union { - struct { - char *path; -#define fae_path fae_data.open.path - int oflag; -#define fae_oflag fae_data.open.oflag - mode_t mode; -#define fae_mode fae_data.open.mode - } open; - struct { - int newfildes; -#define fae_newfildes fae_data.dup2.newfildes - } dup2; - char *dir; -#define fae_dir fae_data.dir - int dirfd; -#define fae_dirfd fae_data.dirfd - } fae_data; -} posix_spawn_file_actions_entry_t; - /* * Spawn routines */ diff --git a/newlib/libc/posix/posix_spawn.h b/newlib/libc/posix/posix_spawn.h new file mode 100644 index 0000000..b4cad1e --- /dev/null +++ b/newlib/libc/posix/posix_spawn.h @@ -0,0 +1,54 @@ +#ifndef _POSIX_SPAWN_H_ +#define _POSIX_SPAWN_H_ + +#include <sys/cdefs.h> +#include <sys/sched.h> +#include <sys/signal.h> +#include <sys/types.h> +#include <sys/queue.h> + +struct __posix_spawnattr { + short sa_flags; + pid_t sa_pgroup; + struct sched_param sa_schedparam; + int sa_schedpolicy; + sigset_t sa_sigdefault; + sigset_t sa_sigmask; +}; + +struct __posix_spawn_file_actions { + STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; +}; + +typedef struct __posix_spawn_file_actions_entry { + STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; + enum { + FAE_OPEN, + FAE_DUP2, + FAE_CLOSE, + FAE_CHDIR, + FAE_FCHDIR + } fae_action; + + int fae_fildes; + union { + struct { + char *path; +#define fae_path fae_data.open.path + int oflag; +#define fae_oflag fae_data.open.oflag + mode_t mode; +#define fae_mode fae_data.open.mode + } open; + struct { + int newfildes; +#define fae_newfildes fae_data.dup2.newfildes + } dup2; + char *dir; +#define fae_dir fae_data.dir + int dirfd; +#define fae_dirfd fae_data.dirfd + } fae_data; +} posix_spawn_file_actions_entry_t; + +#endif /* !_POSIX_SPAWN_H_ */ diff --git a/newlib/libc/search/tdelete.c b/newlib/libc/search/tdelete.c index a595200..b12158e 100644 --- a/newlib/libc/search/tdelete.c +++ b/newlib/libc/search/tdelete.c @@ -27,7 +27,7 @@ __RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $"); /* delete node with given key */ void * tdelete (const void *__restrict vkey, /* key to be deleted */ - void **__restrict vrootp, /* address of the root of tree */ + posix_tnode **__restrict vrootp,/* address of the root of tree */ int (*compar)(const void *, const void *)) { node_t **rootp = (node_t **)vrootp; diff --git a/newlib/libc/search/tfind.c b/newlib/libc/search/tfind.c index 670f41f..8bebdac 100644 --- a/newlib/libc/search/tfind.c +++ b/newlib/libc/search/tfind.c @@ -26,7 +26,7 @@ __RCSID("$NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $"); /* find a node, or return 0 */ void * tfind (const void *vkey, /* key to be found */ - void **vrootp, /* address of the tree root */ + posix_tnode *const *vrootp, /* address of the tree root */ int (*compar)(const void *, const void *)) { node_t **rootp = (node_t **)vrootp; diff --git a/newlib/libc/search/tsearch.c b/newlib/libc/search/tsearch.c index 82d6944..9be77f1 100644 --- a/newlib/libc/search/tsearch.c +++ b/newlib/libc/search/tsearch.c @@ -26,7 +26,7 @@ __RCSID("$NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $"); /* find or insert datum into search tree */ void * tsearch (const void *vkey, /* key to be located */ - void **vrootp, /* address of tree root */ + posix_tnode **vrootp, /* address of tree root */ int (*compar)(const void *, const void *)) { node_t *q; diff --git a/newlib/libc/search/twalk.c b/newlib/libc/search/twalk.c index 7aec6e4..26d037a 100644 --- a/newlib/libc/search/twalk.c +++ b/newlib/libc/search/twalk.c @@ -50,8 +50,8 @@ trecurse( /* Walk the nodes of a tree */ void -twalk (const void *vroot, /* Root of the tree to be walked */ - void (*action)(const void *, VISIT, int)) +twalk (const posix_tnode *vroot,/* Root of the tree to be walked */ + void (*action)(const posix_tnode *, VISIT, int)) { if (vroot != NULL && action != NULL) trecurse(vroot, action, 0); diff --git a/newlib/libc/stdlib/mbtowc_r.c b/newlib/libc/stdlib/mbtowc_r.c index cab8333..6c3bd3d 100644 --- a/newlib/libc/stdlib/mbtowc_r.c +++ b/newlib/libc/stdlib/mbtowc_r.c @@ -677,6 +677,21 @@ __utf8_mbtowc (struct _reent *r, state->__count = 3; else if (n < (size_t)-1) ++n; + if (n < 4) + return -2; + ch = t[i++]; + if (ch < 0x80 || ch > 0xbf) + { + _REENT_ERRNO(r) = EILSEQ; + return -1; + } + /* Note: Originally we created the low surrogate pair on systems with + wchar_t == UTF-16 *before* checking the 4th byte. This was utterly + wrong, because this failed to check the last byte for being a valid + value for a complete UTF-8 4 byte sequence. As a result, calling + functions happily digested the low surrogate and then got an entirely + different character and handled this separately, thus generating + invalid UTF-16 values. */ if (state->__count == 3 && sizeof(wchar_t) == 2) { /* On systems which have wchar_t being UTF-16 values, the value @@ -695,15 +710,7 @@ __utf8_mbtowc (struct _reent *r, | (wint_t)((state->__value.__wchb[2] & 0x3f) << 6); state->__count = 4; *pwc = 0xd800 | ((tmp - 0x10000) >> 10); - return i; - } - if (n < 4) - return -2; - ch = t[i++]; - if (ch < 0x80 || ch > 0xbf) - { - _REENT_ERRNO(r) = EILSEQ; - return -1; + return 3; } tmp = (wint_t)((state->__value.__wchb[0] & 0x07) << 18) | (wint_t)((state->__value.__wchb[1] & 0x3f) << 12) diff --git a/newlib/libc/stdlib/wcstombs_r.c b/newlib/libc/stdlib/wcstombs_r.c index c6a06a3..2c82a2c 100644 --- a/newlib/libc/stdlib/wcstombs_r.c +++ b/newlib/libc/stdlib/wcstombs_r.c @@ -17,14 +17,15 @@ _wcstombs_r (struct _reent *r, if (s == NULL) { size_t num_bytes = 0; - while (*pwcs != 0) + do { - bytes = __WCTOMB (r, buff, *pwcs++, state); + bytes = __WCTOMB (r, buff, *pwcs, state); if (bytes == -1) return -1; num_bytes += bytes; } - return num_bytes; + while (*pwcs++ != 0x00); + return num_bytes - 1; } else { diff --git a/newlib/libc/stdlib/wctomb_r.c b/newlib/libc/stdlib/wctomb_r.c index 5ea1e13..ec6adfa 100644 --- a/newlib/libc/stdlib/wctomb_r.c +++ b/newlib/libc/stdlib/wctomb_r.c @@ -62,8 +62,8 @@ __utf8_wctomb (struct _reent *r, of the surrogate and proceed to convert the given character. Note to return extra 3 bytes. */ wchar_t tmp; - tmp = (state->__value.__wchb[0] << 16 | state->__value.__wchb[1] << 8) - - (0x10000 >> 10 | 0xd80d); + tmp = (((state->__value.__wchb[0] << 16 | state->__value.__wchb[1] << 8) + - 0x10000) >> 10) | 0xd800; *s++ = 0xe0 | ((tmp & 0xf000) >> 12); *s++ = 0x80 | ((tmp & 0xfc0) >> 6); *s++ = 0x80 | (tmp & 0x3f); diff --git a/newlib/libc/sys/rtems/include/limits.h b/newlib/libc/sys/rtems/include/limits.h index 5e71e4b..8dbf88b 100644 --- a/newlib/libc/sys/rtems/include/limits.h +++ b/newlib/libc/sys/rtems/include/limits.h @@ -56,12 +56,14 @@ #define _POSIX_TZNAME_MAX 3 /* - * Definitions of the following may be omitted if the value is >= stated - * minimum but is indeterminate. + * Definitions of the following may be omitted if the value is >= stated + * minimum but is indeterminate. The following are not defined because + * RTEMS does not have an inherent limit. + * + * - AIO_LISTIO_MAX + * - AIO_MAX */ -#define AIO_LISTIO_MAX 2 -#define AIO_MAX 1 #define AIO_PRIO_DELTA_MAX 0 #define DELAYTIMER_MAX 32 #define MQ_OPEN_MAX 8 diff --git a/newlib/libc/sys/rtems/include/semaphore.h b/newlib/libc/sys/rtems/include/semaphore.h index 939135f..6d756d5 100644 --- a/newlib/libc/sys/rtems/include/semaphore.h +++ b/newlib/libc/sys/rtems/include/semaphore.h @@ -55,6 +55,12 @@ int sem_timedwait(sem_t * __restrict, const struct timespec * __restrict); int sem_trywait(sem_t *); int sem_unlink(const char *); int sem_wait(sem_t *); + +#if (__GNU_VISIBLE || __POSIX_VISIBLE >= 202405) +int sem_clockwait(sem_t * __restrict, __clockid_t, + const struct timespec * __restrict); +#endif /* __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 */ + __END_DECLS #endif /* !_SEMAPHORE_H_ */ diff --git a/newlib/libc/sys/rtems/include/sys/dirent.h b/newlib/libc/sys/rtems/include/sys/dirent.h index 6f8ff42..3e41635 100644 --- a/newlib/libc/sys/rtems/include/sys/dirent.h +++ b/newlib/libc/sys/rtems/include/sys/dirent.h @@ -99,7 +99,7 @@ struct dirent { #define __dirfd(dp) ((dp)->dd_fd) -#if __BSD_VISIBLE +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 202405 /* * File types diff --git a/newlib/libc/sys/rtems/include/sys/poll.h b/newlib/libc/sys/rtems/include/sys/poll.h index cc6ad49..fd2f14d 100644 --- a/newlib/libc/sys/rtems/include/sys/poll.h +++ b/newlib/libc/sys/rtems/include/sys/poll.h @@ -35,6 +35,10 @@ #include <sys/cdefs.h> +#if (__GNU_VISIBLE || __POSIX_VISIBLE >= 202405) +#include <signal.h> +#endif + /* * This file is intended to be compatible with the traditional poll.h. */ @@ -100,6 +104,11 @@ struct pollfd { __BEGIN_DECLS int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout); +#if (__GNU_VISIBLE || __POSIX_VISIBLE >= 202405) +int ppoll(struct pollfd _pfd[], nfds_t _nfds, + const struct timespec *__restrict _timeout, + const sigset_t *__restrict _newsigmask); +#endif /* __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 */ __END_DECLS #endif /* !_KERNEL */ diff --git a/newlib/libm/machine/riscv/e_sqrt.c b/newlib/libm/machine/riscv/e_sqrt.c index 0c5aaad..ba000d3 100644 --- a/newlib/libm/machine/riscv/e_sqrt.c +++ b/newlib/libm/machine/riscv/e_sqrt.c @@ -35,6 +35,7 @@ #include <math.h> #include "math_config.h" +#include "riscv_math.h" #if defined(__RISCV_HARD_FLOAT) && __RISCV_HARD_FLOAT >= 64 diff --git a/newlib/libm/machine/riscv/ef_sqrt.c b/newlib/libm/machine/riscv/ef_sqrt.c index cc41813..fd7ab4b 100644 --- a/newlib/libm/machine/riscv/ef_sqrt.c +++ b/newlib/libm/machine/riscv/ef_sqrt.c @@ -35,6 +35,7 @@ #include <math.h> #include "math_config.h" +#include "riscv_math.h" #if defined(__RISCV_HARD_FLOAT) && __RISCV_HARD_FLOAT >= 32 diff --git a/winsup/configure.ac b/winsup/configure.ac index 9b9b59d..18adf3d 100644 --- a/winsup/configure.ac +++ b/winsup/configure.ac @@ -69,12 +69,14 @@ DLL_ENTRY="dll_entry" case "$target_cpu" in x86_64) ;; + aarch64) ;; *) AC_MSG_ERROR([Invalid target processor "$target_cpu"]) ;; esac AC_SUBST(DLL_ENTRY) AM_CONDITIONAL(TARGET_X86_64, [test $target_cpu = "x86_64"]) +AM_CONDITIONAL(TARGET_AARCH64, [test $target_cpu = "aarch64"]) AC_ARG_ENABLE(doc, [AS_HELP_STRING([--disable-doc], [do not build documentation])],, diff --git a/winsup/cygserver/cygserver-config b/winsup/cygserver/cygserver-config index 373bfd2..abda186 100755 --- a/winsup/cygserver/cygserver-config +++ b/winsup/cygserver/cygserver-config @@ -89,7 +89,7 @@ _sys="`uname`" _nt=`expr "${_sys}" : "CYGWIN_NT"` # Check for running cygserver processes first. -if ps -ef | grep -v grep | grep -q ${service_name} +if ps -e | grep -v grep | grep -q ${service_name} then echo echo "There is a cygserver (${service_name}) already running. Nothing to do, apparently." diff --git a/winsup/cygwin/Makefile.am b/winsup/cygwin/Makefile.am index d47a1a2..90a7332 100644 --- a/winsup/cygwin/Makefile.am +++ b/winsup/cygwin/Makefile.am @@ -48,10 +48,11 @@ LIB_NAME=libcygwin.a # sources # -# These objects are included directly into the import library if TARGET_X86_64 TARGET_FILES= \ x86_64/bcopy.S \ + x86_64/fastcwd.cc \ + aarch64/fastcwd.cc \ x86_64/memchr.S \ x86_64/memcpy.S \ x86_64/memmove.S \ @@ -63,6 +64,12 @@ TARGET_FILES= \ x86_64/wmempcpy.S endif +if TARGET_AARCH64 +TARGET_FILES= \ + aarch64/fastcwd.cc +endif + +# These objects are included directly into the import library LIB_FILES= \ lib/_cygwin_crt0_common.cc \ lib/atexit.c \ @@ -76,7 +83,8 @@ LIB_FILES= \ lib/premain1.c \ lib/premain2.c \ lib/premain3.c \ - lib/pseudo-reloc-dummy.c + lib/pseudo-reloc-dummy.c \ + lib/pthreadconst.S FHANDLER_FILES= \ fhandler/base.cc \ @@ -266,6 +274,13 @@ SEC_FILES= \ TZCODE_FILES= \ tzcode/localtime_wrapper.c +if TARGET_X86_64 +UDIS86_FILES= \ + udis86/decode.c \ + udis86/itab.c \ + udis86/udis86.c +endif + DLL_FILES= \ advapi32.cc \ aio.cc \ @@ -306,6 +321,7 @@ DLL_FILES= \ ipc.cc \ kernel32.cc \ ldap.cc \ + lib/pthreadconst.S \ libstdcxx_wrapper.cc \ loadavg.cc \ lsearch.cc \ @@ -388,6 +404,7 @@ libdll_a_SOURCES= \ $(MM_FILES) \ $(SEC_FILES) \ $(TZCODE_FILES) \ + $(UDIS86_FILES) \ $(GENERATED_FILES) # @@ -422,7 +439,7 @@ BUILT_SOURCES = \ # Every time we touch a source file, the version info has to be rebuilt # to maintain a correct build date, especially in uname release output -dirs = $(srcdir) $(srcdir)/fhandler $(srcdir)/lib $(srcdir)/libc $(srcdir)/math $(srcdir)/mm $(srcdir)/regex $(srcdir)/sec $(srcdir)/tzcode +dirs = $(srcdir) $(srcdir)/fhandler $(srcdir)/lib $(srcdir)/libc $(srcdir)/math $(srcdir)/mm $(srcdir)/regex $(srcdir)/sec $(srcdir)/tzcode $(srcdir)/udis86 find_src_files = $(wildcard $(dir)/*.[chS]) $(wildcard $(dir)/*.cc) src_files := $(foreach dir,$(dirs),$(find_src_files)) diff --git a/winsup/cygwin/aarch64/fastcwd.cc b/winsup/cygwin/aarch64/fastcwd.cc new file mode 100644 index 0000000..17ce6bb --- /dev/null +++ b/winsup/cygwin/aarch64/fastcwd.cc @@ -0,0 +1,204 @@ +/* aarch64/fastcwd.cc: find the fast cwd pointer on aarch64 hosts. + + This file is part of Cygwin. + + This software is a copyrighted work licensed under the terms of the + Cygwin license. Please consult the file "CYGWIN_LICENSE" for + details. */ + +/* You might well wonder why this file is included in x86_64 target files + in Makefile.am. It turns out that this code works when built for i686, + x86_64, or aarch64 with just the small #if/#elif block in + GetArm64ProcAddress below caring which. */ + +#include "winsup.h" +#include <assert.h> + +class fcwd_access_t; + +static LPCVOID +GetArm64ProcAddress (HMODULE hModule, LPCSTR procname) +{ + const BYTE *proc = (const BYTE *) GetProcAddress (hModule, procname); +#if defined (__aarch64__) + return proc; +#else +#if defined (__x86_64__) + /* see + https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi#fast-forward-sequences */ + static const BYTE thunk[] = "\x48\x8b\xc4\x48\x89\x58\x20\x55\x5d\xe9"; + /* on windows 11 22000 the thunk is different than documented on that page */ + static const BYTE thunk2[] = "\x48\x8b\xff\x55\x48\x8b\xec\x5d\x90\xe9"; +#else +#error "Unhandled architecture for thunk detection" +#endif + if (proc && (memcmp (proc, thunk, sizeof (thunk) - 1) == 0 || + (sizeof(thunk2) && memcmp (proc, thunk2, sizeof (thunk2) - 1) == 0))) + { + proc += sizeof (thunk) - 1; + proc += 4 + *(const int32_t *) proc; + } + return proc; +#endif +} + +/* these ids and masks, as well as the names of the various other parts of + instructions used in this file, came from + https://developer.arm.com/documentation/ddi0602/2024-09/Index-by-Encoding + (Arm A-profile A64 Instruction Set Architecture) +*/ +#define IS_INSN(pc, name) ((*(pc) & name##_mask) == name##_id) +static const uint32_t add_id = 0x11000000; +static const uint32_t add_mask = 0x7fc00000; +static const uint32_t adrp_id = 0x90000000; +static const uint32_t adrp_mask = 0x9f000000; +static const uint32_t b_id = 0x14000000; +static const uint32_t b_mask = 0xfc000000; +static const uint32_t bl_id = 0x94000000; +static const uint32_t bl_mask = 0xfc000000; +/* matches both cbz and cbnz */ +static const uint32_t cbz_id = 0x34000000; +static const uint32_t cbz_mask = 0x7e000000; +static const uint32_t ldr_id = 0xb9400000; +static const uint32_t ldr_mask = 0xbfc00000; +/* matches both ret and br (which are the same except ret is a 'hint' that + it's a subroutine return */ +static const uint32_t ret_id = 0xd61f0000; +static const uint32_t ret_mask = 0xffbffc1f; + +/* this would work for either bl or b, but we only use it for bl */ +static inline LPCVOID +extract_bl_target (const uint32_t *pc) +{ + assert (IS_INSN (pc, bl) || IS_INSN (pc, b)); + int32_t offset = *pc & ~bl_mask; + /* sign extend */ + if (offset & (1 << 25)) + offset |= bl_mask; + /* Note uint32_t * artithmatic will implicitly multiply the offset by 4 */ + return pc + offset; +} + +static inline uint64_t +extract_adrp_address (const uint32_t *pc) +{ + assert (IS_INSN (pc, adrp)); + uint64_t adrp_base = (uint64_t) pc & ~0xFFF; + int64_t adrp_imm = (*pc >> (5+19+5)) & 0x3; + adrp_imm |= ((*pc >> 5) & 0x7FFFF) << 2; + /* sign extend */ + if (adrp_imm & (1 << 20)) + adrp_imm |= ~((1 << 21) - 1); + adrp_imm <<= 12; + return adrp_base + adrp_imm; +} + +/* This function scans the code in ntdll.dll to find the address of the + global variable used to access the CWD. While the pointer is global, + it's not exported from the DLL, unfortunately. Therefore we have to + use some knowledge to figure out the address. */ + +fcwd_access_t ** +find_fast_cwd_pointer_aarch64 () +{ + /* Fetch entry points of relevant functions in ntdll.dll. */ + HMODULE ntdll = GetModuleHandle ("ntdll.dll"); + if (!ntdll) + return NULL; + LPCVOID get_dir = GetArm64ProcAddress (ntdll, "RtlGetCurrentDirectory_U"); + LPCVOID ent_crit = GetArm64ProcAddress (ntdll, "RtlEnterCriticalSection"); + if (!get_dir || !ent_crit) + return NULL; + + LPCVOID use_cwd = NULL; + const uint32_t *start = (const uint32_t *) get_dir; + const uint32_t *pc = start; + /* find the call to RtlpReferenceCurrentDirectory, and get its address */ + for (; pc < start + 20 && !IS_INSN (pc, ret) && !IS_INSN (pc, b); pc++) + { + if (IS_INSN (pc, bl)) + { + use_cwd = extract_bl_target (pc); + break; + } + } + if (!use_cwd) + return NULL; + + start = pc = (const uint32_t *) use_cwd; + + const uint32_t *ldrpc = NULL; + uint32_t ldroffset, ldrsz; + uint32_t ldrrn, ldrrd; + + /* find the ldr (immediate unsigned offset) for RtlpCurDirRef */ + for (; pc < start + 20 && !IS_INSN (pc, ret) && !IS_INSN (pc, b); pc++) + { + if (IS_INSN (pc, ldr)) + { + ldrpc = pc; + ldrsz = (*pc & 0x40000000); + ldroffset = (*pc >> (5+5)) & 0xFFF; + ldroffset <<= ldrsz ? 3 : 2; + ldrrn = (*pc >> 5) & 0x1F; + ldrrd = *pc & 0x1F; + break; + } + } + if (ldrpc == NULL) + return NULL; + + /* the next instruction after the ldr should be checking if it was NULL: + either a compare and branch if zero or not zero (hence why cbz_mask is 7e + instead of 7f) */ + if (!IS_INSN (pc + 1, cbz) || (*(pc + 1) & 0x1F) != ldrrd + || (*(pc + 1) & 0x80000000) != (ldrsz << 1)) + return NULL; + + /* work backwards, find a bl to RtlEnterCriticalSection whose argument + is the fast peb lock */ + + for (pc = ldrpc; pc >= start; pc--) + { + if (IS_INSN (pc, bl) && extract_bl_target (pc) == ent_crit) + break; + } + uint32_t addoffset; + uint32_t addrn; + for (; pc >= start; pc--) + { + if (IS_INSN (pc, add) && (*pc & 0x1F) == 0) + { + addoffset = (*pc >> (5+5)) & 0xFFF; + addrn = (*pc >> 5) & 0x1F; + break; + } + } + PRTL_CRITICAL_SECTION lockaddr = NULL; + for (; pc >= start; pc--) + { + if (IS_INSN (pc, adrp) && (*pc & 0x1F) == addrn) + { + lockaddr = (PRTL_CRITICAL_SECTION) (extract_adrp_address (pc) + + addoffset); + break; + } + } + if (lockaddr != NtCurrentTeb ()->Peb->FastPebLock) + return NULL; + + /* work backwards from the ldr to find the corresponding adrp */ + fcwd_access_t **RtlpCurDirRef = NULL; + for (pc = ldrpc; pc >= start; pc--) + { + if (IS_INSN (pc, adrp) && (*pc & 0x1F) == ldrrn) + { + RtlpCurDirRef = (fcwd_access_t **) (extract_adrp_address (pc) + + ldroffset); + break; + } + } + + return RtlpCurDirRef; +} + diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 35b207e..d5d344d 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -525,6 +525,8 @@ LoadDLLfunc (CoInitialize, ole32) LoadDLLfunc (CoUninitialize, ole32) LoadDLLfunc (CoTaskMemFree, ole32) +LoadDLLfunc (EnumProcessModules, psapi) + LoadDLLfunc (LsaConnectUntrusted, secur32) LoadDLLfunc (LsaDeregisterLogonProcess, secur32) LoadDLLfunc (LsaFreeReturnBuffer, secur32) diff --git a/winsup/cygwin/create_posix_thread.cc b/winsup/cygwin/create_posix_thread.cc index 8e06099..17bb607 100644 --- a/winsup/cygwin/create_posix_thread.cc +++ b/winsup/cygwin/create_posix_thread.cc @@ -75,7 +75,7 @@ pthread_wrapper (PVOID arg) /* Initialize new _cygtls. */ _my_tls.init_thread (wrapper_arg.stackbase - __CYGTLS_PADSIZE__, (DWORD (*)(void*, void*)) wrapper_arg.func); -#ifdef __x86_64__ +#if defined(__x86_64__) __asm__ ("\n\ leaq %[WRAPPER_ARG], %%rbx # Load &wrapper_arg into rbx \n\ movq (%%rbx), %%r12 # Load thread func into r12 \n\ @@ -99,6 +99,23 @@ pthread_wrapper (PVOID arg) call *%%r12 # Call thread func \n" : : [WRAPPER_ARG] "o" (wrapper_arg), [CYGTLS] "i" (__CYGTLS_PADSIZE__)); +#elif defined(__aarch64__) + /* Sets up a new thread stack, frees the original OS stack, + * and calls the thread function with its arg using AArch64 ABI. */ + __asm__ __volatile__ ("\n\ + ldp x20, x21, [%[WRAPPER_ARG]] // x20 = thread func, x21 = thread arg \n\ + ldp x0, x1, [%[WRAPPER_ARG], #16] // x0 = stackaddr, x1 = stackbase \n\ + sub sp, x1, %[CYGTLS] // sp = stackbase - (CYGTLS) \n\ + mov fp, xzr // clear frame pointer (x29) \n\ + // x0 already has stackaddr \n\ + mov x1, xzr // x1 = 0 (dwSize) \n\ + mov x2, #0x8000 // x2 = MEM_RELEASE \n\ + bl VirtualFree // free original stack \n\ + mov x0, x21 // Move arg into x0 \n\ + blr x20 // call thread function \n" + : : [WRAPPER_ARG] "r" (&wrapper_arg), + [CYGTLS] "r" (__CYGTLS_PADSIZE__) + : "x0", "x1", "x2", "x20", "x21", "x29", "memory"); #else #error unimplemented for this target #endif @@ -206,7 +223,7 @@ class thread_allocator public: thread_allocator () : current (THREAD_STORAGE_HIGH) { - alloc_func = wincap.has_extended_mem_api () ? &_alloc : &_alloc_old; + alloc_func = wincap.has_extended_mem_api () ? &thread_allocator::_alloc : &thread_allocator::_alloc_old; } PVOID alloc (SIZE_T size) { diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index deac201..d7a17b2 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -179,18 +179,25 @@ acl_from_mode NOSIGFE acl_from_text SIGFE acl_get_entry NOSIGFE acl_get_fd SIGFE +acl_get_fd_np SIGFE acl_get_file SIGFE +acl_get_link_np SIGFE acl_get_perm NOSIGFE +acl_get_perm_np = acl_get_perm NOSIGFE acl_get_permset NOSIGFE acl_get_qualifier SIGFE acl_get_tag_type NOSIGFE acl_init SIGFE +acl_is_trivial_np SIGFE acl_set_fd SIGFE +acl_set_fd_np SIGFE acl_set_file SIGFE +acl_set_link_np SIGFE acl_set_permset NOSIGFE acl_set_qualifier NOSIGFE acl_set_tag_type NOSIGFE acl_size NOSIGFE +acl_strip_np SIGFE acl_to_any_text SIGFE acl_to_text SIGFE acl_valid NOSIGFE diff --git a/winsup/cygwin/cygwin.sc.in b/winsup/cygwin/cygwin.sc.in index 69526f5..5007a36 100644 --- a/winsup/cygwin/cygwin.sc.in +++ b/winsup/cygwin/cygwin.sc.in @@ -17,7 +17,7 @@ SECTIONS *(SORT(.text$*)) *(.glue_7t) *(.glue_7) -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__aarch64__) . = ALIGN(8); ___CTOR_LIST__ = .; __CTOR_LIST__ = .; LONG (-1); LONG (-1); *(SORT(.ctors.*)); *(.ctors); *(.ctor); LONG (0); LONG (0); diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index f4c09be..69c233c 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -1030,7 +1030,7 @@ _dll_crt0 () PVOID stackaddr = create_new_main_thread_stack (allocationbase); if (stackaddr) { -#ifdef __x86_64__ +#if defined(__x86_64__) /* Set stack pointer to new address. Set frame pointer to stack pointer and subtract 32 bytes for shadow space. */ __asm__ ("\n\ @@ -1038,6 +1038,13 @@ _dll_crt0 () movq %%rsp, %%rbp \n\ subq $32,%%rsp \n" : : [ADDR] "r" (stackaddr)); +#elif defined(__aarch64__) + /* Set stack and frame pointers to new address. */ + __asm__ ("\n\ + mov fp, %[ADDR] \n\ + mov sp, fp \n" + : : [ADDR] "r" (stackaddr) + : "memory"); #else #error unimplemented for this target #endif diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index fb70524..e06616d 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -7,6 +7,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include "winsup.h" +#include <psapi.h> #include <stdlib.h> #include <dlfcn.h> #include <ctype.h> @@ -194,9 +195,8 @@ dlopen (const char *name, int flags) break; } - DWORD gmheflags = (flags & RTLD_NODELETE) - ? GET_MODULE_HANDLE_EX_FLAG_PIN - : 0; + DWORD nodelete = (flags & RTLD_NODELETE) ? GET_MODULE_HANDLE_EX_FLAG_PIN + : 0; tmp_pathbuf tp; /* single one per stack frame */ tmp_pathbuf_allocator allocator (tp); @@ -267,7 +267,7 @@ dlopen (const char *name, int flags) if (flags & RTLD_NOLOAD) { - GetModuleHandleExW (gmheflags, wpath, (HMODULE *) &ret); + GetModuleHandleExW (nodelete, wpath, (HMODULE *) &ret); if (ret) break; } @@ -276,13 +276,29 @@ dlopen (const char *name, int flags) /* reference counting */ if (ret) { - dll *d = dlls.find (ret); + dll *d = dlls.find (ret, true); if (d) - ++d->count; + { + /* count == INT_MIN is used to specify RTLD_NODELETE */ + if (d->count == INT_MIN || nodelete) + d->count = INT_MIN; + else + ++d->count; + } + else + { + /* All Cygwin DLLs loaded or linked into this process get a dll + record when they call dll_dllcrt0 on init. So if we don't + find the dll it's a native DLL. Add it as DLL_NATIVE. + Simply restore the LoadLibrary count after fork. Don't care + where they are loaded to, don't try to fix up their data and + bss segments after fork, and don't run dtors. */ + dlls.alloc ((HMODULE) ret, user_data, DLL_NATIVE); + } } - if (ret && gmheflags) - GetModuleHandleExW (gmheflags, wpath, (HMODULE *) &ret); + if (ret && nodelete) + GetModuleHandleExW (nodelete, wpath, (HMODULE *) &ret); if (!ret) __seterrno (); @@ -303,32 +319,18 @@ dlsym (void *handle, const char *name) if (handle == RTLD_DEFAULT) { /* search all modules */ - PDEBUG_BUFFER buf; - NTSTATUS status; + HMODULE *modules; + tmp_pathbuf tp; + DWORD size; - buf = RtlCreateQueryDebugBuffer (0, FALSE); - if (!buf) - { - set_errno (ENOMEM); - set_dl_error ("dlsym"); - return NULL; - } - status = RtlQueryProcessDebugInformation (GetCurrentProcessId (), - PDI_MODULES, buf); - if (!NT_SUCCESS (status)) - __seterrno_from_nt_status (status); + modules = (HMODULE *) tp.w_get (); + if (!EnumProcessModules (GetCurrentProcess (), modules, + 2 * NT_MAX_PATH, &size)) + __seterrno (); else - { - PDEBUG_MODULE_ARRAY mods = (PDEBUG_MODULE_ARRAY) - buf->ModuleInformation; - for (ULONG i = 0; i < mods->Count; ++i) - if ((ret = (void *) - GetProcAddress ((HMODULE) mods->Modules[i].Base, name))) - break; - if (!ret) - set_errno (ENOENT); - } - RtlDestroyQueryDebugBuffer (buf); + for (uint32_t i = 0; i < size / sizeof (HMODULE); ++i) + if ((ret = (void *) GetProcAddress (modules[i], name))) + break; } else { @@ -348,16 +350,21 @@ dlclose (void *handle) int ret = 0; if (handle != GetModuleHandle (NULL)) { - /* reference counting */ - dll *d = dlls.find (handle); - if (!d || d->count <= 0) + /* Reference counting. + count == INT_MIN is used to specify RTLD_NODELETE */ + dll *d = dlls.find (handle, true); + if (!d || (d->count <= 0 && d->count != INT_MIN)) { errno = ENOENT; ret = -1; } - else + else if (d->count != INT_MIN) { --d->count; + /* Native DLLs don't call cygwin_detach_dll so they have to be + detached explicitely. */ + if (d->type == DLL_NATIVE && d->count <= 0) + dlls.detach (handle); if (!FreeLibrary ((HMODULE) handle)) { __seterrno (); @@ -388,7 +395,8 @@ extern "C" int dladdr (const void *addr, Dl_info *info) { HMODULE hModule; - BOOL ret = GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + BOOL ret = GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT| + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR) addr, &hModule); if (!ret) @@ -400,14 +408,16 @@ dladdr (const void *addr, Dl_info *info) /* Get the module filename. This pathname may be in short-, long- or //?/ format, depending on how it was specified when loaded, but we assume this is always an absolute pathname. */ - WCHAR fname[MAX_PATH]; - DWORD length = GetModuleFileNameW (hModule, fname, MAX_PATH); - if ((length == 0) || (length == MAX_PATH)) + tmp_pathbuf tp; + PWCHAR fname = tp.w_get (); + DWORD length = GetModuleFileNameW (hModule, fname, NT_MAX_PATH); + if ((length == 0) || (length == NT_MAX_PATH)) return 0; /* Convert to a cygwin pathname */ + static_assert (sizeof (info->dli_fname) == PATH_MAX); ssize_t conv = cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, fname, - info->dli_fname, MAX_PATH); + info->dli_fname, PATH_MAX); if (conv) return 0; diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 1a04751..1369165 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -314,7 +314,8 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) /* Already loaded? For linked DLLs, only compare the basenames. Linked DLLs are loaded using just the basename and the default DLL search path. The Windows loader picks up the first one it finds. - This also applies to cygwin1.dll and the main-executable (DLL_SELF). + This also applies to cygwin1.dll and the main-executable (DLL_SELF) + and native DLLs (DLL_NATIVE). When in_load_after_fork, dynamically loaded dll's are reloaded using their parent's forkable_ntname, if available. */ dll *d = (type != DLL_LOAD) ? dlls.find_by_modname (modname) : @@ -346,7 +347,6 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) { size_t forkntsize = forkable_ntnamesize (type, ntname, modname); - /* FIXME: Change this to new at some point. */ d = (dll *) cmalloc (HEAP_2_DLL, sizeof (*d) + ((ntnamelen + forkntsize) * sizeof (*ntname))); @@ -356,14 +356,20 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) d->modname = d->ntname + (modname - ntname); d->handle = h; d->count = 0; /* Reference counting performed in dlopen/dlclose. */ - /* DLL_SELF dtors (main-executable, cygwin1.dll) are run elsewhere */ - d->has_dtors = type != DLL_SELF; + /* DLL_SELF dtors (main-executable, cygwin1.dll) are run elsewhere, + DLL_NATIVE dtors whereever native DLLs do it. */ + d->has_dtors = (type == DLL_LINK || type == DLL_LOAD); d->p = p; d->ndeps = 0; d->deps = NULL; d->image_size = ((pefile*)h)->optional_hdr ()->SizeOfImage; d->preferred_base = (void*) ((pefile*)h)->optional_hdr()->ImageBase; d->type = type; + if (type == DLL_NATIVE) + { + d->count = 1; + reload_on_fork = 1; + } d->fii.IndexNumber.QuadPart = -1LL; if (!forkntsize) d->forkable_ntname = NULL; @@ -541,8 +547,10 @@ dll_list::topsort_visit (dll* d, bool seek_tail) } +/* If called from dlopen/dlclose, from_dlfcn is true and we return any dll if + the address matches. Otherwise we only want DLL_LINK and DLL_LOAD dlls. */ dll * -dll_list::find (void *retaddr) +dll_list::find (void *retaddr, bool from_dlfcn) { MEMORY_BASIC_INFORMATION m; if (!VirtualQuery (retaddr, &m, sizeof m)) @@ -551,7 +559,8 @@ dll_list::find (void *retaddr) dll *d = &start; while ((d = d->next)) - if (d->type != DLL_SELF && d->handle == h) + if ((from_dlfcn || d->type == DLL_LINK || d->type == DLL_LOAD) + && d->handle == h) break; return d; } @@ -569,12 +578,16 @@ dll_list::detach (void *retaddr) guard (true); if ((d = find (retaddr))) { - /* Ensure our exception handler is enabled for destructors */ - exception protect; - /* Call finalize function if we are not already exiting */ - if (!exit_state) - __cxa_finalize (d->handle); - d->run_dtors (); + /* Only run dtors for Cygwin DLLs. */ + if (d->type == DLL_LINK || d->type == DLL_LOAD) + { + /* Ensure our exception handler is enabled for destructors */ + exception protect; + /* Call finalize function if we are not already exiting */ + if (!exit_state) + __cxa_finalize (d->handle); + d->run_dtors (); + } d->prev->next = d->next; if (d->next) d->next->prev = d->prev; @@ -596,8 +609,9 @@ dll_list::init () /* Walk the dll chain, initializing each dll */ dll *d = &start; dll_global_dtors_recorded = d->next != NULL; + /* Init linked and early loaded Cygwin DLLs. */ while ((d = d->next)) - if (d->type != DLL_SELF) /* linked and early loaded dlls */ + if (d->type == DLL_LINK || d->type == DLL_LOAD) d->init (); } @@ -619,7 +633,7 @@ dll_list::track_self () static PVOID reserve_at (PCWCHAR name, PVOID here, PVOID dll_base, DWORD dll_size) { - DWORD size; + SIZE_T size; MEMORY_BASIC_INFORMATION mb; if (!VirtualQuery (here, &mb, sizeof (mb))) @@ -684,7 +698,10 @@ dll_list::load_after_fork (HANDLE parent) in_load_after_fork = true; if (reload_on_fork) - load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0); + { + load_after_fork_impl (parent, dlls.istart (DLL_NATIVE), 0); + load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0); + } track_self (); in_load_after_fork = false; } @@ -709,7 +726,7 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries) the LoadLibraryExW call unconditional. */ for ( ; d; d = dlls.inext ()) - if (d->handle != d->preferred_base) + if (hold_type == DLL_LOAD && d->handle != d->preferred_base) { /* See if the DLL will load in proper place. If not, unload it, reserve the memory around it, and try again. @@ -757,9 +774,11 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries) interim mapping (for rebased dlls) . The dll list is sorted in dependency order, so we shouldn't pull in any additional dlls outside our control. */ - for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ()) + for (dll *d = dlls.istart (hold_type); d; d = dlls.inext ()) { - if (d->handle == d->preferred_base) + if (hold_type == DLL_NATIVE) + /* just LoadLibrary... */; + else if (d->handle == d->preferred_base) { if (!VirtualFree (d->handle, 0, MEM_RELEASE)) fabort ("unable to release protective reservation for %W (%p), %E", @@ -782,9 +801,19 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries) if (h != d->handle) fabort ("unable to map %W (using %W) to same address as parent: %p != %p", d->ntname, buffered_shortname (d->forkedntname ()), d->handle, h); - /* Fix OS reference count. */ - for (int cnt = 1; cnt < d->count; ++cnt) - LoadLibraryW (buffered_shortname (d->forkedntname ())); + /* Fix OS reference count. + count == INT_MIN is used to specify RTLD_NODELETE. If so, we don't + have to call LoadLibraryW count times, just mark the DLL as pinned. */ + if (d->count == INT_MIN) /* RTLD_NODELETE */ + { + HMODULE hm; + GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_PIN, + buffered_shortname (d->forkedntname ()), + &hm); + } + else + for (int cnt = 1; cnt < d->count; ++cnt) + LoadLibraryW (buffered_shortname (d->forkedntname ())); } } diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 7303f7e..f1832a1 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -326,11 +326,7 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle) if (CTTY_IS_VALID (myself->ctty)) dev.parse (myself->ctty); else - { - dev.parse (FH_CONSOLE); - CloseHandle (handle); - handle = INVALID_HANDLE_VALUE; - } + dev.parse (FH_CONSOLE); } else if (GetCommState (handle, &dcb)) /* FIXME: Not right - assumes ttyS0 */ diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 2e25aa2..f79978f 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -440,7 +440,7 @@ cygwin_exception::dumpstack () } bool -_cygtls::inside_kernel (CONTEXT *cx) +_cygtls::inside_kernel (CONTEXT *cx, bool inside_cygwin) { int res; MEMORY_BASIC_INFORMATION m; @@ -462,6 +462,8 @@ _cygtls::inside_kernel (CONTEXT *cx) else if (h == hntdll) res = true; /* Calling GetModuleFilename on ntdll.dll can hang */ + else if (h == cygwin_hmodule && inside_cygwin) + res = true; else if (h == user_data->hmodule) res = false; else if (!GetModuleFileNameW (h, checkdir, @@ -595,7 +597,7 @@ try_to_debug () { extern void break_here (); break_here (); - return 1; + return 0; } /* Otherwise, invoke the JIT debugger, if set */ @@ -659,7 +661,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, /* If we're exiting, tell Windows to keep looking for an exception handler. */ - if (exit_state || e->ExceptionFlags) + if (exit_state || (e->ExceptionFlags & ~EXCEPTION_SOFTWARE_ORIGINATE)) return ExceptionContinueSearch; siginfo_t si = {}; @@ -810,6 +812,8 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, else if (try_to_debug ()) { debugging = 1; + /* If a JIT debugger just attached, replay the exception for the benefit + of that */ return ExceptionContinueExecution; } @@ -912,6 +916,24 @@ sig_handle_tty_stop (int sig, siginfo_t *, void *) } } /* end extern "C" */ +#ifdef __x86_64__ +static LONG CALLBACK +singlestep_handler (EXCEPTION_POINTERS *ep) +{ + if (_my_tls.suspend_on_exception) + { + _my_tls.in_singlestep_handler = true; + RtlWakeAddressSingle ((void *) &_my_tls.in_singlestep_handler); + while (_my_tls.suspend_on_exception) + ; /* Don't call yield() to prevent the thread + from being suspended in the kernel. */ + if (ep->ExceptionRecord->ExceptionCode == (DWORD) STATUS_SINGLE_STEP) + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + bool _cygtls::interrupt_now (CONTEXT *cx, siginfo_t& si, void *handler, struct sigaction& siga) @@ -925,6 +947,44 @@ _cygtls::interrupt_now (CONTEXT *cx, siginfo_t& si, void *handler, interrupted = false; else { +#ifdef __x86_64__ + /* When the Rip points to an instruction that causes an exception, + modifying Rip and calling ResumeThread() may sometimes result in + a crash. To prevent this, advance execution by a single instruction + by setting the trap flag (TF) before calling ResumeThread(). This + will trigger either STATUS_SINGLE_STEP or the exception caused by + the instruction that Rip originally pointed to. By suspending the + targeted thread within singlestep_handler(), Rip no longer points + to the problematic instruction, allowing safe handling of the + interrupt. As a result, Rip can be adjusted appropriately, + and the thread can resume execution without unexpected crashes. */ + if (!inside_kernel (cx, true)) + { + HANDLE h_veh = AddVectoredExceptionHandler (0, singlestep_handler); + cx->EFlags |= 0x100; /* Set TF (setup single step execution) */ + SetThreadContext (*this, cx); + suspend_on_exception = true; + in_singlestep_handler = false; + bool bool_false = false; + NTSTATUS status = STATUS_SUCCESS; + ResumeThread (*this); + while (!in_singlestep_handler && NT_SUCCESS (status)) + { + LARGE_INTEGER timeout; + timeout.QuadPart = -100000ULL; /* 10ms */ + status = RtlWaitOnAddress (&in_singlestep_handler, &bool_false, + sizeof (bool), &timeout); + if (status == STATUS_TIMEOUT) + break; + } + SuspendThread (*this); + GetThreadContext (*this, cx); + RemoveVectoredExceptionHandler (h_veh); + suspend_on_exception = false; + if (!NT_SUCCESS (status) || status == STATUS_TIMEOUT) + return false; /* Not interrupted */ + } +#endif DWORD64 &ip = cx->_CX_instPtr; push (ip); interrupt_setup (si, handler, siga); @@ -1281,6 +1341,7 @@ set_process_mask_delta () else oldmask = _my_tls.sigmask; newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE; + _my_tls.deltamask = 0; sigproc_printf ("oldmask %lx, newmask %lx, deltamask %lx", oldmask, newmask, _my_tls.deltamask); _my_tls.sigmask = newmask; @@ -1503,12 +1564,15 @@ sigpacket::process () if (tl_entry) { tls = tl_entry->thread; + tl_entry->thread->lock (); if (sigismember (&tls->sigwait_mask, si.si_signo)) issig_wait = true; - else if (!sigismember (&tls->sigmask, si.si_signo)) + else if (!sigismember (&tls->sigmask, si.si_signo) + && !sigismember (&tls->deltamask, si.si_signo)) issig_wait = false; else tls = NULL; + tl_entry->thread->unlock (); } } @@ -1756,7 +1820,7 @@ _cygtls::call_signal_handler () int this_errno = saved_errno; reset_signal_arrived (); - incyg = false; + incyg = 0; current_sig = 0; /* Flag that we can accept another signal */ /* We have to fetch the original return address from the signal stack @@ -1791,6 +1855,13 @@ _cygtls::call_signal_handler () to 16 byte. */ uintptr_t new_sp = ((uintptr_t) _my_tls.altstack.ss_sp + _my_tls.altstack.ss_size) & ~0xf; + /* Copy context1 to the alternate signal stack area, because the + context1 allocated in the normal stack area is not accessible + from the signal handler that uses alternate signal stack. */ + thiscontext = (ucontext_t *) ((new_sp - sizeof (ucontext_t)) & ~0xf); + memcpy (thiscontext, &context1, sizeof (ucontext_t)); + new_sp = (uintptr_t) thiscontext; + /* In assembler: Save regs on new stack, move to alternate stack, call thisfunc, revert stack regs. */ #ifdef __x86_64__ @@ -1834,6 +1905,7 @@ _cygtls::call_signal_handler () #else #error unimplemented for this target #endif + memcpy (&context1, thiscontext, sizeof (ucontext_t)); } else /* No alternate signal stack requested or available, just call @@ -1861,7 +1933,7 @@ _cygtls::call_signal_handler () } unlock (); - incyg = true; + incyg = 1; set_signal_mask (_my_tls.sigmask, (this_sa_flags & SA_SIGINFO) ? context1.uc_sigmask : this_oldmask); diff --git a/winsup/cygwin/fhandler/base.cc b/winsup/cygwin/fhandler/base.cc index a5d15c7..6c95e2b 100644 --- a/winsup/cygwin/fhandler/base.cc +++ b/winsup/cygwin/fhandler/base.cc @@ -526,8 +526,9 @@ fhandler_base::open (int flags, mode_t mode) ULONG file_attributes = 0; ULONG shared = (get_major () == DEV_TAPE_MAJOR ? 0 : FILE_SHARE_VALID_FLAGS); ULONG create_disposition; + FILE_BASIC_INFORMATION fbi; OBJECT_ATTRIBUTES attr; - IO_STATUS_BLOCK io; + IO_STATUS_BLOCK io, io_bi; NTSTATUS status; PFILE_FULL_EA_INFORMATION p = NULL; ULONG plen = 0; @@ -719,16 +720,35 @@ fhandler_base::open (int flags, mode_t mode) goto done; } - if (io.Information == FILE_CREATED) + if (get_device () == FH_FS) { - /* Correct file attributes are needed for later use in, e.g. fchmod. */ - FILE_BASIC_INFORMATION fbi; - - if (!NT_SUCCESS (NtQueryInformationFile (fh, &io, &fbi, sizeof fbi, + /* Fix up file attributes, they are desperately needed later. + + Originally we only did that in the FILE_CREATED case below, but that's + insufficient: + + If two threads try to create the same file at the same time, it's + possible that path_conv::check returns the file as non-existant, i. e., + pc.file_attributes () returns INVALID_FILE_ATTRIBUTES, 0xffffffff. + However, one of the NtCreateFile will beat the other, so only one of + them returns with FILE_CREATED. + + The other fhandler_base::open() will instead run into the O_TRUNC + conditional (further below), blindly check for the SPARSE attribute + and remove that bit. The result is that the attributes will be + 0xfffffdff, i.e., everything but SPARSE. Most annoying is that + pc.isdir() will return TRUE. Hilarity ensues. + + Note that we use a different IO_STATUS_BLOCK, so as not to overwrite + io.Information... */ + if (!NT_SUCCESS (NtQueryInformationFile (fh, &io_bi, &fbi, sizeof fbi, FileBasicInformation))) fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE; pc.file_attributes (fbi.FileAttributes); + } + if (io.Information == FILE_CREATED) + { /* Always create files using a NULL SD. Create correct permission bits afterwards, maintaining the owner and group information just like chmod. This is done for two reasons. @@ -752,18 +772,17 @@ fhandler_base::open (int flags, mode_t mode) set_created_file_access (fh, pc, mode); } - /* If you O_TRUNC a file on Linux, the data is truncated, but the EAs are - preserved. If you open a file on Windows with FILE_OVERWRITE{_IF} or - FILE_SUPERSEDE, all streams are truncated, including the EAs. So we don't - use the FILE_OVERWRITE{_IF} flags, but instead just open the file and set - the size of the data stream explicitely to 0. Apart from being more Linux - compatible, this implementation has the pleasant side-effect to be more - than 5% faster than using FILE_OVERWRITE{_IF} (tested on W7 32 bit). */ if ((flags & O_TRUNC) && (flags & O_ACCMODE) != O_RDONLY && io.Information != FILE_CREATED && get_device () == FH_FS) { + /* If you O_TRUNC a file on Linux, the data is truncated, but the EAs are + preserved. If you open a file on Windows with FILE_OVERWRITE{_IF} or + FILE_SUPERSEDE, all streams are truncated, including the EAs. So we + don't use FILE_OVERWRITE{_IF} but just open the file and truncate the + data stream to size 0. Apart from being more Linux compatible, this + has the pleasant side-effect to be more than 5% faster. */ FILE_END_OF_FILE_INFORMATION feofi = { EndOfFile:{ QuadPart:0 } }; status = NtSetInformationFile (fh, &io, &feofi, sizeof feofi, FileEndOfFileInformation); diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc index f162698..887e2ef 100644 --- a/winsup/cygwin/fhandler/console.cc +++ b/winsup/cygwin/fhandler/console.cc @@ -509,7 +509,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) case not_signalled_but_done: case done_with_debugger: processed = true; - ttyp->output_stopped = false; + ttyp->output_stopped &= ~BY_VSTOP; if (ti.c_lflag & NOFLSH) goto remove_record; con.num_processed = 0; @@ -771,6 +771,8 @@ fhandler_console::setup () con.disable_master_thread = true; con.master_thread_suspended = false; con.num_processed = 0; + con.curr_input_mode = tty::restore; + con.curr_output_mode = tty::restore; } } @@ -829,7 +831,7 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t, break; case tty::cygwin: flags |= ENABLE_WINDOW_INPUT; - if (con.master_thread_suspended) + if (con.master_thread_suspended || con.disable_master_thread) flags |= ENABLE_PROCESSED_INPUT; if (wincap.has_con_24bit_colors () && !con_is_legacy) flags |= ENABLE_VIRTUAL_TERMINAL_INPUT; @@ -849,11 +851,6 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t, flags |= ENABLE_PROCESSED_INPUT; break; } - if (con.curr_input_mode != tty::cygwin && m == tty::cygwin) - { - prev_input_mode_backup = con.prev_input_mode; - con.prev_input_mode = oflags; - } con.curr_input_mode = m; SetConsoleMode (p->input_handle, flags); if (!(oflags & ENABLE_VIRTUAL_TERMINAL_INPUT) @@ -893,11 +890,6 @@ fhandler_console::set_output_mode (tty::cons_mode m, const termios *t, flags |= DISABLE_NEWLINE_AUTO_RETURN; break; } - if (con.curr_output_mode != tty::cygwin && m == tty::cygwin) - { - prev_output_mode_backup = con.prev_output_mode; - GetConsoleMode (p->output_handle, &con.prev_output_mode); - } con.curr_output_mode = m; acquire_attach_mutex (mutex_timeout); DWORD resume_pid = attach_console (con.owner); @@ -913,13 +905,14 @@ fhandler_console::setup_for_non_cygwin_app () /* Setting-up console mode for non-cygwin app. */ /* If conmode is set to tty::native for non-cygwin apps in background, tty settings of the shell is reflected - to the console mode of the app. So, use tty::restore - for background process instead. */ - tty::cons_mode conmode = - (get_ttyp ()->getpgid ()== myself->pgid) ? tty::native : tty::restore; - set_input_mode (conmode, &tc ()->ti, get_handle_set ()); - set_output_mode (conmode, &tc ()->ti, get_handle_set ()); - set_disable_master_thread (true, this); + to the console mode of the app. So, do not change the + console mode. */ + if (get_ttyp ()->getpgid () == myself->pgid) + { + set_input_mode (tty::native, &tc ()->ti, get_handle_set ()); + set_output_mode (tty::native, &tc ()->ti, get_handle_set ()); + set_disable_master_thread (true, this); + } } void @@ -930,12 +923,14 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p) termios *ti = shared_console_info[unit] ? &(shared_console_info[unit]->tty_min_state.ti) : &dummy; /* Cleaning-up console mode for non-cygwin app. */ + set_disable_master_thread (con.owner == GetCurrentProcessId ()); /* conmode can be tty::restore when non-cygwin app is exec'ed from login shell. */ - tty::cons_mode conmode = cons_mode_on_close (); - set_output_mode (conmode, ti, p); - set_input_mode (conmode, ti, p); - set_disable_master_thread (con.owner == GetCurrentProcessId ()); + tty::cons_mode conmode = cons_mode_on_close (p); + if (con.curr_output_mode != conmode) + set_output_mode (conmode, ti, p); + if (con.curr_input_mode != conmode) + set_input_mode (conmode, ti, p); } /* Return the tty structure associated with a given tty number. If the @@ -1128,8 +1123,8 @@ fhandler_console::bg_check (int sig, bool dontsignal) in the same process group. */ if (sig == SIGTTIN && con.curr_input_mode != tty::cygwin) { - set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ()); set_disable_master_thread (false, this); + set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ()); } if (sig == SIGTTOU && con.curr_output_mode != tty::cygwin) set_output_mode (tty::cygwin, &tc ()->ti, get_handle_set ()); @@ -1144,6 +1139,15 @@ fhandler_console::read (void *pv, size_t& buflen) push_process_state process_state (PID_TTYIN); + if (get_ttyp ()->input_stopped && is_nonblocking ()) + { + set_errno (EAGAIN); + buflen = (size_t) -1; + return; + } + while (get_ttyp ()->input_stopped) + cygwait (10); + size_t copied_chars = 0; DWORD timeout = is_nonblocking () ? 0 : @@ -1836,6 +1840,12 @@ fhandler_console::open (int flags, mode_t) handle_set.output_handle = h; release_output_mutex (); + if (con.owner == GetCurrentProcessId ()) + { + GetConsoleMode (get_handle (), &con.prev_input_mode); + GetConsoleMode (get_output_handle (), &con.prev_output_mode); + } + wpbuf.init (); handle_set.input_mutex = input_mutex; @@ -1881,6 +1891,30 @@ fhandler_console::open (int flags, mode_t) setenv ("TERM", "cygwin", 1); } + HANDLE h_in = GetStdHandle (STD_INPUT_HANDLE); + HANDLE h_out = GetStdHandle (STD_OUTPUT_HANDLE); + HANDLE h_err = GetStdHandle (STD_ERROR_HANDLE); + + DWORD dummy; + bool in_is_console = GetConsoleMode (h_in, &dummy); + bool out_is_console = + GetConsoleMode (h_out, &dummy) || GetConsoleMode (h_err, &dummy); + if (in_is_console) + CloseHandle (h_in); + + if (in_is_console && con.curr_input_mode != tty::cygwin) + { + prev_input_mode_backup = con.prev_input_mode; + GetConsoleMode (get_handle (), &con.prev_input_mode); + set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); + } + if (out_is_console && con.curr_output_mode != tty::cygwin) + { + prev_output_mode_backup = con.prev_output_mode; + GetConsoleMode (get_output_handle (), &con.prev_output_mode); + set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); + } + debug_printf ("opened conin$ %p, conout$ %p", get_handle (), get_output_handle ()); @@ -1975,8 +2009,8 @@ fhandler_console::post_open_setup (int fd) /* Setting-up console mode for cygwin app started from non-cygwin app. */ if (fd == 0) { - set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); set_disable_master_thread (false, this); + set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); } else if (fd == 1 || fd == 2) set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); @@ -1991,11 +2025,13 @@ fhandler_console::close (int flag) acquire_output_mutex (mutex_timeout); - if (shared_console_info[unit] && myself->ppid == 1 - && (dev_t) myself->ctty == get_device ()) + if (shared_console_info[unit] && (dev_t) myself->ctty == get_device () + && cons_mode_on_close (&handle_set) == tty::restore) { - set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set); - set_input_mode (tty::restore, &get_ttyp ()->ti, &handle_set); + if (con.curr_output_mode != tty::restore) + set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set); + if (con.curr_input_mode != tty::restore) + set_input_mode (tty::restore, &get_ttyp ()->ti, &handle_set); set_disable_master_thread (true, this); } @@ -2131,6 +2167,7 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) release_output_mutex (); return -1; case FIONREAD: + case TIOCINQ: { DWORD n; int ret = 0; @@ -2183,6 +2220,14 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) return 0; } break; + case TCXONC: + res = this->tcflow ((int)(intptr_t) arg); + release_output_mutex (); + return res; + case TCFLSH: + res = this->tcflush ((int)(intptr_t) arg); + release_output_mutex (); + return res; } release_output_mutex (); @@ -2215,6 +2260,10 @@ int fhandler_console::tcsetattr (int a, struct termios const *t) { get_ttyp ()->ti = *t; + if (con.curr_input_mode == tty::cygwin) + set_input_mode (tty::cygwin, t, &handle_set); + if (con.curr_output_mode == tty::cygwin) + set_output_mode (tty::cygwin, t, &handle_set); return 0; } @@ -2980,7 +3029,12 @@ fhandler_console::char_command (char c) if (con.args[i] == 1) /* DECCKM */ con.cursor_key_app_mode = (c == 'h'); if (con.args[i] == 9001) /* win32-input-mode (https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md) */ - set_disable_master_thread (c == 'h', this); + { + set_disable_master_thread (c == 'h', this); + if (con.curr_input_mode == tty::cygwin) + set_input_mode (tty::cygwin, + &tc ()->ti, get_handle_set ()); + } } /* Call fix_tab_position() if screen has been alternated. */ if (need_fix_tab_position) @@ -4170,8 +4224,8 @@ fhandler_console::write (const void *vsrc, size_t len) void fhandler_console::doecho (const void *str, DWORD len) { - bool stopped = get_ttyp ()->output_stopped; - get_ttyp ()->output_stopped = false; + int stopped = get_ttyp ()->output_stopped; + get_ttyp ()->output_stopped = 0; write (str, len); get_ttyp ()->output_stopped = stopped; } @@ -4702,10 +4756,31 @@ fhandler_console::fstat (struct stat *st) } tty::cons_mode -fhandler_console::cons_mode_on_close () +fhandler_console::cons_mode_on_close (handle_set_t *p) { + int unit = p->unit; if (myself->ppid != 1) /* Execed from normal cygwin process. */ return tty::cygwin; + if (!process_alive (con.owner)) /* The Master process already died. */ + return tty::restore; + if (con.owner == GetCurrentProcessId ()) /* Master process */ + return tty::restore; + + PROCESS_BASIC_INFORMATION pbi; + NTSTATUS status = + NtQueryInformationProcess (GetCurrentProcess (), ProcessBasicInformation, + &pbi, sizeof (pbi), NULL); + if (NT_SUCCESS (status) && cygwin_pid (con.owner) + && !process_alive ((DWORD) pbi.InheritedFromUniqueProcessId)) + /* Execed from normal cygwin process and the parent has been exited. */ + return tty::cygwin; + return tty::restore; /* otherwise, restore */ } + +int +fhandler_console::tcdrain () +{ + return 0; +} diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc index ac8bbe7..2312688 100644 --- a/winsup/cygwin/fhandler/pipe.cc +++ b/winsup/cygwin/fhandler/pipe.cc @@ -326,7 +326,6 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) ULONG_PTR nbytes_now = 0; ULONG len1 = (ULONG) (len - nbytes); DWORD select_sem_timeout = 0; - bool real_non_blocking_mode = false; FILE_PIPE_LOCAL_INFORMATION fpli; status = NtQueryInformationFile (get_handle (), &io, @@ -393,7 +392,10 @@ fhandler_pipe::raw_read (void *ptr, size_t& len) status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, ptr, len1, NULL, NULL); if (real_non_blocking_mode) - set_pipe_non_blocking (false); + { + set_pipe_non_blocking (false); + real_non_blocking_mode = false; + } if (isclosed ()) /* A signal handler might have closed the fd. */ { set_errno (EBADF); @@ -443,7 +445,6 @@ ssize_t fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) { size_t nbytes = 0; - ULONG chunk; NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK io; HANDLE evt; @@ -453,7 +454,11 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) return 0; ssize_t avail = pipe_buf_size; - bool real_non_blocking_mode = false; + + /* Workaround for native ninja. Native ninja creates pipe with size == 0, + and starts cygwin process with that pipe. */ + if (avail == 0) + avail = PIPE_BUF; if (pipe_mtx) /* pipe_mtx is NULL in the fifo case */ { @@ -486,14 +491,14 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) FilePipeLocalInformation); if (NT_SUCCESS (status)) { - if (fpli.WriteQuotaAvailable != 0) + if (fpli.WriteQuotaAvailable == fpli.InboundQuota) avail = fpli.WriteQuotaAvailable; - else /* WriteQuotaAvailable == 0 */ + else /* WriteQuotaAvailable != InboundQuota */ { /* Refer to the comment in select.cc: pipe_data_available(). */ /* NtSetInformationFile() in set_pipe_non_blocking(true) seems to fail with STATUS_PIPE_BUSY if the pipe is not empty. - In this case, the pipe is really full if WriteQuotaAvailable - is zero. Otherwise, the pipe is empty. */ + In this case, WriteQuotaAvailable indicates real pipe space. + Otherwise, the pipe is empty. */ status = fh->set_pipe_non_blocking (true); if (NT_SUCCESS (status)) /* Pipe should be empty because reader is waiting for data. */ @@ -501,9 +506,14 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) fh->set_pipe_non_blocking (false); else if (status == STATUS_PIPE_BUSY) { - /* Full */ - set_errno (EAGAIN); - goto err; + if (fpli.WriteQuotaAvailable == 0) + { + /* Full */ + set_errno (EAGAIN); + goto err; + } + avail = fpli.WriteQuotaAvailable; + status = STATUS_SUCCESS; } } } @@ -535,11 +545,6 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) } } - if (len <= (size_t) avail) - chunk = len; - else - chunk = avail; - if (!(evt = CreateEvent (NULL, false, false, NULL))) { __seterrno (); @@ -556,8 +561,8 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) ULONG len1; DWORD waitret = WAIT_OBJECT_0; - if (left > chunk && !is_nonblocking ()) - len1 = chunk; + if (left > (size_t) avail && !is_nonblocking ()) + len1 = (ULONG) avail; else len1 = (ULONG) left; @@ -645,9 +650,7 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) if (io.Information > 0 || len <= PIPE_BUF || short_write_once) break; /* Independent of being blocking or non-blocking, if we're here, - the pipe has less space than requested. If the pipe is a - non-Cygwin pipe, just try the old strategy of trying a half - write. If the pipe has at + the pipe has less space than requested. If the pipe has at least PIPE_BUF bytes available, try to write all matching PIPE_BUF sized blocks. If it's less than PIPE_BUF, try the next less power of 2 bytes. This is not really the Linux @@ -655,12 +658,13 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) in a very implementation-defined way we can't emulate, but it resembles it closely enough to get useful results. */ avail = pipe_data_available (-1, this, get_handle (), PDA_WRITE); - if (avail < 1) /* error or pipe closed */ + if (avail == PDA_UNKNOWN && real_non_blocking_mode) + avail = len1; + else if (avail == 0 || !PDA_NOERROR (avail)) + /* error or pipe closed */ break; if (avail > len1) /* somebody read from the pipe */ avail = len1; - if (avail == 1) /* 1 byte left or non-Cygwin pipe */ - len1 >>= 1; else if (avail >= PIPE_BUF) len1 = avail & ~(PIPE_BUF - 1); else @@ -701,7 +705,10 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len) } if (real_non_blocking_mode) - ((fhandler_pipe *) this)->set_pipe_non_blocking (false); + { + ((fhandler_pipe *) this)->set_pipe_non_blocking (false); + real_non_blocking_mode = false; + } CloseHandle (evt); if (pipe_mtx) /* pipe_mtx is NULL in the fifo case */ diff --git a/winsup/cygwin/fhandler/process.cc b/winsup/cygwin/fhandler/process.cc index 8fae9be..e00cae5 100644 --- a/winsup/cygwin/fhandler/process.cc +++ b/winsup/cygwin/fhandler/process.cc @@ -621,14 +621,39 @@ struct heap_info : heap_vm_chunks (NULL) { PDEBUG_BUFFER buf; + wchar_t mtx_name [32]; + HANDLE mtx; NTSTATUS status; PDEBUG_HEAP_ARRAY harray; + /* We need a global mutex here, because RtlQueryProcessDebugInformation + is neither thread-safe, nor multi-process-safe. If it's called in + parallel on the same process it can crash that process. We can't + avoid this if a non-Cygwin app calls RtlQueryProcessDebugInformation + on the same process in parallel, but we can avoid Cygwin processes + crashing process PID just because they open /proc/PID/maps in parallel + by serializing RtlQueryProcessDebugInformation on the same process. + + Note that the mutex guards the entire code from + RtlCreateQueryDebugBuffer to RtlDestroyQueryDebugBuffer including the + code accessing the debug buffer. Apparently the debug buffer needs + safeguarded against parallel access all the time it's used!!! */ + __small_swprintf (mtx_name, L"cyg-heapinfo-mtx-%u", pid); + mtx = CreateMutexW (&sec_none_nih, FALSE, mtx_name); + if (!mtx) + return; + WaitForSingleObject (mtx, INFINITE); buf = RtlCreateQueryDebugBuffer (16 * 65536, FALSE); + if (buf) + status = RtlQueryProcessDebugInformation (pid, + PDI_HEAPS | PDI_HEAP_BLOCKS, + buf); if (!buf) - return; - status = RtlQueryProcessDebugInformation (pid, PDI_HEAPS | PDI_HEAP_BLOCKS, - buf); + { + ReleaseMutex (mtx); + CloseHandle (mtx); + return; + } if (NT_SUCCESS (status) && (harray = (PDEBUG_HEAP_ARRAY) buf->HeapInformation) != NULL) for (ULONG hcnt = 0; hcnt < harray->Count; ++hcnt) @@ -653,6 +678,8 @@ struct heap_info } } RtlDestroyQueryDebugBuffer (buf); + ReleaseMutex (mtx); + CloseHandle (mtx); } char *fill_if_match (char *base, ULONG type, char *dest) diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index e61a1c8..b882b90 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -1304,6 +1304,15 @@ fhandler_pty_slave::read (void *ptr, size_t& len) push_process_state process_state (PID_TTYIN); + if (get_ttyp ()->input_stopped && is_nonblocking ()) + { + set_errno (EAGAIN); + len = (size_t) -1; + return; + } + while (get_ttyp ()->input_stopped) + cygwait (10); + if (ptr) /* Indicating not tcflush(). */ mask_switch_to_nat_pipe (true, true); @@ -1650,6 +1659,7 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg) retval = this->tcsetpgrp ((pid_t) (intptr_t) arg); goto out; case FIONREAD: + case TIOCINQ: { DWORD n; if (!bytes_available (n)) @@ -1664,6 +1674,12 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg) } } goto out; + case TCXONC: + retval = this->tcflow ((int)(intptr_t) arg); + goto out; + case TCFLSH: + retval = this->tcflush ((int)(intptr_t) arg); + goto out; default: return fhandler_base::ioctl (cmd, arg); } @@ -1933,7 +1949,10 @@ int fhandler_pty_master::open (int flags, mode_t) { if (!setup ()) + { + set_errno (EMFILE); return 0; + } set_open_status (); dwProcessId = GetCurrentProcessId (); return 1; @@ -2339,6 +2358,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) case TIOCSPGRP: return this->tcsetpgrp ((pid_t) (intptr_t) arg); case FIONREAD: + case TIOCINQ: { DWORD n; if (!bytes_available (n)) @@ -2349,6 +2369,10 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) *(int *) arg = (int) n; } break; + case TCXONC: + return this->tcflow ((int)(intptr_t) arg); + case TCFLSH: + return this->tcflush ((int)(intptr_t) arg); default: return fhandler_base::ioctl (cmd, arg); } @@ -4191,3 +4215,12 @@ fhandler_pty_common::resume_from_temporarily_attach (DWORD resume_pid) } release_attach_mutex (); } + +int +fhandler_pty_common::tcdrain () +{ + DWORD n; + while (bytes_available (n) && n > 0) + cygwait (10); + return 0; +} diff --git a/winsup/cygwin/fhandler/socket_inet.cc b/winsup/cygwin/fhandler/socket_inet.cc index 22dfed6..5ed0cb0 100644 --- a/winsup/cygwin/fhandler/socket_inet.cc +++ b/winsup/cygwin/fhandler/socket_inet.cc @@ -20,7 +20,12 @@ #undef u_long #define u_long __ms_u_long #include <w32api/ws2tcpip.h> +/* 2025-06-09: win32api headers v13 now define a cmsghdr type which clashes with + our socket.h. Arrange not to see it here. */ +#undef cmsghdr +#define cmsghdr __ms_cmsghdr #include <w32api/mswsock.h> +#undef cmsghdr #include <w32api/mstcpip.h> #include <netinet/tcp.h> #include <netinet/udp.h> diff --git a/winsup/cygwin/fhandler/socket_local.cc b/winsup/cygwin/fhandler/socket_local.cc index 270a1ef..0498edc 100644 --- a/winsup/cygwin/fhandler/socket_local.cc +++ b/winsup/cygwin/fhandler/socket_local.cc @@ -21,7 +21,12 @@ #define u_long __ms_u_long #include "ntsecapi.h" #include <w32api/ws2tcpip.h> +/* 2025-06-09: win32api headers v13 now define a cmsghdr type which clashes with + our socket.h. Arrange not to see it here. */ +#undef cmsghdr +#define cmsghdr __ms_cmsghdr #include <w32api/mswsock.h> +#undef cmsghdr #include <unistd.h> #include <asm/byteorder.h> #include <sys/socket.h> @@ -87,6 +92,8 @@ get_inet_addr_local (const struct sockaddr *in, int inlen, addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); *outlen = sizeof addr; memcpy (out, &addr, *outlen); + if (type) + *type = SOCK_DGRAM; return 0; } diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/termios.cc index a3cecdb..19d6220 100644 --- a/winsup/cygwin/fhandler/termios.cc +++ b/winsup/cygwin/fhandler/termios.cc @@ -491,16 +491,16 @@ fhandler_termios::process_stop_start (char c, tty *ttyp) { if (CCEQ (ti.c_cc[VSTOP], c)) { - ttyp->output_stopped = true; + ttyp->output_stopped |= BY_VSTOP; return true; } else if (CCEQ (ti.c_cc[VSTART], c)) { restart_output: - ttyp->output_stopped = false; + ttyp->output_stopped &= ~BY_VSTOP; return true; } - else if ((ti.c_iflag & IXANY) && ttyp->output_stopped) + else if ((ti.c_iflag & IXANY) && (ttyp->output_stopped & BY_VSTOP)) goto restart_output; } if ((ti.c_lflag & ICANON) && (ti.c_lflag & IEXTEN) @@ -540,7 +540,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, fallthrough; case not_signalled_but_done: case done_with_debugger: - get_ttyp ()->output_stopped = false; + get_ttyp ()->output_stopped &= ~BY_VSTOP; continue; case not_signalled_with_nat_reader: disable_eof_key = true; @@ -915,3 +915,26 @@ fhandler_termios::get_console_process_id (DWORD pid, bool match, } return res_pri ?: res; } + +int +fhandler_termios::tcflow (int action) +{ + switch (action) + { + case TCOOFF: + get_ttyp ()->output_stopped |= BY_TCFLOW; + return 0; + case TCOON: + get_ttyp ()->output_stopped = 0; + return 0; + case TCIOFF: + get_ttyp ()->input_stopped |= BY_TCFLOW; + return 0; + case TCION: + get_ttyp ()->input_stopped = 0; + return 0; + default: + set_errno (EINVAL); + return -1; + } +} diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 783971b..4abc525 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -187,7 +187,6 @@ frok::child (volatile char * volatile here) ForceCloseHandle1 (fork_info->forker_finished, forker_finished); - pthread::atforkchild (); cygbench ("fork-child"); ld_preload (); fixup_hooks_after_fork (); @@ -199,6 +198,7 @@ frok::child (volatile char * volatile here) CloseHandle (hParent); hParent = NULL; cygwin_finished_initializing = true; + pthread::atforkchild (); return 0; } @@ -660,8 +660,10 @@ dofork (void **proc, bool *with_forkables) ischild = !!setjmp (grouped.ch.jmp); volatile char * volatile stackp; -#ifdef __x86_64__ +#if defined(__x86_64__) __asm__ volatile ("movq %%rsp,%0": "=r" (stackp)); +#elif defined(__aarch64__) + __asm__ volatile ("mov %0, sp" : "=r" (stackp)); #else #error unimplemented for this target #endif diff --git a/winsup/cygwin/include/cygwin/config.h b/winsup/cygwin/include/cygwin/config.h index 2a70832..d9f911d 100644 --- a/winsup/cygwin/include/cygwin/config.h +++ b/winsup/cygwin/include/cygwin/config.h @@ -36,8 +36,13 @@ __attribute__((__gnu_inline__)) extern inline struct _reent *__getreent (void) { register char *ret; -#ifdef __x86_64__ +#if defined(__x86_64__) __asm __volatile__ ("movq %%gs:8,%0" : "=r" (ret)); +#elif defined(__aarch64__) + /* x18 register points to TEB, offset 0x8 points to stack base. + See _TEB structure definition in winsup\cygwin\local_includes\ntdll.h + for more details. */ + __asm __volatile__ ("ldr %0, [x18, #0x8]" : "=r" (ret)); #else #error unimplemented for this target #endif diff --git a/winsup/cygwin/include/cygwin/limits.h b/winsup/cygwin/include/cygwin/limits.h index 204154d..728dfd4 100644 --- a/winsup/cygwin/include/cygwin/limits.h +++ b/winsup/cygwin/include/cygwin/limits.h @@ -43,7 +43,13 @@ details. */ #define __SEM_VALUE_MAX 1147483648 #define __SIGQUEUE_MAX 1024 #define __STREAM_MAX 20 -#define __SYMLOOP_MAX 10 +/* __SYMLOOP_MAX + https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-points + ... There is a limit of 63 reparse points on any given path. + NOTE: The limit can be reduced depending on the length of the + reparse point. For example, if your reparse point targets a fully + qualified path, the limit becomes 31. */ +#define __SYMLOOP_MAX 63 #define __TIMER_MAX 32 #define __TTY_NAME_MAX 32 #define __FILESIZEBITS 64 diff --git a/winsup/cygwin/include/cygwin/time.h b/winsup/cygwin/include/cygwin/time.h index 9b63e9a..d7f9d3f 100644 --- a/winsup/cygwin/include/cygwin/time.h +++ b/winsup/cygwin/include/cygwin/time.h @@ -35,12 +35,6 @@ extern long timezone __asm__ (_SYMSTR (_timezone)); #endif /* __SVID_VISIBLE || __XSI_VISIBLE */ -#if __ISO_C_VISIBLE >= 2011 -#define TIME_UTC 1 - -extern int timespec_get (struct timespec *, int); -#endif - #ifdef __cplusplus } #endif diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index f341dba..e4c16db 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -493,12 +493,14 @@ details. */ 356: Export posix_spawn_file_actions_addchdir and posix_spawn_file_actions_addfchdir. 357: Export posix_close. + 358: Export acl_get_fd_np, acl_get_link_np, acl_get_perm_np, + acl_is_trivial_np, acl_set_fd_np, acl_set_link_np, acl_strip_np. Note that we forgot to bump the api for ualarm, strtoll, strtoull, sigaltstack, sethostname. */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 357 +#define CYGWIN_VERSION_API_MINOR 358 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible changes are made to the shared diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index 8e29630..01cabee 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -31,8 +31,6 @@ extern "C" #define PTHREAD_CANCEL_DEFERRED 0 #define PTHREAD_CANCEL_DISABLE 1 #define PTHREAD_CANCELED ((void *)-1) -/* this should be a value that can never be a valid address */ -#define PTHREAD_COND_INITIALIZER (pthread_cond_t)21 #define PTHREAD_CREATE_DETACHED 1 /* the default : joinable */ #define PTHREAD_CREATE_JOINABLE 0 @@ -42,10 +40,6 @@ extern "C" #define PTHREAD_MUTEX_ERRORCHECK 1 #define PTHREAD_MUTEX_NORMAL 2 #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL -/* this should be too low to ever be a valid address */ -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (pthread_mutex_t)18 -#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (pthread_mutex_t)19 -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (pthread_mutex_t)20 #define PTHREAD_MUTEX_INITIALIZER PTHREAD_NORMAL_MUTEX_INITIALIZER_NP #define PTHREAD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, 0 } #if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT >= 0 @@ -55,12 +49,35 @@ extern "C" #endif #define PTHREAD_PROCESS_SHARED 1 #define PTHREAD_PROCESS_PRIVATE 0 -#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)22 /* process is the default */ #define PTHREAD_SCOPE_PROCESS 0 #define PTHREAD_SCOPE_SYSTEM 1 #define PTHREAD_BARRIER_SERIAL_THREAD (-1) +/* This condition matches the one in <sys/_pthreadtypes.h> */ +#if !defined(__INSIDE_CYGWIN__) || !defined(__cplusplus) +/* Constants for initializer macros */ +extern struct __pthread_mutex_t __pthread_recursive_mutex_initializer_np; +extern struct __pthread_mutex_t __pthread_normal_mutex_initializer_np; +extern struct __pthread_mutex_t __pthread_errorcheck_mutex_initializer_np; +extern struct __pthread_cond_t __pthread_cond_initializer; +extern struct __pthread_rwlock_t __pthread_rwlock_initializer; +#define PTHREAD_COND_INITIALIZER (&__pthread_cond_initializer) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (&__pthread_recursive_mutex_initializer_np) +#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (&__pthread_normal_mutex_initializer_np) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (&__pthread_errorcheck_mutex_initializer_np) +#define PTHREAD_RWLOCK_INITIALIZER (&__pthread_rwlock_initializer) +#else +/* Inside the Cygwin DLL's C++ code, using absolute linker symbols sometimes + results in "relocation truncated to fit" errors due to being built with + -mcmodel=small. */ +#define PTHREAD_COND_INITIALIZER (pthread_cond_t)21 +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (pthread_mutex_t)18 +#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (pthread_mutex_t)19 +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (pthread_mutex_t)20 +#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)22 +#endif + /* Register Fork Handlers */ int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); @@ -123,7 +140,7 @@ int pthread_cond_broadcast (pthread_cond_t *); int pthread_cond_destroy (pthread_cond_t *); int pthread_cond_init (pthread_cond_t *, const pthread_condattr_t *); int pthread_cond_signal (pthread_cond_t *); -#if __GNU_VISIBLE +#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 int pthread_cond_clockwait (pthread_cond_t *, pthread_mutex_t *, clockid_t, const struct timespec *); #endif @@ -170,7 +187,7 @@ int pthread_mutex_getprioceiling (const pthread_mutex_t *, int *); int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *); int pthread_mutex_lock (pthread_mutex_t *); int pthread_mutex_setprioceiling (pthread_mutex_t *, int, int *); -#if __GNU_VISIBLE +#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 int pthread_mutex_clocklock (pthread_mutex_t *, clockid_t, const struct timespec *); #endif @@ -202,14 +219,14 @@ int pthread_spin_unlock (pthread_spinlock_t *); int pthread_rwlock_destroy (pthread_rwlock_t *); int pthread_rwlock_init (pthread_rwlock_t *, const pthread_rwlockattr_t *); int pthread_rwlock_rdlock (pthread_rwlock_t *); -#if __GNU_VISIBLE +#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 int pthread_rwlock_clockrdlock (pthread_rwlock_t *, clockid_t, const struct timespec *); #endif int pthread_rwlock_timedrdlock (pthread_rwlock_t *, const struct timespec *); int pthread_rwlock_tryrdlock (pthread_rwlock_t *); int pthread_rwlock_wrlock (pthread_rwlock_t *); -#if __GNU_VISIBLE +#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 int pthread_rwlock_clockwrlock (pthread_rwlock_t *, clockid_t, const struct timespec *); #endif diff --git a/winsup/cygwin/include/search.h b/winsup/cygwin/include/search.h index f532eae..7c6d7b4 100644 --- a/winsup/cygwin/include/search.h +++ b/winsup/cygwin/include/search.h @@ -39,6 +39,8 @@ typedef struct node } node_t; #endif +typedef void posix_tnode; + struct hsearch_data { struct internal_head *htable; @@ -58,13 +60,13 @@ ENTRY *hsearch (ENTRY, ACTION); int hcreate_r (size_t, struct hsearch_data *); void hdestroy_r (struct hsearch_data *); int hsearch_r (ENTRY, ACTION, ENTRY **, struct hsearch_data *); -void *tdelete (const void * __restrict, void ** __restrict, +void *tdelete (const void * __restrict, posix_tnode ** __restrict, int (*) (const void *, const void *)); void tdestroy (void *, void (*)(void *)); -void *tfind (const void *, void **, +posix_tnode *tfind (const void *, posix_tnode *const *, int (*) (const void *, const void *)); -void *tsearch (const void *, void **, int (*) (const void *, const void *)); -void twalk (const void *, void (*) (const void *, VISIT, int)); +posix_tnode *tsearch (const void *, posix_tnode **, int (*) (const void *, const void *)); +void twalk (const posix_tnode *, void (*) (const posix_tnode *, VISIT, int)); void *lfind (const void *, const void *, size_t *, size_t, int (*) (const void *, const void *)); void *lsearch (const void *, void *, size_t *, size_t, diff --git a/winsup/cygwin/include/semaphore.h b/winsup/cygwin/include/semaphore.h index e20bdc5..6ff462d 100644 --- a/winsup/cygwin/include/semaphore.h +++ b/winsup/cygwin/include/semaphore.h @@ -32,7 +32,7 @@ extern "C" int sem_unlink (const char *__name); int sem_wait (sem_t *__sem); int sem_trywait (sem_t *__sem); -#if __GNU_VISIBLE +#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 int sem_clockwait (sem_t *__sem, clockid_t __clock_id, const struct timespec *__abstime); #endif int sem_timedwait (sem_t *__sem, const struct timespec *__abstime); diff --git a/winsup/cygwin/include/sys/acl.h b/winsup/cygwin/include/sys/acl.h index 74e50ba..5789dd0 100644 --- a/winsup/cygwin/include/sys/acl.h +++ b/winsup/cygwin/include/sys/acl.h @@ -92,6 +92,18 @@ extern ssize_t acl_size (acl_t __acl); extern char *acl_to_text (acl_t __acl, ssize_t *__len_p); extern int acl_valid (acl_t __acl); +/* Non-libacl extensions to POSIX.1e draft 17 */ + +/* FreeBSD, NetBSD */ +extern acl_t acl_get_fd_np (int __fd, acl_type_t __type); +extern acl_t acl_get_link_np (const char *__path_p, acl_type_t __type); +extern int acl_get_perm_np (acl_permset_t __permset_d, acl_perm_t __perm); +extern int acl_is_trivial_np (const acl_t __acl, int *__trivialp); +extern int acl_set_fd_np (int __fd, acl_t __acl, acl_type_t __type); +extern int acl_set_link_np (const char *__path_p, acl_type_t __type, + acl_t __acl); +extern acl_t acl_strip_np (const acl_t __acl, int __recalculate_mask); + #ifdef __cplusplus } #endif diff --git a/winsup/cygwin/include/sys/poll.h b/winsup/cygwin/include/sys/poll.h index 65822ed..5d58b36 100644 --- a/winsup/cygwin/include/sys/poll.h +++ b/winsup/cygwin/include/sys/poll.h @@ -39,7 +39,7 @@ struct pollfd { typedef unsigned int nfds_t; extern int poll __P ((struct pollfd *fds, nfds_t nfds, int timeout)); -#if __GNU_VISIBLE +#if __GNU_VISIBLE || __POSIX_VISIBLE >= 202405 extern int ppoll __P ((struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t *sigmask)); diff --git a/winsup/cygwin/include/sys/termios.h b/winsup/cygwin/include/sys/termios.h index d1b4a0a..4c03042 100644 --- a/winsup/cygwin/include/sys/termios.h +++ b/winsup/cygwin/include/sys/termios.h @@ -18,6 +18,7 @@ details. */ #define TIOCMBIC 0x5417 #define TIOCMSET 0x5418 #define TIOCINQ 0x541B +#define TCXONC 0x540A #define TIOCSCTTY 0x540E /* TIOCINQ is utilized instead of FIONREAD which has been diff --git a/winsup/cygwin/lib/pthreadconst.S b/winsup/cygwin/lib/pthreadconst.S new file mode 100644 index 0000000..6e55a83 --- /dev/null +++ b/winsup/cygwin/lib/pthreadconst.S @@ -0,0 +1,17 @@ +#if defined(__i386__) +# define SYM(x) _##x +#else +# define SYM(x) x +#endif + +/* these should all be too low to ever be valid addresses */ +.globl SYM(__pthread_recursive_mutex_initializer_np) +.set __pthread_recursive_mutex_initializer_np, 18 +.globl SYM(__pthread_normal_mutex_initializer_np) +.set __pthread_normal_mutex_initializer_np, 19 +.globl SYM(__pthread_errorcheck_mutex_initializer_np) +.set __pthread_errorcheck_mutex_initializer_np, 20 +.globl SYM(__pthread_cond_initializer) +.set __pthread_cond_initializer, 21 +.globl SYM(__pthread_rwlock_initializer) +.set __pthread_rwlock_initializer, 22 diff --git a/winsup/cygwin/local_includes/cygmalloc.h b/winsup/cygwin/local_includes/cygmalloc.h index 5e1fe81..898ea56 100644 --- a/winsup/cygwin/local_includes/cygmalloc.h +++ b/winsup/cygwin/local_includes/cygmalloc.h @@ -21,7 +21,10 @@ int dlmalloc_trim (size_t); int dlmallopt (int p, int v); void dlmalloc_stats (); +// Already defined for AArch64 in newlib/libc/include/sys/config.h +#ifndef MALLOC_ALIGNMENT #define MALLOC_ALIGNMENT ((size_t)16U) +#endif #if defined (DLMALLOC_VERSION) /* Building malloc.cc */ diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h index 079ada9..9f83c13 100644 --- a/winsup/cygwin/local_includes/cygtls.h +++ b/winsup/cygwin/local_includes/cygtls.h @@ -198,11 +198,13 @@ public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */ class san *andreas; waitq wq; volatile int current_sig; - unsigned incyg; + volatile unsigned incyg; volatile unsigned stacklock; __tlsstack_t *stackptr; __tlsstack_t stack[TLS_STACK_SIZE]; unsigned initialized; + volatile bool suspend_on_exception; + volatile bool in_singlestep_handler; public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */ void init_thread (void *, DWORD (*) (void *, void *)); @@ -229,7 +231,7 @@ public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */ bool interrupt_now (CONTEXT *, siginfo_t&, void *, struct sigaction&); void interrupt_setup (siginfo_t&, void *, struct sigaction&); - bool inside_kernel (CONTEXT *); + bool inside_kernel (CONTEXT *, bool inside_cygwin = false); void signal_debugger (siginfo_t&); #ifdef CYGTLS_HANDLE @@ -242,8 +244,11 @@ public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */ { while (InterlockedExchange (&stacklock, 1)) { -#ifdef __x86_64__ +#if defined(__x86_64__) __asm__ ("pause"); +#elif defined(__aarch64__) + __asm__ ("dmb ishst\n" + "yield"); #else #error unimplemented for this target #endif @@ -321,7 +326,13 @@ public: address of the _except block to restore the context correctly. See comment preceeding myfault_altstack_handler in exception.cc. */ ret = (DWORD64) _ret; +#if defined(__x86_64__) __asm__ volatile ("movq %%rsp,%0": "=o" (frame)); +#elif defined(__aarch64__) + __asm__ volatile ("mov %0, sp" : "=r" (frame)); +#else +#error unimplemented for this target +#endif } ~san () __attribute__ ((always_inline)) { diff --git a/winsup/cygwin/local_includes/dll_init.h b/winsup/cygwin/local_includes/dll_init.h index 65f4213..0ca6cd2 100644 --- a/winsup/cygwin/local_includes/dll_init.h +++ b/winsup/cygwin/local_includes/dll_init.h @@ -34,7 +34,9 @@ struct per_module typedef enum { DLL_NONE, - DLL_SELF, /* main-program.exe, cygwin1.dll */ + DLL_SELF, /* main-program.exe, cygwin1.dll */ + DLL_NATIVE, /* dlopen'ed native DLLs. reload after fork, but otherwise + do nothing, just as with DLL_SELF. */ DLL_LINK, DLL_LOAD, DLL_ANY @@ -57,7 +59,6 @@ struct dll PWCHAR forkable_ntname; WCHAR ntname[1]; /* must be the last data member */ - void detach (); int init (); bool stat_real_file_once (); void nominate_forkable (PCWCHAR); @@ -131,7 +132,7 @@ public: int reload_on_fork; dll *operator [] (PCWCHAR ntname); dll *alloc (HINSTANCE, per_process *, dll_type); - dll *find (void *); + dll *find (void *, bool = false); void detach (void *); void init (); void load_after_fork (HANDLE); diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 8c71d84..04e2ca4 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -1203,6 +1203,7 @@ class fhandler_pipe_fifo: public fhandler_base protected: size_t pipe_buf_size; HANDLE pipe_mtx; /* Used only in the pipe case */ + bool real_non_blocking_mode; /* Used only in the pipe case */ virtual void release_select_sem (const char *) {}; IMPLEMENT_STATUS_FLAG (bool, isclosed) @@ -1212,6 +1213,8 @@ class fhandler_pipe_fifo: public fhandler_base virtual bool reader_closed () { return false; }; ssize_t raw_write (const void *ptr, size_t len); + + friend ssize_t pipe_data_available (int, fhandler_base *, HANDLE, int); }; class fhandler_pipe: public fhandler_pipe_fifo @@ -1699,9 +1702,9 @@ class fhandler_disk_file: public fhandler_base uint64_t fs_ioc_getflags (); int fs_ioc_setflags (uint64_t); - falloc_allocate (int, off_t, off_t); - falloc_punch_hole (off_t, off_t); - falloc_zero_range (int, off_t, off_t); + int falloc_allocate (int, off_t, off_t); + int falloc_punch_hole (off_t, off_t); + int falloc_zero_range (int, off_t, off_t); public: fhandler_disk_file (); @@ -1979,6 +1982,7 @@ class fhandler_termios: public fhandler_base virtual off_t lseek (off_t, int); pid_t tcgetsid (); virtual int fstat (struct stat *buf); + int tcflow (int); fhandler_termios (void *) {} @@ -2143,12 +2147,12 @@ class dev_console char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command char *cons_rapoi; bool cursor_key_app_mode; - bool disable_master_thread; + volatile bool disable_master_thread; tty::cons_mode curr_input_mode; tty::cons_mode curr_output_mode; DWORD prev_input_mode; DWORD prev_output_mode; - bool master_thread_suspended; + volatile bool master_thread_suspended; int num_processed; /* Number of input events in the current input buffer already processed by cons_master_thread(). */ @@ -2273,6 +2277,7 @@ private: int tcflush (int); int tcsetattr (int a, const struct termios *t); int tcgetattr (struct termios *t); + int tcdrain (); int ioctl (unsigned int cmd, void *); int init (HANDLE, DWORD, mode_t, int64_t = 0); @@ -2368,7 +2373,7 @@ private: void setup_pcon_hand_over (); static void pcon_hand_over_proc (); - static tty::cons_mode cons_mode_on_close (); + static tty::cons_mode cons_mode_on_close (handle_set_t *); friend tty_min * tty_list::get_cttyp (); }; @@ -2391,6 +2396,7 @@ class fhandler_pty_common: public fhandler_termios DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms); void __release_output_mutex (const char *fn, int ln); + int tcdrain (); int close (int flag = -1); off_t lseek (off_t, int); bool bytes_available (DWORD& n); diff --git a/winsup/cygwin/local_includes/ntdll.h b/winsup/cygwin/local_includes/ntdll.h index 97a83d1..1990893 100644 --- a/winsup/cygwin/local_includes/ntdll.h +++ b/winsup/cygwin/local_includes/ntdll.h @@ -490,6 +490,8 @@ typedef struct _FILE_DISPOSITION_INFORMATION_EX // 64 ULONG Flags; } FILE_DISPOSITION_INFORMATION_EX, *PFILE_DISPOSITION_INFORMATION_EX; +#if __MINGW64_VERSION_MAJOR < 13 + typedef struct _FILE_STAT_INFORMATION // 68 { LARGE_INTEGER FileId; @@ -510,6 +512,8 @@ typedef struct _FILE_CASE_SENSITIVE_INFORMATION // 71 ULONG Flags; } FILE_CASE_SENSITIVE_INFORMATION, *PFILE_CASE_SENSITIVE_INFORMATION; +#endif + enum { FILE_LINK_REPLACE_IF_EXISTS = 0x01, FILE_LINK_POSIX_SEMANTICS = 0x02, @@ -1362,7 +1366,8 @@ typedef enum _THREADINFOCLASS ThreadBasicInformation = 0, ThreadTimes = 1, ThreadImpersonationToken = 5, - ThreadQuerySetWin32StartAddress = 9 + ThreadQuerySetWin32StartAddress = 9, + ThreadSuspendCount = 35 } THREADINFOCLASS, *PTHREADINFOCLASS; typedef struct _THREAD_BASIC_INFORMATION @@ -1655,6 +1660,8 @@ extern "C" BOOLEAN); WCHAR RtlUpcaseUnicodeChar (WCHAR); NTSTATUS RtlUpcaseUnicodeString (PUNICODE_STRING, PUNICODE_STRING, BOOLEAN); + VOID RtlWakeAddressSingle (PVOID); + NTSTATUS RtlWaitOnAddress (volatile void *, PVOID, SIZE_T, PLARGE_INTEGER); NTSTATUS RtlWriteRegistryValue (ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG); #ifdef __cplusplus diff --git a/winsup/cygwin/local_includes/select.h b/winsup/cygwin/local_includes/select.h index 43ceb1d..afc05e1 100644 --- a/winsup/cygwin/local_includes/select.h +++ b/winsup/cygwin/local_includes/select.h @@ -143,5 +143,8 @@ ssize_t pipe_data_available (int, fhandler_base *, HANDLE, int); #define PDA_READ 0x00 #define PDA_WRITE 0x01 +#define PDA_ERROR -1 +#define PDA_UNKNOWN -2 +#define PDA_NOERROR(x) (x >= 0) #endif /* _SELECT_H_ */ diff --git a/winsup/cygwin/local_includes/thread.h b/winsup/cygwin/local_includes/thread.h index b349628..cbbbc3f 100644 --- a/winsup/cygwin/local_includes/thread.h +++ b/winsup/cygwin/local_includes/thread.h @@ -221,13 +221,12 @@ public: ~pthread_key (); static void fixup_before_fork () { - keys.for_each (&pthread_key::_fixup_before_fork); + for_each (&pthread_key::_fixup_before_fork); } static void fixup_after_fork () { - keys.fixup_after_fork (); - keys.for_each (&pthread_key::_fixup_after_fork); + for_each (&pthread_key::_fixup_after_fork); } static void run_all_destructors () @@ -246,21 +245,39 @@ public: for (int i = 0; i < PTHREAD_DESTRUCTOR_ITERATIONS; ++i) { iterate_dtors_once_more = false; - keys.for_each (&pthread_key::run_destructor); + for_each (&pthread_key::run_destructor); if (!iterate_dtors_once_more) break; } } - /* List support calls */ - class pthread_key *next; private: - static List<pthread_key> keys; + int key_idx; + static class keys_list { + LONG64 seq; + LONG64 busy_cnt; + pthread_key *key; + static bool used (LONG64 seq1) { return (seq1 & 3) != 0; } + static bool ready (LONG64 seq1) { return (seq1 & 3) == 2; } + public: + keys_list () : seq (0), busy_cnt (INT64_MIN), key (NULL) {} + friend class pthread_key; + } keys[PTHREAD_KEYS_MAX]; void _fixup_before_fork (); void _fixup_after_fork (); void (*destructor) (void *); void run_destructor (); void *fork_buf; + static void for_each (void (pthread_key::*callback) ()) { + for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; cnt++) + { + if (!keys_list::ready (keys[cnt].seq)) + continue; + if (InterlockedIncrement64 (&keys[cnt].busy_cnt) > 0) + (keys[cnt].key->*callback) (); + InterlockedDecrement64 (&keys[cnt].busy_cnt); + } + } }; class pthread_attr: public verifyable_object diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_includes/tty.h index 2a047d7..a418ab1 100644 --- a/winsup/cygwin/local_includes/tty.h +++ b/winsup/cygwin/local_includes/tty.h @@ -30,6 +30,9 @@ details. */ #define MIN_CTRL_C_SLOP 50 #endif +#define BY_TCFLOW 2 +#define BY_VSTOP 1 + typedef void *HPCON; #include "devices.h" @@ -43,7 +46,8 @@ class tty_min public: pid_t pgid; - bool output_stopped; /* FIXME: Maybe do this with a mutex someday? */ + volatile int output_stopped; /* FIXME: Maybe do this with a mutex someday? */ + volatile int input_stopped; fh_devices ntty; ULONGLONG last_ctrl_c; /* tick count of last ctrl-c */ bool is_console; diff --git a/winsup/cygwin/local_includes/winlean.h b/winsup/cygwin/local_includes/winlean.h index 62b651b..500f569 100644 --- a/winsup/cygwin/local_includes/winlean.h +++ b/winsup/cygwin/local_includes/winlean.h @@ -111,6 +111,10 @@ details. */ #define DOMAIN_ALIAS_RID_DEVICE_OWNERS (__MSABI_LONG(0x00000247)) #endif +#ifndef EXCEPTION_SOFTWARE_ORIGINATE +#define EXCEPTION_SOFTWARE_ORIGINATE 0x80 +#endif + /* So-called "Microsoft Account" SIDs (S-1-11-...) have a netbios domain name "MicrosoftAccounts". The new "Application Container SIDs" (S-1-15-...) have a netbios domain name "APPLICATION PACKAGE AUTHORITY" diff --git a/winsup/cygwin/mm/cygheap.cc b/winsup/cygwin/mm/cygheap.cc index 4cc8517..3388864 100644 --- a/winsup/cygwin/mm/cygheap.cc +++ b/winsup/cygwin/mm/cygheap.cc @@ -743,6 +743,7 @@ init_cygheap::find_tls (int sig, bool& issig_wait) while (++ix < (int) nthreads) { /* Only pthreads have tid set to non-0. */ + threadlist[ix].thread->lock (); if (!threadlist[ix].thread->tid || !threadlist[ix].thread->initialized) ; @@ -752,13 +753,21 @@ init_cygheap::find_tls (int sig, bool& issig_wait) issig_wait = true; break; } - else if (!t && !sigismember (&(threadlist[ix].thread->sigmask), sig)) + else if (!t && !sigismember (&(threadlist[ix].thread->sigmask), sig) + && !sigismember (&(threadlist[ix].thread->deltamask), sig)) + { t = &cygheap->threadlist[ix]; + break; + } + threadlist[ix].thread->unlock (); } /* Leave with locked mutex. The calling function is responsible for unlocking the mutex. */ if (t) - WaitForSingleObject (t->mutex, INFINITE); + { + threadlist[ix].thread->unlock (); + WaitForSingleObject (t->mutex, INFINITE); + } return t; } diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 9d7224a..579b1a7 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -18,7 +18,12 @@ details. */ #undef u_long #define u_long __ms_u_long #include <w32api/ws2tcpip.h> +/* 2025-06-09: win32api headers v13 now define a cmsghdr type which clashes with + our socket.h. Arrange not to see it here. */ +#undef cmsghdr +#define cmsghdr __ms_cmsghdr #include <w32api/mswsock.h> +#undef cmsghdr #include <w32api/iphlpapi.h> #define gethostname cygwin_gethostname #include <unistd.h> diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index d2aaed3..310876b 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1855,9 +1855,18 @@ symlink_native (const char *oldpath, path_conv &win32_newpath) while (towupper (*++c_old) == towupper (*++c_new)) ; /* The last component could share a common prefix, so make sure we end - up on the first char after the last common backslash. */ - while (c_old[-1] != L'\\') - --c_old, --c_new; + up on the first char after the last common backslash. + + However, if c_old is a strict prefix of c_new (at a component + boundary), or vice versa, then do not try to find the last common + backslash. */ + if ((!*c_old || *c_old == L'\\') && (!*c_new || *c_new == L'\\')) + c_old += !!*c_old, c_new += !!*c_new; + else + { + while (c_old[-1] != L'\\') + --c_old, --c_new; + } /* 2. Check if prefix is long enough. The prefix must at least points to a complete device: \\?\X:\ or \\?\UNC\server\share\ are the minimum @@ -1882,8 +1891,10 @@ symlink_native (const char *oldpath, path_conv &win32_newpath) final_oldpath = &final_oldpath_buf; final_oldpath->Buffer = tp.w_get (); PWCHAR e_old = final_oldpath->Buffer; - while (num-- > 0) - e_old = wcpcpy (e_old, L"..\\"); + while (num > 1 || (num == 1 && *c_old)) + e_old = wcpcpy (e_old, L"..\\"), num--; + if (num > 0) + e_old = wcpcpy (e_old, L".."); wcpcpy (e_old, c_old); } } @@ -3911,6 +3922,7 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to, int how = what & CCP_CONVFLAGS_MASK; what &= CCP_CONVTYPE_MASK; int ret = -1; + bool prependglobalroot = false; __try { @@ -4019,7 +4031,7 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to, { /* Device name points to somewhere else in the NT namespace. Use GLOBALROOT prefix to convert to Win32 path. */ - to = (void *) wcpcpy ((wchar_t *) to, ro_u_globalroot.Buffer); + prependglobalroot = true; lsiz += ro_u_globalroot.Length / sizeof (WCHAR); } /* TODO: Same ".\\" band-aid as in CCP_POSIX_TO_WIN_A case. */ @@ -4075,6 +4087,8 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to, stpcpy ((char *) to, buf); break; case CCP_POSIX_TO_WIN_W: + if (prependglobalroot) + to = (void *) wcpcpy ((PWCHAR) to, ro_u_globalroot.Buffer); wcpcpy ((PWCHAR) to, path); break; } @@ -4490,138 +4504,41 @@ fcwd_access_t::SetDirHandleFromBufferPointer (PWCHAR buf_p, HANDLE dir) f_cwd->DirectoryHandle = dir; } -/* This function scans the code in ntdll.dll to find the address of the - global variable used to access the CWD. While the pointer is global, - it's not exported from the DLL, unfortunately. Therefore we have to - use some knowledge to figure out the address. */ - -#define peek32(x) (*(int32_t *)(x)) - -static fcwd_access_t ** -find_fast_cwd_pointer () -{ - /* Fetch entry points of relevant functions in ntdll.dll. */ - HMODULE ntdll = GetModuleHandle ("ntdll.dll"); - if (!ntdll) - return NULL; - const uint8_t *get_dir = (const uint8_t *) - GetProcAddress (ntdll, "RtlGetCurrentDirectory_U"); - const uint8_t *ent_crit = (const uint8_t *) - GetProcAddress (ntdll, "RtlEnterCriticalSection"); - if (!get_dir || !ent_crit) - return NULL; - /* Search first relative call instruction in RtlGetCurrentDirectory_U. */ - const uint8_t *rcall = (const uint8_t *) memchr (get_dir, 0xe8, 80); - if (!rcall) - return NULL; - /* Fetch offset from instruction and compute address of called function. - This function actually fetches the current FAST_CWD instance and - performs some other actions, not important to us. */ - const uint8_t *use_cwd = rcall + 5 + peek32 (rcall + 1); - /* Next we search for the locking mechanism and perform a sanity check. - On Pre-Windows 8 we basically look for the RtlEnterCriticalSection call. - Windows 8 does not call RtlEnterCriticalSection. The code manipulates - the FastPebLock manually, probably because RtlEnterCriticalSection has - been converted to an inline function. Either way, we test if the code - uses the FastPebLock. */ - const uint8_t *movrbx; - const uint8_t *lock = (const uint8_t *) - memmem ((const char *) use_cwd, 80, - "\xf0\x0f\xba\x35", 4); - if (lock) - { - /* The lock instruction tweaks the LockCount member, which is not at - the start of the PRTL_CRITICAL_SECTION structure. So we have to - subtract the offset of LockCount to get the real address. */ - PRTL_CRITICAL_SECTION lockaddr = - (PRTL_CRITICAL_SECTION) (lock + 9 + peek32 (lock + 4) - - offsetof (RTL_CRITICAL_SECTION, LockCount)); - /* Test if lock address is FastPebLock. */ - if (lockaddr != NtCurrentTeb ()->Peb->FastPebLock) - return NULL; - /* Search `mov rel(%rip),%rbx'. This is the instruction fetching the - address of the current fcwd_access_t pointer, and it should be pretty - near to the locking stuff. */ - movrbx = (const uint8_t *) memmem ((const char *) lock, 40, - "\x48\x8b\x1d", 3); - } - else - { - /* Usually the callq RtlEnterCriticalSection follows right after - fetching the lock address. */ - int call_rtl_offset = 7; - /* Search `lea rel(%rip),%rcx'. This loads the address of the lock into - %rcx for the subsequent RtlEnterCriticalSection call. */ - lock = (const uint8_t *) memmem ((const char *) use_cwd, 80, - "\x48\x8d\x0d", 3); - if (!lock) - { - /* Windows 8.1 Preview calls `lea rel(rip),%r12' then some unrelated - ops, then `mov %r12,%rcx', then `callq RtlEnterCriticalSection'. */ - lock = (const uint8_t *) memmem ((const char *) use_cwd, 80, - "\x4c\x8d\x25", 3); - call_rtl_offset = 14; - } - - if (!lock) - { - /* A recent Windows 11 Preview calls `lea rel(rip),%r13' then - some unrelated instructions, then `callq RtlEnterCriticalSection'. - */ - lock = (const uint8_t *) memmem ((const char *) use_cwd, 80, - "\x4c\x8d\x2d", 3); - call_rtl_offset = 24; - } - - if (!lock) - { - return NULL; - } +#ifdef __x86_64__ +fcwd_access_t ** +find_fast_cwd_pointer_x86_64 (); +#endif - PRTL_CRITICAL_SECTION lockaddr = - (PRTL_CRITICAL_SECTION) (lock + 7 + peek32 (lock + 3)); - /* Test if lock address is FastPebLock. */ - if (lockaddr != NtCurrentTeb ()->Peb->FastPebLock) - return NULL; - /* Next is the `callq RtlEnterCriticalSection'. */ - lock += call_rtl_offset; - if (lock[0] != 0xe8) - return NULL; - const uint8_t *call_addr = (const uint8_t *) - (lock + 5 + peek32 (lock + 1)); - if (call_addr != ent_crit) - return NULL; - /* In contrast to the above Windows 8 code, we don't have to search - for the `mov rel(%rip),%rbx' instruction. It follows right after - the call to RtlEnterCriticalSection. */ - movrbx = lock + 5; - } - if (!movrbx) - return NULL; - /* Check that the next instruction tests if the fetched value is NULL. */ - const uint8_t *testrbx = (const uint8_t *) - memmem (movrbx + 7, 3, "\x48\x85\xdb", 3); - if (!testrbx) - return NULL; - /* Compute address of the fcwd_access_t ** pointer. */ - return (fcwd_access_t **) (testrbx + peek32 (movrbx + 3)); -} +fcwd_access_t ** +find_fast_cwd_pointer_aarch64 (); static fcwd_access_t ** find_fast_cwd () { fcwd_access_t **f_cwd_ptr; - /* First check if we're running on an ARM64 system. Skip - fetching FAST_CWD pointer as long as there's no solution for finding - it on that system. */ - if (wincap.host_machine () == IMAGE_FILE_MACHINE_ARM64) - return NULL; + switch (wincap.host_machine ()) + { + case IMAGE_FILE_MACHINE_ARM64: + f_cwd_ptr = find_fast_cwd_pointer_aarch64 (); + break; +#ifdef __x86_64__ + case IMAGE_FILE_MACHINE_AMD64: + f_cwd_ptr = find_fast_cwd_pointer_x86_64 (); + break; +#endif + default: + small_printf ("Cygwin WARNING:\n" +" Couldn't compute FAST_CWD pointer for an unknown architecture (%04y)\n" +" Please update to the latest available Cygwin version from\n" +" https://cygwin.com/. If the problem persists, please see\n" +" https://cygwin.com/problems.html\n\n", (int) wincap.host_machine ()); + return NULL; + } /* Fetch the pointer but don't set the global fast_cwd_ptr yet. First we have to make sure we know the version of the FAST_CWD structure used on the system. */ - f_cwd_ptr = find_fast_cwd_pointer (); if (!f_cwd_ptr) small_printf ("Cygwin WARNING:\n" " Couldn't compute FAST_CWD pointer. This typically occurs if you're using\n" diff --git a/winsup/cygwin/release/3.6.1 b/winsup/cygwin/release/3.6.1 index 40ef297..e24766d 100644 --- a/winsup/cygwin/release/3.6.1 +++ b/winsup/cygwin/release/3.6.1 @@ -10,3 +10,42 @@ Fixes: - getlocalename_l: Fix a crash and handle LC_ALL according to final POSIX-1.2024 docs. Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257715.html + +- Copy context to alternate signal stack area in call_signal_handler() + in the SA_ONSTACK case, because locally-copied context on the normal + stack area is not accessible from the signal handler. + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257714.html + +- Fix reference counting when dlopen/dlclose is called on the Cygwin DLL + or on non-Cygwin DLLs. + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257783.html + +- Fix reference counting when dlopen/dlclose a DLL with RTLD_NODELETE. + +- Disallow accounts from the BUILTIN, NT AUTHORITY, NT SERVICE domains + as USER entry in a POSIX ACL. Only allow USER_OBJ, GROUP_OBJ and GROUP. + +- Accommodate a change in Windows exception handling affecting software + generated exceptions. + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257808.html + +- Return EMFILE when opening /dev/ptmx too many times. + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257786.html + +- Move pthread::atforkchild() at the end of fork::child(). This fixes + subprocess failure in cmake (>= 3.29.x). + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257800.html + Addresses: https://github.com/msys2/msys2-runtime/issues/272 + +- Don't increment DLL reference count in dladdr. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257862.html + +- Fix tcsetattr() for console which has been broken sinse cygwin 3.5.5. + +- Fix up cached DOS attributes when trying to create the same file in + two (or more) threads/processes concurrently. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257871.html + +- Fix deadlock when calling pthread_key_create in the destructor of + a pthread_key. + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257705.html diff --git a/winsup/cygwin/release/3.6.2 b/winsup/cygwin/release/3.6.2 new file mode 100644 index 0000000..f6a3548 --- /dev/null +++ b/winsup/cygwin/release/3.6.2 @@ -0,0 +1,42 @@ +Changes: +-------- + +- Update <search.h> to align with POSIX.1-2024, adding the posix_tnode type +and declaring functions using it. + +Fixes: +------ + +- Fix a high latency problem when trying to fetch SID info for SIDs + not resolved by Windows functions anyway. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257916.html + +- Fix connect(2) returning WSAEPROTOTYPE on abstract sockets. + Addresses: https://sourceware.org/pipermail/cygwin-patches/2025q2/013638.html + +- Fix the console states after the console is closed. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257909.html + +- Fix compilation of sys/unistd.h with std=c90 + Addresses: https://sourceware.org/pipermail/cygwin-patches/2025q2/013644.html + +- Fix setting DOS attributes on devices. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/257940.html + +- Fix cygwin_conv_path writing to 'to' pointer before size is checked. + Addresses: https://cygwin.com/pipermail/cygwin/2025-April/258068.html + +- Fix handle leak occured when the signal handler calls longjmp(). + https://sourceware.org/pipermail/cygwin/2025-March/257726.html + +- Fix cygserver-config error. + https://cygwin.com/pipermail/cygwin/2025-April/258086.html + +- Fix deadlock for opening both side of a fifo in a process. + Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258138.html + +- Fix infinite exception loop on segmentation fault when strace-ing + Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258144.html + +- Fix size truncation in dll_init reserve_at function. + Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258154.html diff --git a/winsup/cygwin/release/3.6.3 b/winsup/cygwin/release/3.6.3 new file mode 100644 index 0000000..60031e5 --- /dev/null +++ b/winsup/cygwin/release/3.6.3 @@ -0,0 +1,5 @@ +Fixes: +------ + +- Fix "There are no available terminals" error with AzureAD accounts. + Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258214.html diff --git a/winsup/cygwin/release/3.6.4 b/winsup/cygwin/release/3.6.4 new file mode 100644 index 0000000..3286991 --- /dev/null +++ b/winsup/cygwin/release/3.6.4 @@ -0,0 +1,27 @@ +Fixes: +------ + +- Fix unexpected crash when SIGSEGV occurs too frequently. + Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258153.html + +- Make pthread initializer macros compatible with C++ constinit. + Addresses: https://cygwin.com/pipermail/cygwin/2025-June/258305.html + +- Fix creating native symlinks to `..` (it used to target `../../<dir>` + instead). + +- Fix CI (stress-ng) for arm64 windows failure. + Addresses: https://cygwin.com/pipermail/cygwin/2025-June/258332.html + +- Fix handling of invalid 4 byte UTF-8 sequences. + Addresses: https://cygwin.com/pipermail/cygwin/2025-June/258358.html + +- Fix SSH hang with non-cygwin pipe reader. + Addresses: https://github.com/git-for-windows/git/issues/5682 + +- Fix unexpected blocking mode change by pipe_data_available() + Addresses: https://github.com/git-for-windows/git/issues/5682#issuecomment-2997428207 + +- Fix potential crashing a process PID by accessing /proc/PID/maps + in parallel. + Addresses: https://cygwin.com/pipermail/cygwin/2025-May/258198.html diff --git a/winsup/cygwin/scripts/gentls_offsets b/winsup/cygwin/scripts/gentls_offsets index 040b5de..c375a61 100755 --- a/winsup/cygwin/scripts/gentls_offsets +++ b/winsup/cygwin/scripts/gentls_offsets @@ -62,7 +62,7 @@ start_offset=$(gawk '\ /^__CYGTLS__/ { varname = gensub (/__CYGTLS__(\w+):/, "\\1", "g"); } - /\s*\.long\s+/ { + /\s*\.(word|long)\s+/ { if (length (varname) > 0) { if (varname == "start_offset") { print $2; @@ -85,7 +85,7 @@ gawk -v start_offset="$start_offset" '\ varname = ""; } } - /\s*\.long\s+/ { + /\s*\.(word|long)\s+/ { if (length (varname) > 0) { if (varname == "start_offset") { printf (".equ _cygtls.%s, -%u\n", varname, start_offset); diff --git a/winsup/cygwin/sec/acl.cc b/winsup/cygwin/sec/acl.cc index fa4ea4c..129fe9a 100644 --- a/winsup/cygwin/sec/acl.cc +++ b/winsup/cygwin/sec/acl.cc @@ -219,10 +219,10 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid, aclbufp[3].a_type = DEF_USER_OBJ; aclbufp[3].a_id = ACL_UNDEFINED_ID; aclbufp[3].a_perm = (attr >> 6) & S_IRWXO; - aclbufp[4].a_type = GROUP_OBJ; + aclbufp[4].a_type = DEF_GROUP_OBJ; aclbufp[4].a_id = ACL_UNDEFINED_ID; aclbufp[4].a_perm = (attr >> 3) & S_IRWXO; - aclbufp[5].a_type = OTHER_OBJ; + aclbufp[5].a_type = DEF_OTHER_OBJ; aclbufp[5].a_id = ACL_UNDEFINED_ID; aclbufp[5].a_perm = attr & S_IRWXO; nentries += MIN_ACL_ENTRIES; @@ -256,7 +256,21 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid, } } if (!aclsid[idx]) - aclsid[idx] = sidfromuid (aclbufp[idx].a_id, &cldap); + { + struct passwd *pw = internal_getpwuid (aclbufp[idx].a_id, &cldap); + if (pw) + { + /* Don't allow to pass special accounts as USER, only as + USER_OBJ, GROUP_OBJ, or GROUP */ +#define BUILTIN "U-BUILTIN\\" +#define NT_AUTH "U-NT AUTHORITY\\" +#define NT_SVC "U-NT SERVICE\\" + if (strncmp (pw->pw_gecos, BUILTIN, strlen (BUILTIN)) != 0 + && strncmp (pw->pw_gecos, NT_AUTH, strlen (NT_AUTH)) != 0 + && strncmp (pw->pw_gecos, NT_SVC, strlen (NT_SVC)) != 0) + aclsid[idx] = (PSID) ((pg_pwd *) pw)->sid; + } + } break; case GROUP_OBJ: aclsid[idx] = group; diff --git a/winsup/cygwin/sec/posixacl.cc b/winsup/cygwin/sec/posixacl.cc index 6b01ded..6f3ef15 100644 --- a/winsup/cygwin/sec/posixacl.cc +++ b/winsup/cygwin/sec/posixacl.cc @@ -322,7 +322,7 @@ acl_delete_perm (acl_permset_t permset_d, acl_perm_t perm) } __except (EINVAL) {} __endtry - return -1; + return -1; } extern "C" int @@ -674,14 +674,11 @@ fhandler_socket_unix::acl_get (acl_type_t type) extern "C" acl_t acl_get_fd (int fd) { - cygheap_fdget cfd (fd); - if (cfd < 0) - return NULL; - return cfd->acl_get (ACL_TYPE_ACCESS); + return acl_get_fd_np (fd, ACL_TYPE_ACCESS); } -extern "C" acl_t -acl_get_file (const char *path_p, acl_type_t type) +static acl_t +__acl_get_file (const char *path_p, acl_type_t type, unsigned follow_mode) { if (type != ACL_TYPE_ACCESS && type != ACL_TYPE_DEFAULT) { @@ -689,7 +686,7 @@ acl_get_file (const char *path_p, acl_type_t type) return NULL; } fhandler_base *fh; - if (!(fh = build_fh_name (path_p, PC_SYM_FOLLOW, stat_suffixes))) + if (!(fh = build_fh_name (path_p, follow_mode, stat_suffixes))) return NULL; if (fh->error ()) { @@ -701,6 +698,12 @@ acl_get_file (const char *path_p, acl_type_t type) return acl; } +extern "C" acl_t +acl_get_file (const char *path_p, acl_type_t type) +{ + return __acl_get_file (path_p, type, PC_SYM_FOLLOW); +} + int fhandler_base::acl_set (acl_t acl, acl_type_t type) { @@ -844,14 +847,12 @@ fhandler_socket_unix::acl_set (acl_t acl, acl_type_t type) extern "C" int acl_set_fd (int fd, acl_t acl) { - cygheap_fdget cfd (fd); - if (cfd < 0) - return -1; - return cfd->acl_set (acl, ACL_TYPE_ACCESS); + return acl_set_fd_np (fd, acl, ACL_TYPE_ACCESS); } -extern "C" int -acl_set_file(const char *path_p, acl_type_t type, acl_t acl) +static int +__acl_set_file (const char *path_p, acl_type_t type, acl_t acl, + unsigned follow_mode) { if (type != ACL_TYPE_ACCESS && type != ACL_TYPE_DEFAULT) { @@ -859,7 +860,7 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl) return -1; } fhandler_base *fh; - if (!(fh = build_fh_name (path_p, PC_SYM_FOLLOW, stat_suffixes))) + if (!(fh = build_fh_name (path_p, follow_mode, stat_suffixes))) return -1; if (fh->error ()) { @@ -872,6 +873,12 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl) } extern "C" int +acl_set_file (const char *path_p, acl_type_t type, acl_t acl) +{ + return __acl_set_file (path_p, type, acl, PC_SYM_FOLLOW); +} + +extern "C" int acl_delete_def_file (const char *path_p) { acl_t acl = (acl_t) alloca (sizeof (struct __acl_t)); @@ -1151,3 +1158,145 @@ acl_to_any_text (acl_t acl, const char *prefix, char separator, int options) __endtry return NULL; } + +/* FreeBSD extensions */ + +extern "C" acl_t +acl_get_fd_np (int fd, acl_type_t type) +{ + cygheap_fdget cfd (fd); + if (cfd < 0) + return NULL; + return cfd->acl_get (type); +} + +extern "C" int +acl_is_trivial_np (const acl_t acl, int *trivialp) +{ + __try + { + if (!(__aclcheck (acl->entry, acl->count, NULL, true))) + *trivialp = acl->count - acl->deleted <= MIN_ACL_ENTRIES ? 1 : 0; + return 0; + } + __except (EINVAL) {} + __endtry + return -1; +} + +extern "C" acl_t +acl_get_link_np (const char *path_p, acl_type_t type) +{ + return __acl_get_file (path_p, type, PC_SYM_NOFOLLOW); +} + +extern "C" int +acl_set_fd_np (int fd, acl_t acl, acl_type_t type) +{ + if (type != ACL_TYPE_ACCESS && type != ACL_TYPE_DEFAULT) + { + set_errno (EINVAL); + return -1; + } + cygheap_fdget cfd (fd); + if (cfd < 0) + return -1; + return cfd->acl_set (acl, type); +} + +extern "C" int +acl_set_link_np (const char *path_p, acl_type_t type, acl_t acl) +{ + return __acl_set_file (path_p, type, acl, PC_SYM_NOFOLLOW); +} + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2001 Chris D. Faulhaber + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +extern "C" acl_t +acl_strip_np (const acl_t acl, int recalculate_mask) +{ + acl_t acl_new, acl_old; + acl_entry_t entry, entry_new; + acl_tag_t tag; + int entry_id, have_mask_entry; + + acl_old = acl_dup (acl); + if (acl_old == NULL) + return NULL; + + have_mask_entry = 0; + acl_new = acl_init (MAX_ACL_ENTRIES); + if (acl_new == NULL) + { + acl_free (acl_old); + return NULL; + } + tag = ACL_UNDEFINED_TAG; + + /* only save the default user/group/other entries */ + entry_id = ACL_FIRST_ENTRY; + while (acl_get_entry (acl_old, entry_id, &entry) == 1) + { + entry_id = ACL_NEXT_ENTRY; + + if (acl_get_tag_type (entry, &tag) == -1) + goto fail; + + switch (tag) + { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_OTHER: + if (acl_create_entry (&acl_new, &entry_new) == -1) + goto fail; + if (acl_copy_entry (entry_new, entry) == -1) + goto fail; + break; + case ACL_MASK: + have_mask_entry = 1; + break; + default: + break; + } + } + + if (have_mask_entry && recalculate_mask) + { + if (acl_calc_mask (&acl_new) == -1) + goto fail; + } + + return (acl_new); + +fail: + acl_free (acl_new); + acl_free (acl_old); + + return NULL; +} diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 422c8e8..a7e82a0 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -601,7 +601,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode) if (mode == PDA_READ && PeekNamedPipe (h, NULL, 0, NULL, &nbytes_in_pipe, NULL)) return nbytes_in_pipe; - return -1; + return PDA_ERROR; } IO_STATUS_BLOCK iosb = {{0}, 0}; @@ -618,48 +618,52 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode) access on the write end. */ select_printf ("fd %d, %s, NtQueryInformationFile failed, status %y", fd, fh->get_name (), status); - return (mode == PDA_WRITE) ? 1 : -1; + return (mode == PDA_WRITE) ? PDA_UNKNOWN : PDA_ERROR; } if (mode == PDA_WRITE) { /* If there is anything available in the pipe buffer then signal - that. This means that a pipe could still block since you could - be trying to write more to the pipe than is available in the - buffer but that is the hazard of select(). - - Note that WriteQuotaAvailable is unreliable. - - Usually WriteQuotaAvailable on the write side reflects the space - available in the inbound buffer on the read side. However, if a - pipe read is currently pending, WriteQuotaAvailable on the write side - is decremented by the number of bytes the read side is requesting. - So it's possible (even likely) that WriteQuotaAvailable is 0, even - if the inbound buffer on the read side is not full. This can lead to - a deadlock situation: The reader is waiting for data, but select - on the writer side assumes that no space is available in the read - side inbound buffer. - - Consequentially, there are two possibilities when WriteQuotaAvailable - is 0. One is that the buffer is really full. The other is that the - reader is currently trying to read the pipe and it is pending. - In the latter case, the fact that the reader cannot read the data - immediately means that the pipe is empty. In the former case, - NtSetInformationFile() in set_pipe_non_blocking(true) will fail - with STATUS_PIPE_BUSY, while it succeeds in the latter case. - Therefore, we can distinguish these cases by calling set_pipe_non_ - blocking(true). If it returns success, the pipe is empty, so we - return the pipe buffer size. Otherwise, we return 0. */ - if (fh->get_device () == FH_PIPEW && fpli.WriteQuotaAvailable == 0) + that. This means that a pipe could still block since you could + be trying to write more to the pipe than is available in the + buffer but that is the hazard of select(). + + Note that WriteQuotaAvailable is unreliable. + + Usually WriteQuotaAvailable on the write side reflects the space + available in the inbound buffer on the read side. However, if a + pipe read is currently pending, WriteQuotaAvailable on the write side + is decremented by the number of bytes the read side is requesting. + So it's possible (even likely) that WriteQuotaAvailable is less than + actual space available in the pipe, even if the inbound buffer is + empty. This can lead to a deadlock situation: The reader is waiting + for data, but select on the writer side assumes that no space is + available in the read side inbound buffer. + + Consequentially, there are two possibilities when WriteQuotaAvailable + is less than pipe size. One is that the buffer is really not empty. + The other is that the reader is currently trying to read the pipe + and it is pending. + In the latter case, the fact that the reader cannot read the data + immediately means that the pipe is empty. In the former case, + NtSetInformationFile() in set_pipe_non_blocking(!orig_mode) will + fail with STATUS_PIPE_BUSY, while it succeeds in the latter case. + Therefore, we can distinguish these cases by calling set_pipe_non_ + blocking(true). If it returns success, the pipe is empty, so we + return the pipe buffer size. Otherwise, we return the value of + WriteQuotaAvailable as is. */ + if (fh->get_device () == FH_PIPEW + && fpli.WriteQuotaAvailable < fpli.InboundQuota) { + bool orig_mode = ((fhandler_pipe *) fh)->real_non_blocking_mode; NTSTATUS status = - ((fhandler_pipe *) fh)->set_pipe_non_blocking (true); + ((fhandler_pipe *) fh)->set_pipe_non_blocking (!orig_mode); if (status == STATUS_PIPE_BUSY) - return 0; /* Full */ + return fpli.WriteQuotaAvailable; /* Not empty */ else if (!NT_SUCCESS (status)) /* We cannot know actual write pipe space. */ - return 1; - /* Restore pipe mode to blocking mode */ - ((fhandler_pipe *) fh)->set_pipe_non_blocking (false); + return PDA_UNKNOWN; + /* Restore pipe mode to original blocking mode */ + ((fhandler_pipe *) fh)->set_pipe_non_blocking (orig_mode); /* Empty */ fpli.WriteQuotaAvailable = fpli.InboundQuota; } @@ -670,7 +674,9 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode) fpli.WriteQuotaAvailable); return fpli.WriteQuotaAvailable; } - /* TODO: Buffer really full or non-Cygwin reader? */ + return PIPE_BUF; /* Workaround for native ninja. Native ninja creates + pipe with size == 0, and starts cygwin process + with that pipe. */ } else if (fpli.ReadDataAvailable) { @@ -679,7 +685,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode) return fpli.ReadDataAvailable; } if (fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE) - return -1; + return PDA_ERROR; return 0; } @@ -729,7 +735,7 @@ peek_pipe (select_record *s, bool from_select) if (n == 0 && fh->get_echo_handle ()) n = pipe_data_available (s->fd, fh, fh->get_echo_handle (), PDA_READ); - if (n < 0) + if (n == PDA_ERROR) { select_printf ("read: %s, n %d", fh->get_name (), n); if (s->except_selected) @@ -770,8 +776,8 @@ out: } ssize_t n = pipe_data_available (s->fd, fh, h, PDA_WRITE); select_printf ("write: %s, n %d", fh->get_name (), n); - gotone += s->write_ready = (n > 0); - if (n < 0 && s->except_selected) + gotone += s->write_ready = (n > 0 || n == PDA_UNKNOWN); + if (n == PDA_ERROR && s->except_selected) gotone += s->except_ready = true; } return gotone; @@ -984,7 +990,7 @@ out: ssize_t n = pipe_data_available (s->fd, fh, fh->get_handle (), PDA_WRITE); select_printf ("write: %s, n %d", fh->get_name (), n); gotone += s->write_ready = (n > 0); - if (n < 0 && s->except_selected) + if (n == PDA_ERROR && s->except_selected) gotone += s->except_ready = true; } return gotone; @@ -1410,7 +1416,7 @@ out: ssize_t n = pipe_data_available (s->fd, fh, h, PDA_WRITE); select_printf ("write: %s, n %d", fh->get_name (), n); gotone += s->write_ready = (n > 0); - if (n < 0 && s->except_selected) + if (n == PDA_ERROR && s->except_selected) gotone += s->except_ready = true; } return gotone; diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index fc28be9..3618879 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -611,7 +611,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) bool communing = si.si_signo == __SIGCOMMUNE; pack.wakeup = NULL; - bool wait_for_completion; + bool wait_for_completion = false; if (!(its_me = p == NULL || p == myself || p == myself_nowait)) { /* It is possible that the process is not yet ready to receive messages @@ -762,13 +762,10 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) memcpy (p, si._si_commune._si_str, n); p += n; } - unsigned cw_mask; - cw_mask = pack.si.si_signo == __SIGFLUSHFAST ? 0 : cw_sig_restart; - char mtx_name[MAX_PATH]; shared_name (mtx_name, "sig_send", p->pid); mtx = CreateMutex (&sec_none_nih, FALSE, mtx_name); - cygwait (mtx, INFINITE, cw_mask); + WaitForSingleObject (mtx, INFINITE); if (its_me && (si.si_signo == __SIGFLUSHFAST || si.si_signo == __SIGFLUSH)) { @@ -791,7 +788,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) CloseHandle (mtx); ResetEvent (sigflush_done_evt); SetEvent (sigflush_evt); - cygwait (sigflush_done_evt, INFINITE, cw_mask); + WaitForSingleObject (sigflush_done_evt, INFINITE); rc = 0; goto out; } @@ -807,8 +804,8 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) if (!res || packsize == nb) break; ReleaseMutex (mtx); - cygwait (NULL, 10, cw_mask); - cygwait (mtx, INFINITE, cw_mask); + Sleep (10); + WaitForSingleObject (mtx, INFINITE); res = 0; } ReleaseMutex (mtx); @@ -843,7 +840,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) if (wait_for_completion) { sigproc_printf ("Waiting for pack.wakeup %p", pack.wakeup); - rc = cygwait (pack.wakeup, WSSC, cw_mask); + rc = WaitForSingleObject (pack.wakeup, WSSC); ForceCloseHandle (pack.wakeup); } else @@ -874,6 +871,11 @@ out: } if (pack.wakeup) ForceCloseHandle (pack.wakeup); + + /* Handle signals here if it was not handled yet */ + if (wait_for_completion && pack.si.si_signo != __SIGFLUSHFAST) + _my_tls.call_signal_handler (); + if (si.si_signo != __SIGPENDING && si.si_signo != __SIGPENDINGALL) /* nothing */; else if (!rc) diff --git a/winsup/cygwin/strfuncs.cc b/winsup/cygwin/strfuncs.cc index 66667bd..cb7911c 100644 --- a/winsup/cygwin/strfuncs.cc +++ b/winsup/cygwin/strfuncs.cc @@ -23,7 +23,7 @@ details. */ is affected as well, but we can't transform it as long as we accept Win32 paths as input. */ static const WCHAR tfx_chars[] = { - 0xf000 | 0, 0xf000 | 1, 0xf000 | 2, 0xf000 | 3, + 0, 0xf000 | 1, 0xf000 | 2, 0xf000 | 3, 0xf000 | 4, 0xf000 | 5, 0xf000 | 6, 0xf000 | 7, 0xf000 | 8, 0xf000 | 9, 0xf000 | 10, 0xf000 | 11, 0xf000 | 12, 0xf000 | 13, 0xf000 | 14, 0xf000 | 15, @@ -62,7 +62,7 @@ static const WCHAR tfx_chars[] = { converting back space and dot on filesystems only supporting DOS filenames. */ static const WCHAR tfx_rev_chars[] = { - 0xf000 | 0, 0xf000 | 1, 0xf000 | 2, 0xf000 | 3, + 0, 0xf000 | 1, 0xf000 | 2, 0xf000 | 3, 0xf000 | 4, 0xf000 | 5, 0xf000 | 6, 0xf000 | 7, 0xf000 | 8, 0xf000 | 9, 0xf000 | 10, 0xf000 | 11, 0xf000 | 12, 0xf000 | 13, 0xf000 | 14, 0xf000 | 15, @@ -109,7 +109,7 @@ transform_chars_af_unix (PWCHAR out, const char *path, __socklen_t len) { len -= sizeof (__sa_family_t); for (const unsigned char *p = (const unsigned char *) path; len-- > 0; ++p) - *out++ = (*p <= 0x7f) ? tfx_chars[*p] : *p; + *out++ = (*p <= 0x7f) ? (*p == 0) ? 0xf000 : tfx_chars[*p] : *p; return out; } diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index c93bf4c..d6a2c2d 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1472,11 +1472,6 @@ open (const char *unix_path, int flags, ...) mode = va_arg (ap, mode_t); va_end (ap); - cygheap_fdnew fd; - - if (fd < 0) - __leave; /* errno already set */ - /* When O_PATH is specified in flags, flag bits other than O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored. */ if (flags & O_PATH) @@ -1577,6 +1572,12 @@ open (const char *unix_path, int flags, ...) if ((flags & O_TMPFILE) && !fh->pc.isremote ()) try_to_bin (fh->pc, fh->get_handle (), DELETE, FILE_OPEN_FOR_BACKUP_INTENT); + + cygheap_fdnew fd; + + if (fd < 0) + __leave; /* errno already set */ + fd = fh; if (fd <= 2) set_std_handle (fd); diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 9ee9650..510e2be 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -1666,27 +1666,49 @@ pthread_rwlock::_fixup_after_fork () /* pthread_key */ /* static members */ /* This stores pthread_key information across fork() boundaries */ -List<pthread_key> pthread_key::keys; +pthread_key::keys_list pthread_key::keys[PTHREAD_KEYS_MAX]; /* non-static members */ -pthread_key::pthread_key (void (*aDestructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor) +pthread_key::pthread_key (void (*aDestructor) (void *)) : + verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor) { tls_index = TlsAlloc (); if (tls_index == TLS_OUT_OF_INDEXES) magic = 0; else - keys.insert (this); + for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; cnt++) + { + LONG64 seq = keys[cnt].seq; + if (!keys_list::used (seq) + && InterlockedCompareExchange64 (&keys[cnt].seq, + seq + 1, seq) == seq) + { + keys[cnt].key = this; + keys[cnt].busy_cnt = 0; + key_idx = cnt; + InterlockedIncrement64 (&keys[key_idx].seq); + break; + } + } } pthread_key::~pthread_key () { - /* We may need to make the list code lock the list during operations - */ if (magic != 0) { - keys.remove (this); - TlsFree (tls_index); + LONG64 seq = keys[key_idx].seq; + if (keys_list::ready (seq) + && InterlockedCompareExchange64 (&keys[key_idx].seq, + seq + 1, seq) == seq) + { + while (InterlockedCompareExchange64 (&keys[key_idx].busy_cnt, + INT64_MIN, 0) > 0) + yield (); + keys[key_idx].key = NULL; + InterlockedIncrement64 (&keys[key_idx].seq); + TlsFree (tls_index); + } } } @@ -1946,7 +1968,12 @@ pthread_spinlock::lock () else if (spins < FAST_SPINS_LIMIT) { ++spins; +#if defined(__x86_64__) __asm__ volatile ("pause":::); +#elif defined(__aarch64__) + __asm__ volatile ("dmb ishst\n" + "yield":::); +#endif } else { diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc index a89980d..3c3ba92 100644 --- a/winsup/cygwin/times.cc +++ b/winsup/cygwin/times.cc @@ -490,7 +490,8 @@ clock_settime (clockid_t clk_id, const struct timespec *tp) return -1; } - if (clk_id != CLOCK_REALTIME_COARSE && clk_id != CLOCK_REALTIME) + if ((clk_id != CLOCK_REALTIME_COARSE && clk_id != CLOCK_REALTIME) + || tp->tv_nsec < 0) /* Otherwise -999...-1 would be accepted */ { set_errno (EINVAL); return -1; diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index 2cd4ae6..a4b7167 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -147,7 +147,7 @@ tty_list::allocate (HANDLE& r, HANDLE& w) termios_printf ("pty%d allocated", freetty); else { - system_printf ("No pty allocated"); + termios_printf ("No pty allocated"); r = w = NULL; } diff --git a/winsup/cygwin/udis86/decode.c b/winsup/cygwin/udis86/decode.c new file mode 100644 index 0000000..1fe50e1 --- /dev/null +++ b/winsup/cygwin/udis86/decode.c @@ -0,0 +1,1113 @@ +/* udis86 - libudis86/decode.c + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * + * 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 OWNER 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 "winsup.h" +#include "types.h" +#include "udint.h" +#include "decode.h" + +#ifndef __UD_STANDALONE__ +# include <string.h> +#endif /* __UD_STANDALONE__ */ + +/* The max number of prefixes to an instruction */ +#define MAX_PREFIXES 15 + +/* rex prefix bits */ +#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) +#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) +#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) +#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) +#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ + ( P_REXR(n) << 2 ) | \ + ( P_REXX(n) << 1 ) | \ + ( P_REXB(n) << 0 ) ) + +/* scable-index-base bits */ +#define SIB_S(b) ( ( b ) >> 6 ) +#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) +#define SIB_B(b) ( ( b ) & 7 ) + +/* modrm bits */ +#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) +#define MODRM_RM(b) ( ( b ) & 7 ) + +static int decode_ext(struct ud *u, uint16_t ptr); + +enum reg_class { /* register classes */ + REGCLASS_GPR, + REGCLASS_MMX, + REGCLASS_CR, + REGCLASS_DB, + REGCLASS_SEG, + REGCLASS_XMM +}; + + /* + * inp_start + * Should be called before each de-code operation. + */ +static void +inp_start(struct ud *u) +{ + u->inp_ctr = 0; +} + + +static uint8_t +inp_next(struct ud *u) +{ + if (u->inp_end == 0) { + if (u->inp_buf != NULL) { + if (u->inp_buf_index < u->inp_buf_size) { + u->inp_ctr++; + return (u->inp_curr = u->inp_buf[u->inp_buf_index++]); + } + } else { + int c; + if ((c = u->inp_hook(u)) != UD_EOI) { + u->inp_curr = c; + u->inp_sess[u->inp_ctr++] = u->inp_curr; + return u->inp_curr; + } + } + } + u->inp_end = 1; + UDERR(u, "byte expected, eoi received\n"); + return 0; +} + +static uint8_t +inp_curr(struct ud *u) +{ + return u->inp_curr; +} + + +/* + * inp_uint8 + * int_uint16 + * int_uint32 + * int_uint64 + * Load little-endian values from input + */ +static uint8_t +inp_uint8(struct ud* u) +{ + return inp_next(u); +} + +static uint16_t +inp_uint16(struct ud* u) +{ + uint16_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + return ret | (r << 8); +} + +static uint32_t +inp_uint32(struct ud* u) +{ + uint32_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + return ret | (r << 24); +} + +static uint64_t +inp_uint64(struct ud* u) +{ + uint64_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + ret = ret | (r << 24); + r = inp_next(u); + ret = ret | (r << 32); + r = inp_next(u); + ret = ret | (r << 40); + r = inp_next(u); + ret = ret | (r << 48); + r = inp_next(u); + return ret | (r << 56); +} + + +static inline int +eff_opr_mode(int dis_mode, int rex_w, int pfx_opr) +{ + if (dis_mode == 64) { + return rex_w ? 64 : (pfx_opr ? 16 : 32); + } else if (dis_mode == 32) { + return pfx_opr ? 16 : 32; + } else { + UD_ASSERT(dis_mode == 16); + return pfx_opr ? 32 : 16; + } +} + + +static inline int +eff_adr_mode(int dis_mode, int pfx_adr) +{ + if (dis_mode == 64) { + return pfx_adr ? 32 : 64; + } else if (dis_mode == 32) { + return pfx_adr ? 16 : 32; + } else { + UD_ASSERT(dis_mode == 16); + return pfx_adr ? 32 : 16; + } +} + + +/* + * decode_prefixes + * + * Extracts instruction prefixes. + */ +static int +decode_prefixes(struct ud *u) +{ + int done = 0; + uint8_t curr = 0, last = 0; + UD_RETURN_ON_ERROR(u); + + do { + last = curr; + curr = inp_next(u); + UD_RETURN_ON_ERROR(u); + if (u->inp_ctr == MAX_INSN_LENGTH) { + UD_RETURN_WITH_ERROR(u, "max instruction length"); + } + + switch (curr) + { + case 0x2E: + u->pfx_seg = UD_R_CS; + break; + case 0x36: + u->pfx_seg = UD_R_SS; + break; + case 0x3E: + u->pfx_seg = UD_R_DS; + break; + case 0x26: + u->pfx_seg = UD_R_ES; + break; + case 0x64: + u->pfx_seg = UD_R_FS; + break; + case 0x65: + u->pfx_seg = UD_R_GS; + break; + case 0x67: /* adress-size override prefix */ + u->pfx_adr = 0x67; + break; + case 0xF0: + u->pfx_lock = 0xF0; + break; + case 0x66: + u->pfx_opr = 0x66; + break; + case 0xF2: + u->pfx_str = 0xf2; + break; + case 0xF3: + u->pfx_str = 0xf3; + break; + default: + /* consume if rex */ + done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1; + break; + } + } while (!done); + /* rex prefixes in 64bit mode, must be the last prefix */ + if (u->dis_mode == 64 && (last & 0xF0) == 0x40) { + u->pfx_rex = last; + } + return 0; +} + + +static inline unsigned int modrm( struct ud * u ) +{ + if ( !u->have_modrm ) { + u->modrm = inp_next( u ); + u->have_modrm = 1; + } + return u->modrm; +} + + +static unsigned int +resolve_operand_size( const struct ud * u, unsigned int s ) +{ + switch ( s ) + { + case SZ_V: + return ( u->opr_mode ); + case SZ_Z: + return ( u->opr_mode == 16 ) ? 16 : 32; + case SZ_Y: + return ( u->opr_mode == 16 ) ? 32 : u->opr_mode; + case SZ_RDQ: + return ( u->dis_mode == 64 ) ? 64 : 32; + default: + return s; + } +} + + +static int resolve_mnemonic( struct ud* u ) +{ + /* resolve 3dnow weirdness. */ + if ( u->mnemonic == UD_I3dnow ) { + u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic; + } + /* SWAPGS is only valid in 64bits mode */ + if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { + UDERR(u, "swapgs invalid in 64bits mode\n"); + return -1; + } + + if (u->mnemonic == UD_Ixchg) { + if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX && + u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) || + (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX && + u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) { + u->operand[0].type = UD_NONE; + u->operand[1].type = UD_NONE; + u->mnemonic = UD_Inop; + } + } + + if (u->mnemonic == UD_Inop && u->pfx_repe) { + u->pfx_repe = 0; + u->mnemonic = UD_Ipause; + } + return 0; +} + + +/* ----------------------------------------------------------------------------- + * decode_a()- Decodes operands of the type seg:offset + * ----------------------------------------------------------------------------- + */ +static void +decode_a(struct ud* u, struct ud_operand *op) +{ + if (u->opr_mode == 16) { + /* seg16:off16 */ + op->type = UD_OP_PTR; + op->size = 32; + op->lval.ptr.off = inp_uint16(u); + op->lval.ptr.seg = inp_uint16(u); + } else { + /* seg16:off32 */ + op->type = UD_OP_PTR; + op->size = 48; + op->lval.ptr.off = inp_uint32(u); + op->lval.ptr.seg = inp_uint16(u); + } +} + +/* ----------------------------------------------------------------------------- + * decode_gpr() - Returns decoded General Purpose Register + * ----------------------------------------------------------------------------- + */ +static enum ud_type +decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) +{ + switch (s) { + case 64: + return UD_R_RAX + rm; + case 32: + return UD_R_EAX + rm; + case 16: + return UD_R_AX + rm; + case 8: + if (u->dis_mode == 64 && u->pfx_rex) { + if (rm >= 4) + return UD_R_SPL + (rm-4); + return UD_R_AL + rm; + } else return UD_R_AL + rm; + case 0: + /* invalid size in case of a decode error */ + UD_ASSERT(u->error); + return UD_NONE; + default: + UD_ASSERT(!"invalid operand size"); + return UD_NONE; + } +} + +static void +decode_reg(struct ud *u, + struct ud_operand *opr, + int type, + int num, + int size) +{ + int reg; + size = resolve_operand_size(u, size); + switch (type) { + case REGCLASS_GPR : reg = decode_gpr(u, size, num); break; + case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break; + case REGCLASS_XMM : reg = UD_R_XMM0 + num; break; + case REGCLASS_CR : reg = UD_R_CR0 + num; break; + case REGCLASS_DB : reg = UD_R_DR0 + num; break; + case REGCLASS_SEG : { + /* + * Only 6 segment registers, anything else is an error. + */ + if ((num & 7) > 5) { + UDERR(u, "invalid segment register value\n"); + return; + } else { + reg = UD_R_ES + (num & 7); + } + break; + } + default: + UD_ASSERT(!"invalid register type"); + return; + } + opr->type = UD_OP_REG; + opr->base = reg; + opr->size = size; +} + + +/* + * decode_imm + * + * Decode Immediate values. + */ +static void +decode_imm(struct ud* u, unsigned int size, struct ud_operand *op) +{ + op->size = resolve_operand_size(u, size); + op->type = UD_OP_IMM; + + switch (op->size) { + case 8: op->lval.sbyte = inp_uint8(u); break; + case 16: op->lval.uword = inp_uint16(u); break; + case 32: op->lval.udword = inp_uint32(u); break; + case 64: op->lval.uqword = inp_uint64(u); break; + default: return; + } +} + + +/* + * decode_mem_disp + * + * Decode mem address displacement. + */ +static void +decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op) +{ + switch (size) { + case 8: + op->offset = 8; + op->lval.ubyte = inp_uint8(u); + break; + case 16: + op->offset = 16; + op->lval.uword = inp_uint16(u); + break; + case 32: + op->offset = 32; + op->lval.udword = inp_uint32(u); + break; + case 64: + op->offset = 64; + op->lval.uqword = inp_uint64(u); + break; + default: + return; + } +} + + +/* + * decode_modrm_reg + * + * Decodes reg field of mod/rm byte + * + */ +static inline void +decode_modrm_reg(struct ud *u, + struct ud_operand *operand, + unsigned int type, + unsigned int size) +{ + uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); + decode_reg(u, operand, type, reg, size); +} + + +/* + * decode_modrm_rm + * + * Decodes rm field of mod/rm byte + * + */ +static void +decode_modrm_rm(struct ud *u, + struct ud_operand *op, + unsigned char type, /* register type */ + unsigned int size) /* operand size */ + +{ + size_t offset = 0; + unsigned char mod, rm; + + /* get mod, r/m and reg fields */ + mod = MODRM_MOD(modrm(u)); + rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u)); + + /* + * If mod is 11b, then the modrm.rm specifies a register. + * + */ + if (mod == 3) { + decode_reg(u, op, type, rm, size); + return; + } + + /* + * !11b => Memory Address + */ + op->type = UD_OP_MEM; + op->size = resolve_operand_size(u, size); + + if (u->adr_mode == 64) { + op->base = UD_R_RAX + rm; + if (mod == 1) { + offset = 8; + } else if (mod == 2) { + offset = 32; + } else if (mod == 0 && (rm & 7) == 5) { + op->base = UD_R_RIP; + offset = 32; + } else { + offset = 0; + } + /* + * Scale-Index-Base (SIB) + */ + if ((rm & 7) == 4) { + inp_next(u); + + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; + op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); + op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); + + /* special conditions for base reference */ + if (op->index == UD_R_RSP) { + op->index = UD_NONE; + op->scale = UD_NONE; + } + + if (op->base == UD_R_RBP || op->base == UD_R_R13) { + if (mod == 0) { + op->base = UD_NONE; + } + if (mod == 1) { + offset = 8; + } else { + offset = 32; + } + } + } + } else if (u->adr_mode == 32) { + op->base = UD_R_EAX + rm; + if (mod == 1) { + offset = 8; + } else if (mod == 2) { + offset = 32; + } else if (mod == 0 && rm == 5) { + op->base = UD_NONE; + offset = 32; + } else { + offset = 0; + } + + /* Scale-Index-Base (SIB) */ + if ((rm & 7) == 4) { + inp_next(u); + + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; + op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); + op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); + + if (op->index == UD_R_ESP) { + op->index = UD_NONE; + op->scale = UD_NONE; + } + + /* special condition for base reference */ + if (op->base == UD_R_EBP) { + if (mod == 0) { + op->base = UD_NONE; + } + if (mod == 1) { + offset = 8; + } else { + offset = 32; + } + } + } + } else { + const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, + UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; + const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, + UD_NONE, UD_NONE, UD_NONE, UD_NONE }; + op->base = bases[rm & 7]; + op->index = indices[rm & 7]; + if (mod == 0 && rm == 6) { + offset = 16; + op->base = UD_NONE; + } else if (mod == 1) { + offset = 8; + } else if (mod == 2) { + offset = 16; + } + } + + if (offset) { + decode_mem_disp(u, offset, op); + } +} + + +/* + * decode_moffset + * Decode offset-only memory operand + */ +static void +decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr) +{ + opr->type = UD_OP_MEM; + opr->size = resolve_operand_size(u, size); + decode_mem_disp(u, u->adr_mode, opr); +} + + +/* ----------------------------------------------------------------------------- + * decode_operands() - Disassembles Operands. + * ----------------------------------------------------------------------------- + */ +static int +decode_operand(struct ud *u, + struct ud_operand *operand, + enum ud_operand_code type, + unsigned int size) +{ + operand->_oprcode = type; + + switch (type) { + case OP_A : + decode_a(u, operand); + break; + case OP_MR: + decode_modrm_rm(u, operand, REGCLASS_GPR, + MODRM_MOD(modrm(u)) == 3 ? + Mx_reg_size(size) : Mx_mem_size(size)); + break; + case OP_F: + u->br_far = 1; + fallthrough; + case OP_M: + if (MODRM_MOD(modrm(u)) == 3) { + UDERR(u, "expected modrm.mod != 3\n"); + } + fallthrough; + case OP_E: + decode_modrm_rm(u, operand, REGCLASS_GPR, size); + break; + case OP_G: + decode_modrm_reg(u, operand, REGCLASS_GPR, size); + break; + case OP_sI: + case OP_I: + decode_imm(u, size, operand); + break; + case OP_I1: + operand->type = UD_OP_CONST; + operand->lval.udword = 1; + break; + case OP_N: + if (MODRM_MOD(modrm(u)) != 3) { + UDERR(u, "expected modrm.mod == 3\n"); + } + fallthrough; + case OP_Q: + decode_modrm_rm(u, operand, REGCLASS_MMX, size); + break; + case OP_P: + decode_modrm_reg(u, operand, REGCLASS_MMX, size); + break; + case OP_U: + if (MODRM_MOD(modrm(u)) != 3) { + UDERR(u, "expected modrm.mod == 3\n"); + } + fallthrough; + case OP_W: + decode_modrm_rm(u, operand, REGCLASS_XMM, size); + break; + case OP_V: + decode_modrm_reg(u, operand, REGCLASS_XMM, size); + break; + case OP_MU: + decode_modrm_rm(u, operand, REGCLASS_XMM, + MODRM_MOD(modrm(u)) == 3 ? + Mx_reg_size(size) : Mx_mem_size(size)); + break; + case OP_S: + decode_modrm_reg(u, operand, REGCLASS_SEG, size); + break; + case OP_O: + decode_moffset(u, size, operand); + break; + case OP_R0: + case OP_R1: + case OP_R2: + case OP_R3: + case OP_R4: + case OP_R5: + case OP_R6: + case OP_R7: + decode_reg(u, operand, REGCLASS_GPR, + (REX_B(u->pfx_rex) << 3) | (type - OP_R0), size); + break; + case OP_AL: + case OP_AX: + case OP_eAX: + case OP_rAX: + decode_reg(u, operand, REGCLASS_GPR, 0, size); + break; + case OP_CL: + case OP_CX: + case OP_eCX: + decode_reg(u, operand, REGCLASS_GPR, 1, size); + break; + case OP_DL: + case OP_DX: + case OP_eDX: + decode_reg(u, operand, REGCLASS_GPR, 2, size); + break; + case OP_ES: + case OP_CS: + case OP_DS: + case OP_SS: + case OP_FS: + case OP_GS: + /* in 64bits mode, only fs and gs are allowed */ + if (u->dis_mode == 64) { + if (type != OP_FS && type != OP_GS) { + UDERR(u, "invalid segment register in 64bits\n"); + } + } + operand->type = UD_OP_REG; + operand->base = (type - OP_ES) + UD_R_ES; + operand->size = 16; + break; + case OP_J : + decode_imm(u, size, operand); + operand->type = UD_OP_JIMM; + break ; + case OP_R : + if (MODRM_MOD(modrm(u)) != 3) { + UDERR(u, "expected modrm.mod == 3\n"); + } + decode_modrm_rm(u, operand, REGCLASS_GPR, size); + break; + case OP_C: + decode_modrm_reg(u, operand, REGCLASS_CR, size); + break; + case OP_D: + decode_modrm_reg(u, operand, REGCLASS_DB, size); + break; + case OP_I3 : + operand->type = UD_OP_CONST; + operand->lval.sbyte = 3; + break; + case OP_ST0: + case OP_ST1: + case OP_ST2: + case OP_ST3: + case OP_ST4: + case OP_ST5: + case OP_ST6: + case OP_ST7: + operand->type = UD_OP_REG; + operand->base = (type - OP_ST0) + UD_R_ST0; + operand->size = 80; + break; + default : + break; + } + return 0; +} + + +/* + * decode_operands + * + * Disassemble upto 3 operands of the current instruction being + * disassembled. By the end of the function, the operand fields + * of the ud structure will have been filled. + */ +static int +decode_operands(struct ud* u) +{ + decode_operand(u, &u->operand[0], + u->itab_entry->operand1.type, + u->itab_entry->operand1.size); + decode_operand(u, &u->operand[1], + u->itab_entry->operand2.type, + u->itab_entry->operand2.size); + decode_operand(u, &u->operand[2], + u->itab_entry->operand3.type, + u->itab_entry->operand3.size); + return 0; +} + +/* ----------------------------------------------------------------------------- + * clear_insn() - clear instruction structure + * ----------------------------------------------------------------------------- + */ +static void +clear_insn(register struct ud* u) +{ + u->error = 0; + u->pfx_seg = 0; + u->pfx_opr = 0; + u->pfx_adr = 0; + u->pfx_lock = 0; + u->pfx_repne = 0; + u->pfx_rep = 0; + u->pfx_repe = 0; + u->pfx_rex = 0; + u->pfx_str = 0; + u->mnemonic = UD_Inone; + u->itab_entry = NULL; + u->have_modrm = 0; + u->br_far = 0; + + memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) ); + memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) ); + memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) ); +} + + +static inline int +resolve_pfx_str(struct ud* u) +{ + if (u->pfx_str == 0xf3) { + if (P_STR(u->itab_entry->prefix)) { + u->pfx_rep = 0xf3; + } else { + u->pfx_repe = 0xf3; + } + } else if (u->pfx_str == 0xf2) { + u->pfx_repne = 0xf3; + } + return 0; +} + + +static int +resolve_mode( struct ud* u ) +{ + int default64; + /* if in error state, bail out */ + if ( u->error ) return -1; + + /* propagate prefix effects */ + if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ + + /* Check validity of instruction m64 */ + if ( P_INV64( u->itab_entry->prefix ) ) { + UDERR(u, "instruction invalid in 64bits\n"); + return -1; + } + + /* effective rex prefix is the effective mask for the + * instruction hard-coded in the opcode map. + */ + u->pfx_rex = ( u->pfx_rex & 0x40 ) | + ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) ); + + /* whether this instruction has a default operand size of + * 64bit, also hardcoded into the opcode map. + */ + default64 = P_DEF64( u->itab_entry->prefix ); + /* calculate effective operand size */ + if ( REX_W( u->pfx_rex ) ) { + u->opr_mode = 64; + } else if ( u->pfx_opr ) { + u->opr_mode = 16; + } else { + /* unless the default opr size of instruction is 64, + * the effective operand size in the absence of rex.w + * prefix is 32. + */ + u->opr_mode = default64 ? 64 : 32; + } + + /* calculate effective address size */ + u->adr_mode = (u->pfx_adr) ? 32 : 64; + } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ + u->opr_mode = ( u->pfx_opr ) ? 16 : 32; + u->adr_mode = ( u->pfx_adr ) ? 16 : 32; + } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ + u->opr_mode = ( u->pfx_opr ) ? 32 : 16; + u->adr_mode = ( u->pfx_adr ) ? 32 : 16; + } + + return 0; +} + + +static inline int +decode_insn(struct ud *u, uint16_t ptr) +{ + UD_ASSERT((ptr & 0x8000) == 0); + u->itab_entry = &ud_itab[ ptr ]; + u->mnemonic = u->itab_entry->mnemonic; + return (resolve_pfx_str(u) == 0 && + resolve_mode(u) == 0 && + decode_operands(u) == 0 && + resolve_mnemonic(u) == 0) ? 0 : -1; +} + + +/* + * decode_3dnow() + * + * Decoding 3dnow is a little tricky because of its strange opcode + * structure. The final opcode disambiguation depends on the last + * byte that comes after the operands have been decoded. Fortunately, + * all 3dnow instructions have the same set of operand types. So we + * go ahead and decode the instruction by picking an arbitrarily chosen + * valid entry in the table, decode the operands, and read the final + * byte to resolve the menmonic. + */ +static inline int +decode_3dnow(struct ud* u) +{ + uint16_t ptr; + UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); + UD_ASSERT(u->le->table[0xc] != 0); + decode_insn(u, u->le->table[0xc]); + inp_next(u); + if (u->error) { + return -1; + } + ptr = u->le->table[inp_curr(u)]; + UD_ASSERT((ptr & 0x8000) == 0); + u->mnemonic = ud_itab[ptr].mnemonic; + return 0; +} + + +static int +decode_ssepfx(struct ud *u) +{ + uint8_t idx; + uint8_t pfx; + + /* + * String prefixes (f2, f3) take precedence over operand + * size prefix (66). + */ + pfx = u->pfx_str; + if (pfx == 0) { + pfx = u->pfx_opr; + } + idx = ((pfx & 0xf) + 1) / 2; + if (u->le->table[idx] == 0) { + idx = 0; + } + if (idx && u->le->table[idx] != 0) { + /* + * "Consume" the prefix as a part of the opcode, so it is no + * longer exported as an instruction prefix. + */ + u->pfx_str = 0; + if (pfx == 0x66) { + /* + * consume "66" only if it was used for decoding, leaving + * it to be used as an operands size override for some + * simd instructions. + */ + u->pfx_opr = 0; + } + } + return decode_ext(u, u->le->table[idx]); +} + + +/* + * decode_ext() + * + * Decode opcode extensions (if any) + */ +static int +decode_ext(struct ud *u, uint16_t ptr) +{ + uint8_t idx = 0; + if ((ptr & 0x8000) == 0) { + return decode_insn(u, ptr); + } + u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; + if (u->le->type == UD_TAB__OPC_3DNOW) { + return decode_3dnow(u); + } + + switch (u->le->type) { + case UD_TAB__OPC_MOD: + /* !11 = 0, 11 = 1 */ + idx = (MODRM_MOD(modrm(u)) + 1) / 4; + break; + /* disassembly mode/operand size/address size based tables. + * 16 = 0,, 32 = 1, 64 = 2 + */ + case UD_TAB__OPC_MODE: + idx = u->dis_mode != 64 ? 0 : 1; + break; + case UD_TAB__OPC_OSIZE: + idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; + break; + case UD_TAB__OPC_ASIZE: + idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; + break; + case UD_TAB__OPC_X87: + idx = modrm(u) - 0xC0; + break; + case UD_TAB__OPC_VENDOR: + if (u->vendor == UD_VENDOR_ANY) { + /* choose a valid entry */ + idx = (u->le->table[idx] != 0) ? 0 : 1; + } else if (u->vendor == UD_VENDOR_AMD) { + idx = 0; + } else { + idx = 1; + } + break; + case UD_TAB__OPC_RM: + idx = MODRM_RM(modrm(u)); + break; + case UD_TAB__OPC_REG: + idx = MODRM_REG(modrm(u)); + break; + case UD_TAB__OPC_SSE: + return decode_ssepfx(u); + default: + UD_ASSERT(!"not reached"); + break; + } + + return decode_ext(u, u->le->table[idx]); +} + + +static int +decode_opcode(struct ud *u) +{ + uint16_t ptr; + UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); + UD_RETURN_ON_ERROR(u); + u->primary_opcode = inp_curr(u); + ptr = u->le->table[inp_curr(u)]; + if (ptr & 0x8000) { + u->le = &ud_lookup_table_list[ptr & ~0x8000]; + if (u->le->type == UD_TAB__OPC_TABLE) { + inp_next(u); + return decode_opcode(u); + } + } + return decode_ext(u, ptr); +} + + +/* ============================================================================= + * ud_decode() - Instruction decoder. Returns the number of bytes decoded. + * ============================================================================= + */ +unsigned int +ud_decode(struct ud *u) +{ + inp_start(u); + clear_insn(u); + u->le = &ud_lookup_table_list[0]; + u->error = decode_prefixes(u) == -1 || + decode_opcode(u) == -1 || + u->error; + /* Handle decode error. */ + if (u->error) { + /* clear out the decode data. */ + clear_insn(u); + /* mark the sequence of bytes as invalid. */ + u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */ + u->mnemonic = u->itab_entry->mnemonic; + } + + /* maybe this stray segment override byte + * should be spewed out? + */ + if ( !P_SEG( u->itab_entry->prefix ) && + u->operand[0].type != UD_OP_MEM && + u->operand[1].type != UD_OP_MEM ) + u->pfx_seg = 0; + + u->insn_offset = u->pc; /* set offset of instruction */ + u->asm_buf_fill = 0; /* set translation buffer index to 0 */ + u->pc += u->inp_ctr; /* move program counter by bytes decoded */ + + /* return number of bytes disassembled. */ + return u->inp_ctr; +} + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/winsup/cygwin/udis86/decode.h b/winsup/cygwin/udis86/decode.h new file mode 100644 index 0000000..8d1af57 --- /dev/null +++ b/winsup/cygwin/udis86/decode.h @@ -0,0 +1,195 @@ +/* udis86 - libudis86/decode.h + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * + * 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 OWNER 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 UD_DECODE_H +#define UD_DECODE_H + +#include "types.h" +#include "itab.h" + +#define MAX_INSN_LENGTH 15 + +/* itab prefix bits */ +#define P_none ( 0 ) +#define P_cast ( 1 << 0 ) +#define P_CAST(n) ( ( n >> 0 ) & 1 ) +#define P_rexb ( 1 << 1 ) +#define P_REXB(n) ( ( n >> 1 ) & 1 ) +#define P_inv64 ( 1 << 4 ) +#define P_INV64(n) ( ( n >> 4 ) & 1 ) +#define P_rexw ( 1 << 5 ) +#define P_REXW(n) ( ( n >> 5 ) & 1 ) +#define P_def64 ( 1 << 7 ) +#define P_DEF64(n) ( ( n >> 7 ) & 1 ) +#define P_rexr ( 1 << 8 ) +#define P_REXR(n) ( ( n >> 8 ) & 1 ) +#define P_oso ( 1 << 9 ) +#define P_OSO(n) ( ( n >> 9 ) & 1 ) +#define P_aso ( 1 << 10 ) +#define P_ASO(n) ( ( n >> 10 ) & 1 ) +#define P_rexx ( 1 << 11 ) +#define P_REXX(n) ( ( n >> 11 ) & 1 ) +#define P_ImpAddr ( 1 << 12 ) +#define P_IMPADDR(n) ( ( n >> 12 ) & 1 ) +#define P_seg ( 1 << 13 ) +#define P_SEG(n) ( ( n >> 13 ) & 1 ) +#define P_str ( 1 << 14 ) +#define P_STR(n) ( ( n >> 14 ) & 1 ) +#define P_strz ( 1 << 15 ) +#define P_STR_ZF(n) ( ( n >> 15 ) & 1 ) + +/* operand type constants -- order is important! */ + +enum ud_operand_code { + OP_NONE, + + OP_A, OP_E, OP_M, OP_G, + OP_I, OP_F, + + OP_R0, OP_R1, OP_R2, OP_R3, + OP_R4, OP_R5, OP_R6, OP_R7, + + OP_AL, OP_CL, OP_DL, + OP_AX, OP_CX, OP_DX, + OP_eAX, OP_eCX, OP_eDX, + OP_rAX, OP_rCX, OP_rDX, + + OP_ES, OP_CS, OP_SS, OP_DS, + OP_FS, OP_GS, + + OP_ST0, OP_ST1, OP_ST2, OP_ST3, + OP_ST4, OP_ST5, OP_ST6, OP_ST7, + + OP_J, OP_S, OP_O, + OP_I1, OP_I3, OP_sI, + + OP_V, OP_W, OP_Q, OP_P, + OP_U, OP_N, OP_MU, + + OP_R, OP_C, OP_D, + + OP_MR +} UD_ATTR_PACKED; + + +/* operand size constants */ + +enum ud_operand_size { + SZ_NA = 0, + SZ_Z = 1, + SZ_V = 2, + SZ_RDQ = 7, + + /* the following values are used as is, + * and thus hard-coded. changing them + * will break internals + */ + SZ_B = 8, + SZ_W = 16, + SZ_D = 32, + SZ_Q = 64, + SZ_T = 80, + SZ_O = 128, + + SZ_Y = 17, + + /* + * complex size types, that encode sizes for operands + * of type MR (memory or register), for internal use + * only. Id space 256 and above. + */ + SZ_BD = (SZ_B << 8) | SZ_D, + SZ_BV = (SZ_B << 8) | SZ_V, + SZ_WD = (SZ_W << 8) | SZ_D, + SZ_WV = (SZ_W << 8) | SZ_V, + SZ_WY = (SZ_W << 8) | SZ_Y, + SZ_DY = (SZ_D << 8) | SZ_Y, + SZ_WO = (SZ_W << 8) | SZ_O, + SZ_DO = (SZ_D << 8) | SZ_O, + SZ_QO = (SZ_Q << 8) | SZ_O, + +} UD_ATTR_PACKED; + + +/* resolve complex size type. + */ +static inline enum ud_operand_size +Mx_mem_size(enum ud_operand_size size) +{ + return (size >> 8) & 0xff; +} + +static inline enum ud_operand_size +Mx_reg_size(enum ud_operand_size size) +{ + return size & 0xff; +} + +/* A single operand of an entry in the instruction table. + * (internal use only) + */ +struct ud_itab_entry_operand +{ + enum ud_operand_code type; + enum ud_operand_size size; +}; + + +/* A single entry in an instruction table. + *(internal use only) + */ +struct ud_itab_entry +{ + enum ud_mnemonic_code mnemonic; + struct ud_itab_entry_operand operand1; + struct ud_itab_entry_operand operand2; + struct ud_itab_entry_operand operand3; + uint32_t prefix; +}; + +struct ud_lookup_table_list_entry { + const uint16_t *table; + enum ud_table_type type; + const char *meta; +}; + + + +static inline int +ud_opcode_field_sext(uint8_t primary_opcode) +{ + return (primary_opcode & 0x02) != 0; +} + +extern const struct ud_itab_entry ud_itab[]; +extern const struct ud_lookup_table_list_entry ud_lookup_table_list[]; + +#endif /* UD_DECODE_H */ + +/* vim:cindent + * vim:expandtab + * vim:ts=4 + * vim:sw=4 + */ diff --git a/winsup/cygwin/udis86/extern.h b/winsup/cygwin/udis86/extern.h new file mode 100644 index 0000000..0a5e892 --- /dev/null +++ b/winsup/cygwin/udis86/extern.h @@ -0,0 +1,109 @@ +/* udis86 - libudis86/extern.h + * + * Copyright (c) 2002-2009, 2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * + * 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 OWNER 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 UD_EXTERN_H +#define UD_EXTERN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +/* ============================= PUBLIC API ================================= */ + +extern void ud_init(struct ud*); + +extern void ud_set_mode(struct ud*, uint8_t); + +extern void ud_set_pc(struct ud*, uint64_t); + +extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); + +extern void ud_set_input_buffer(struct ud*, const uint8_t*, size_t); + +#ifndef __UD_STANDALONE__ +extern void ud_set_input_file(struct ud*, FILE*); +#endif /* __UD_STANDALONE__ */ + +extern void ud_set_vendor(struct ud*, unsigned); + +extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); + +extern void ud_input_skip(struct ud*, size_t); + +extern int ud_input_end(const struct ud*); + +extern unsigned int ud_decode(struct ud*); + +extern unsigned int ud_disassemble(struct ud*); + +#ifndef __INSIDE_CYGWIN__ +extern void ud_translate_intel(struct ud*); + +extern void ud_translate_att(struct ud*); +#endif /* __INSIDE_CYGWIN__ */ + +extern const char* ud_insn_asm(const struct ud* u); + +extern const uint8_t* ud_insn_ptr(const struct ud* u); + +extern uint64_t ud_insn_off(const struct ud*); + +extern const char* ud_insn_hex(struct ud*); + +extern unsigned int ud_insn_len(const struct ud* u); + +extern const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n); + +extern int ud_opr_is_sreg(const struct ud_operand *opr); + +extern int ud_opr_is_gpr(const struct ud_operand *opr); + +extern enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u); + +#ifndef __INSIDE_CYGWIN__ +extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); +#endif /* __INSIDE_CYGWIN__ */ + +extern void ud_set_user_opaque_data(struct ud*, void*); + +extern void* ud_get_user_opaque_data(const struct ud*); + +extern uint64_t ud_insn_sext_imm(const struct ud*, const struct ud_operand*); + +extern void ud_set_asm_buffer(struct ud *u, char *buf, size_t size); + +extern void ud_set_sym_resolver(struct ud *u, + const char* (*resolver)(struct ud*, + uint64_t addr, + int64_t *offset)); + +/* ========================================================================== */ + +#ifdef __cplusplus +} +#endif +#endif /* UD_EXTERN_H */ diff --git a/winsup/cygwin/udis86/itab.c b/winsup/cygwin/udis86/itab.c new file mode 100644 index 0000000..11c350b --- /dev/null +++ b/winsup/cygwin/udis86/itab.c @@ -0,0 +1,8404 @@ +/* itab.c -- generated by udis86:scripts/ud_itab.py, do no edit */ +#include "winsup.h" +#include "decode.h" + +#define GROUP(n) (0x8000 | (n)) + + +static const uint16_t ud_itab__1[] = { + /* 0 */ 7, 0, +}; + +static const uint16_t ud_itab__2[] = { + /* 0 */ 8, 0, +}; + +static const uint16_t ud_itab__3[] = { + /* 0 */ 15, 0, +}; + +static const uint16_t ud_itab__6[] = { + /* 0 */ 16, 0, 0, 0, +}; + +static const uint16_t ud_itab__7[] = { + /* 0 */ 17, 0, 0, 0, +}; + +static const uint16_t ud_itab__8[] = { + /* 0 */ 18, 0, 0, 0, +}; + +static const uint16_t ud_itab__9[] = { + /* 0 */ 19, 0, 0, 0, +}; + +static const uint16_t ud_itab__10[] = { + /* 0 */ 20, 0, 0, 0, +}; + +static const uint16_t ud_itab__11[] = { + /* 0 */ 21, 0, 0, 0, +}; + +static const uint16_t ud_itab__5[] = { + /* 0 */ GROUP(6), GROUP(7), GROUP(8), GROUP(9), + /* 4 */ GROUP(10), GROUP(11), 0, 0, +}; + +static const uint16_t ud_itab__15[] = { + /* 0 */ 22, 0, +}; + +static const uint16_t ud_itab__14[] = { + /* 0 */ GROUP(15), 0, 0, 0, +}; + +static const uint16_t ud_itab__17[] = { + /* 0 */ 23, 0, +}; + +static const uint16_t ud_itab__16[] = { + /* 0 */ GROUP(17), 0, 0, 0, +}; + +static const uint16_t ud_itab__19[] = { + /* 0 */ 24, 0, +}; + +static const uint16_t ud_itab__18[] = { + /* 0 */ GROUP(19), 0, 0, 0, +}; + +static const uint16_t ud_itab__21[] = { + /* 0 */ 25, 0, +}; + +static const uint16_t ud_itab__20[] = { + /* 0 */ GROUP(21), 0, 0, 0, +}; + +static const uint16_t ud_itab__23[] = { + /* 0 */ 26, 0, +}; + +static const uint16_t ud_itab__22[] = { + /* 0 */ GROUP(23), 0, 0, 0, +}; + +static const uint16_t ud_itab__25[] = { + /* 0 */ 27, 0, +}; + +static const uint16_t ud_itab__24[] = { + /* 0 */ GROUP(25), 0, 0, 0, +}; + +static const uint16_t ud_itab__27[] = { + /* 0 */ 28, 0, +}; + +static const uint16_t ud_itab__26[] = { + /* 0 */ GROUP(27), 0, 0, 0, +}; + +static const uint16_t ud_itab__13[] = { + /* 0 */ GROUP(14), GROUP(16), GROUP(18), GROUP(20), + /* 4 */ GROUP(22), 0, GROUP(24), GROUP(26), +}; + +static const uint16_t ud_itab__32[] = { + /* 0 */ 0, 29, 0, +}; + +static const uint16_t ud_itab__31[] = { + /* 0 */ 0, GROUP(32), +}; + +static const uint16_t ud_itab__30[] = { + /* 0 */ GROUP(31), 0, 0, 0, +}; + +static const uint16_t ud_itab__35[] = { + /* 0 */ 0, 30, 0, +}; + +static const uint16_t ud_itab__34[] = { + /* 0 */ 0, GROUP(35), +}; + +static const uint16_t ud_itab__33[] = { + /* 0 */ GROUP(34), 0, 0, 0, +}; + +static const uint16_t ud_itab__38[] = { + /* 0 */ 0, 31, 0, +}; + +static const uint16_t ud_itab__37[] = { + /* 0 */ 0, GROUP(38), +}; + +static const uint16_t ud_itab__36[] = { + /* 0 */ GROUP(37), 0, 0, 0, +}; + +static const uint16_t ud_itab__41[] = { + /* 0 */ 0, 32, 0, +}; + +static const uint16_t ud_itab__40[] = { + /* 0 */ 0, GROUP(41), +}; + +static const uint16_t ud_itab__39[] = { + /* 0 */ GROUP(40), 0, 0, 0, +}; + +static const uint16_t ud_itab__29[] = { + /* 0 */ 0, GROUP(30), GROUP(33), GROUP(36), + /* 4 */ GROUP(39), 0, 0, 0, +}; + +static const uint16_t ud_itab__44[] = { + /* 0 */ 0, 33, +}; + +static const uint16_t ud_itab__43[] = { + /* 0 */ GROUP(44), 0, 0, 0, +}; + +static const uint16_t ud_itab__46[] = { + /* 0 */ 0, 34, +}; + +static const uint16_t ud_itab__45[] = { + /* 0 */ GROUP(46), 0, 0, 0, +}; + +static const uint16_t ud_itab__42[] = { + /* 0 */ GROUP(43), GROUP(45), 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__49[] = { + /* 0 */ 0, 35, +}; + +static const uint16_t ud_itab__48[] = { + /* 0 */ GROUP(49), 0, 0, 0, +}; + +static const uint16_t ud_itab__51[] = { + /* 0 */ 0, 36, +}; + +static const uint16_t ud_itab__50[] = { + /* 0 */ GROUP(51), 0, 0, 0, +}; + +static const uint16_t ud_itab__47[] = { + /* 0 */ GROUP(48), GROUP(50), 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__55[] = { + /* 0 */ 37, 0, 0, +}; + +static const uint16_t ud_itab__54[] = { + /* 0 */ 0, GROUP(55), +}; + +static const uint16_t ud_itab__53[] = { + /* 0 */ GROUP(54), 0, 0, 0, +}; + +static const uint16_t ud_itab__58[] = { + /* 0 */ 38, 0, 0, +}; + +static const uint16_t ud_itab__57[] = { + /* 0 */ 0, GROUP(58), +}; + +static const uint16_t ud_itab__56[] = { + /* 0 */ GROUP(57), 0, 0, 0, +}; + +static const uint16_t ud_itab__61[] = { + /* 0 */ 39, 0, 0, +}; + +static const uint16_t ud_itab__60[] = { + /* 0 */ 0, GROUP(61), +}; + +static const uint16_t ud_itab__59[] = { + /* 0 */ GROUP(60), 0, 0, 0, +}; + +static const uint16_t ud_itab__64[] = { + /* 0 */ 40, 0, 0, +}; + +static const uint16_t ud_itab__63[] = { + /* 0 */ 0, GROUP(64), +}; + +static const uint16_t ud_itab__62[] = { + /* 0 */ GROUP(63), 0, 0, 0, +}; + +static const uint16_t ud_itab__67[] = { + /* 0 */ 41, 0, 0, +}; + +static const uint16_t ud_itab__66[] = { + /* 0 */ 0, GROUP(67), +}; + +static const uint16_t ud_itab__65[] = { + /* 0 */ GROUP(66), 0, 0, 0, +}; + +static const uint16_t ud_itab__70[] = { + /* 0 */ 42, 0, 0, +}; + +static const uint16_t ud_itab__69[] = { + /* 0 */ 0, GROUP(70), +}; + +static const uint16_t ud_itab__68[] = { + /* 0 */ GROUP(69), 0, 0, 0, +}; + +static const uint16_t ud_itab__73[] = { + /* 0 */ 43, 0, 0, +}; + +static const uint16_t ud_itab__72[] = { + /* 0 */ 0, GROUP(73), +}; + +static const uint16_t ud_itab__71[] = { + /* 0 */ GROUP(72), 0, 0, 0, +}; + +static const uint16_t ud_itab__76[] = { + /* 0 */ 44, 0, 0, +}; + +static const uint16_t ud_itab__75[] = { + /* 0 */ 0, GROUP(76), +}; + +static const uint16_t ud_itab__74[] = { + /* 0 */ GROUP(75), 0, 0, 0, +}; + +static const uint16_t ud_itab__52[] = { + /* 0 */ GROUP(53), GROUP(56), GROUP(59), GROUP(62), + /* 4 */ GROUP(65), GROUP(68), GROUP(71), GROUP(74), +}; + +static const uint16_t ud_itab__78[] = { + /* 0 */ 0, 45, +}; + +static const uint16_t ud_itab__77[] = { + /* 0 */ GROUP(78), 0, 0, 0, +}; + +static const uint16_t ud_itab__80[] = { + /* 0 */ 0, 46, +}; + +static const uint16_t ud_itab__79[] = { + /* 0 */ GROUP(80), 0, 0, 0, +}; + +static const uint16_t ud_itab__83[] = { + /* 0 */ 0, 47, +}; + +static const uint16_t ud_itab__82[] = { + /* 0 */ GROUP(83), 0, 0, 0, +}; + +static const uint16_t ud_itab__86[] = { + /* 0 */ 48, 0, 0, +}; + +static const uint16_t ud_itab__85[] = { + /* 0 */ 0, GROUP(86), +}; + +static const uint16_t ud_itab__84[] = { + /* 0 */ GROUP(85), 0, 0, 0, +}; + +static const uint16_t ud_itab__81[] = { + /* 0 */ GROUP(82), GROUP(84), 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__28[] = { + /* 0 */ GROUP(29), GROUP(42), GROUP(47), GROUP(52), + /* 4 */ GROUP(77), 0, GROUP(79), GROUP(81), +}; + +static const uint16_t ud_itab__12[] = { + /* 0 */ GROUP(13), GROUP(28), +}; + +static const uint16_t ud_itab__87[] = { + /* 0 */ 49, 0, 0, 0, +}; + +static const uint16_t ud_itab__88[] = { + /* 0 */ 50, 0, 0, 0, +}; + +static const uint16_t ud_itab__89[] = { + /* 0 */ 51, 0, 0, 0, +}; + +static const uint16_t ud_itab__90[] = { + /* 0 */ 52, 0, 0, 0, +}; + +static const uint16_t ud_itab__91[] = { + /* 0 */ 53, 0, 0, 0, +}; + +static const uint16_t ud_itab__92[] = { + /* 0 */ 54, 0, 0, 0, +}; + +static const uint16_t ud_itab__93[] = { + /* 0 */ 55, 0, 0, 0, +}; + +static const uint16_t ud_itab__94[] = { + /* 0 */ 56, 0, 0, 0, +}; + +static const uint16_t ud_itab__96[] = { + /* 0 */ 57, 0, 0, 0, +}; + +static const uint16_t ud_itab__97[] = { + /* 0 */ 58, 0, 0, 0, +}; + +static const uint16_t ud_itab__98[] = { + /* 0 */ 59, 0, 0, 0, +}; + +static const uint16_t ud_itab__99[] = { + /* 0 */ 60, 0, 0, 0, +}; + +static const uint16_t ud_itab__100[] = { + /* 0 */ 61, 0, 0, 0, +}; + +static const uint16_t ud_itab__101[] = { + /* 0 */ 62, 0, 0, 0, +}; + +static const uint16_t ud_itab__102[] = { + /* 0 */ 63, 0, 0, 0, +}; + +static const uint16_t ud_itab__103[] = { + /* 0 */ 64, 0, 0, 0, +}; + +static const uint16_t ud_itab__95[] = { + /* 0 */ GROUP(96), GROUP(97), GROUP(98), GROUP(99), + /* 4 */ GROUP(100), GROUP(101), GROUP(102), GROUP(103), +}; + +static const uint16_t ud_itab__104[] = { + /* 0 */ 65, 0, 0, 0, +}; + +static const uint16_t ud_itab__105[] = { + /* 0 */ 0, 0, 0, 0, + /* 4 */ 0, 0, 0, 0, + /* 8 */ 0, 0, 0, 0, + /* c */ 66, 67, 0, 0, + /* 10 */ 0, 0, 0, 0, + /* 14 */ 0, 0, 0, 0, + /* 18 */ 0, 0, 0, 0, + /* 1c */ 68, 69, 0, 0, + /* 20 */ 0, 0, 0, 0, + /* 24 */ 0, 0, 0, 0, + /* 28 */ 0, 0, 0, 0, + /* 2c */ 0, 0, 0, 0, + /* 30 */ 0, 0, 0, 0, + /* 34 */ 0, 0, 0, 0, + /* 38 */ 0, 0, 0, 0, + /* 3c */ 0, 0, 0, 0, + /* 40 */ 0, 0, 0, 0, + /* 44 */ 0, 0, 0, 0, + /* 48 */ 0, 0, 0, 0, + /* 4c */ 0, 0, 0, 0, + /* 50 */ 0, 0, 0, 0, + /* 54 */ 0, 0, 0, 0, + /* 58 */ 0, 0, 0, 0, + /* 5c */ 0, 0, 0, 0, + /* 60 */ 0, 0, 0, 0, + /* 64 */ 0, 0, 0, 0, + /* 68 */ 0, 0, 0, 0, + /* 6c */ 0, 0, 0, 0, + /* 70 */ 0, 0, 0, 0, + /* 74 */ 0, 0, 0, 0, + /* 78 */ 0, 0, 0, 0, + /* 7c */ 0, 0, 0, 0, + /* 80 */ 0, 0, 0, 0, + /* 84 */ 0, 0, 0, 0, + /* 88 */ 0, 0, 70, 0, + /* 8c */ 0, 0, 71, 0, + /* 90 */ 72, 0, 0, 0, + /* 94 */ 73, 0, 74, 75, + /* 98 */ 0, 0, 76, 0, + /* 9c */ 0, 0, 77, 0, + /* a0 */ 78, 0, 0, 0, + /* a4 */ 79, 0, 80, 81, + /* a8 */ 0, 0, 82, 0, + /* ac */ 0, 0, 83, 0, + /* b0 */ 84, 0, 0, 0, + /* b4 */ 85, 0, 86, 87, + /* b8 */ 0, 0, 0, 88, + /* bc */ 0, 0, 0, 89, + /* c0 */ 0, 0, 0, 0, + /* c4 */ 0, 0, 0, 0, + /* c8 */ 0, 0, 0, 0, + /* cc */ 0, 0, 0, 0, + /* d0 */ 0, 0, 0, 0, + /* d4 */ 0, 0, 0, 0, + /* d8 */ 0, 0, 0, 0, + /* dc */ 0, 0, 0, 0, + /* e0 */ 0, 0, 0, 0, + /* e4 */ 0, 0, 0, 0, + /* e8 */ 0, 0, 0, 0, + /* ec */ 0, 0, 0, 0, + /* f0 */ 0, 0, 0, 0, + /* f4 */ 0, 0, 0, 0, + /* f8 */ 0, 0, 0, 0, + /* fc */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__106[] = { + /* 0 */ 90, 91, 92, 93, +}; + +static const uint16_t ud_itab__107[] = { + /* 0 */ 94, 95, 96, 97, +}; + +static const uint16_t ud_itab__110[] = { + /* 0 */ 98, 0, +}; + +static const uint16_t ud_itab__111[] = { + /* 0 */ 99, 0, +}; + +static const uint16_t ud_itab__112[] = { + /* 0 */ 100, 0, +}; + +static const uint16_t ud_itab__113[] = { + /* 0 */ 101, 0, +}; + +static const uint16_t ud_itab__109[] = { + /* 0 */ GROUP(110), GROUP(111), GROUP(112), GROUP(113), +}; + +static const uint16_t ud_itab__115[] = { + /* 0 */ 0, 102, +}; + +static const uint16_t ud_itab__116[] = { + /* 0 */ 0, 103, +}; + +static const uint16_t ud_itab__117[] = { + /* 0 */ 0, 104, +}; + +static const uint16_t ud_itab__114[] = { + /* 0 */ GROUP(115), GROUP(116), GROUP(117), 0, +}; + +static const uint16_t ud_itab__108[] = { + /* 0 */ GROUP(109), GROUP(114), +}; + +static const uint16_t ud_itab__118[] = { + /* 0 */ 105, 0, 0, 106, +}; + +static const uint16_t ud_itab__119[] = { + /* 0 */ 107, 0, 0, 108, +}; + +static const uint16_t ud_itab__120[] = { + /* 0 */ 109, 0, 0, 110, +}; + +static const uint16_t ud_itab__123[] = { + /* 0 */ 111, 0, +}; + +static const uint16_t ud_itab__124[] = { + /* 0 */ 112, 0, +}; + +static const uint16_t ud_itab__125[] = { + /* 0 */ 113, 0, +}; + +static const uint16_t ud_itab__122[] = { + /* 0 */ GROUP(123), 0, GROUP(124), GROUP(125), +}; + +static const uint16_t ud_itab__127[] = { + /* 0 */ 0, 114, +}; + +static const uint16_t ud_itab__128[] = { + /* 0 */ 0, 115, +}; + +static const uint16_t ud_itab__126[] = { + /* 0 */ GROUP(127), 0, GROUP(128), 0, +}; + +static const uint16_t ud_itab__121[] = { + /* 0 */ GROUP(122), GROUP(126), +}; + +static const uint16_t ud_itab__129[] = { + /* 0 */ 116, 0, 0, 117, +}; + +static const uint16_t ud_itab__131[] = { + /* 0 */ 118, 0, 0, 0, +}; + +static const uint16_t ud_itab__132[] = { + /* 0 */ 119, 0, 0, 0, +}; + +static const uint16_t ud_itab__133[] = { + /* 0 */ 120, 0, 0, 0, +}; + +static const uint16_t ud_itab__134[] = { + /* 0 */ 121, 0, 0, 0, +}; + +static const uint16_t ud_itab__130[] = { + /* 0 */ GROUP(131), GROUP(132), GROUP(133), GROUP(134), + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__135[] = { + /* 0 */ 122, 0, 0, 0, +}; + +static const uint16_t ud_itab__136[] = { + /* 0 */ 123, 0, 0, 0, +}; + +static const uint16_t ud_itab__137[] = { + /* 0 */ 124, 0, 0, 0, +}; + +static const uint16_t ud_itab__138[] = { + /* 0 */ 125, 0, 0, 0, +}; + +static const uint16_t ud_itab__139[] = { + /* 0 */ 126, 0, 0, 0, +}; + +static const uint16_t ud_itab__140[] = { + /* 0 */ 127, 0, 0, 0, +}; + +static const uint16_t ud_itab__141[] = { + /* 0 */ 128, 0, 0, 0, +}; + +static const uint16_t ud_itab__142[] = { + /* 0 */ 129, 0, 0, 0, +}; + +static const uint16_t ud_itab__143[] = { + /* 0 */ 130, 0, 0, 0, +}; + +static const uint16_t ud_itab__144[] = { + /* 0 */ 131, 0, 0, 0, +}; + +static const uint16_t ud_itab__145[] = { + /* 0 */ 132, 0, 0, 0, +}; + +static const uint16_t ud_itab__146[] = { + /* 0 */ 133, 0, 0, 134, +}; + +static const uint16_t ud_itab__147[] = { + /* 0 */ 135, 0, 0, 136, +}; + +static const uint16_t ud_itab__148[] = { + /* 0 */ 137, 138, 139, 140, +}; + +static const uint16_t ud_itab__149[] = { + /* 0 */ 141, 0, 0, 142, +}; + +static const uint16_t ud_itab__150[] = { + /* 0 */ 143, 144, 145, 146, +}; + +static const uint16_t ud_itab__151[] = { + /* 0 */ 147, 148, 149, 150, +}; + +static const uint16_t ud_itab__152[] = { + /* 0 */ 151, 0, 0, 152, +}; + +static const uint16_t ud_itab__153[] = { + /* 0 */ 153, 0, 0, 154, +}; + +static const uint16_t ud_itab__154[] = { + /* 0 */ 155, 0, 0, 0, +}; + +static const uint16_t ud_itab__155[] = { + /* 0 */ 156, 0, 0, 0, +}; + +static const uint16_t ud_itab__156[] = { + /* 0 */ 157, 0, 0, 0, +}; + +static const uint16_t ud_itab__157[] = { + /* 0 */ 158, 0, 0, 0, +}; + +static const uint16_t ud_itab__160[] = { + /* 0 */ 0, 160, 0, +}; + +static const uint16_t ud_itab__159[] = { + /* 0 */ 159, GROUP(160), +}; + +static const uint16_t ud_itab__158[] = { + /* 0 */ GROUP(159), 0, 0, 0, +}; + +static const uint16_t ud_itab__163[] = { + /* 0 */ 0, 162, 0, +}; + +static const uint16_t ud_itab__162[] = { + /* 0 */ 161, GROUP(163), +}; + +static const uint16_t ud_itab__161[] = { + /* 0 */ GROUP(162), 0, 0, 0, +}; + +static const uint16_t ud_itab__164[] = { + /* 0 */ 163, 0, 0, 0, +}; + +static const uint16_t ud_itab__166[] = { + /* 0 */ 164, 0, 0, 165, +}; + +static const uint16_t ud_itab__167[] = { + /* 0 */ 166, 0, 0, 167, +}; + +static const uint16_t ud_itab__168[] = { + /* 0 */ 168, 0, 0, 169, +}; + +static const uint16_t ud_itab__169[] = { + /* 0 */ 170, 0, 0, 171, +}; + +static const uint16_t ud_itab__170[] = { + /* 0 */ 172, 0, 0, 173, +}; + +static const uint16_t ud_itab__171[] = { + /* 0 */ 174, 0, 0, 175, +}; + +static const uint16_t ud_itab__172[] = { + /* 0 */ 176, 0, 0, 177, +}; + +static const uint16_t ud_itab__173[] = { + /* 0 */ 178, 0, 0, 179, +}; + +static const uint16_t ud_itab__174[] = { + /* 0 */ 180, 0, 0, 181, +}; + +static const uint16_t ud_itab__175[] = { + /* 0 */ 182, 0, 0, 183, +}; + +static const uint16_t ud_itab__176[] = { + /* 0 */ 184, 0, 0, 185, +}; + +static const uint16_t ud_itab__177[] = { + /* 0 */ 186, 0, 0, 187, +}; + +static const uint16_t ud_itab__178[] = { + /* 0 */ 0, 0, 0, 188, +}; + +static const uint16_t ud_itab__179[] = { + /* 0 */ 0, 0, 0, 189, +}; + +static const uint16_t ud_itab__180[] = { + /* 0 */ 0, 0, 0, 190, +}; + +static const uint16_t ud_itab__181[] = { + /* 0 */ 0, 0, 0, 191, +}; + +static const uint16_t ud_itab__182[] = { + /* 0 */ 192, 0, 0, 193, +}; + +static const uint16_t ud_itab__183[] = { + /* 0 */ 194, 0, 0, 195, +}; + +static const uint16_t ud_itab__184[] = { + /* 0 */ 196, 0, 0, 197, +}; + +static const uint16_t ud_itab__185[] = { + /* 0 */ 0, 0, 0, 198, +}; + +static const uint16_t ud_itab__186[] = { + /* 0 */ 0, 0, 0, 199, +}; + +static const uint16_t ud_itab__187[] = { + /* 0 */ 0, 0, 0, 200, +}; + +static const uint16_t ud_itab__188[] = { + /* 0 */ 0, 0, 0, 201, +}; + +static const uint16_t ud_itab__189[] = { + /* 0 */ 0, 0, 0, 202, +}; + +static const uint16_t ud_itab__190[] = { + /* 0 */ 0, 0, 0, 203, +}; + +static const uint16_t ud_itab__191[] = { + /* 0 */ 0, 0, 0, 204, +}; + +static const uint16_t ud_itab__192[] = { + /* 0 */ 0, 0, 0, 205, +}; + +static const uint16_t ud_itab__193[] = { + /* 0 */ 0, 0, 0, 206, +}; + +static const uint16_t ud_itab__194[] = { + /* 0 */ 0, 0, 0, 207, +}; + +static const uint16_t ud_itab__195[] = { + /* 0 */ 0, 0, 0, 208, +}; + +static const uint16_t ud_itab__196[] = { + /* 0 */ 0, 0, 0, 209, +}; + +static const uint16_t ud_itab__197[] = { + /* 0 */ 0, 0, 0, 210, +}; + +static const uint16_t ud_itab__198[] = { + /* 0 */ 0, 0, 0, 211, +}; + +static const uint16_t ud_itab__199[] = { + /* 0 */ 0, 0, 0, 212, +}; + +static const uint16_t ud_itab__200[] = { + /* 0 */ 0, 0, 0, 213, +}; + +static const uint16_t ud_itab__201[] = { + /* 0 */ 0, 0, 0, 214, +}; + +static const uint16_t ud_itab__202[] = { + /* 0 */ 0, 0, 0, 215, +}; + +static const uint16_t ud_itab__203[] = { + /* 0 */ 0, 0, 0, 216, +}; + +static const uint16_t ud_itab__204[] = { + /* 0 */ 0, 0, 0, 217, +}; + +static const uint16_t ud_itab__205[] = { + /* 0 */ 0, 0, 0, 218, +}; + +static const uint16_t ud_itab__206[] = { + /* 0 */ 0, 0, 0, 219, +}; + +static const uint16_t ud_itab__207[] = { + /* 0 */ 0, 0, 0, 220, +}; + +static const uint16_t ud_itab__208[] = { + /* 0 */ 0, 0, 0, 221, +}; + +static const uint16_t ud_itab__209[] = { + /* 0 */ 0, 0, 0, 222, +}; + +static const uint16_t ud_itab__210[] = { + /* 0 */ 0, 0, 0, 223, +}; + +static const uint16_t ud_itab__211[] = { + /* 0 */ 0, 0, 0, 224, +}; + +static const uint16_t ud_itab__214[] = { + /* 0 */ 0, 225, 0, +}; + +static const uint16_t ud_itab__213[] = { + /* 0 */ 0, GROUP(214), +}; + +static const uint16_t ud_itab__212[] = { + /* 0 */ 0, 0, 0, GROUP(213), +}; + +static const uint16_t ud_itab__217[] = { + /* 0 */ 0, 226, 0, +}; + +static const uint16_t ud_itab__216[] = { + /* 0 */ 0, GROUP(217), +}; + +static const uint16_t ud_itab__215[] = { + /* 0 */ 0, 0, 0, GROUP(216), +}; + +static const uint16_t ud_itab__218[] = { + /* 0 */ 0, 0, 0, 227, +}; + +static const uint16_t ud_itab__219[] = { + /* 0 */ 0, 0, 0, 228, +}; + +static const uint16_t ud_itab__220[] = { + /* 0 */ 0, 0, 0, 229, +}; + +static const uint16_t ud_itab__221[] = { + /* 0 */ 0, 0, 0, 230, +}; + +static const uint16_t ud_itab__222[] = { + /* 0 */ 0, 0, 0, 231, +}; + +static const uint16_t ud_itab__223[] = { + /* 0 */ 232, 233, 0, 0, +}; + +static const uint16_t ud_itab__224[] = { + /* 0 */ 234, 235, 0, 0, +}; + +static const uint16_t ud_itab__165[] = { + /* 0 */ GROUP(166), GROUP(167), GROUP(168), GROUP(169), + /* 4 */ GROUP(170), GROUP(171), GROUP(172), GROUP(173), + /* 8 */ GROUP(174), GROUP(175), GROUP(176), GROUP(177), + /* c */ 0, 0, 0, 0, + /* 10 */ GROUP(178), 0, 0, 0, + /* 14 */ GROUP(179), GROUP(180), 0, GROUP(181), + /* 18 */ 0, 0, 0, 0, + /* 1c */ GROUP(182), GROUP(183), GROUP(184), 0, + /* 20 */ GROUP(185), GROUP(186), GROUP(187), GROUP(188), + /* 24 */ GROUP(189), GROUP(190), 0, 0, + /* 28 */ GROUP(191), GROUP(192), GROUP(193), GROUP(194), + /* 2c */ 0, 0, 0, 0, + /* 30 */ GROUP(195), GROUP(196), GROUP(197), GROUP(198), + /* 34 */ GROUP(199), GROUP(200), 0, GROUP(201), + /* 38 */ GROUP(202), GROUP(203), GROUP(204), GROUP(205), + /* 3c */ GROUP(206), GROUP(207), GROUP(208), GROUP(209), + /* 40 */ GROUP(210), GROUP(211), 0, 0, + /* 44 */ 0, 0, 0, 0, + /* 48 */ 0, 0, 0, 0, + /* 4c */ 0, 0, 0, 0, + /* 50 */ 0, 0, 0, 0, + /* 54 */ 0, 0, 0, 0, + /* 58 */ 0, 0, 0, 0, + /* 5c */ 0, 0, 0, 0, + /* 60 */ 0, 0, 0, 0, + /* 64 */ 0, 0, 0, 0, + /* 68 */ 0, 0, 0, 0, + /* 6c */ 0, 0, 0, 0, + /* 70 */ 0, 0, 0, 0, + /* 74 */ 0, 0, 0, 0, + /* 78 */ 0, 0, 0, 0, + /* 7c */ 0, 0, 0, 0, + /* 80 */ GROUP(212), GROUP(215), 0, 0, + /* 84 */ 0, 0, 0, 0, + /* 88 */ 0, 0, 0, 0, + /* 8c */ 0, 0, 0, 0, + /* 90 */ 0, 0, 0, 0, + /* 94 */ 0, 0, 0, 0, + /* 98 */ 0, 0, 0, 0, + /* 9c */ 0, 0, 0, 0, + /* a0 */ 0, 0, 0, 0, + /* a4 */ 0, 0, 0, 0, + /* a8 */ 0, 0, 0, 0, + /* ac */ 0, 0, 0, 0, + /* b0 */ 0, 0, 0, 0, + /* b4 */ 0, 0, 0, 0, + /* b8 */ 0, 0, 0, 0, + /* bc */ 0, 0, 0, 0, + /* c0 */ 0, 0, 0, 0, + /* c4 */ 0, 0, 0, 0, + /* c8 */ 0, 0, 0, 0, + /* cc */ 0, 0, 0, 0, + /* d0 */ 0, 0, 0, 0, + /* d4 */ 0, 0, 0, 0, + /* d8 */ 0, 0, 0, GROUP(218), + /* dc */ GROUP(219), GROUP(220), GROUP(221), GROUP(222), + /* e0 */ 0, 0, 0, 0, + /* e4 */ 0, 0, 0, 0, + /* e8 */ 0, 0, 0, 0, + /* ec */ 0, 0, 0, 0, + /* f0 */ GROUP(223), GROUP(224), 0, 0, + /* f4 */ 0, 0, 0, 0, + /* f8 */ 0, 0, 0, 0, + /* fc */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__226[] = { + /* 0 */ 0, 0, 0, 236, +}; + +static const uint16_t ud_itab__227[] = { + /* 0 */ 0, 0, 0, 237, +}; + +static const uint16_t ud_itab__228[] = { + /* 0 */ 0, 0, 0, 238, +}; + +static const uint16_t ud_itab__229[] = { + /* 0 */ 0, 0, 0, 239, +}; + +static const uint16_t ud_itab__230[] = { + /* 0 */ 0, 0, 0, 240, +}; + +static const uint16_t ud_itab__231[] = { + /* 0 */ 0, 0, 0, 241, +}; + +static const uint16_t ud_itab__232[] = { + /* 0 */ 0, 0, 0, 242, +}; + +static const uint16_t ud_itab__233[] = { + /* 0 */ 243, 0, 0, 244, +}; + +static const uint16_t ud_itab__234[] = { + /* 0 */ 0, 0, 0, 245, +}; + +static const uint16_t ud_itab__235[] = { + /* 0 */ 0, 0, 0, 246, +}; + +static const uint16_t ud_itab__237[] = { + /* 0 */ 247, 248, 249, +}; + +static const uint16_t ud_itab__236[] = { + /* 0 */ 0, 0, 0, GROUP(237), +}; + +static const uint16_t ud_itab__238[] = { + /* 0 */ 0, 0, 0, 250, +}; + +static const uint16_t ud_itab__239[] = { + /* 0 */ 0, 0, 0, 251, +}; + +static const uint16_t ud_itab__240[] = { + /* 0 */ 0, 0, 0, 252, +}; + +static const uint16_t ud_itab__242[] = { + /* 0 */ 253, 254, 255, +}; + +static const uint16_t ud_itab__241[] = { + /* 0 */ 0, 0, 0, GROUP(242), +}; + +static const uint16_t ud_itab__243[] = { + /* 0 */ 0, 0, 0, 256, +}; + +static const uint16_t ud_itab__244[] = { + /* 0 */ 0, 0, 0, 257, +}; + +static const uint16_t ud_itab__245[] = { + /* 0 */ 0, 0, 0, 258, +}; + +static const uint16_t ud_itab__246[] = { + /* 0 */ 0, 0, 0, 259, +}; + +static const uint16_t ud_itab__247[] = { + /* 0 */ 0, 0, 0, 260, +}; + +static const uint16_t ud_itab__248[] = { + /* 0 */ 0, 0, 0, 261, +}; + +static const uint16_t ud_itab__249[] = { + /* 0 */ 0, 0, 0, 262, +}; + +static const uint16_t ud_itab__250[] = { + /* 0 */ 0, 0, 0, 263, +}; + +static const uint16_t ud_itab__251[] = { + /* 0 */ 0, 0, 0, 264, +}; + +static const uint16_t ud_itab__225[] = { + /* 0 */ 0, 0, 0, 0, + /* 4 */ 0, 0, 0, 0, + /* 8 */ GROUP(226), GROUP(227), GROUP(228), GROUP(229), + /* c */ GROUP(230), GROUP(231), GROUP(232), GROUP(233), + /* 10 */ 0, 0, 0, 0, + /* 14 */ GROUP(234), GROUP(235), GROUP(236), GROUP(238), + /* 18 */ 0, 0, 0, 0, + /* 1c */ 0, 0, 0, 0, + /* 20 */ GROUP(239), GROUP(240), GROUP(241), 0, + /* 24 */ 0, 0, 0, 0, + /* 28 */ 0, 0, 0, 0, + /* 2c */ 0, 0, 0, 0, + /* 30 */ 0, 0, 0, 0, + /* 34 */ 0, 0, 0, 0, + /* 38 */ 0, 0, 0, 0, + /* 3c */ 0, 0, 0, 0, + /* 40 */ GROUP(243), GROUP(244), GROUP(245), 0, + /* 44 */ GROUP(246), 0, 0, 0, + /* 48 */ 0, 0, 0, 0, + /* 4c */ 0, 0, 0, 0, + /* 50 */ 0, 0, 0, 0, + /* 54 */ 0, 0, 0, 0, + /* 58 */ 0, 0, 0, 0, + /* 5c */ 0, 0, 0, 0, + /* 60 */ GROUP(247), GROUP(248), GROUP(249), GROUP(250), + /* 64 */ 0, 0, 0, 0, + /* 68 */ 0, 0, 0, 0, + /* 6c */ 0, 0, 0, 0, + /* 70 */ 0, 0, 0, 0, + /* 74 */ 0, 0, 0, 0, + /* 78 */ 0, 0, 0, 0, + /* 7c */ 0, 0, 0, 0, + /* 80 */ 0, 0, 0, 0, + /* 84 */ 0, 0, 0, 0, + /* 88 */ 0, 0, 0, 0, + /* 8c */ 0, 0, 0, 0, + /* 90 */ 0, 0, 0, 0, + /* 94 */ 0, 0, 0, 0, + /* 98 */ 0, 0, 0, 0, + /* 9c */ 0, 0, 0, 0, + /* a0 */ 0, 0, 0, 0, + /* a4 */ 0, 0, 0, 0, + /* a8 */ 0, 0, 0, 0, + /* ac */ 0, 0, 0, 0, + /* b0 */ 0, 0, 0, 0, + /* b4 */ 0, 0, 0, 0, + /* b8 */ 0, 0, 0, 0, + /* bc */ 0, 0, 0, 0, + /* c0 */ 0, 0, 0, 0, + /* c4 */ 0, 0, 0, 0, + /* c8 */ 0, 0, 0, 0, + /* cc */ 0, 0, 0, 0, + /* d0 */ 0, 0, 0, 0, + /* d4 */ 0, 0, 0, 0, + /* d8 */ 0, 0, 0, 0, + /* dc */ 0, 0, 0, GROUP(251), + /* e0 */ 0, 0, 0, 0, + /* e4 */ 0, 0, 0, 0, + /* e8 */ 0, 0, 0, 0, + /* ec */ 0, 0, 0, 0, + /* f0 */ 0, 0, 0, 0, + /* f4 */ 0, 0, 0, 0, + /* f8 */ 0, 0, 0, 0, + /* fc */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__252[] = { + /* 0 */ 265, 0, 0, 0, +}; + +static const uint16_t ud_itab__253[] = { + /* 0 */ 266, 0, 0, 0, +}; + +static const uint16_t ud_itab__254[] = { + /* 0 */ 267, 0, 0, 0, +}; + +static const uint16_t ud_itab__255[] = { + /* 0 */ 268, 0, 0, 0, +}; + +static const uint16_t ud_itab__256[] = { + /* 0 */ 269, 0, 0, 0, +}; + +static const uint16_t ud_itab__257[] = { + /* 0 */ 270, 0, 0, 0, +}; + +static const uint16_t ud_itab__258[] = { + /* 0 */ 271, 0, 0, 0, +}; + +static const uint16_t ud_itab__259[] = { + /* 0 */ 272, 0, 0, 0, +}; + +static const uint16_t ud_itab__260[] = { + /* 0 */ 273, 0, 0, 0, +}; + +static const uint16_t ud_itab__261[] = { + /* 0 */ 274, 0, 0, 0, +}; + +static const uint16_t ud_itab__262[] = { + /* 0 */ 275, 0, 0, 0, +}; + +static const uint16_t ud_itab__263[] = { + /* 0 */ 276, 0, 0, 0, +}; + +static const uint16_t ud_itab__264[] = { + /* 0 */ 277, 0, 0, 0, +}; + +static const uint16_t ud_itab__265[] = { + /* 0 */ 278, 0, 0, 0, +}; + +static const uint16_t ud_itab__266[] = { + /* 0 */ 279, 0, 0, 0, +}; + +static const uint16_t ud_itab__267[] = { + /* 0 */ 280, 0, 0, 0, +}; + +static const uint16_t ud_itab__268[] = { + /* 0 */ 281, 0, 0, 282, +}; + +static const uint16_t ud_itab__269[] = { + /* 0 */ 283, 284, 285, 286, +}; + +static const uint16_t ud_itab__270[] = { + /* 0 */ 287, 0, 288, 0, +}; + +static const uint16_t ud_itab__271[] = { + /* 0 */ 289, 0, 290, 0, +}; + +static const uint16_t ud_itab__272[] = { + /* 0 */ 291, 0, 0, 292, +}; + +static const uint16_t ud_itab__273[] = { + /* 0 */ 293, 0, 0, 294, +}; + +static const uint16_t ud_itab__274[] = { + /* 0 */ 295, 0, 0, 296, +}; + +static const uint16_t ud_itab__275[] = { + /* 0 */ 297, 0, 0, 298, +}; + +static const uint16_t ud_itab__276[] = { + /* 0 */ 299, 300, 301, 302, +}; + +static const uint16_t ud_itab__277[] = { + /* 0 */ 303, 304, 305, 306, +}; + +static const uint16_t ud_itab__278[] = { + /* 0 */ 307, 308, 309, 310, +}; + +static const uint16_t ud_itab__279[] = { + /* 0 */ 311, 0, 312, 313, +}; + +static const uint16_t ud_itab__280[] = { + /* 0 */ 314, 315, 316, 317, +}; + +static const uint16_t ud_itab__281[] = { + /* 0 */ 318, 319, 320, 321, +}; + +static const uint16_t ud_itab__282[] = { + /* 0 */ 322, 323, 324, 325, +}; + +static const uint16_t ud_itab__283[] = { + /* 0 */ 326, 327, 328, 329, +}; + +static const uint16_t ud_itab__284[] = { + /* 0 */ 330, 0, 0, 331, +}; + +static const uint16_t ud_itab__285[] = { + /* 0 */ 332, 0, 0, 333, +}; + +static const uint16_t ud_itab__286[] = { + /* 0 */ 334, 0, 0, 335, +}; + +static const uint16_t ud_itab__287[] = { + /* 0 */ 336, 0, 0, 337, +}; + +static const uint16_t ud_itab__288[] = { + /* 0 */ 338, 0, 0, 339, +}; + +static const uint16_t ud_itab__289[] = { + /* 0 */ 340, 0, 0, 341, +}; + +static const uint16_t ud_itab__290[] = { + /* 0 */ 342, 0, 0, 343, +}; + +static const uint16_t ud_itab__291[] = { + /* 0 */ 344, 0, 0, 345, +}; + +static const uint16_t ud_itab__292[] = { + /* 0 */ 346, 0, 0, 347, +}; + +static const uint16_t ud_itab__293[] = { + /* 0 */ 348, 0, 0, 349, +}; + +static const uint16_t ud_itab__294[] = { + /* 0 */ 350, 0, 0, 351, +}; + +static const uint16_t ud_itab__295[] = { + /* 0 */ 352, 0, 0, 353, +}; + +static const uint16_t ud_itab__296[] = { + /* 0 */ 0, 0, 0, 354, +}; + +static const uint16_t ud_itab__297[] = { + /* 0 */ 0, 0, 0, 355, +}; + +static const uint16_t ud_itab__298[] = { + /* 0 */ 356, 0, 0, 357, +}; + +static const uint16_t ud_itab__299[] = { + /* 0 */ 358, 0, 359, 360, +}; + +static const uint16_t ud_itab__300[] = { + /* 0 */ 361, 362, 363, 364, +}; + +static const uint16_t ud_itab__302[] = { + /* 0 */ 365, 0, 0, 366, +}; + +static const uint16_t ud_itab__303[] = { + /* 0 */ 367, 0, 0, 368, +}; + +static const uint16_t ud_itab__304[] = { + /* 0 */ 369, 0, 0, 370, +}; + +static const uint16_t ud_itab__301[] = { + /* 0 */ 0, 0, GROUP(302), 0, + /* 4 */ GROUP(303), 0, GROUP(304), 0, +}; + +static const uint16_t ud_itab__306[] = { + /* 0 */ 371, 0, 0, 372, +}; + +static const uint16_t ud_itab__307[] = { + /* 0 */ 373, 0, 0, 374, +}; + +static const uint16_t ud_itab__308[] = { + /* 0 */ 375, 0, 0, 376, +}; + +static const uint16_t ud_itab__305[] = { + /* 0 */ 0, 0, GROUP(306), 0, + /* 4 */ GROUP(307), 0, GROUP(308), 0, +}; + +static const uint16_t ud_itab__310[] = { + /* 0 */ 377, 0, 0, 378, +}; + +static const uint16_t ud_itab__311[] = { + /* 0 */ 0, 0, 0, 379, +}; + +static const uint16_t ud_itab__312[] = { + /* 0 */ 380, 0, 0, 381, +}; + +static const uint16_t ud_itab__313[] = { + /* 0 */ 0, 0, 0, 382, +}; + +static const uint16_t ud_itab__309[] = { + /* 0 */ 0, 0, GROUP(310), GROUP(311), + /* 4 */ 0, 0, GROUP(312), GROUP(313), +}; + +static const uint16_t ud_itab__314[] = { + /* 0 */ 383, 0, 0, 384, +}; + +static const uint16_t ud_itab__315[] = { + /* 0 */ 385, 0, 0, 386, +}; + +static const uint16_t ud_itab__316[] = { + /* 0 */ 387, 0, 0, 388, +}; + +static const uint16_t ud_itab__317[] = { + /* 0 */ 389, 0, 0, 0, +}; + +static const uint16_t ud_itab__319[] = { + /* 0 */ 0, 390, 0, +}; + +static const uint16_t ud_itab__318[] = { + /* 0 */ GROUP(319), 0, 0, 0, +}; + +static const uint16_t ud_itab__321[] = { + /* 0 */ 0, 391, 0, +}; + +static const uint16_t ud_itab__320[] = { + /* 0 */ GROUP(321), 0, 0, 0, +}; + +static const uint16_t ud_itab__322[] = { + /* 0 */ 0, 392, 0, 393, +}; + +static const uint16_t ud_itab__323[] = { + /* 0 */ 0, 394, 0, 395, +}; + +static const uint16_t ud_itab__324[] = { + /* 0 */ 396, 0, 397, 398, +}; + +static const uint16_t ud_itab__325[] = { + /* 0 */ 399, 0, 400, 401, +}; + +static const uint16_t ud_itab__326[] = { + /* 0 */ 402, 0, 0, 0, +}; + +static const uint16_t ud_itab__327[] = { + /* 0 */ 403, 0, 0, 0, +}; + +static const uint16_t ud_itab__328[] = { + /* 0 */ 404, 0, 0, 0, +}; + +static const uint16_t ud_itab__329[] = { + /* 0 */ 405, 0, 0, 0, +}; + +static const uint16_t ud_itab__330[] = { + /* 0 */ 406, 0, 0, 0, +}; + +static const uint16_t ud_itab__331[] = { + /* 0 */ 407, 0, 0, 0, +}; + +static const uint16_t ud_itab__332[] = { + /* 0 */ 408, 0, 0, 0, +}; + +static const uint16_t ud_itab__333[] = { + /* 0 */ 409, 0, 0, 0, +}; + +static const uint16_t ud_itab__334[] = { + /* 0 */ 410, 0, 0, 0, +}; + +static const uint16_t ud_itab__335[] = { + /* 0 */ 411, 0, 0, 0, +}; + +static const uint16_t ud_itab__336[] = { + /* 0 */ 412, 0, 0, 0, +}; + +static const uint16_t ud_itab__337[] = { + /* 0 */ 413, 0, 0, 0, +}; + +static const uint16_t ud_itab__338[] = { + /* 0 */ 414, 0, 0, 0, +}; + +static const uint16_t ud_itab__339[] = { + /* 0 */ 415, 0, 0, 0, +}; + +static const uint16_t ud_itab__340[] = { + /* 0 */ 416, 0, 0, 0, +}; + +static const uint16_t ud_itab__341[] = { + /* 0 */ 417, 0, 0, 0, +}; + +static const uint16_t ud_itab__342[] = { + /* 0 */ 418, 0, 0, 0, +}; + +static const uint16_t ud_itab__343[] = { + /* 0 */ 419, 0, 0, 0, +}; + +static const uint16_t ud_itab__344[] = { + /* 0 */ 420, 0, 0, 0, +}; + +static const uint16_t ud_itab__345[] = { + /* 0 */ 421, 0, 0, 0, +}; + +static const uint16_t ud_itab__346[] = { + /* 0 */ 422, 0, 0, 0, +}; + +static const uint16_t ud_itab__347[] = { + /* 0 */ 423, 0, 0, 0, +}; + +static const uint16_t ud_itab__348[] = { + /* 0 */ 424, 0, 0, 0, +}; + +static const uint16_t ud_itab__349[] = { + /* 0 */ 425, 0, 0, 0, +}; + +static const uint16_t ud_itab__350[] = { + /* 0 */ 426, 0, 0, 0, +}; + +static const uint16_t ud_itab__351[] = { + /* 0 */ 427, 0, 0, 0, +}; + +static const uint16_t ud_itab__352[] = { + /* 0 */ 428, 0, 0, 0, +}; + +static const uint16_t ud_itab__353[] = { + /* 0 */ 429, 0, 0, 0, +}; + +static const uint16_t ud_itab__354[] = { + /* 0 */ 430, 0, 0, 0, +}; + +static const uint16_t ud_itab__355[] = { + /* 0 */ 431, 0, 0, 0, +}; + +static const uint16_t ud_itab__356[] = { + /* 0 */ 432, 0, 0, 0, +}; + +static const uint16_t ud_itab__357[] = { + /* 0 */ 433, 0, 0, 0, +}; + +static const uint16_t ud_itab__358[] = { + /* 0 */ 434, 0, 0, 0, +}; + +static const uint16_t ud_itab__359[] = { + /* 0 */ 435, 0, 0, 0, +}; + +static const uint16_t ud_itab__360[] = { + /* 0 */ 436, 0, 0, 0, +}; + +static const uint16_t ud_itab__361[] = { + /* 0 */ 437, 0, 0, 0, +}; + +static const uint16_t ud_itab__362[] = { + /* 0 */ 438, 0, 0, 0, +}; + +static const uint16_t ud_itab__363[] = { + /* 0 */ 439, 0, 0, 0, +}; + +static const uint16_t ud_itab__368[] = { + /* 0 */ 0, 440, +}; + +static const uint16_t ud_itab__367[] = { + /* 0 */ GROUP(368), 0, 0, 0, +}; + +static const uint16_t ud_itab__366[] = { + /* 0 */ GROUP(367), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__371[] = { + /* 0 */ 0, 441, +}; + +static const uint16_t ud_itab__370[] = { + /* 0 */ GROUP(371), 0, 0, 0, +}; + +static const uint16_t ud_itab__369[] = { + /* 0 */ GROUP(370), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__374[] = { + /* 0 */ 0, 442, +}; + +static const uint16_t ud_itab__373[] = { + /* 0 */ GROUP(374), 0, 0, 0, +}; + +static const uint16_t ud_itab__372[] = { + /* 0 */ GROUP(373), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__365[] = { + /* 0 */ GROUP(366), GROUP(369), GROUP(372), 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__364[] = { + /* 0 */ 0, GROUP(365), +}; + +static const uint16_t ud_itab__379[] = { + /* 0 */ 0, 443, +}; + +static const uint16_t ud_itab__378[] = { + /* 0 */ GROUP(379), 0, 0, 0, +}; + +static const uint16_t ud_itab__377[] = { + /* 0 */ GROUP(378), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__382[] = { + /* 0 */ 0, 444, +}; + +static const uint16_t ud_itab__381[] = { + /* 0 */ GROUP(382), 0, 0, 0, +}; + +static const uint16_t ud_itab__380[] = { + /* 0 */ GROUP(381), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__385[] = { + /* 0 */ 0, 445, +}; + +static const uint16_t ud_itab__384[] = { + /* 0 */ GROUP(385), 0, 0, 0, +}; + +static const uint16_t ud_itab__383[] = { + /* 0 */ GROUP(384), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__388[] = { + /* 0 */ 0, 446, +}; + +static const uint16_t ud_itab__387[] = { + /* 0 */ GROUP(388), 0, 0, 0, +}; + +static const uint16_t ud_itab__386[] = { + /* 0 */ GROUP(387), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__391[] = { + /* 0 */ 0, 447, +}; + +static const uint16_t ud_itab__390[] = { + /* 0 */ GROUP(391), 0, 0, 0, +}; + +static const uint16_t ud_itab__389[] = { + /* 0 */ GROUP(390), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__394[] = { + /* 0 */ 0, 448, +}; + +static const uint16_t ud_itab__393[] = { + /* 0 */ GROUP(394), 0, 0, 0, +}; + +static const uint16_t ud_itab__392[] = { + /* 0 */ GROUP(393), 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__376[] = { + /* 0 */ GROUP(377), GROUP(380), GROUP(383), GROUP(386), + /* 4 */ GROUP(389), GROUP(392), 0, 0, +}; + +static const uint16_t ud_itab__375[] = { + /* 0 */ 0, GROUP(376), +}; + +static const uint16_t ud_itab__395[] = { + /* 0 */ 449, 0, 0, 0, +}; + +static const uint16_t ud_itab__396[] = { + /* 0 */ 450, 0, 0, 0, +}; + +static const uint16_t ud_itab__397[] = { + /* 0 */ 451, 0, 0, 0, +}; + +static const uint16_t ud_itab__398[] = { + /* 0 */ 452, 0, 0, 0, +}; + +static const uint16_t ud_itab__399[] = { + /* 0 */ 453, 0, 0, 0, +}; + +static const uint16_t ud_itab__400[] = { + /* 0 */ 454, 0, 0, 0, +}; + +static const uint16_t ud_itab__404[] = { + /* 0 */ 455, 0, +}; + +static const uint16_t ud_itab__403[] = { + /* 0 */ GROUP(404), 0, 0, 0, +}; + +static const uint16_t ud_itab__406[] = { + /* 0 */ 456, 0, +}; + +static const uint16_t ud_itab__405[] = { + /* 0 */ GROUP(406), 0, 0, 0, +}; + +static const uint16_t ud_itab__408[] = { + /* 0 */ 457, 0, +}; + +static const uint16_t ud_itab__407[] = { + /* 0 */ GROUP(408), 0, 0, 0, +}; + +static const uint16_t ud_itab__410[] = { + /* 0 */ 458, 0, +}; + +static const uint16_t ud_itab__409[] = { + /* 0 */ GROUP(410), 0, 0, 0, +}; + +static const uint16_t ud_itab__412[] = { + /* 0 */ 459, 0, +}; + +static const uint16_t ud_itab__411[] = { + /* 0 */ GROUP(412), 0, 0, 0, +}; + +static const uint16_t ud_itab__414[] = { + /* 0 */ 460, 0, +}; + +static const uint16_t ud_itab__413[] = { + /* 0 */ GROUP(414), 0, 0, 0, +}; + +static const uint16_t ud_itab__416[] = { + /* 0 */ 461, 0, +}; + +static const uint16_t ud_itab__415[] = { + /* 0 */ GROUP(416), 0, 0, 0, +}; + +static const uint16_t ud_itab__402[] = { + /* 0 */ GROUP(403), GROUP(405), GROUP(407), GROUP(409), + /* 4 */ GROUP(411), GROUP(413), 0, GROUP(415), +}; + +static const uint16_t ud_itab__420[] = { + /* 0 */ 0, 462, +}; + +static const uint16_t ud_itab__419[] = { + /* 0 */ GROUP(420), 0, 0, 0, +}; + +static const uint16_t ud_itab__422[] = { + /* 0 */ 0, 463, +}; + +static const uint16_t ud_itab__421[] = { + /* 0 */ GROUP(422), 0, 0, 0, +}; + +static const uint16_t ud_itab__424[] = { + /* 0 */ 0, 464, +}; + +static const uint16_t ud_itab__423[] = { + /* 0 */ GROUP(424), 0, 0, 0, +}; + +static const uint16_t ud_itab__426[] = { + /* 0 */ 0, 465, +}; + +static const uint16_t ud_itab__425[] = { + /* 0 */ GROUP(426), 0, 0, 0, +}; + +static const uint16_t ud_itab__428[] = { + /* 0 */ 0, 466, +}; + +static const uint16_t ud_itab__427[] = { + /* 0 */ GROUP(428), 0, 0, 0, +}; + +static const uint16_t ud_itab__430[] = { + /* 0 */ 0, 467, +}; + +static const uint16_t ud_itab__429[] = { + /* 0 */ GROUP(430), 0, 0, 0, +}; + +static const uint16_t ud_itab__432[] = { + /* 0 */ 0, 468, +}; + +static const uint16_t ud_itab__431[] = { + /* 0 */ GROUP(432), 0, 0, 0, +}; + +static const uint16_t ud_itab__434[] = { + /* 0 */ 0, 469, +}; + +static const uint16_t ud_itab__433[] = { + /* 0 */ GROUP(434), 0, 0, 0, +}; + +static const uint16_t ud_itab__418[] = { + /* 0 */ GROUP(419), GROUP(421), GROUP(423), GROUP(425), + /* 4 */ GROUP(427), GROUP(429), GROUP(431), GROUP(433), +}; + +static const uint16_t ud_itab__437[] = { + /* 0 */ 0, 470, +}; + +static const uint16_t ud_itab__436[] = { + /* 0 */ GROUP(437), 0, 0, 0, +}; + +static const uint16_t ud_itab__439[] = { + /* 0 */ 0, 471, +}; + +static const uint16_t ud_itab__438[] = { + /* 0 */ GROUP(439), 0, 0, 0, +}; + +static const uint16_t ud_itab__441[] = { + /* 0 */ 0, 472, +}; + +static const uint16_t ud_itab__440[] = { + /* 0 */ GROUP(441), 0, 0, 0, +}; + +static const uint16_t ud_itab__443[] = { + /* 0 */ 0, 473, +}; + +static const uint16_t ud_itab__442[] = { + /* 0 */ GROUP(443), 0, 0, 0, +}; + +static const uint16_t ud_itab__445[] = { + /* 0 */ 0, 474, +}; + +static const uint16_t ud_itab__444[] = { + /* 0 */ GROUP(445), 0, 0, 0, +}; + +static const uint16_t ud_itab__447[] = { + /* 0 */ 0, 475, +}; + +static const uint16_t ud_itab__446[] = { + /* 0 */ GROUP(447), 0, 0, 0, +}; + +static const uint16_t ud_itab__449[] = { + /* 0 */ 0, 476, +}; + +static const uint16_t ud_itab__448[] = { + /* 0 */ GROUP(449), 0, 0, 0, +}; + +static const uint16_t ud_itab__451[] = { + /* 0 */ 0, 477, +}; + +static const uint16_t ud_itab__450[] = { + /* 0 */ GROUP(451), 0, 0, 0, +}; + +static const uint16_t ud_itab__435[] = { + /* 0 */ GROUP(436), GROUP(438), GROUP(440), GROUP(442), + /* 4 */ GROUP(444), GROUP(446), GROUP(448), GROUP(450), +}; + +static const uint16_t ud_itab__454[] = { + /* 0 */ 0, 478, +}; + +static const uint16_t ud_itab__453[] = { + /* 0 */ GROUP(454), 0, 0, 0, +}; + +static const uint16_t ud_itab__456[] = { + /* 0 */ 0, 479, +}; + +static const uint16_t ud_itab__455[] = { + /* 0 */ GROUP(456), 0, 0, 0, +}; + +static const uint16_t ud_itab__458[] = { + /* 0 */ 0, 480, +}; + +static const uint16_t ud_itab__457[] = { + /* 0 */ GROUP(458), 0, 0, 0, +}; + +static const uint16_t ud_itab__460[] = { + /* 0 */ 0, 481, +}; + +static const uint16_t ud_itab__459[] = { + /* 0 */ GROUP(460), 0, 0, 0, +}; + +static const uint16_t ud_itab__462[] = { + /* 0 */ 0, 482, +}; + +static const uint16_t ud_itab__461[] = { + /* 0 */ GROUP(462), 0, 0, 0, +}; + +static const uint16_t ud_itab__464[] = { + /* 0 */ 0, 483, +}; + +static const uint16_t ud_itab__463[] = { + /* 0 */ GROUP(464), 0, 0, 0, +}; + +static const uint16_t ud_itab__466[] = { + /* 0 */ 0, 484, +}; + +static const uint16_t ud_itab__465[] = { + /* 0 */ GROUP(466), 0, 0, 0, +}; + +static const uint16_t ud_itab__468[] = { + /* 0 */ 0, 485, +}; + +static const uint16_t ud_itab__467[] = { + /* 0 */ GROUP(468), 0, 0, 0, +}; + +static const uint16_t ud_itab__452[] = { + /* 0 */ GROUP(453), GROUP(455), GROUP(457), GROUP(459), + /* 4 */ GROUP(461), GROUP(463), GROUP(465), GROUP(467), +}; + +static const uint16_t ud_itab__417[] = { + /* 0 */ 0, 0, 0, 0, + /* 4 */ 0, GROUP(418), GROUP(435), GROUP(452), +}; + +static const uint16_t ud_itab__401[] = { + /* 0 */ GROUP(402), GROUP(417), +}; + +static const uint16_t ud_itab__469[] = { + /* 0 */ 486, 0, 0, 0, +}; + +static const uint16_t ud_itab__470[] = { + /* 0 */ 487, 0, 0, 0, +}; + +static const uint16_t ud_itab__471[] = { + /* 0 */ 488, 0, 0, 0, +}; + +static const uint16_t ud_itab__472[] = { + /* 0 */ 489, 0, 0, 0, +}; + +static const uint16_t ud_itab__473[] = { + /* 0 */ 490, 0, 0, 0, +}; + +static const uint16_t ud_itab__474[] = { + /* 0 */ 491, 0, 0, 0, +}; + +static const uint16_t ud_itab__475[] = { + /* 0 */ 492, 0, 0, 0, +}; + +static const uint16_t ud_itab__476[] = { + /* 0 */ 493, 0, 0, 0, +}; + +static const uint16_t ud_itab__477[] = { + /* 0 */ 494, 0, 0, 0, +}; + +static const uint16_t ud_itab__478[] = { + /* 0 */ 0, 0, 495, 0, +}; + +static const uint16_t ud_itab__480[] = { + /* 0 */ 496, 0, 0, 0, +}; + +static const uint16_t ud_itab__481[] = { + /* 0 */ 497, 0, 0, 0, +}; + +static const uint16_t ud_itab__482[] = { + /* 0 */ 498, 0, 0, 0, +}; + +static const uint16_t ud_itab__483[] = { + /* 0 */ 499, 0, 0, 0, +}; + +static const uint16_t ud_itab__479[] = { + /* 0 */ 0, 0, 0, 0, + /* 4 */ GROUP(480), GROUP(481), GROUP(482), GROUP(483), +}; + +static const uint16_t ud_itab__484[] = { + /* 0 */ 500, 0, 0, 0, +}; + +static const uint16_t ud_itab__485[] = { + /* 0 */ 501, 0, 0, 0, +}; + +static const uint16_t ud_itab__486[] = { + /* 0 */ 502, 0, 0, 0, +}; + +static const uint16_t ud_itab__487[] = { + /* 0 */ 503, 0, 0, 0, +}; + +static const uint16_t ud_itab__488[] = { + /* 0 */ 504, 0, 0, 0, +}; + +static const uint16_t ud_itab__489[] = { + /* 0 */ 505, 0, 0, 0, +}; + +static const uint16_t ud_itab__490[] = { + /* 0 */ 506, 0, 0, 0, +}; + +static const uint16_t ud_itab__491[] = { + /* 0 */ 507, 508, 509, 510, +}; + +static const uint16_t ud_itab__492[] = { + /* 0 */ 511, 0, 0, 0, +}; + +static const uint16_t ud_itab__493[] = { + /* 0 */ 512, 0, 0, 513, +}; + +static const uint16_t ud_itab__494[] = { + /* 0 */ 514, 0, 0, 515, +}; + +static const uint16_t ud_itab__495[] = { + /* 0 */ 516, 0, 0, 517, +}; + +static const uint16_t ud_itab__498[] = { + /* 0 */ 518, 519, 520, +}; + +static const uint16_t ud_itab__497[] = { + /* 0 */ GROUP(498), 0, 0, 0, +}; + +static const uint16_t ud_itab__500[] = { + /* 0 */ 0, 521, 0, +}; + +static const uint16_t ud_itab__501[] = { + /* 0 */ 0, 522, 0, +}; + +static const uint16_t ud_itab__502[] = { + /* 0 */ 0, 523, 0, +}; + +static const uint16_t ud_itab__499[] = { + /* 0 */ GROUP(500), 0, GROUP(501), GROUP(502), +}; + +static const uint16_t ud_itab__504[] = { + /* 0 */ 0, 524, 0, +}; + +static const uint16_t ud_itab__503[] = { + /* 0 */ GROUP(504), 0, 0, 0, +}; + +static const uint16_t ud_itab__496[] = { + /* 0 */ 0, GROUP(497), 0, 0, + /* 4 */ 0, 0, GROUP(499), GROUP(503), +}; + +static const uint16_t ud_itab__505[] = { + /* 0 */ 525, 0, 0, 0, +}; + +static const uint16_t ud_itab__506[] = { + /* 0 */ 526, 0, 0, 0, +}; + +static const uint16_t ud_itab__507[] = { + /* 0 */ 527, 0, 0, 0, +}; + +static const uint16_t ud_itab__508[] = { + /* 0 */ 528, 0, 0, 0, +}; + +static const uint16_t ud_itab__509[] = { + /* 0 */ 529, 0, 0, 0, +}; + +static const uint16_t ud_itab__510[] = { + /* 0 */ 530, 0, 0, 0, +}; + +static const uint16_t ud_itab__511[] = { + /* 0 */ 531, 0, 0, 0, +}; + +static const uint16_t ud_itab__512[] = { + /* 0 */ 532, 0, 0, 0, +}; + +static const uint16_t ud_itab__513[] = { + /* 0 */ 0, 533, 0, 534, +}; + +static const uint16_t ud_itab__514[] = { + /* 0 */ 535, 0, 0, 536, +}; + +static const uint16_t ud_itab__515[] = { + /* 0 */ 537, 0, 0, 538, +}; + +static const uint16_t ud_itab__516[] = { + /* 0 */ 539, 0, 0, 540, +}; + +static const uint16_t ud_itab__517[] = { + /* 0 */ 541, 0, 0, 542, +}; + +static const uint16_t ud_itab__518[] = { + /* 0 */ 543, 0, 0, 544, +}; + +static const uint16_t ud_itab__519[] = { + /* 0 */ 0, 545, 546, 547, +}; + +static const uint16_t ud_itab__520[] = { + /* 0 */ 548, 0, 0, 549, +}; + +static const uint16_t ud_itab__521[] = { + /* 0 */ 550, 0, 0, 551, +}; + +static const uint16_t ud_itab__522[] = { + /* 0 */ 552, 0, 0, 553, +}; + +static const uint16_t ud_itab__523[] = { + /* 0 */ 554, 0, 0, 555, +}; + +static const uint16_t ud_itab__524[] = { + /* 0 */ 556, 0, 0, 557, +}; + +static const uint16_t ud_itab__525[] = { + /* 0 */ 558, 0, 0, 559, +}; + +static const uint16_t ud_itab__526[] = { + /* 0 */ 560, 0, 0, 561, +}; + +static const uint16_t ud_itab__527[] = { + /* 0 */ 562, 0, 0, 563, +}; + +static const uint16_t ud_itab__528[] = { + /* 0 */ 564, 0, 0, 565, +}; + +static const uint16_t ud_itab__529[] = { + /* 0 */ 566, 0, 0, 567, +}; + +static const uint16_t ud_itab__530[] = { + /* 0 */ 568, 0, 0, 569, +}; + +static const uint16_t ud_itab__531[] = { + /* 0 */ 570, 0, 0, 571, +}; + +static const uint16_t ud_itab__532[] = { + /* 0 */ 572, 0, 0, 573, +}; + +static const uint16_t ud_itab__533[] = { + /* 0 */ 574, 0, 0, 575, +}; + +static const uint16_t ud_itab__534[] = { + /* 0 */ 576, 0, 0, 577, +}; + +static const uint16_t ud_itab__535[] = { + /* 0 */ 0, 578, 579, 580, +}; + +static const uint16_t ud_itab__536[] = { + /* 0 */ 581, 0, 0, 582, +}; + +static const uint16_t ud_itab__537[] = { + /* 0 */ 583, 0, 0, 584, +}; + +static const uint16_t ud_itab__538[] = { + /* 0 */ 585, 0, 0, 586, +}; + +static const uint16_t ud_itab__539[] = { + /* 0 */ 587, 0, 0, 588, +}; + +static const uint16_t ud_itab__540[] = { + /* 0 */ 589, 0, 0, 590, +}; + +static const uint16_t ud_itab__541[] = { + /* 0 */ 591, 0, 0, 592, +}; + +static const uint16_t ud_itab__542[] = { + /* 0 */ 593, 0, 0, 594, +}; + +static const uint16_t ud_itab__543[] = { + /* 0 */ 595, 0, 0, 596, +}; + +static const uint16_t ud_itab__544[] = { + /* 0 */ 597, 0, 0, 598, +}; + +static const uint16_t ud_itab__545[] = { + /* 0 */ 0, 599, 0, 0, +}; + +static const uint16_t ud_itab__546[] = { + /* 0 */ 600, 0, 0, 601, +}; + +static const uint16_t ud_itab__547[] = { + /* 0 */ 602, 0, 0, 603, +}; + +static const uint16_t ud_itab__548[] = { + /* 0 */ 604, 0, 0, 605, +}; + +static const uint16_t ud_itab__549[] = { + /* 0 */ 606, 0, 0, 607, +}; + +static const uint16_t ud_itab__550[] = { + /* 0 */ 608, 0, 0, 609, +}; + +static const uint16_t ud_itab__551[] = { + /* 0 */ 610, 0, 0, 611, +}; + +static const uint16_t ud_itab__554[] = { + /* 0 */ 0, 612, +}; + +static const uint16_t ud_itab__555[] = { + /* 0 */ 0, 613, +}; + +static const uint16_t ud_itab__553[] = { + /* 0 */ GROUP(554), 0, 0, GROUP(555), +}; + +static const uint16_t ud_itab__552[] = { + /* 0 */ 0, GROUP(553), +}; + +static const uint16_t ud_itab__556[] = { + /* 0 */ 614, 0, 0, 615, +}; + +static const uint16_t ud_itab__557[] = { + /* 0 */ 616, 0, 0, 617, +}; + +static const uint16_t ud_itab__558[] = { + /* 0 */ 618, 0, 0, 619, +}; + +static const uint16_t ud_itab__559[] = { + /* 0 */ 620, 0, 0, 621, +}; + +static const uint16_t ud_itab__560[] = { + /* 0 */ 622, 0, 0, 623, +}; + +static const uint16_t ud_itab__561[] = { + /* 0 */ 624, 0, 0, 625, +}; + +static const uint16_t ud_itab__562[] = { + /* 0 */ 626, 0, 0, 627, +}; + +static const uint16_t ud_itab__4[] = { + /* 0 */ GROUP(5), GROUP(12), GROUP(87), GROUP(88), + /* 4 */ 0, GROUP(89), GROUP(90), GROUP(91), + /* 8 */ GROUP(92), GROUP(93), 0, GROUP(94), + /* c */ 0, GROUP(95), GROUP(104), GROUP(105), + /* 10 */ GROUP(106), GROUP(107), GROUP(108), GROUP(118), + /* 14 */ GROUP(119), GROUP(120), GROUP(121), GROUP(129), + /* 18 */ GROUP(130), GROUP(135), GROUP(136), GROUP(137), + /* 1c */ GROUP(138), GROUP(139), GROUP(140), GROUP(141), + /* 20 */ GROUP(142), GROUP(143), GROUP(144), GROUP(145), + /* 24 */ 0, 0, 0, 0, + /* 28 */ GROUP(146), GROUP(147), GROUP(148), GROUP(149), + /* 2c */ GROUP(150), GROUP(151), GROUP(152), GROUP(153), + /* 30 */ GROUP(154), GROUP(155), GROUP(156), GROUP(157), + /* 34 */ GROUP(158), GROUP(161), 0, GROUP(164), + /* 38 */ GROUP(165), 0, GROUP(225), 0, + /* 3c */ 0, 0, 0, 0, + /* 40 */ GROUP(252), GROUP(253), GROUP(254), GROUP(255), + /* 44 */ GROUP(256), GROUP(257), GROUP(258), GROUP(259), + /* 48 */ GROUP(260), GROUP(261), GROUP(262), GROUP(263), + /* 4c */ GROUP(264), GROUP(265), GROUP(266), GROUP(267), + /* 50 */ GROUP(268), GROUP(269), GROUP(270), GROUP(271), + /* 54 */ GROUP(272), GROUP(273), GROUP(274), GROUP(275), + /* 58 */ GROUP(276), GROUP(277), GROUP(278), GROUP(279), + /* 5c */ GROUP(280), GROUP(281), GROUP(282), GROUP(283), + /* 60 */ GROUP(284), GROUP(285), GROUP(286), GROUP(287), + /* 64 */ GROUP(288), GROUP(289), GROUP(290), GROUP(291), + /* 68 */ GROUP(292), GROUP(293), GROUP(294), GROUP(295), + /* 6c */ GROUP(296), GROUP(297), GROUP(298), GROUP(299), + /* 70 */ GROUP(300), GROUP(301), GROUP(305), GROUP(309), + /* 74 */ GROUP(314), GROUP(315), GROUP(316), GROUP(317), + /* 78 */ GROUP(318), GROUP(320), 0, 0, + /* 7c */ GROUP(322), GROUP(323), GROUP(324), GROUP(325), + /* 80 */ GROUP(326), GROUP(327), GROUP(328), GROUP(329), + /* 84 */ GROUP(330), GROUP(331), GROUP(332), GROUP(333), + /* 88 */ GROUP(334), GROUP(335), GROUP(336), GROUP(337), + /* 8c */ GROUP(338), GROUP(339), GROUP(340), GROUP(341), + /* 90 */ GROUP(342), GROUP(343), GROUP(344), GROUP(345), + /* 94 */ GROUP(346), GROUP(347), GROUP(348), GROUP(349), + /* 98 */ GROUP(350), GROUP(351), GROUP(352), GROUP(353), + /* 9c */ GROUP(354), GROUP(355), GROUP(356), GROUP(357), + /* a0 */ GROUP(358), GROUP(359), GROUP(360), GROUP(361), + /* a4 */ GROUP(362), GROUP(363), GROUP(364), GROUP(375), + /* a8 */ GROUP(395), GROUP(396), GROUP(397), GROUP(398), + /* ac */ GROUP(399), GROUP(400), GROUP(401), GROUP(469), + /* b0 */ GROUP(470), GROUP(471), GROUP(472), GROUP(473), + /* b4 */ GROUP(474), GROUP(475), GROUP(476), GROUP(477), + /* b8 */ GROUP(478), 0, GROUP(479), GROUP(484), + /* bc */ GROUP(485), GROUP(486), GROUP(487), GROUP(488), + /* c0 */ GROUP(489), GROUP(490), GROUP(491), GROUP(492), + /* c4 */ GROUP(493), GROUP(494), GROUP(495), GROUP(496), + /* c8 */ GROUP(505), GROUP(506), GROUP(507), GROUP(508), + /* cc */ GROUP(509), GROUP(510), GROUP(511), GROUP(512), + /* d0 */ GROUP(513), GROUP(514), GROUP(515), GROUP(516), + /* d4 */ GROUP(517), GROUP(518), GROUP(519), GROUP(520), + /* d8 */ GROUP(521), GROUP(522), GROUP(523), GROUP(524), + /* dc */ GROUP(525), GROUP(526), GROUP(527), GROUP(528), + /* e0 */ GROUP(529), GROUP(530), GROUP(531), GROUP(532), + /* e4 */ GROUP(533), GROUP(534), GROUP(535), GROUP(536), + /* e8 */ GROUP(537), GROUP(538), GROUP(539), GROUP(540), + /* ec */ GROUP(541), GROUP(542), GROUP(543), GROUP(544), + /* f0 */ GROUP(545), GROUP(546), GROUP(547), GROUP(548), + /* f4 */ GROUP(549), GROUP(550), GROUP(551), GROUP(552), + /* f8 */ GROUP(556), GROUP(557), GROUP(558), GROUP(559), + /* fc */ GROUP(560), GROUP(561), GROUP(562), 0, +}; + +static const uint16_t ud_itab__563[] = { + /* 0 */ 634, 0, +}; + +static const uint16_t ud_itab__564[] = { + /* 0 */ 635, 0, +}; + +static const uint16_t ud_itab__565[] = { + /* 0 */ 642, 0, +}; + +static const uint16_t ud_itab__566[] = { + /* 0 */ 643, 0, +}; + +static const uint16_t ud_itab__567[] = { + /* 0 */ 650, 0, +}; + +static const uint16_t ud_itab__568[] = { + /* 0 */ 657, 0, +}; + +static const uint16_t ud_itab__569[] = { + /* 0 */ 664, 0, +}; + +static const uint16_t ud_itab__570[] = { + /* 0 */ 671, 0, +}; + +static const uint16_t ud_itab__572[] = { + /* 0 */ 704, 0, +}; + +static const uint16_t ud_itab__573[] = { + /* 0 */ 705, 0, +}; + +static const uint16_t ud_itab__571[] = { + /* 0 */ GROUP(572), GROUP(573), 0, +}; + +static const uint16_t ud_itab__575[] = { + /* 0 */ 706, 0, +}; + +static const uint16_t ud_itab__576[] = { + /* 0 */ 707, 0, +}; + +static const uint16_t ud_itab__574[] = { + /* 0 */ GROUP(575), GROUP(576), 0, +}; + +static const uint16_t ud_itab__577[] = { + /* 0 */ 708, 0, +}; + +static const uint16_t ud_itab__578[] = { + /* 0 */ 709, 710, +}; + +static const uint16_t ud_itab__579[] = { + /* 0 */ 716, 717, 0, +}; + +static const uint16_t ud_itab__580[] = { + /* 0 */ 719, 720, 0, +}; + +static const uint16_t ud_itab__581[] = { + /* 0 */ 737, 738, 739, 740, + /* 4 */ 741, 742, 743, 744, +}; + +static const uint16_t ud_itab__582[] = { + /* 0 */ 745, 746, 747, 748, + /* 4 */ 749, 750, 751, 752, +}; + +static const uint16_t ud_itab__584[] = { + /* 0 */ 753, 0, +}; + +static const uint16_t ud_itab__585[] = { + /* 0 */ 754, 0, +}; + +static const uint16_t ud_itab__586[] = { + /* 0 */ 755, 0, +}; + +static const uint16_t ud_itab__587[] = { + /* 0 */ 756, 0, +}; + +static const uint16_t ud_itab__588[] = { + /* 0 */ 757, 0, +}; + +static const uint16_t ud_itab__589[] = { + /* 0 */ 758, 0, +}; + +static const uint16_t ud_itab__590[] = { + /* 0 */ 759, 0, +}; + +static const uint16_t ud_itab__591[] = { + /* 0 */ 760, 0, +}; + +static const uint16_t ud_itab__583[] = { + /* 0 */ GROUP(584), GROUP(585), GROUP(586), GROUP(587), + /* 4 */ GROUP(588), GROUP(589), GROUP(590), GROUP(591), +}; + +static const uint16_t ud_itab__592[] = { + /* 0 */ 761, 762, 763, 764, + /* 4 */ 765, 766, 767, 768, +}; + +static const uint16_t ud_itab__593[] = { + /* 0 */ 780, 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__594[] = { + /* 0 */ 789, 790, 791, +}; + +static const uint16_t ud_itab__595[] = { + /* 0 */ 792, 793, 794, +}; + +static const uint16_t ud_itab__596[] = { + /* 0 */ 795, 0, +}; + +static const uint16_t ud_itab__598[] = { + /* 0 */ 797, 798, +}; + +static const uint16_t ud_itab__599[] = { + /* 0 */ 799, 800, +}; + +static const uint16_t ud_itab__600[] = { + /* 0 */ 0, 801, +}; + +static const uint16_t ud_itab__597[] = { + /* 0 */ GROUP(598), GROUP(599), GROUP(600), +}; + +static const uint16_t ud_itab__602[] = { + /* 0 */ 802, 0, +}; + +static const uint16_t ud_itab__603[] = { + /* 0 */ 803, 804, +}; + +static const uint16_t ud_itab__604[] = { + /* 0 */ 0, 805, +}; + +static const uint16_t ud_itab__601[] = { + /* 0 */ GROUP(602), GROUP(603), GROUP(604), +}; + +static const uint16_t ud_itab__605[] = { + /* 0 */ 813, 814, 815, +}; + +static const uint16_t ud_itab__606[] = { + /* 0 */ 817, 818, 819, +}; + +static const uint16_t ud_itab__607[] = { + /* 0 */ 823, 824, 825, +}; + +static const uint16_t ud_itab__608[] = { + /* 0 */ 827, 828, 829, +}; + +static const uint16_t ud_itab__609[] = { + /* 0 */ 831, 832, 833, +}; + +static const uint16_t ud_itab__610[] = { + /* 0 */ 850, 851, 852, 853, + /* 4 */ 854, 855, 856, 857, +}; + +static const uint16_t ud_itab__611[] = { + /* 0 */ 858, 859, 860, 861, + /* 4 */ 862, 863, 864, 865, +}; + +static const uint16_t ud_itab__612[] = { + /* 0 */ 868, 0, +}; + +static const uint16_t ud_itab__613[] = { + /* 0 */ 869, 0, +}; + +static const uint16_t ud_itab__614[] = { + /* 0 */ 870, 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__615[] = { + /* 0 */ 871, 0, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__616[] = { + /* 0 */ 878, 0, +}; + +static const uint16_t ud_itab__617[] = { + /* 0 */ 879, 880, 881, +}; + +static const uint16_t ud_itab__618[] = { + /* 0 */ 882, 883, 884, 885, + /* 4 */ 886, 887, 888, 889, +}; + +static const uint16_t ud_itab__619[] = { + /* 0 */ 890, 891, 892, 893, + /* 4 */ 894, 895, 896, 897, +}; + +static const uint16_t ud_itab__620[] = { + /* 0 */ 898, 899, 900, 901, + /* 4 */ 902, 903, 904, 905, +}; + +static const uint16_t ud_itab__621[] = { + /* 0 */ 906, 907, 908, 909, + /* 4 */ 910, 911, 912, 913, +}; + +static const uint16_t ud_itab__622[] = { + /* 0 */ 914, 0, +}; + +static const uint16_t ud_itab__623[] = { + /* 0 */ 915, 0, +}; + +static const uint16_t ud_itab__624[] = { + /* 0 */ 916, 0, +}; + +static const uint16_t ud_itab__627[] = { + /* 0 */ 918, 0, +}; + +static const uint16_t ud_itab__628[] = { + /* 0 */ 919, 0, +}; + +static const uint16_t ud_itab__629[] = { + /* 0 */ 920, 0, +}; + +static const uint16_t ud_itab__630[] = { + /* 0 */ 921, 0, +}; + +static const uint16_t ud_itab__631[] = { + /* 0 */ 922, 0, +}; + +static const uint16_t ud_itab__632[] = { + /* 0 */ 923, 0, +}; + +static const uint16_t ud_itab__633[] = { + /* 0 */ 924, 0, +}; + +static const uint16_t ud_itab__634[] = { + /* 0 */ 925, 0, +}; + +static const uint16_t ud_itab__626[] = { + /* 0 */ GROUP(627), GROUP(628), GROUP(629), GROUP(630), + /* 4 */ GROUP(631), GROUP(632), GROUP(633), GROUP(634), +}; + +static const uint16_t ud_itab__636[] = { + /* 0 */ 0, 926, +}; + +static const uint16_t ud_itab__637[] = { + /* 0 */ 0, 927, +}; + +static const uint16_t ud_itab__638[] = { + /* 0 */ 0, 928, +}; + +static const uint16_t ud_itab__639[] = { + /* 0 */ 0, 929, +}; + +static const uint16_t ud_itab__640[] = { + /* 0 */ 0, 930, +}; + +static const uint16_t ud_itab__641[] = { + /* 0 */ 0, 931, +}; + +static const uint16_t ud_itab__642[] = { + /* 0 */ 0, 932, +}; + +static const uint16_t ud_itab__643[] = { + /* 0 */ 0, 933, +}; + +static const uint16_t ud_itab__644[] = { + /* 0 */ 0, 934, +}; + +static const uint16_t ud_itab__645[] = { + /* 0 */ 0, 935, +}; + +static const uint16_t ud_itab__646[] = { + /* 0 */ 0, 936, +}; + +static const uint16_t ud_itab__647[] = { + /* 0 */ 0, 937, +}; + +static const uint16_t ud_itab__648[] = { + /* 0 */ 0, 938, +}; + +static const uint16_t ud_itab__649[] = { + /* 0 */ 0, 939, +}; + +static const uint16_t ud_itab__650[] = { + /* 0 */ 0, 940, +}; + +static const uint16_t ud_itab__651[] = { + /* 0 */ 0, 941, +}; + +static const uint16_t ud_itab__652[] = { + /* 0 */ 0, 942, +}; + +static const uint16_t ud_itab__653[] = { + /* 0 */ 0, 943, +}; + +static const uint16_t ud_itab__654[] = { + /* 0 */ 0, 944, +}; + +static const uint16_t ud_itab__655[] = { + /* 0 */ 0, 945, +}; + +static const uint16_t ud_itab__656[] = { + /* 0 */ 0, 946, +}; + +static const uint16_t ud_itab__657[] = { + /* 0 */ 0, 947, +}; + +static const uint16_t ud_itab__658[] = { + /* 0 */ 0, 948, +}; + +static const uint16_t ud_itab__659[] = { + /* 0 */ 0, 949, +}; + +static const uint16_t ud_itab__660[] = { + /* 0 */ 0, 950, +}; + +static const uint16_t ud_itab__661[] = { + /* 0 */ 0, 951, +}; + +static const uint16_t ud_itab__662[] = { + /* 0 */ 0, 952, +}; + +static const uint16_t ud_itab__663[] = { + /* 0 */ 0, 953, +}; + +static const uint16_t ud_itab__664[] = { + /* 0 */ 0, 954, +}; + +static const uint16_t ud_itab__665[] = { + /* 0 */ 0, 955, +}; + +static const uint16_t ud_itab__666[] = { + /* 0 */ 0, 956, +}; + +static const uint16_t ud_itab__667[] = { + /* 0 */ 0, 957, +}; + +static const uint16_t ud_itab__668[] = { + /* 0 */ 0, 958, +}; + +static const uint16_t ud_itab__669[] = { + /* 0 */ 0, 959, +}; + +static const uint16_t ud_itab__670[] = { + /* 0 */ 0, 960, +}; + +static const uint16_t ud_itab__671[] = { + /* 0 */ 0, 961, +}; + +static const uint16_t ud_itab__672[] = { + /* 0 */ 0, 962, +}; + +static const uint16_t ud_itab__673[] = { + /* 0 */ 0, 963, +}; + +static const uint16_t ud_itab__674[] = { + /* 0 */ 0, 964, +}; + +static const uint16_t ud_itab__675[] = { + /* 0 */ 0, 965, +}; + +static const uint16_t ud_itab__676[] = { + /* 0 */ 0, 966, +}; + +static const uint16_t ud_itab__677[] = { + /* 0 */ 0, 967, +}; + +static const uint16_t ud_itab__678[] = { + /* 0 */ 0, 968, +}; + +static const uint16_t ud_itab__679[] = { + /* 0 */ 0, 969, +}; + +static const uint16_t ud_itab__680[] = { + /* 0 */ 0, 970, +}; + +static const uint16_t ud_itab__681[] = { + /* 0 */ 0, 971, +}; + +static const uint16_t ud_itab__682[] = { + /* 0 */ 0, 972, +}; + +static const uint16_t ud_itab__683[] = { + /* 0 */ 0, 973, +}; + +static const uint16_t ud_itab__684[] = { + /* 0 */ 0, 974, +}; + +static const uint16_t ud_itab__685[] = { + /* 0 */ 0, 975, +}; + +static const uint16_t ud_itab__686[] = { + /* 0 */ 0, 976, +}; + +static const uint16_t ud_itab__687[] = { + /* 0 */ 0, 977, +}; + +static const uint16_t ud_itab__688[] = { + /* 0 */ 0, 978, +}; + +static const uint16_t ud_itab__689[] = { + /* 0 */ 0, 979, +}; + +static const uint16_t ud_itab__690[] = { + /* 0 */ 0, 980, +}; + +static const uint16_t ud_itab__691[] = { + /* 0 */ 0, 981, +}; + +static const uint16_t ud_itab__692[] = { + /* 0 */ 0, 982, +}; + +static const uint16_t ud_itab__693[] = { + /* 0 */ 0, 983, +}; + +static const uint16_t ud_itab__694[] = { + /* 0 */ 0, 984, +}; + +static const uint16_t ud_itab__695[] = { + /* 0 */ 0, 985, +}; + +static const uint16_t ud_itab__696[] = { + /* 0 */ 0, 986, +}; + +static const uint16_t ud_itab__697[] = { + /* 0 */ 0, 987, +}; + +static const uint16_t ud_itab__698[] = { + /* 0 */ 0, 988, +}; + +static const uint16_t ud_itab__699[] = { + /* 0 */ 0, 989, +}; + +static const uint16_t ud_itab__635[] = { + /* 0 */ GROUP(636), GROUP(637), GROUP(638), GROUP(639), + /* 4 */ GROUP(640), GROUP(641), GROUP(642), GROUP(643), + /* 8 */ GROUP(644), GROUP(645), GROUP(646), GROUP(647), + /* c */ GROUP(648), GROUP(649), GROUP(650), GROUP(651), + /* 10 */ GROUP(652), GROUP(653), GROUP(654), GROUP(655), + /* 14 */ GROUP(656), GROUP(657), GROUP(658), GROUP(659), + /* 18 */ GROUP(660), GROUP(661), GROUP(662), GROUP(663), + /* 1c */ GROUP(664), GROUP(665), GROUP(666), GROUP(667), + /* 20 */ GROUP(668), GROUP(669), GROUP(670), GROUP(671), + /* 24 */ GROUP(672), GROUP(673), GROUP(674), GROUP(675), + /* 28 */ GROUP(676), GROUP(677), GROUP(678), GROUP(679), + /* 2c */ GROUP(680), GROUP(681), GROUP(682), GROUP(683), + /* 30 */ GROUP(684), GROUP(685), GROUP(686), GROUP(687), + /* 34 */ GROUP(688), GROUP(689), GROUP(690), GROUP(691), + /* 38 */ GROUP(692), GROUP(693), GROUP(694), GROUP(695), + /* 3c */ GROUP(696), GROUP(697), GROUP(698), GROUP(699), +}; + +static const uint16_t ud_itab__625[] = { + /* 0 */ GROUP(626), GROUP(635), +}; + +static const uint16_t ud_itab__702[] = { + /* 0 */ 990, 0, +}; + +static const uint16_t ud_itab__703[] = { + /* 0 */ 991, 0, +}; + +static const uint16_t ud_itab__704[] = { + /* 0 */ 992, 0, +}; + +static const uint16_t ud_itab__705[] = { + /* 0 */ 993, 0, +}; + +static const uint16_t ud_itab__706[] = { + /* 0 */ 994, 0, +}; + +static const uint16_t ud_itab__707[] = { + /* 0 */ 995, 0, +}; + +static const uint16_t ud_itab__708[] = { + /* 0 */ 996, 0, +}; + +static const uint16_t ud_itab__701[] = { + /* 0 */ GROUP(702), 0, GROUP(703), GROUP(704), + /* 4 */ GROUP(705), GROUP(706), GROUP(707), GROUP(708), +}; + +static const uint16_t ud_itab__710[] = { + /* 0 */ 0, 997, +}; + +static const uint16_t ud_itab__711[] = { + /* 0 */ 0, 998, +}; + +static const uint16_t ud_itab__712[] = { + /* 0 */ 0, 999, +}; + +static const uint16_t ud_itab__713[] = { + /* 0 */ 0, 1000, +}; + +static const uint16_t ud_itab__714[] = { + /* 0 */ 0, 1001, +}; + +static const uint16_t ud_itab__715[] = { + /* 0 */ 0, 1002, +}; + +static const uint16_t ud_itab__716[] = { + /* 0 */ 0, 1003, +}; + +static const uint16_t ud_itab__717[] = { + /* 0 */ 0, 1004, +}; + +static const uint16_t ud_itab__718[] = { + /* 0 */ 0, 1005, +}; + +static const uint16_t ud_itab__719[] = { + /* 0 */ 0, 1006, +}; + +static const uint16_t ud_itab__720[] = { + /* 0 */ 0, 1007, +}; + +static const uint16_t ud_itab__721[] = { + /* 0 */ 0, 1008, +}; + +static const uint16_t ud_itab__722[] = { + /* 0 */ 0, 1009, +}; + +static const uint16_t ud_itab__723[] = { + /* 0 */ 0, 1010, +}; + +static const uint16_t ud_itab__724[] = { + /* 0 */ 0, 1011, +}; + +static const uint16_t ud_itab__725[] = { + /* 0 */ 0, 1012, +}; + +static const uint16_t ud_itab__726[] = { + /* 0 */ 0, 1013, +}; + +static const uint16_t ud_itab__727[] = { + /* 0 */ 0, 1014, +}; + +static const uint16_t ud_itab__728[] = { + /* 0 */ 0, 1015, +}; + +static const uint16_t ud_itab__729[] = { + /* 0 */ 0, 1016, +}; + +static const uint16_t ud_itab__730[] = { + /* 0 */ 0, 1017, +}; + +static const uint16_t ud_itab__731[] = { + /* 0 */ 0, 1018, +}; + +static const uint16_t ud_itab__732[] = { + /* 0 */ 0, 1019, +}; + +static const uint16_t ud_itab__733[] = { + /* 0 */ 0, 1020, +}; + +static const uint16_t ud_itab__734[] = { + /* 0 */ 0, 1021, +}; + +static const uint16_t ud_itab__735[] = { + /* 0 */ 0, 1022, +}; + +static const uint16_t ud_itab__736[] = { + /* 0 */ 0, 1023, +}; + +static const uint16_t ud_itab__737[] = { + /* 0 */ 0, 1024, +}; + +static const uint16_t ud_itab__738[] = { + /* 0 */ 0, 1025, +}; + +static const uint16_t ud_itab__739[] = { + /* 0 */ 0, 1026, +}; + +static const uint16_t ud_itab__740[] = { + /* 0 */ 0, 1027, +}; + +static const uint16_t ud_itab__741[] = { + /* 0 */ 0, 1028, +}; + +static const uint16_t ud_itab__742[] = { + /* 0 */ 0, 1029, +}; + +static const uint16_t ud_itab__743[] = { + /* 0 */ 0, 1030, +}; + +static const uint16_t ud_itab__744[] = { + /* 0 */ 0, 1031, +}; + +static const uint16_t ud_itab__745[] = { + /* 0 */ 0, 1032, +}; + +static const uint16_t ud_itab__746[] = { + /* 0 */ 0, 1033, +}; + +static const uint16_t ud_itab__747[] = { + /* 0 */ 0, 1034, +}; + +static const uint16_t ud_itab__748[] = { + /* 0 */ 0, 1035, +}; + +static const uint16_t ud_itab__749[] = { + /* 0 */ 0, 1036, +}; + +static const uint16_t ud_itab__750[] = { + /* 0 */ 0, 1037, +}; + +static const uint16_t ud_itab__751[] = { + /* 0 */ 0, 1038, +}; + +static const uint16_t ud_itab__752[] = { + /* 0 */ 0, 1039, +}; + +static const uint16_t ud_itab__753[] = { + /* 0 */ 0, 1040, +}; + +static const uint16_t ud_itab__754[] = { + /* 0 */ 0, 1041, +}; + +static const uint16_t ud_itab__755[] = { + /* 0 */ 0, 1042, +}; + +static const uint16_t ud_itab__756[] = { + /* 0 */ 0, 1043, +}; + +static const uint16_t ud_itab__757[] = { + /* 0 */ 0, 1044, +}; + +static const uint16_t ud_itab__758[] = { + /* 0 */ 0, 1045, +}; + +static const uint16_t ud_itab__759[] = { + /* 0 */ 0, 1046, +}; + +static const uint16_t ud_itab__760[] = { + /* 0 */ 0, 1047, +}; + +static const uint16_t ud_itab__761[] = { + /* 0 */ 0, 1048, +}; + +static const uint16_t ud_itab__709[] = { + /* 0 */ GROUP(710), GROUP(711), GROUP(712), GROUP(713), + /* 4 */ GROUP(714), GROUP(715), GROUP(716), GROUP(717), + /* 8 */ GROUP(718), GROUP(719), GROUP(720), GROUP(721), + /* c */ GROUP(722), GROUP(723), GROUP(724), GROUP(725), + /* 10 */ GROUP(726), 0, 0, 0, + /* 14 */ 0, 0, 0, 0, + /* 18 */ GROUP(727), GROUP(728), GROUP(729), GROUP(730), + /* 1c */ GROUP(731), GROUP(732), GROUP(733), GROUP(734), + /* 20 */ GROUP(735), GROUP(736), 0, 0, + /* 24 */ GROUP(737), GROUP(738), 0, 0, + /* 28 */ GROUP(739), GROUP(740), GROUP(741), GROUP(742), + /* 2c */ GROUP(743), GROUP(744), GROUP(745), 0, + /* 30 */ GROUP(746), GROUP(747), GROUP(748), GROUP(749), + /* 34 */ GROUP(750), GROUP(751), GROUP(752), GROUP(753), + /* 38 */ GROUP(754), GROUP(755), GROUP(756), GROUP(757), + /* 3c */ GROUP(758), GROUP(759), GROUP(760), GROUP(761), +}; + +static const uint16_t ud_itab__700[] = { + /* 0 */ GROUP(701), GROUP(709), +}; + +static const uint16_t ud_itab__764[] = { + /* 0 */ 1049, 0, +}; + +static const uint16_t ud_itab__765[] = { + /* 0 */ 1050, 0, +}; + +static const uint16_t ud_itab__766[] = { + /* 0 */ 1051, 0, +}; + +static const uint16_t ud_itab__767[] = { + /* 0 */ 1052, 0, +}; + +static const uint16_t ud_itab__768[] = { + /* 0 */ 1053, 0, +}; + +static const uint16_t ud_itab__769[] = { + /* 0 */ 1054, 0, +}; + +static const uint16_t ud_itab__770[] = { + /* 0 */ 1055, 0, +}; + +static const uint16_t ud_itab__771[] = { + /* 0 */ 1056, 0, +}; + +static const uint16_t ud_itab__763[] = { + /* 0 */ GROUP(764), GROUP(765), GROUP(766), GROUP(767), + /* 4 */ GROUP(768), GROUP(769), GROUP(770), GROUP(771), +}; + +static const uint16_t ud_itab__773[] = { + /* 0 */ 0, 1057, +}; + +static const uint16_t ud_itab__774[] = { + /* 0 */ 0, 1058, +}; + +static const uint16_t ud_itab__775[] = { + /* 0 */ 0, 1059, +}; + +static const uint16_t ud_itab__776[] = { + /* 0 */ 0, 1060, +}; + +static const uint16_t ud_itab__777[] = { + /* 0 */ 0, 1061, +}; + +static const uint16_t ud_itab__778[] = { + /* 0 */ 0, 1062, +}; + +static const uint16_t ud_itab__779[] = { + /* 0 */ 0, 1063, +}; + +static const uint16_t ud_itab__780[] = { + /* 0 */ 0, 1064, +}; + +static const uint16_t ud_itab__781[] = { + /* 0 */ 0, 1065, +}; + +static const uint16_t ud_itab__782[] = { + /* 0 */ 0, 1066, +}; + +static const uint16_t ud_itab__783[] = { + /* 0 */ 0, 1067, +}; + +static const uint16_t ud_itab__784[] = { + /* 0 */ 0, 1068, +}; + +static const uint16_t ud_itab__785[] = { + /* 0 */ 0, 1069, +}; + +static const uint16_t ud_itab__786[] = { + /* 0 */ 0, 1070, +}; + +static const uint16_t ud_itab__787[] = { + /* 0 */ 0, 1071, +}; + +static const uint16_t ud_itab__788[] = { + /* 0 */ 0, 1072, +}; + +static const uint16_t ud_itab__789[] = { + /* 0 */ 0, 1073, +}; + +static const uint16_t ud_itab__790[] = { + /* 0 */ 0, 1074, +}; + +static const uint16_t ud_itab__791[] = { + /* 0 */ 0, 1075, +}; + +static const uint16_t ud_itab__792[] = { + /* 0 */ 0, 1076, +}; + +static const uint16_t ud_itab__793[] = { + /* 0 */ 0, 1077, +}; + +static const uint16_t ud_itab__794[] = { + /* 0 */ 0, 1078, +}; + +static const uint16_t ud_itab__795[] = { + /* 0 */ 0, 1079, +}; + +static const uint16_t ud_itab__796[] = { + /* 0 */ 0, 1080, +}; + +static const uint16_t ud_itab__797[] = { + /* 0 */ 0, 1081, +}; + +static const uint16_t ud_itab__798[] = { + /* 0 */ 0, 1082, +}; + +static const uint16_t ud_itab__799[] = { + /* 0 */ 0, 1083, +}; + +static const uint16_t ud_itab__800[] = { + /* 0 */ 0, 1084, +}; + +static const uint16_t ud_itab__801[] = { + /* 0 */ 0, 1085, +}; + +static const uint16_t ud_itab__802[] = { + /* 0 */ 0, 1086, +}; + +static const uint16_t ud_itab__803[] = { + /* 0 */ 0, 1087, +}; + +static const uint16_t ud_itab__804[] = { + /* 0 */ 0, 1088, +}; + +static const uint16_t ud_itab__805[] = { + /* 0 */ 0, 1089, +}; + +static const uint16_t ud_itab__772[] = { + /* 0 */ GROUP(773), GROUP(774), GROUP(775), GROUP(776), + /* 4 */ GROUP(777), GROUP(778), GROUP(779), GROUP(780), + /* 8 */ GROUP(781), GROUP(782), GROUP(783), GROUP(784), + /* c */ GROUP(785), GROUP(786), GROUP(787), GROUP(788), + /* 10 */ GROUP(789), GROUP(790), GROUP(791), GROUP(792), + /* 14 */ GROUP(793), GROUP(794), GROUP(795), GROUP(796), + /* 18 */ GROUP(797), GROUP(798), GROUP(799), GROUP(800), + /* 1c */ GROUP(801), GROUP(802), GROUP(803), GROUP(804), + /* 20 */ 0, 0, 0, 0, + /* 24 */ 0, 0, 0, 0, + /* 28 */ 0, GROUP(805), 0, 0, + /* 2c */ 0, 0, 0, 0, + /* 30 */ 0, 0, 0, 0, + /* 34 */ 0, 0, 0, 0, + /* 38 */ 0, 0, 0, 0, + /* 3c */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__762[] = { + /* 0 */ GROUP(763), GROUP(772), +}; + +static const uint16_t ud_itab__808[] = { + /* 0 */ 1090, 0, +}; + +static const uint16_t ud_itab__809[] = { + /* 0 */ 1091, 0, +}; + +static const uint16_t ud_itab__810[] = { + /* 0 */ 1092, 0, +}; + +static const uint16_t ud_itab__811[] = { + /* 0 */ 1093, 0, +}; + +static const uint16_t ud_itab__812[] = { + /* 0 */ 1094, 0, +}; + +static const uint16_t ud_itab__813[] = { + /* 0 */ 1095, 0, +}; + +static const uint16_t ud_itab__807[] = { + /* 0 */ GROUP(808), GROUP(809), GROUP(810), GROUP(811), + /* 4 */ 0, GROUP(812), 0, GROUP(813), +}; + +static const uint16_t ud_itab__815[] = { + /* 0 */ 0, 1096, +}; + +static const uint16_t ud_itab__816[] = { + /* 0 */ 0, 1097, +}; + +static const uint16_t ud_itab__817[] = { + /* 0 */ 0, 1098, +}; + +static const uint16_t ud_itab__818[] = { + /* 0 */ 0, 1099, +}; + +static const uint16_t ud_itab__819[] = { + /* 0 */ 0, 1100, +}; + +static const uint16_t ud_itab__820[] = { + /* 0 */ 0, 1101, +}; + +static const uint16_t ud_itab__821[] = { + /* 0 */ 0, 1102, +}; + +static const uint16_t ud_itab__822[] = { + /* 0 */ 0, 1103, +}; + +static const uint16_t ud_itab__823[] = { + /* 0 */ 0, 1104, +}; + +static const uint16_t ud_itab__824[] = { + /* 0 */ 0, 1105, +}; + +static const uint16_t ud_itab__825[] = { + /* 0 */ 0, 1106, +}; + +static const uint16_t ud_itab__826[] = { + /* 0 */ 0, 1107, +}; + +static const uint16_t ud_itab__827[] = { + /* 0 */ 0, 1108, +}; + +static const uint16_t ud_itab__828[] = { + /* 0 */ 0, 1109, +}; + +static const uint16_t ud_itab__829[] = { + /* 0 */ 0, 1110, +}; + +static const uint16_t ud_itab__830[] = { + /* 0 */ 0, 1111, +}; + +static const uint16_t ud_itab__831[] = { + /* 0 */ 0, 1112, +}; + +static const uint16_t ud_itab__832[] = { + /* 0 */ 0, 1113, +}; + +static const uint16_t ud_itab__833[] = { + /* 0 */ 0, 1114, +}; + +static const uint16_t ud_itab__834[] = { + /* 0 */ 0, 1115, +}; + +static const uint16_t ud_itab__835[] = { + /* 0 */ 0, 1116, +}; + +static const uint16_t ud_itab__836[] = { + /* 0 */ 0, 1117, +}; + +static const uint16_t ud_itab__837[] = { + /* 0 */ 0, 1118, +}; + +static const uint16_t ud_itab__838[] = { + /* 0 */ 0, 1119, +}; + +static const uint16_t ud_itab__839[] = { + /* 0 */ 0, 1120, +}; + +static const uint16_t ud_itab__840[] = { + /* 0 */ 0, 1121, +}; + +static const uint16_t ud_itab__841[] = { + /* 0 */ 0, 1122, +}; + +static const uint16_t ud_itab__842[] = { + /* 0 */ 0, 1123, +}; + +static const uint16_t ud_itab__843[] = { + /* 0 */ 0, 1124, +}; + +static const uint16_t ud_itab__844[] = { + /* 0 */ 0, 1125, +}; + +static const uint16_t ud_itab__845[] = { + /* 0 */ 0, 1126, +}; + +static const uint16_t ud_itab__846[] = { + /* 0 */ 0, 1127, +}; + +static const uint16_t ud_itab__847[] = { + /* 0 */ 0, 1128, +}; + +static const uint16_t ud_itab__848[] = { + /* 0 */ 0, 1129, +}; + +static const uint16_t ud_itab__849[] = { + /* 0 */ 0, 1130, +}; + +static const uint16_t ud_itab__850[] = { + /* 0 */ 0, 1131, +}; + +static const uint16_t ud_itab__851[] = { + /* 0 */ 0, 1132, +}; + +static const uint16_t ud_itab__852[] = { + /* 0 */ 0, 1133, +}; + +static const uint16_t ud_itab__853[] = { + /* 0 */ 0, 1134, +}; + +static const uint16_t ud_itab__854[] = { + /* 0 */ 0, 1135, +}; + +static const uint16_t ud_itab__855[] = { + /* 0 */ 0, 1136, +}; + +static const uint16_t ud_itab__856[] = { + /* 0 */ 0, 1137, +}; + +static const uint16_t ud_itab__857[] = { + /* 0 */ 0, 1138, +}; + +static const uint16_t ud_itab__858[] = { + /* 0 */ 0, 1139, +}; + +static const uint16_t ud_itab__859[] = { + /* 0 */ 0, 1140, +}; + +static const uint16_t ud_itab__860[] = { + /* 0 */ 0, 1141, +}; + +static const uint16_t ud_itab__861[] = { + /* 0 */ 0, 1142, +}; + +static const uint16_t ud_itab__862[] = { + /* 0 */ 0, 1143, +}; + +static const uint16_t ud_itab__863[] = { + /* 0 */ 0, 1144, +}; + +static const uint16_t ud_itab__864[] = { + /* 0 */ 0, 1145, +}; + +static const uint16_t ud_itab__814[] = { + /* 0 */ GROUP(815), GROUP(816), GROUP(817), GROUP(818), + /* 4 */ GROUP(819), GROUP(820), GROUP(821), GROUP(822), + /* 8 */ GROUP(823), GROUP(824), GROUP(825), GROUP(826), + /* c */ GROUP(827), GROUP(828), GROUP(829), GROUP(830), + /* 10 */ GROUP(831), GROUP(832), GROUP(833), GROUP(834), + /* 14 */ GROUP(835), GROUP(836), GROUP(837), GROUP(838), + /* 18 */ GROUP(839), GROUP(840), GROUP(841), GROUP(842), + /* 1c */ GROUP(843), GROUP(844), GROUP(845), GROUP(846), + /* 20 */ 0, 0, GROUP(847), GROUP(848), + /* 24 */ 0, 0, 0, 0, + /* 28 */ GROUP(849), GROUP(850), GROUP(851), GROUP(852), + /* 2c */ GROUP(853), GROUP(854), GROUP(855), GROUP(856), + /* 30 */ GROUP(857), GROUP(858), GROUP(859), GROUP(860), + /* 34 */ GROUP(861), GROUP(862), GROUP(863), GROUP(864), + /* 38 */ 0, 0, 0, 0, + /* 3c */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__806[] = { + /* 0 */ GROUP(807), GROUP(814), +}; + +static const uint16_t ud_itab__867[] = { + /* 0 */ 1146, 0, +}; + +static const uint16_t ud_itab__868[] = { + /* 0 */ 1147, 0, +}; + +static const uint16_t ud_itab__869[] = { + /* 0 */ 1148, 0, +}; + +static const uint16_t ud_itab__870[] = { + /* 0 */ 1149, 0, +}; + +static const uint16_t ud_itab__871[] = { + /* 0 */ 1150, 0, +}; + +static const uint16_t ud_itab__872[] = { + /* 0 */ 1151, 0, +}; + +static const uint16_t ud_itab__873[] = { + /* 0 */ 1152, 0, +}; + +static const uint16_t ud_itab__874[] = { + /* 0 */ 1153, 0, +}; + +static const uint16_t ud_itab__866[] = { + /* 0 */ GROUP(867), GROUP(868), GROUP(869), GROUP(870), + /* 4 */ GROUP(871), GROUP(872), GROUP(873), GROUP(874), +}; + +static const uint16_t ud_itab__876[] = { + /* 0 */ 0, 1154, +}; + +static const uint16_t ud_itab__877[] = { + /* 0 */ 0, 1155, +}; + +static const uint16_t ud_itab__878[] = { + /* 0 */ 0, 1156, +}; + +static const uint16_t ud_itab__879[] = { + /* 0 */ 0, 1157, +}; + +static const uint16_t ud_itab__880[] = { + /* 0 */ 0, 1158, +}; + +static const uint16_t ud_itab__881[] = { + /* 0 */ 0, 1159, +}; + +static const uint16_t ud_itab__882[] = { + /* 0 */ 0, 1160, +}; + +static const uint16_t ud_itab__883[] = { + /* 0 */ 0, 1161, +}; + +static const uint16_t ud_itab__884[] = { + /* 0 */ 0, 1162, +}; + +static const uint16_t ud_itab__885[] = { + /* 0 */ 0, 1163, +}; + +static const uint16_t ud_itab__886[] = { + /* 0 */ 0, 1164, +}; + +static const uint16_t ud_itab__887[] = { + /* 0 */ 0, 1165, +}; + +static const uint16_t ud_itab__888[] = { + /* 0 */ 0, 1166, +}; + +static const uint16_t ud_itab__889[] = { + /* 0 */ 0, 1167, +}; + +static const uint16_t ud_itab__890[] = { + /* 0 */ 0, 1168, +}; + +static const uint16_t ud_itab__891[] = { + /* 0 */ 0, 1169, +}; + +static const uint16_t ud_itab__892[] = { + /* 0 */ 0, 1170, +}; + +static const uint16_t ud_itab__893[] = { + /* 0 */ 0, 1171, +}; + +static const uint16_t ud_itab__894[] = { + /* 0 */ 0, 1172, +}; + +static const uint16_t ud_itab__895[] = { + /* 0 */ 0, 1173, +}; + +static const uint16_t ud_itab__896[] = { + /* 0 */ 0, 1174, +}; + +static const uint16_t ud_itab__897[] = { + /* 0 */ 0, 1175, +}; + +static const uint16_t ud_itab__898[] = { + /* 0 */ 0, 1176, +}; + +static const uint16_t ud_itab__899[] = { + /* 0 */ 0, 1177, +}; + +static const uint16_t ud_itab__900[] = { + /* 0 */ 0, 1178, +}; + +static const uint16_t ud_itab__901[] = { + /* 0 */ 0, 1179, +}; + +static const uint16_t ud_itab__902[] = { + /* 0 */ 0, 1180, +}; + +static const uint16_t ud_itab__903[] = { + /* 0 */ 0, 1181, +}; + +static const uint16_t ud_itab__904[] = { + /* 0 */ 0, 1182, +}; + +static const uint16_t ud_itab__905[] = { + /* 0 */ 0, 1183, +}; + +static const uint16_t ud_itab__906[] = { + /* 0 */ 0, 1184, +}; + +static const uint16_t ud_itab__907[] = { + /* 0 */ 0, 1185, +}; + +static const uint16_t ud_itab__908[] = { + /* 0 */ 0, 1186, +}; + +static const uint16_t ud_itab__909[] = { + /* 0 */ 0, 1187, +}; + +static const uint16_t ud_itab__910[] = { + /* 0 */ 0, 1188, +}; + +static const uint16_t ud_itab__911[] = { + /* 0 */ 0, 1189, +}; + +static const uint16_t ud_itab__912[] = { + /* 0 */ 0, 1190, +}; + +static const uint16_t ud_itab__913[] = { + /* 0 */ 0, 1191, +}; + +static const uint16_t ud_itab__914[] = { + /* 0 */ 0, 1192, +}; + +static const uint16_t ud_itab__915[] = { + /* 0 */ 0, 1193, +}; + +static const uint16_t ud_itab__916[] = { + /* 0 */ 0, 1194, +}; + +static const uint16_t ud_itab__917[] = { + /* 0 */ 0, 1195, +}; + +static const uint16_t ud_itab__918[] = { + /* 0 */ 0, 1196, +}; + +static const uint16_t ud_itab__919[] = { + /* 0 */ 0, 1197, +}; + +static const uint16_t ud_itab__920[] = { + /* 0 */ 0, 1198, +}; + +static const uint16_t ud_itab__921[] = { + /* 0 */ 0, 1199, +}; + +static const uint16_t ud_itab__922[] = { + /* 0 */ 0, 1200, +}; + +static const uint16_t ud_itab__923[] = { + /* 0 */ 0, 1201, +}; + +static const uint16_t ud_itab__924[] = { + /* 0 */ 0, 1202, +}; + +static const uint16_t ud_itab__925[] = { + /* 0 */ 0, 1203, +}; + +static const uint16_t ud_itab__926[] = { + /* 0 */ 0, 1204, +}; + +static const uint16_t ud_itab__927[] = { + /* 0 */ 0, 1205, +}; + +static const uint16_t ud_itab__928[] = { + /* 0 */ 0, 1206, +}; + +static const uint16_t ud_itab__929[] = { + /* 0 */ 0, 1207, +}; + +static const uint16_t ud_itab__930[] = { + /* 0 */ 0, 1208, +}; + +static const uint16_t ud_itab__931[] = { + /* 0 */ 0, 1209, +}; + +static const uint16_t ud_itab__932[] = { + /* 0 */ 0, 1210, +}; + +static const uint16_t ud_itab__933[] = { + /* 0 */ 0, 1211, +}; + +static const uint16_t ud_itab__934[] = { + /* 0 */ 0, 1212, +}; + +static const uint16_t ud_itab__935[] = { + /* 0 */ 0, 1213, +}; + +static const uint16_t ud_itab__936[] = { + /* 0 */ 0, 1214, +}; + +static const uint16_t ud_itab__937[] = { + /* 0 */ 0, 1215, +}; + +static const uint16_t ud_itab__938[] = { + /* 0 */ 0, 1216, +}; + +static const uint16_t ud_itab__939[] = { + /* 0 */ 0, 1217, +}; + +static const uint16_t ud_itab__875[] = { + /* 0 */ GROUP(876), GROUP(877), GROUP(878), GROUP(879), + /* 4 */ GROUP(880), GROUP(881), GROUP(882), GROUP(883), + /* 8 */ GROUP(884), GROUP(885), GROUP(886), GROUP(887), + /* c */ GROUP(888), GROUP(889), GROUP(890), GROUP(891), + /* 10 */ GROUP(892), GROUP(893), GROUP(894), GROUP(895), + /* 14 */ GROUP(896), GROUP(897), GROUP(898), GROUP(899), + /* 18 */ GROUP(900), GROUP(901), GROUP(902), GROUP(903), + /* 1c */ GROUP(904), GROUP(905), GROUP(906), GROUP(907), + /* 20 */ GROUP(908), GROUP(909), GROUP(910), GROUP(911), + /* 24 */ GROUP(912), GROUP(913), GROUP(914), GROUP(915), + /* 28 */ GROUP(916), GROUP(917), GROUP(918), GROUP(919), + /* 2c */ GROUP(920), GROUP(921), GROUP(922), GROUP(923), + /* 30 */ GROUP(924), GROUP(925), GROUP(926), GROUP(927), + /* 34 */ GROUP(928), GROUP(929), GROUP(930), GROUP(931), + /* 38 */ GROUP(932), GROUP(933), GROUP(934), GROUP(935), + /* 3c */ GROUP(936), GROUP(937), GROUP(938), GROUP(939), +}; + +static const uint16_t ud_itab__865[] = { + /* 0 */ GROUP(866), GROUP(875), +}; + +static const uint16_t ud_itab__942[] = { + /* 0 */ 1218, 0, +}; + +static const uint16_t ud_itab__943[] = { + /* 0 */ 1219, 0, +}; + +static const uint16_t ud_itab__944[] = { + /* 0 */ 1220, 0, +}; + +static const uint16_t ud_itab__945[] = { + /* 0 */ 1221, 0, +}; + +static const uint16_t ud_itab__946[] = { + /* 0 */ 1222, 0, +}; + +static const uint16_t ud_itab__947[] = { + /* 0 */ 1223, 0, +}; + +static const uint16_t ud_itab__948[] = { + /* 0 */ 1224, 0, +}; + +static const uint16_t ud_itab__941[] = { + /* 0 */ GROUP(942), GROUP(943), GROUP(944), GROUP(945), + /* 4 */ GROUP(946), 0, GROUP(947), GROUP(948), +}; + +static const uint16_t ud_itab__950[] = { + /* 0 */ 0, 1225, +}; + +static const uint16_t ud_itab__951[] = { + /* 0 */ 0, 1226, +}; + +static const uint16_t ud_itab__952[] = { + /* 0 */ 0, 1227, +}; + +static const uint16_t ud_itab__953[] = { + /* 0 */ 0, 1228, +}; + +static const uint16_t ud_itab__954[] = { + /* 0 */ 0, 1229, +}; + +static const uint16_t ud_itab__955[] = { + /* 0 */ 0, 1230, +}; + +static const uint16_t ud_itab__956[] = { + /* 0 */ 0, 1231, +}; + +static const uint16_t ud_itab__957[] = { + /* 0 */ 0, 1232, +}; + +static const uint16_t ud_itab__958[] = { + /* 0 */ 0, 1233, +}; + +static const uint16_t ud_itab__959[] = { + /* 0 */ 0, 1234, +}; + +static const uint16_t ud_itab__960[] = { + /* 0 */ 0, 1235, +}; + +static const uint16_t ud_itab__961[] = { + /* 0 */ 0, 1236, +}; + +static const uint16_t ud_itab__962[] = { + /* 0 */ 0, 1237, +}; + +static const uint16_t ud_itab__963[] = { + /* 0 */ 0, 1238, +}; + +static const uint16_t ud_itab__964[] = { + /* 0 */ 0, 1239, +}; + +static const uint16_t ud_itab__965[] = { + /* 0 */ 0, 1240, +}; + +static const uint16_t ud_itab__966[] = { + /* 0 */ 0, 1241, +}; + +static const uint16_t ud_itab__967[] = { + /* 0 */ 0, 1242, +}; + +static const uint16_t ud_itab__968[] = { + /* 0 */ 0, 1243, +}; + +static const uint16_t ud_itab__969[] = { + /* 0 */ 0, 1244, +}; + +static const uint16_t ud_itab__970[] = { + /* 0 */ 0, 1245, +}; + +static const uint16_t ud_itab__971[] = { + /* 0 */ 0, 1246, +}; + +static const uint16_t ud_itab__972[] = { + /* 0 */ 0, 1247, +}; + +static const uint16_t ud_itab__973[] = { + /* 0 */ 0, 1248, +}; + +static const uint16_t ud_itab__974[] = { + /* 0 */ 0, 1249, +}; + +static const uint16_t ud_itab__975[] = { + /* 0 */ 0, 1250, +}; + +static const uint16_t ud_itab__976[] = { + /* 0 */ 0, 1251, +}; + +static const uint16_t ud_itab__977[] = { + /* 0 */ 0, 1252, +}; + +static const uint16_t ud_itab__978[] = { + /* 0 */ 0, 1253, +}; + +static const uint16_t ud_itab__979[] = { + /* 0 */ 0, 1254, +}; + +static const uint16_t ud_itab__980[] = { + /* 0 */ 0, 1255, +}; + +static const uint16_t ud_itab__981[] = { + /* 0 */ 0, 1256, +}; + +static const uint16_t ud_itab__982[] = { + /* 0 */ 0, 1257, +}; + +static const uint16_t ud_itab__983[] = { + /* 0 */ 0, 1258, +}; + +static const uint16_t ud_itab__984[] = { + /* 0 */ 0, 1259, +}; + +static const uint16_t ud_itab__985[] = { + /* 0 */ 0, 1260, +}; + +static const uint16_t ud_itab__986[] = { + /* 0 */ 0, 1261, +}; + +static const uint16_t ud_itab__987[] = { + /* 0 */ 0, 1262, +}; + +static const uint16_t ud_itab__988[] = { + /* 0 */ 0, 1263, +}; + +static const uint16_t ud_itab__989[] = { + /* 0 */ 0, 1264, +}; + +static const uint16_t ud_itab__990[] = { + /* 0 */ 0, 1265, +}; + +static const uint16_t ud_itab__991[] = { + /* 0 */ 0, 1266, +}; + +static const uint16_t ud_itab__992[] = { + /* 0 */ 0, 1267, +}; + +static const uint16_t ud_itab__993[] = { + /* 0 */ 0, 1268, +}; + +static const uint16_t ud_itab__994[] = { + /* 0 */ 0, 1269, +}; + +static const uint16_t ud_itab__995[] = { + /* 0 */ 0, 1270, +}; + +static const uint16_t ud_itab__996[] = { + /* 0 */ 0, 1271, +}; + +static const uint16_t ud_itab__997[] = { + /* 0 */ 0, 1272, +}; + +static const uint16_t ud_itab__949[] = { + /* 0 */ GROUP(950), GROUP(951), GROUP(952), GROUP(953), + /* 4 */ GROUP(954), GROUP(955), GROUP(956), GROUP(957), + /* 8 */ GROUP(958), GROUP(959), GROUP(960), GROUP(961), + /* c */ GROUP(962), GROUP(963), GROUP(964), GROUP(965), + /* 10 */ GROUP(966), GROUP(967), GROUP(968), GROUP(969), + /* 14 */ GROUP(970), GROUP(971), GROUP(972), GROUP(973), + /* 18 */ GROUP(974), GROUP(975), GROUP(976), GROUP(977), + /* 1c */ GROUP(978), GROUP(979), GROUP(980), GROUP(981), + /* 20 */ GROUP(982), GROUP(983), GROUP(984), GROUP(985), + /* 24 */ GROUP(986), GROUP(987), GROUP(988), GROUP(989), + /* 28 */ GROUP(990), GROUP(991), GROUP(992), GROUP(993), + /* 2c */ GROUP(994), GROUP(995), GROUP(996), GROUP(997), + /* 30 */ 0, 0, 0, 0, + /* 34 */ 0, 0, 0, 0, + /* 38 */ 0, 0, 0, 0, + /* 3c */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__940[] = { + /* 0 */ GROUP(941), GROUP(949), +}; + +static const uint16_t ud_itab__1000[] = { + /* 0 */ 1273, 0, +}; + +static const uint16_t ud_itab__1001[] = { + /* 0 */ 1274, 0, +}; + +static const uint16_t ud_itab__1002[] = { + /* 0 */ 1275, 0, +}; + +static const uint16_t ud_itab__1003[] = { + /* 0 */ 1276, 0, +}; + +static const uint16_t ud_itab__1004[] = { + /* 0 */ 1277, 0, +}; + +static const uint16_t ud_itab__1005[] = { + /* 0 */ 1278, 0, +}; + +static const uint16_t ud_itab__1006[] = { + /* 0 */ 1279, 0, +}; + +static const uint16_t ud_itab__1007[] = { + /* 0 */ 1280, 0, +}; + +static const uint16_t ud_itab__999[] = { + /* 0 */ GROUP(1000), GROUP(1001), GROUP(1002), GROUP(1003), + /* 4 */ GROUP(1004), GROUP(1005), GROUP(1006), GROUP(1007), +}; + +static const uint16_t ud_itab__1009[] = { + /* 0 */ 0, 1281, +}; + +static const uint16_t ud_itab__1010[] = { + /* 0 */ 0, 1282, +}; + +static const uint16_t ud_itab__1011[] = { + /* 0 */ 0, 1283, +}; + +static const uint16_t ud_itab__1012[] = { + /* 0 */ 0, 1284, +}; + +static const uint16_t ud_itab__1013[] = { + /* 0 */ 0, 1285, +}; + +static const uint16_t ud_itab__1014[] = { + /* 0 */ 0, 1286, +}; + +static const uint16_t ud_itab__1015[] = { + /* 0 */ 0, 1287, +}; + +static const uint16_t ud_itab__1016[] = { + /* 0 */ 0, 1288, +}; + +static const uint16_t ud_itab__1017[] = { + /* 0 */ 0, 1289, +}; + +static const uint16_t ud_itab__1018[] = { + /* 0 */ 0, 1290, +}; + +static const uint16_t ud_itab__1019[] = { + /* 0 */ 0, 1291, +}; + +static const uint16_t ud_itab__1020[] = { + /* 0 */ 0, 1292, +}; + +static const uint16_t ud_itab__1021[] = { + /* 0 */ 0, 1293, +}; + +static const uint16_t ud_itab__1022[] = { + /* 0 */ 0, 1294, +}; + +static const uint16_t ud_itab__1023[] = { + /* 0 */ 0, 1295, +}; + +static const uint16_t ud_itab__1024[] = { + /* 0 */ 0, 1296, +}; + +static const uint16_t ud_itab__1025[] = { + /* 0 */ 0, 1297, +}; + +static const uint16_t ud_itab__1026[] = { + /* 0 */ 0, 1298, +}; + +static const uint16_t ud_itab__1027[] = { + /* 0 */ 0, 1299, +}; + +static const uint16_t ud_itab__1028[] = { + /* 0 */ 0, 1300, +}; + +static const uint16_t ud_itab__1029[] = { + /* 0 */ 0, 1301, +}; + +static const uint16_t ud_itab__1030[] = { + /* 0 */ 0, 1302, +}; + +static const uint16_t ud_itab__1031[] = { + /* 0 */ 0, 1303, +}; + +static const uint16_t ud_itab__1032[] = { + /* 0 */ 0, 1304, +}; + +static const uint16_t ud_itab__1033[] = { + /* 0 */ 0, 1305, +}; + +static const uint16_t ud_itab__1034[] = { + /* 0 */ 0, 1306, +}; + +static const uint16_t ud_itab__1035[] = { + /* 0 */ 0, 1307, +}; + +static const uint16_t ud_itab__1036[] = { + /* 0 */ 0, 1308, +}; + +static const uint16_t ud_itab__1037[] = { + /* 0 */ 0, 1309, +}; + +static const uint16_t ud_itab__1038[] = { + /* 0 */ 0, 1310, +}; + +static const uint16_t ud_itab__1039[] = { + /* 0 */ 0, 1311, +}; + +static const uint16_t ud_itab__1040[] = { + /* 0 */ 0, 1312, +}; + +static const uint16_t ud_itab__1041[] = { + /* 0 */ 0, 1313, +}; + +static const uint16_t ud_itab__1042[] = { + /* 0 */ 0, 1314, +}; + +static const uint16_t ud_itab__1043[] = { + /* 0 */ 0, 1315, +}; + +static const uint16_t ud_itab__1044[] = { + /* 0 */ 0, 1316, +}; + +static const uint16_t ud_itab__1045[] = { + /* 0 */ 0, 1317, +}; + +static const uint16_t ud_itab__1046[] = { + /* 0 */ 0, 1318, +}; + +static const uint16_t ud_itab__1047[] = { + /* 0 */ 0, 1319, +}; + +static const uint16_t ud_itab__1048[] = { + /* 0 */ 0, 1320, +}; + +static const uint16_t ud_itab__1049[] = { + /* 0 */ 0, 1321, +}; + +static const uint16_t ud_itab__1050[] = { + /* 0 */ 0, 1322, +}; + +static const uint16_t ud_itab__1051[] = { + /* 0 */ 0, 1323, +}; + +static const uint16_t ud_itab__1052[] = { + /* 0 */ 0, 1324, +}; + +static const uint16_t ud_itab__1053[] = { + /* 0 */ 0, 1325, +}; + +static const uint16_t ud_itab__1054[] = { + /* 0 */ 0, 1326, +}; + +static const uint16_t ud_itab__1055[] = { + /* 0 */ 0, 1327, +}; + +static const uint16_t ud_itab__1056[] = { + /* 0 */ 0, 1328, +}; + +static const uint16_t ud_itab__1057[] = { + /* 0 */ 0, 1329, +}; + +static const uint16_t ud_itab__1058[] = { + /* 0 */ 0, 1330, +}; + +static const uint16_t ud_itab__1059[] = { + /* 0 */ 0, 1331, +}; + +static const uint16_t ud_itab__1060[] = { + /* 0 */ 0, 1332, +}; + +static const uint16_t ud_itab__1061[] = { + /* 0 */ 0, 1333, +}; + +static const uint16_t ud_itab__1062[] = { + /* 0 */ 0, 1334, +}; + +static const uint16_t ud_itab__1063[] = { + /* 0 */ 0, 1335, +}; + +static const uint16_t ud_itab__1064[] = { + /* 0 */ 0, 1336, +}; + +static const uint16_t ud_itab__1065[] = { + /* 0 */ 0, 1337, +}; + +static const uint16_t ud_itab__1008[] = { + /* 0 */ GROUP(1009), GROUP(1010), GROUP(1011), GROUP(1012), + /* 4 */ GROUP(1013), GROUP(1014), GROUP(1015), GROUP(1016), + /* 8 */ GROUP(1017), GROUP(1018), GROUP(1019), GROUP(1020), + /* c */ GROUP(1021), GROUP(1022), GROUP(1023), GROUP(1024), + /* 10 */ GROUP(1025), GROUP(1026), GROUP(1027), GROUP(1028), + /* 14 */ GROUP(1029), GROUP(1030), GROUP(1031), GROUP(1032), + /* 18 */ 0, GROUP(1033), 0, 0, + /* 1c */ 0, 0, 0, 0, + /* 20 */ GROUP(1034), GROUP(1035), GROUP(1036), GROUP(1037), + /* 24 */ GROUP(1038), GROUP(1039), GROUP(1040), GROUP(1041), + /* 28 */ GROUP(1042), GROUP(1043), GROUP(1044), GROUP(1045), + /* 2c */ GROUP(1046), GROUP(1047), GROUP(1048), GROUP(1049), + /* 30 */ GROUP(1050), GROUP(1051), GROUP(1052), GROUP(1053), + /* 34 */ GROUP(1054), GROUP(1055), GROUP(1056), GROUP(1057), + /* 38 */ GROUP(1058), GROUP(1059), GROUP(1060), GROUP(1061), + /* 3c */ GROUP(1062), GROUP(1063), GROUP(1064), GROUP(1065), +}; + +static const uint16_t ud_itab__998[] = { + /* 0 */ GROUP(999), GROUP(1008), +}; + +static const uint16_t ud_itab__1068[] = { + /* 0 */ 1338, 0, +}; + +static const uint16_t ud_itab__1069[] = { + /* 0 */ 1339, 0, +}; + +static const uint16_t ud_itab__1070[] = { + /* 0 */ 1340, 0, +}; + +static const uint16_t ud_itab__1071[] = { + /* 0 */ 1341, 0, +}; + +static const uint16_t ud_itab__1072[] = { + /* 0 */ 1342, 0, +}; + +static const uint16_t ud_itab__1073[] = { + /* 0 */ 1343, 0, +}; + +static const uint16_t ud_itab__1074[] = { + /* 0 */ 1344, 0, +}; + +static const uint16_t ud_itab__1075[] = { + /* 0 */ 1345, 0, +}; + +static const uint16_t ud_itab__1067[] = { + /* 0 */ GROUP(1068), GROUP(1069), GROUP(1070), GROUP(1071), + /* 4 */ GROUP(1072), GROUP(1073), GROUP(1074), GROUP(1075), +}; + +static const uint16_t ud_itab__1077[] = { + /* 0 */ 0, 1346, +}; + +static const uint16_t ud_itab__1078[] = { + /* 0 */ 0, 1347, +}; + +static const uint16_t ud_itab__1079[] = { + /* 0 */ 0, 1348, +}; + +static const uint16_t ud_itab__1080[] = { + /* 0 */ 0, 1349, +}; + +static const uint16_t ud_itab__1081[] = { + /* 0 */ 0, 1350, +}; + +static const uint16_t ud_itab__1082[] = { + /* 0 */ 0, 1351, +}; + +static const uint16_t ud_itab__1083[] = { + /* 0 */ 0, 1352, +}; + +static const uint16_t ud_itab__1084[] = { + /* 0 */ 0, 1353, +}; + +static const uint16_t ud_itab__1085[] = { + /* 0 */ 0, 1354, +}; + +static const uint16_t ud_itab__1086[] = { + /* 0 */ 0, 1355, +}; + +static const uint16_t ud_itab__1087[] = { + /* 0 */ 0, 1356, +}; + +static const uint16_t ud_itab__1088[] = { + /* 0 */ 0, 1357, +}; + +static const uint16_t ud_itab__1089[] = { + /* 0 */ 0, 1358, +}; + +static const uint16_t ud_itab__1090[] = { + /* 0 */ 0, 1359, +}; + +static const uint16_t ud_itab__1091[] = { + /* 0 */ 0, 1360, +}; + +static const uint16_t ud_itab__1092[] = { + /* 0 */ 0, 1361, +}; + +static const uint16_t ud_itab__1093[] = { + /* 0 */ 0, 1362, +}; + +static const uint16_t ud_itab__1094[] = { + /* 0 */ 0, 1363, +}; + +static const uint16_t ud_itab__1095[] = { + /* 0 */ 0, 1364, +}; + +static const uint16_t ud_itab__1096[] = { + /* 0 */ 0, 1365, +}; + +static const uint16_t ud_itab__1097[] = { + /* 0 */ 0, 1366, +}; + +static const uint16_t ud_itab__1098[] = { + /* 0 */ 0, 1367, +}; + +static const uint16_t ud_itab__1099[] = { + /* 0 */ 0, 1368, +}; + +static const uint16_t ud_itab__1100[] = { + /* 0 */ 0, 1369, +}; + +static const uint16_t ud_itab__1101[] = { + /* 0 */ 0, 1370, +}; + +static const uint16_t ud_itab__1102[] = { + /* 0 */ 0, 1371, +}; + +static const uint16_t ud_itab__1103[] = { + /* 0 */ 0, 1372, +}; + +static const uint16_t ud_itab__1104[] = { + /* 0 */ 0, 1373, +}; + +static const uint16_t ud_itab__1105[] = { + /* 0 */ 0, 1374, +}; + +static const uint16_t ud_itab__1106[] = { + /* 0 */ 0, 1375, +}; + +static const uint16_t ud_itab__1107[] = { + /* 0 */ 0, 1376, +}; + +static const uint16_t ud_itab__1108[] = { + /* 0 */ 0, 1377, +}; + +static const uint16_t ud_itab__1109[] = { + /* 0 */ 0, 1378, +}; + +static const uint16_t ud_itab__1110[] = { + /* 0 */ 0, 1379, +}; + +static const uint16_t ud_itab__1111[] = { + /* 0 */ 0, 1380, +}; + +static const uint16_t ud_itab__1112[] = { + /* 0 */ 0, 1381, +}; + +static const uint16_t ud_itab__1113[] = { + /* 0 */ 0, 1382, +}; + +static const uint16_t ud_itab__1114[] = { + /* 0 */ 0, 1383, +}; + +static const uint16_t ud_itab__1115[] = { + /* 0 */ 0, 1384, +}; + +static const uint16_t ud_itab__1116[] = { + /* 0 */ 0, 1385, +}; + +static const uint16_t ud_itab__1117[] = { + /* 0 */ 0, 1386, +}; + +static const uint16_t ud_itab__1118[] = { + /* 0 */ 0, 1387, +}; + +static const uint16_t ud_itab__1119[] = { + /* 0 */ 0, 1388, +}; + +static const uint16_t ud_itab__1120[] = { + /* 0 */ 0, 1389, +}; + +static const uint16_t ud_itab__1121[] = { + /* 0 */ 0, 1390, +}; + +static const uint16_t ud_itab__1122[] = { + /* 0 */ 0, 1391, +}; + +static const uint16_t ud_itab__1123[] = { + /* 0 */ 0, 1392, +}; + +static const uint16_t ud_itab__1124[] = { + /* 0 */ 0, 1393, +}; + +static const uint16_t ud_itab__1125[] = { + /* 0 */ 0, 1394, +}; + +static const uint16_t ud_itab__1076[] = { + /* 0 */ GROUP(1077), GROUP(1078), GROUP(1079), GROUP(1080), + /* 4 */ GROUP(1081), GROUP(1082), GROUP(1083), GROUP(1084), + /* 8 */ GROUP(1085), GROUP(1086), GROUP(1087), GROUP(1088), + /* c */ GROUP(1089), GROUP(1090), GROUP(1091), GROUP(1092), + /* 10 */ GROUP(1093), GROUP(1094), GROUP(1095), GROUP(1096), + /* 14 */ GROUP(1097), GROUP(1098), GROUP(1099), GROUP(1100), + /* 18 */ GROUP(1101), GROUP(1102), GROUP(1103), GROUP(1104), + /* 1c */ GROUP(1105), GROUP(1106), GROUP(1107), GROUP(1108), + /* 20 */ GROUP(1109), 0, 0, 0, + /* 24 */ 0, 0, 0, 0, + /* 28 */ GROUP(1110), GROUP(1111), GROUP(1112), GROUP(1113), + /* 2c */ GROUP(1114), GROUP(1115), GROUP(1116), GROUP(1117), + /* 30 */ GROUP(1118), GROUP(1119), GROUP(1120), GROUP(1121), + /* 34 */ GROUP(1122), GROUP(1123), GROUP(1124), GROUP(1125), + /* 38 */ 0, 0, 0, 0, + /* 3c */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__1066[] = { + /* 0 */ GROUP(1067), GROUP(1076), +}; + +static const uint16_t ud_itab__1126[] = { + /* 0 */ 1398, 1399, 1400, +}; + +static const uint16_t ud_itab__1127[] = { + /* 0 */ 1407, 0, +}; + +static const uint16_t ud_itab__1128[] = { + /* 0 */ 1419, 1420, 1421, 1422, + /* 4 */ 1423, 1424, 1425, 1426, +}; + +static const uint16_t ud_itab__1129[] = { + /* 0 */ 1427, 1428, 1429, 1430, + /* 4 */ 1431, 1432, 1433, 1434, +}; + +static const uint16_t ud_itab__1130[] = { + /* 0 */ 1441, 1442, 0, 0, + /* 4 */ 0, 0, 0, 0, +}; + +static const uint16_t ud_itab__1132[] = { + /* 0 */ 1445, 1446, +}; + +static const uint16_t ud_itab__1131[] = { + /* 0 */ 1443, 1444, GROUP(1132), 1447, + /* 4 */ 1448, 1449, 1450, 0, +}; + +const uint16_t ud_itab__0[] = { + /* 0 */ 1, 2, 3, 4, + /* 4 */ 5, 6, GROUP(1), GROUP(2), + /* 8 */ 9, 10, 11, 12, + /* c */ 13, 14, GROUP(3), GROUP(4), + /* 10 */ 628, 629, 630, 631, + /* 14 */ 632, 633, GROUP(563), GROUP(564), + /* 18 */ 636, 637, 638, 639, + /* 1c */ 640, 641, GROUP(565), GROUP(566), + /* 20 */ 644, 645, 646, 647, + /* 24 */ 648, 649, 0, GROUP(567), + /* 28 */ 651, 652, 653, 654, + /* 2c */ 655, 656, 0, GROUP(568), + /* 30 */ 658, 659, 660, 661, + /* 34 */ 662, 663, 0, GROUP(569), + /* 38 */ 665, 666, 667, 668, + /* 3c */ 669, 670, 0, GROUP(570), + /* 40 */ 672, 673, 674, 675, + /* 44 */ 676, 677, 678, 679, + /* 48 */ 680, 681, 682, 683, + /* 4c */ 684, 685, 686, 687, + /* 50 */ 688, 689, 690, 691, + /* 54 */ 692, 693, 694, 695, + /* 58 */ 696, 697, 698, 699, + /* 5c */ 700, 701, 702, 703, + /* 60 */ GROUP(571), GROUP(574), GROUP(577), GROUP(578), + /* 64 */ 0, 0, 0, 0, + /* 68 */ 711, 712, 713, 714, + /* 6c */ 715, GROUP(579), 718, GROUP(580), + /* 70 */ 721, 722, 723, 724, + /* 74 */ 725, 726, 727, 728, + /* 78 */ 729, 730, 731, 732, + /* 7c */ 733, 734, 735, 736, + /* 80 */ GROUP(581), GROUP(582), GROUP(583), GROUP(592), + /* 84 */ 769, 770, 771, 772, + /* 88 */ 773, 774, 775, 776, + /* 8c */ 777, 778, 779, GROUP(593), + /* 90 */ 781, 782, 783, 784, + /* 94 */ 785, 786, 787, 788, + /* 98 */ GROUP(594), GROUP(595), GROUP(596), 796, + /* 9c */ GROUP(597), GROUP(601), 806, 807, + /* a0 */ 808, 809, 810, 811, + /* a4 */ 812, GROUP(605), 816, GROUP(606), + /* a8 */ 820, 821, 822, GROUP(607), + /* ac */ 826, GROUP(608), 830, GROUP(609), + /* b0 */ 834, 835, 836, 837, + /* b4 */ 838, 839, 840, 841, + /* b8 */ 842, 843, 844, 845, + /* bc */ 846, 847, 848, 849, + /* c0 */ GROUP(610), GROUP(611), 866, 867, + /* c4 */ GROUP(612), GROUP(613), GROUP(614), GROUP(615), + /* c8 */ 872, 873, 874, 875, + /* cc */ 876, 877, GROUP(616), GROUP(617), + /* d0 */ GROUP(618), GROUP(619), GROUP(620), GROUP(621), + /* d4 */ GROUP(622), GROUP(623), GROUP(624), 917, + /* d8 */ GROUP(625), GROUP(700), GROUP(762), GROUP(806), + /* dc */ GROUP(865), GROUP(940), GROUP(998), GROUP(1066), + /* e0 */ 1395, 1396, 1397, GROUP(1126), + /* e4 */ 1401, 1402, 1403, 1404, + /* e8 */ 1405, 1406, GROUP(1127), 1408, + /* ec */ 1409, 1410, 1411, 1412, + /* f0 */ 1413, 1414, 1415, 1416, + /* f4 */ 1417, 1418, GROUP(1128), GROUP(1129), + /* f8 */ 1435, 1436, 1437, 1438, + /* fc */ 1439, 1440, GROUP(1130), GROUP(1131), +}; + + +const struct ud_lookup_table_list_entry ud_lookup_table_list[] = { + /* 000 */ { ud_itab__0, UD_TAB__OPC_TABLE, "table0" }, + /* 001 */ { ud_itab__1, UD_TAB__OPC_MODE, "/m" }, + /* 002 */ { ud_itab__2, UD_TAB__OPC_MODE, "/m" }, + /* 003 */ { ud_itab__3, UD_TAB__OPC_MODE, "/m" }, + /* 004 */ { ud_itab__4, UD_TAB__OPC_TABLE, "0f" }, + /* 005 */ { ud_itab__5, UD_TAB__OPC_REG, "/reg" }, + /* 006 */ { ud_itab__6, UD_TAB__OPC_SSE, "/sse" }, + /* 007 */ { ud_itab__7, UD_TAB__OPC_SSE, "/sse" }, + /* 008 */ { ud_itab__8, UD_TAB__OPC_SSE, "/sse" }, + /* 009 */ { ud_itab__9, UD_TAB__OPC_SSE, "/sse" }, + /* 010 */ { ud_itab__10, UD_TAB__OPC_SSE, "/sse" }, + /* 011 */ { ud_itab__11, UD_TAB__OPC_SSE, "/sse" }, + /* 012 */ { ud_itab__12, UD_TAB__OPC_MOD, "/mod" }, + /* 013 */ { ud_itab__13, UD_TAB__OPC_REG, "/reg" }, + /* 014 */ { ud_itab__14, UD_TAB__OPC_SSE, "/sse" }, + /* 015 */ { ud_itab__15, UD_TAB__OPC_MOD, "/mod" }, + /* 016 */ { ud_itab__16, UD_TAB__OPC_SSE, "/sse" }, + /* 017 */ { ud_itab__17, UD_TAB__OPC_MOD, "/mod" }, + /* 018 */ { ud_itab__18, UD_TAB__OPC_SSE, "/sse" }, + /* 019 */ { ud_itab__19, UD_TAB__OPC_MOD, "/mod" }, + /* 020 */ { ud_itab__20, UD_TAB__OPC_SSE, "/sse" }, + /* 021 */ { ud_itab__21, UD_TAB__OPC_MOD, "/mod" }, + /* 022 */ { ud_itab__22, UD_TAB__OPC_SSE, "/sse" }, + /* 023 */ { ud_itab__23, UD_TAB__OPC_MOD, "/mod" }, + /* 024 */ { ud_itab__24, UD_TAB__OPC_SSE, "/sse" }, + /* 025 */ { ud_itab__25, UD_TAB__OPC_MOD, "/mod" }, + /* 026 */ { ud_itab__26, UD_TAB__OPC_SSE, "/sse" }, + /* 027 */ { ud_itab__27, UD_TAB__OPC_MOD, "/mod" }, + /* 028 */ { ud_itab__28, UD_TAB__OPC_REG, "/reg" }, + /* 029 */ { ud_itab__29, UD_TAB__OPC_RM, "/rm" }, + /* 030 */ { ud_itab__30, UD_TAB__OPC_SSE, "/sse" }, + /* 031 */ { ud_itab__31, UD_TAB__OPC_MOD, "/mod" }, + /* 032 */ { ud_itab__32, UD_TAB__OPC_VENDOR, "intel" }, + /* 033 */ { ud_itab__33, UD_TAB__OPC_SSE, "/sse" }, + /* 034 */ { ud_itab__34, UD_TAB__OPC_MOD, "/mod" }, + /* 035 */ { ud_itab__35, UD_TAB__OPC_VENDOR, "intel" }, + /* 036 */ { ud_itab__36, UD_TAB__OPC_SSE, "/sse" }, + /* 037 */ { ud_itab__37, UD_TAB__OPC_MOD, "/mod" }, + /* 038 */ { ud_itab__38, UD_TAB__OPC_VENDOR, "intel" }, + /* 039 */ { ud_itab__39, UD_TAB__OPC_SSE, "/sse" }, + /* 040 */ { ud_itab__40, UD_TAB__OPC_MOD, "/mod" }, + /* 041 */ { ud_itab__41, UD_TAB__OPC_VENDOR, "intel" }, + /* 042 */ { ud_itab__42, UD_TAB__OPC_RM, "/rm" }, + /* 043 */ { ud_itab__43, UD_TAB__OPC_SSE, "/sse" }, + /* 044 */ { ud_itab__44, UD_TAB__OPC_MOD, "/mod" }, + /* 045 */ { ud_itab__45, UD_TAB__OPC_SSE, "/sse" }, + /* 046 */ { ud_itab__46, UD_TAB__OPC_MOD, "/mod" }, + /* 047 */ { ud_itab__47, UD_TAB__OPC_RM, "/rm" }, + /* 048 */ { ud_itab__48, UD_TAB__OPC_SSE, "/sse" }, + /* 049 */ { ud_itab__49, UD_TAB__OPC_MOD, "/mod" }, + /* 050 */ { ud_itab__50, UD_TAB__OPC_SSE, "/sse" }, + /* 051 */ { ud_itab__51, UD_TAB__OPC_MOD, "/mod" }, + /* 052 */ { ud_itab__52, UD_TAB__OPC_RM, "/rm" }, + /* 053 */ { ud_itab__53, UD_TAB__OPC_SSE, "/sse" }, + /* 054 */ { ud_itab__54, UD_TAB__OPC_MOD, "/mod" }, + /* 055 */ { ud_itab__55, UD_TAB__OPC_VENDOR, "amd" }, + /* 056 */ { ud_itab__56, UD_TAB__OPC_SSE, "/sse" }, + /* 057 */ { ud_itab__57, UD_TAB__OPC_MOD, "/mod" }, + /* 058 */ { ud_itab__58, UD_TAB__OPC_VENDOR, "amd" }, + /* 059 */ { ud_itab__59, UD_TAB__OPC_SSE, "/sse" }, + /* 060 */ { ud_itab__60, UD_TAB__OPC_MOD, "/mod" }, + /* 061 */ { ud_itab__61, UD_TAB__OPC_VENDOR, "amd" }, + /* 062 */ { ud_itab__62, UD_TAB__OPC_SSE, "/sse" }, + /* 063 */ { ud_itab__63, UD_TAB__OPC_MOD, "/mod" }, + /* 064 */ { ud_itab__64, UD_TAB__OPC_VENDOR, "amd" }, + /* 065 */ { ud_itab__65, UD_TAB__OPC_SSE, "/sse" }, + /* 066 */ { ud_itab__66, UD_TAB__OPC_MOD, "/mod" }, + /* 067 */ { ud_itab__67, UD_TAB__OPC_VENDOR, "amd" }, + /* 068 */ { ud_itab__68, UD_TAB__OPC_SSE, "/sse" }, + /* 069 */ { ud_itab__69, UD_TAB__OPC_MOD, "/mod" }, + /* 070 */ { ud_itab__70, UD_TAB__OPC_VENDOR, "amd" }, + /* 071 */ { ud_itab__71, UD_TAB__OPC_SSE, "/sse" }, + /* 072 */ { ud_itab__72, UD_TAB__OPC_MOD, "/mod" }, + /* 073 */ { ud_itab__73, UD_TAB__OPC_VENDOR, "amd" }, + /* 074 */ { ud_itab__74, UD_TAB__OPC_SSE, "/sse" }, + /* 075 */ { ud_itab__75, UD_TAB__OPC_MOD, "/mod" }, + /* 076 */ { ud_itab__76, UD_TAB__OPC_VENDOR, "amd" }, + /* 077 */ { ud_itab__77, UD_TAB__OPC_SSE, "/sse" }, + /* 078 */ { ud_itab__78, UD_TAB__OPC_MOD, "/mod" }, + /* 079 */ { ud_itab__79, UD_TAB__OPC_SSE, "/sse" }, + /* 080 */ { ud_itab__80, UD_TAB__OPC_MOD, "/mod" }, + /* 081 */ { ud_itab__81, UD_TAB__OPC_RM, "/rm" }, + /* 082 */ { ud_itab__82, UD_TAB__OPC_SSE, "/sse" }, + /* 083 */ { ud_itab__83, UD_TAB__OPC_MOD, "/mod" }, + /* 084 */ { ud_itab__84, UD_TAB__OPC_SSE, "/sse" }, + /* 085 */ { ud_itab__85, UD_TAB__OPC_MOD, "/mod" }, + /* 086 */ { ud_itab__86, UD_TAB__OPC_VENDOR, "amd" }, + /* 087 */ { ud_itab__87, UD_TAB__OPC_SSE, "/sse" }, + /* 088 */ { ud_itab__88, UD_TAB__OPC_SSE, "/sse" }, + /* 089 */ { ud_itab__89, UD_TAB__OPC_SSE, "/sse" }, + /* 090 */ { ud_itab__90, UD_TAB__OPC_SSE, "/sse" }, + /* 091 */ { ud_itab__91, UD_TAB__OPC_SSE, "/sse" }, + /* 092 */ { ud_itab__92, UD_TAB__OPC_SSE, "/sse" }, + /* 093 */ { ud_itab__93, UD_TAB__OPC_SSE, "/sse" }, + /* 094 */ { ud_itab__94, UD_TAB__OPC_SSE, "/sse" }, + /* 095 */ { ud_itab__95, UD_TAB__OPC_REG, "/reg" }, + /* 096 */ { ud_itab__96, UD_TAB__OPC_SSE, "/sse" }, + /* 097 */ { ud_itab__97, UD_TAB__OPC_SSE, "/sse" }, + /* 098 */ { ud_itab__98, UD_TAB__OPC_SSE, "/sse" }, + /* 099 */ { ud_itab__99, UD_TAB__OPC_SSE, "/sse" }, + /* 100 */ { ud_itab__100, UD_TAB__OPC_SSE, "/sse" }, + /* 101 */ { ud_itab__101, UD_TAB__OPC_SSE, "/sse" }, + /* 102 */ { ud_itab__102, UD_TAB__OPC_SSE, "/sse" }, + /* 103 */ { ud_itab__103, UD_TAB__OPC_SSE, "/sse" }, + /* 104 */ { ud_itab__104, UD_TAB__OPC_SSE, "/sse" }, + /* 105 */ { ud_itab__105, UD_TAB__OPC_3DNOW, "/3dnow" }, + /* 106 */ { ud_itab__106, UD_TAB__OPC_SSE, "/sse" }, + /* 107 */ { ud_itab__107, UD_TAB__OPC_SSE, "/sse" }, + /* 108 */ { ud_itab__108, UD_TAB__OPC_MOD, "/mod" }, + /* 109 */ { ud_itab__109, UD_TAB__OPC_SSE, "/sse" }, + /* 110 */ { ud_itab__110, UD_TAB__OPC_MOD, "/mod" }, + /* 111 */ { ud_itab__111, UD_TAB__OPC_MOD, "/mod" }, + /* 112 */ { ud_itab__112, UD_TAB__OPC_MOD, "/mod" }, + /* 113 */ { ud_itab__113, UD_TAB__OPC_MOD, "/mod" }, + /* 114 */ { ud_itab__114, UD_TAB__OPC_SSE, "/sse" }, + /* 115 */ { ud_itab__115, UD_TAB__OPC_MOD, "/mod" }, + /* 116 */ { ud_itab__116, UD_TAB__OPC_MOD, "/mod" }, + /* 117 */ { ud_itab__117, UD_TAB__OPC_MOD, "/mod" }, + /* 118 */ { ud_itab__118, UD_TAB__OPC_SSE, "/sse" }, + /* 119 */ { ud_itab__119, UD_TAB__OPC_SSE, "/sse" }, + /* 120 */ { ud_itab__120, UD_TAB__OPC_SSE, "/sse" }, + /* 121 */ { ud_itab__121, UD_TAB__OPC_MOD, "/mod" }, + /* 122 */ { ud_itab__122, UD_TAB__OPC_SSE, "/sse" }, + /* 123 */ { ud_itab__123, UD_TAB__OPC_MOD, "/mod" }, + /* 124 */ { ud_itab__124, UD_TAB__OPC_MOD, "/mod" }, + /* 125 */ { ud_itab__125, UD_TAB__OPC_MOD, "/mod" }, + /* 126 */ { ud_itab__126, UD_TAB__OPC_SSE, "/sse" }, + /* 127 */ { ud_itab__127, UD_TAB__OPC_MOD, "/mod" }, + /* 128 */ { ud_itab__128, UD_TAB__OPC_MOD, "/mod" }, + /* 129 */ { ud_itab__129, UD_TAB__OPC_SSE, "/sse" }, + /* 130 */ { ud_itab__130, UD_TAB__OPC_REG, "/reg" }, + /* 131 */ { ud_itab__131, UD_TAB__OPC_SSE, "/sse" }, + /* 132 */ { ud_itab__132, UD_TAB__OPC_SSE, "/sse" }, + /* 133 */ { ud_itab__133, UD_TAB__OPC_SSE, "/sse" }, + /* 134 */ { ud_itab__134, UD_TAB__OPC_SSE, "/sse" }, + /* 135 */ { ud_itab__135, UD_TAB__OPC_SSE, "/sse" }, + /* 136 */ { ud_itab__136, UD_TAB__OPC_SSE, "/sse" }, + /* 137 */ { ud_itab__137, UD_TAB__OPC_SSE, "/sse" }, + /* 138 */ { ud_itab__138, UD_TAB__OPC_SSE, "/sse" }, + /* 139 */ { ud_itab__139, UD_TAB__OPC_SSE, "/sse" }, + /* 140 */ { ud_itab__140, UD_TAB__OPC_SSE, "/sse" }, + /* 141 */ { ud_itab__141, UD_TAB__OPC_SSE, "/sse" }, + /* 142 */ { ud_itab__142, UD_TAB__OPC_SSE, "/sse" }, + /* 143 */ { ud_itab__143, UD_TAB__OPC_SSE, "/sse" }, + /* 144 */ { ud_itab__144, UD_TAB__OPC_SSE, "/sse" }, + /* 145 */ { ud_itab__145, UD_TAB__OPC_SSE, "/sse" }, + /* 146 */ { ud_itab__146, UD_TAB__OPC_SSE, "/sse" }, + /* 147 */ { ud_itab__147, UD_TAB__OPC_SSE, "/sse" }, + /* 148 */ { ud_itab__148, UD_TAB__OPC_SSE, "/sse" }, + /* 149 */ { ud_itab__149, UD_TAB__OPC_SSE, "/sse" }, + /* 150 */ { ud_itab__150, UD_TAB__OPC_SSE, "/sse" }, + /* 151 */ { ud_itab__151, UD_TAB__OPC_SSE, "/sse" }, + /* 152 */ { ud_itab__152, UD_TAB__OPC_SSE, "/sse" }, + /* 153 */ { ud_itab__153, UD_TAB__OPC_SSE, "/sse" }, + /* 154 */ { ud_itab__154, UD_TAB__OPC_SSE, "/sse" }, + /* 155 */ { ud_itab__155, UD_TAB__OPC_SSE, "/sse" }, + /* 156 */ { ud_itab__156, UD_TAB__OPC_SSE, "/sse" }, + /* 157 */ { ud_itab__157, UD_TAB__OPC_SSE, "/sse" }, + /* 158 */ { ud_itab__158, UD_TAB__OPC_SSE, "/sse" }, + /* 159 */ { ud_itab__159, UD_TAB__OPC_MODE, "/m" }, + /* 160 */ { ud_itab__160, UD_TAB__OPC_VENDOR, "intel" }, + /* 161 */ { ud_itab__161, UD_TAB__OPC_SSE, "/sse" }, + /* 162 */ { ud_itab__162, UD_TAB__OPC_MODE, "/m" }, + /* 163 */ { ud_itab__163, UD_TAB__OPC_VENDOR, "intel" }, + /* 164 */ { ud_itab__164, UD_TAB__OPC_SSE, "/sse" }, + /* 165 */ { ud_itab__165, UD_TAB__OPC_TABLE, "38" }, + /* 166 */ { ud_itab__166, UD_TAB__OPC_SSE, "/sse" }, + /* 167 */ { ud_itab__167, UD_TAB__OPC_SSE, "/sse" }, + /* 168 */ { ud_itab__168, UD_TAB__OPC_SSE, "/sse" }, + /* 169 */ { ud_itab__169, UD_TAB__OPC_SSE, "/sse" }, + /* 170 */ { ud_itab__170, UD_TAB__OPC_SSE, "/sse" }, + /* 171 */ { ud_itab__171, UD_TAB__OPC_SSE, "/sse" }, + /* 172 */ { ud_itab__172, UD_TAB__OPC_SSE, "/sse" }, + /* 173 */ { ud_itab__173, UD_TAB__OPC_SSE, "/sse" }, + /* 174 */ { ud_itab__174, UD_TAB__OPC_SSE, "/sse" }, + /* 175 */ { ud_itab__175, UD_TAB__OPC_SSE, "/sse" }, + /* 176 */ { ud_itab__176, UD_TAB__OPC_SSE, "/sse" }, + /* 177 */ { ud_itab__177, UD_TAB__OPC_SSE, "/sse" }, + /* 178 */ { ud_itab__178, UD_TAB__OPC_SSE, "/sse" }, + /* 179 */ { ud_itab__179, UD_TAB__OPC_SSE, "/sse" }, + /* 180 */ { ud_itab__180, UD_TAB__OPC_SSE, "/sse" }, + /* 181 */ { ud_itab__181, UD_TAB__OPC_SSE, "/sse" }, + /* 182 */ { ud_itab__182, UD_TAB__OPC_SSE, "/sse" }, + /* 183 */ { ud_itab__183, UD_TAB__OPC_SSE, "/sse" }, + /* 184 */ { ud_itab__184, UD_TAB__OPC_SSE, "/sse" }, + /* 185 */ { ud_itab__185, UD_TAB__OPC_SSE, "/sse" }, + /* 186 */ { ud_itab__186, UD_TAB__OPC_SSE, "/sse" }, + /* 187 */ { ud_itab__187, UD_TAB__OPC_SSE, "/sse" }, + /* 188 */ { ud_itab__188, UD_TAB__OPC_SSE, "/sse" }, + /* 189 */ { ud_itab__189, UD_TAB__OPC_SSE, "/sse" }, + /* 190 */ { ud_itab__190, UD_TAB__OPC_SSE, "/sse" }, + /* 191 */ { ud_itab__191, UD_TAB__OPC_SSE, "/sse" }, + /* 192 */ { ud_itab__192, UD_TAB__OPC_SSE, "/sse" }, + /* 193 */ { ud_itab__193, UD_TAB__OPC_SSE, "/sse" }, + /* 194 */ { ud_itab__194, UD_TAB__OPC_SSE, "/sse" }, + /* 195 */ { ud_itab__195, UD_TAB__OPC_SSE, "/sse" }, + /* 196 */ { ud_itab__196, UD_TAB__OPC_SSE, "/sse" }, + /* 197 */ { ud_itab__197, UD_TAB__OPC_SSE, "/sse" }, + /* 198 */ { ud_itab__198, UD_TAB__OPC_SSE, "/sse" }, + /* 199 */ { ud_itab__199, UD_TAB__OPC_SSE, "/sse" }, + /* 200 */ { ud_itab__200, UD_TAB__OPC_SSE, "/sse" }, + /* 201 */ { ud_itab__201, UD_TAB__OPC_SSE, "/sse" }, + /* 202 */ { ud_itab__202, UD_TAB__OPC_SSE, "/sse" }, + /* 203 */ { ud_itab__203, UD_TAB__OPC_SSE, "/sse" }, + /* 204 */ { ud_itab__204, UD_TAB__OPC_SSE, "/sse" }, + /* 205 */ { ud_itab__205, UD_TAB__OPC_SSE, "/sse" }, + /* 206 */ { ud_itab__206, UD_TAB__OPC_SSE, "/sse" }, + /* 207 */ { ud_itab__207, UD_TAB__OPC_SSE, "/sse" }, + /* 208 */ { ud_itab__208, UD_TAB__OPC_SSE, "/sse" }, + /* 209 */ { ud_itab__209, UD_TAB__OPC_SSE, "/sse" }, + /* 210 */ { ud_itab__210, UD_TAB__OPC_SSE, "/sse" }, + /* 211 */ { ud_itab__211, UD_TAB__OPC_SSE, "/sse" }, + /* 212 */ { ud_itab__212, UD_TAB__OPC_SSE, "/sse" }, + /* 213 */ { ud_itab__213, UD_TAB__OPC_MODE, "/m" }, + /* 214 */ { ud_itab__214, UD_TAB__OPC_VENDOR, "intel" }, + /* 215 */ { ud_itab__215, UD_TAB__OPC_SSE, "/sse" }, + /* 216 */ { ud_itab__216, UD_TAB__OPC_MODE, "/m" }, + /* 217 */ { ud_itab__217, UD_TAB__OPC_VENDOR, "intel" }, + /* 218 */ { ud_itab__218, UD_TAB__OPC_SSE, "/sse" }, + /* 219 */ { ud_itab__219, UD_TAB__OPC_SSE, "/sse" }, + /* 220 */ { ud_itab__220, UD_TAB__OPC_SSE, "/sse" }, + /* 221 */ { ud_itab__221, UD_TAB__OPC_SSE, "/sse" }, + /* 222 */ { ud_itab__222, UD_TAB__OPC_SSE, "/sse" }, + /* 223 */ { ud_itab__223, UD_TAB__OPC_SSE, "/sse" }, + /* 224 */ { ud_itab__224, UD_TAB__OPC_SSE, "/sse" }, + /* 225 */ { ud_itab__225, UD_TAB__OPC_TABLE, "3a" }, + /* 226 */ { ud_itab__226, UD_TAB__OPC_SSE, "/sse" }, + /* 227 */ { ud_itab__227, UD_TAB__OPC_SSE, "/sse" }, + /* 228 */ { ud_itab__228, UD_TAB__OPC_SSE, "/sse" }, + /* 229 */ { ud_itab__229, UD_TAB__OPC_SSE, "/sse" }, + /* 230 */ { ud_itab__230, UD_TAB__OPC_SSE, "/sse" }, + /* 231 */ { ud_itab__231, UD_TAB__OPC_SSE, "/sse" }, + /* 232 */ { ud_itab__232, UD_TAB__OPC_SSE, "/sse" }, + /* 233 */ { ud_itab__233, UD_TAB__OPC_SSE, "/sse" }, + /* 234 */ { ud_itab__234, UD_TAB__OPC_SSE, "/sse" }, + /* 235 */ { ud_itab__235, UD_TAB__OPC_SSE, "/sse" }, + /* 236 */ { ud_itab__236, UD_TAB__OPC_SSE, "/sse" }, + /* 237 */ { ud_itab__237, UD_TAB__OPC_OSIZE, "/o" }, + /* 238 */ { ud_itab__238, UD_TAB__OPC_SSE, "/sse" }, + /* 239 */ { ud_itab__239, UD_TAB__OPC_SSE, "/sse" }, + /* 240 */ { ud_itab__240, UD_TAB__OPC_SSE, "/sse" }, + /* 241 */ { ud_itab__241, UD_TAB__OPC_SSE, "/sse" }, + /* 242 */ { ud_itab__242, UD_TAB__OPC_OSIZE, "/o" }, + /* 243 */ { ud_itab__243, UD_TAB__OPC_SSE, "/sse" }, + /* 244 */ { ud_itab__244, UD_TAB__OPC_SSE, "/sse" }, + /* 245 */ { ud_itab__245, UD_TAB__OPC_SSE, "/sse" }, + /* 246 */ { ud_itab__246, UD_TAB__OPC_SSE, "/sse" }, + /* 247 */ { ud_itab__247, UD_TAB__OPC_SSE, "/sse" }, + /* 248 */ { ud_itab__248, UD_TAB__OPC_SSE, "/sse" }, + /* 249 */ { ud_itab__249, UD_TAB__OPC_SSE, "/sse" }, + /* 250 */ { ud_itab__250, UD_TAB__OPC_SSE, "/sse" }, + /* 251 */ { ud_itab__251, UD_TAB__OPC_SSE, "/sse" }, + /* 252 */ { ud_itab__252, UD_TAB__OPC_SSE, "/sse" }, + /* 253 */ { ud_itab__253, UD_TAB__OPC_SSE, "/sse" }, + /* 254 */ { ud_itab__254, UD_TAB__OPC_SSE, "/sse" }, + /* 255 */ { ud_itab__255, UD_TAB__OPC_SSE, "/sse" }, + /* 256 */ { ud_itab__256, UD_TAB__OPC_SSE, "/sse" }, + /* 257 */ { ud_itab__257, UD_TAB__OPC_SSE, "/sse" }, + /* 258 */ { ud_itab__258, UD_TAB__OPC_SSE, "/sse" }, + /* 259 */ { ud_itab__259, UD_TAB__OPC_SSE, "/sse" }, + /* 260 */ { ud_itab__260, UD_TAB__OPC_SSE, "/sse" }, + /* 261 */ { ud_itab__261, UD_TAB__OPC_SSE, "/sse" }, + /* 262 */ { ud_itab__262, UD_TAB__OPC_SSE, "/sse" }, + /* 263 */ { ud_itab__263, UD_TAB__OPC_SSE, "/sse" }, + /* 264 */ { ud_itab__264, UD_TAB__OPC_SSE, "/sse" }, + /* 265 */ { ud_itab__265, UD_TAB__OPC_SSE, "/sse" }, + /* 266 */ { ud_itab__266, UD_TAB__OPC_SSE, "/sse" }, + /* 267 */ { ud_itab__267, UD_TAB__OPC_SSE, "/sse" }, + /* 268 */ { ud_itab__268, UD_TAB__OPC_SSE, "/sse" }, + /* 269 */ { ud_itab__269, UD_TAB__OPC_SSE, "/sse" }, + /* 270 */ { ud_itab__270, UD_TAB__OPC_SSE, "/sse" }, + /* 271 */ { ud_itab__271, UD_TAB__OPC_SSE, "/sse" }, + /* 272 */ { ud_itab__272, UD_TAB__OPC_SSE, "/sse" }, + /* 273 */ { ud_itab__273, UD_TAB__OPC_SSE, "/sse" }, + /* 274 */ { ud_itab__274, UD_TAB__OPC_SSE, "/sse" }, + /* 275 */ { ud_itab__275, UD_TAB__OPC_SSE, "/sse" }, + /* 276 */ { ud_itab__276, UD_TAB__OPC_SSE, "/sse" }, + /* 277 */ { ud_itab__277, UD_TAB__OPC_SSE, "/sse" }, + /* 278 */ { ud_itab__278, UD_TAB__OPC_SSE, "/sse" }, + /* 279 */ { ud_itab__279, UD_TAB__OPC_SSE, "/sse" }, + /* 280 */ { ud_itab__280, UD_TAB__OPC_SSE, "/sse" }, + /* 281 */ { ud_itab__281, UD_TAB__OPC_SSE, "/sse" }, + /* 282 */ { ud_itab__282, UD_TAB__OPC_SSE, "/sse" }, + /* 283 */ { ud_itab__283, UD_TAB__OPC_SSE, "/sse" }, + /* 284 */ { ud_itab__284, UD_TAB__OPC_SSE, "/sse" }, + /* 285 */ { ud_itab__285, UD_TAB__OPC_SSE, "/sse" }, + /* 286 */ { ud_itab__286, UD_TAB__OPC_SSE, "/sse" }, + /* 287 */ { ud_itab__287, UD_TAB__OPC_SSE, "/sse" }, + /* 288 */ { ud_itab__288, UD_TAB__OPC_SSE, "/sse" }, + /* 289 */ { ud_itab__289, UD_TAB__OPC_SSE, "/sse" }, + /* 290 */ { ud_itab__290, UD_TAB__OPC_SSE, "/sse" }, + /* 291 */ { ud_itab__291, UD_TAB__OPC_SSE, "/sse" }, + /* 292 */ { ud_itab__292, UD_TAB__OPC_SSE, "/sse" }, + /* 293 */ { ud_itab__293, UD_TAB__OPC_SSE, "/sse" }, + /* 294 */ { ud_itab__294, UD_TAB__OPC_SSE, "/sse" }, + /* 295 */ { ud_itab__295, UD_TAB__OPC_SSE, "/sse" }, + /* 296 */ { ud_itab__296, UD_TAB__OPC_SSE, "/sse" }, + /* 297 */ { ud_itab__297, UD_TAB__OPC_SSE, "/sse" }, + /* 298 */ { ud_itab__298, UD_TAB__OPC_SSE, "/sse" }, + /* 299 */ { ud_itab__299, UD_TAB__OPC_SSE, "/sse" }, + /* 300 */ { ud_itab__300, UD_TAB__OPC_SSE, "/sse" }, + /* 301 */ { ud_itab__301, UD_TAB__OPC_REG, "/reg" }, + /* 302 */ { ud_itab__302, UD_TAB__OPC_SSE, "/sse" }, + /* 303 */ { ud_itab__303, UD_TAB__OPC_SSE, "/sse" }, + /* 304 */ { ud_itab__304, UD_TAB__OPC_SSE, "/sse" }, + /* 305 */ { ud_itab__305, UD_TAB__OPC_REG, "/reg" }, + /* 306 */ { ud_itab__306, UD_TAB__OPC_SSE, "/sse" }, + /* 307 */ { ud_itab__307, UD_TAB__OPC_SSE, "/sse" }, + /* 308 */ { ud_itab__308, UD_TAB__OPC_SSE, "/sse" }, + /* 309 */ { ud_itab__309, UD_TAB__OPC_REG, "/reg" }, + /* 310 */ { ud_itab__310, UD_TAB__OPC_SSE, "/sse" }, + /* 311 */ { ud_itab__311, UD_TAB__OPC_SSE, "/sse" }, + /* 312 */ { ud_itab__312, UD_TAB__OPC_SSE, "/sse" }, + /* 313 */ { ud_itab__313, UD_TAB__OPC_SSE, "/sse" }, + /* 314 */ { ud_itab__314, UD_TAB__OPC_SSE, "/sse" }, + /* 315 */ { ud_itab__315, UD_TAB__OPC_SSE, "/sse" }, + /* 316 */ { ud_itab__316, UD_TAB__OPC_SSE, "/sse" }, + /* 317 */ { ud_itab__317, UD_TAB__OPC_SSE, "/sse" }, + /* 318 */ { ud_itab__318, UD_TAB__OPC_SSE, "/sse" }, + /* 319 */ { ud_itab__319, UD_TAB__OPC_VENDOR, "intel" }, + /* 320 */ { ud_itab__320, UD_TAB__OPC_SSE, "/sse" }, + /* 321 */ { ud_itab__321, UD_TAB__OPC_VENDOR, "intel" }, + /* 322 */ { ud_itab__322, UD_TAB__OPC_SSE, "/sse" }, + /* 323 */ { ud_itab__323, UD_TAB__OPC_SSE, "/sse" }, + /* 324 */ { ud_itab__324, UD_TAB__OPC_SSE, "/sse" }, + /* 325 */ { ud_itab__325, UD_TAB__OPC_SSE, "/sse" }, + /* 326 */ { ud_itab__326, UD_TAB__OPC_SSE, "/sse" }, + /* 327 */ { ud_itab__327, UD_TAB__OPC_SSE, "/sse" }, + /* 328 */ { ud_itab__328, UD_TAB__OPC_SSE, "/sse" }, + /* 329 */ { ud_itab__329, UD_TAB__OPC_SSE, "/sse" }, + /* 330 */ { ud_itab__330, UD_TAB__OPC_SSE, "/sse" }, + /* 331 */ { ud_itab__331, UD_TAB__OPC_SSE, "/sse" }, + /* 332 */ { ud_itab__332, UD_TAB__OPC_SSE, "/sse" }, + /* 333 */ { ud_itab__333, UD_TAB__OPC_SSE, "/sse" }, + /* 334 */ { ud_itab__334, UD_TAB__OPC_SSE, "/sse" }, + /* 335 */ { ud_itab__335, UD_TAB__OPC_SSE, "/sse" }, + /* 336 */ { ud_itab__336, UD_TAB__OPC_SSE, "/sse" }, + /* 337 */ { ud_itab__337, UD_TAB__OPC_SSE, "/sse" }, + /* 338 */ { ud_itab__338, UD_TAB__OPC_SSE, "/sse" }, + /* 339 */ { ud_itab__339, UD_TAB__OPC_SSE, "/sse" }, + /* 340 */ { ud_itab__340, UD_TAB__OPC_SSE, "/sse" }, + /* 341 */ { ud_itab__341, UD_TAB__OPC_SSE, "/sse" }, + /* 342 */ { ud_itab__342, UD_TAB__OPC_SSE, "/sse" }, + /* 343 */ { ud_itab__343, UD_TAB__OPC_SSE, "/sse" }, + /* 344 */ { ud_itab__344, UD_TAB__OPC_SSE, "/sse" }, + /* 345 */ { ud_itab__345, UD_TAB__OPC_SSE, "/sse" }, + /* 346 */ { ud_itab__346, UD_TAB__OPC_SSE, "/sse" }, + /* 347 */ { ud_itab__347, UD_TAB__OPC_SSE, "/sse" }, + /* 348 */ { ud_itab__348, UD_TAB__OPC_SSE, "/sse" }, + /* 349 */ { ud_itab__349, UD_TAB__OPC_SSE, "/sse" }, + /* 350 */ { ud_itab__350, UD_TAB__OPC_SSE, "/sse" }, + /* 351 */ { ud_itab__351, UD_TAB__OPC_SSE, "/sse" }, + /* 352 */ { ud_itab__352, UD_TAB__OPC_SSE, "/sse" }, + /* 353 */ { ud_itab__353, UD_TAB__OPC_SSE, "/sse" }, + /* 354 */ { ud_itab__354, UD_TAB__OPC_SSE, "/sse" }, + /* 355 */ { ud_itab__355, UD_TAB__OPC_SSE, "/sse" }, + /* 356 */ { ud_itab__356, UD_TAB__OPC_SSE, "/sse" }, + /* 357 */ { ud_itab__357, UD_TAB__OPC_SSE, "/sse" }, + /* 358 */ { ud_itab__358, UD_TAB__OPC_SSE, "/sse" }, + /* 359 */ { ud_itab__359, UD_TAB__OPC_SSE, "/sse" }, + /* 360 */ { ud_itab__360, UD_TAB__OPC_SSE, "/sse" }, + /* 361 */ { ud_itab__361, UD_TAB__OPC_SSE, "/sse" }, + /* 362 */ { ud_itab__362, UD_TAB__OPC_SSE, "/sse" }, + /* 363 */ { ud_itab__363, UD_TAB__OPC_SSE, "/sse" }, + /* 364 */ { ud_itab__364, UD_TAB__OPC_MOD, "/mod" }, + /* 365 */ { ud_itab__365, UD_TAB__OPC_REG, "/reg" }, + /* 366 */ { ud_itab__366, UD_TAB__OPC_RM, "/rm" }, + /* 367 */ { ud_itab__367, UD_TAB__OPC_SSE, "/sse" }, + /* 368 */ { ud_itab__368, UD_TAB__OPC_MOD, "/mod" }, + /* 369 */ { ud_itab__369, UD_TAB__OPC_RM, "/rm" }, + /* 370 */ { ud_itab__370, UD_TAB__OPC_SSE, "/sse" }, + /* 371 */ { ud_itab__371, UD_TAB__OPC_MOD, "/mod" }, + /* 372 */ { ud_itab__372, UD_TAB__OPC_RM, "/rm" }, + /* 373 */ { ud_itab__373, UD_TAB__OPC_SSE, "/sse" }, + /* 374 */ { ud_itab__374, UD_TAB__OPC_MOD, "/mod" }, + /* 375 */ { ud_itab__375, UD_TAB__OPC_MOD, "/mod" }, + /* 376 */ { ud_itab__376, UD_TAB__OPC_REG, "/reg" }, + /* 377 */ { ud_itab__377, UD_TAB__OPC_RM, "/rm" }, + /* 378 */ { ud_itab__378, UD_TAB__OPC_SSE, "/sse" }, + /* 379 */ { ud_itab__379, UD_TAB__OPC_MOD, "/mod" }, + /* 380 */ { ud_itab__380, UD_TAB__OPC_RM, "/rm" }, + /* 381 */ { ud_itab__381, UD_TAB__OPC_SSE, "/sse" }, + /* 382 */ { ud_itab__382, UD_TAB__OPC_MOD, "/mod" }, + /* 383 */ { ud_itab__383, UD_TAB__OPC_RM, "/rm" }, + /* 384 */ { ud_itab__384, UD_TAB__OPC_SSE, "/sse" }, + /* 385 */ { ud_itab__385, UD_TAB__OPC_MOD, "/mod" }, + /* 386 */ { ud_itab__386, UD_TAB__OPC_RM, "/rm" }, + /* 387 */ { ud_itab__387, UD_TAB__OPC_SSE, "/sse" }, + /* 388 */ { ud_itab__388, UD_TAB__OPC_MOD, "/mod" }, + /* 389 */ { ud_itab__389, UD_TAB__OPC_RM, "/rm" }, + /* 390 */ { ud_itab__390, UD_TAB__OPC_SSE, "/sse" }, + /* 391 */ { ud_itab__391, UD_TAB__OPC_MOD, "/mod" }, + /* 392 */ { ud_itab__392, UD_TAB__OPC_RM, "/rm" }, + /* 393 */ { ud_itab__393, UD_TAB__OPC_SSE, "/sse" }, + /* 394 */ { ud_itab__394, UD_TAB__OPC_MOD, "/mod" }, + /* 395 */ { ud_itab__395, UD_TAB__OPC_SSE, "/sse" }, + /* 396 */ { ud_itab__396, UD_TAB__OPC_SSE, "/sse" }, + /* 397 */ { ud_itab__397, UD_TAB__OPC_SSE, "/sse" }, + /* 398 */ { ud_itab__398, UD_TAB__OPC_SSE, "/sse" }, + /* 399 */ { ud_itab__399, UD_TAB__OPC_SSE, "/sse" }, + /* 400 */ { ud_itab__400, UD_TAB__OPC_SSE, "/sse" }, + /* 401 */ { ud_itab__401, UD_TAB__OPC_MOD, "/mod" }, + /* 402 */ { ud_itab__402, UD_TAB__OPC_REG, "/reg" }, + /* 403 */ { ud_itab__403, UD_TAB__OPC_SSE, "/sse" }, + /* 404 */ { ud_itab__404, UD_TAB__OPC_MOD, "/mod" }, + /* 405 */ { ud_itab__405, UD_TAB__OPC_SSE, "/sse" }, + /* 406 */ { ud_itab__406, UD_TAB__OPC_MOD, "/mod" }, + /* 407 */ { ud_itab__407, UD_TAB__OPC_SSE, "/sse" }, + /* 408 */ { ud_itab__408, UD_TAB__OPC_MOD, "/mod" }, + /* 409 */ { ud_itab__409, UD_TAB__OPC_SSE, "/sse" }, + /* 410 */ { ud_itab__410, UD_TAB__OPC_MOD, "/mod" }, + /* 411 */ { ud_itab__411, UD_TAB__OPC_SSE, "/sse" }, + /* 412 */ { ud_itab__412, UD_TAB__OPC_MOD, "/mod" }, + /* 413 */ { ud_itab__413, UD_TAB__OPC_SSE, "/sse" }, + /* 414 */ { ud_itab__414, UD_TAB__OPC_MOD, "/mod" }, + /* 415 */ { ud_itab__415, UD_TAB__OPC_SSE, "/sse" }, + /* 416 */ { ud_itab__416, UD_TAB__OPC_MOD, "/mod" }, + /* 417 */ { ud_itab__417, UD_TAB__OPC_REG, "/reg" }, + /* 418 */ { ud_itab__418, UD_TAB__OPC_RM, "/rm" }, + /* 419 */ { ud_itab__419, UD_TAB__OPC_SSE, "/sse" }, + /* 420 */ { ud_itab__420, UD_TAB__OPC_MOD, "/mod" }, + /* 421 */ { ud_itab__421, UD_TAB__OPC_SSE, "/sse" }, + /* 422 */ { ud_itab__422, UD_TAB__OPC_MOD, "/mod" }, + /* 423 */ { ud_itab__423, UD_TAB__OPC_SSE, "/sse" }, + /* 424 */ { ud_itab__424, UD_TAB__OPC_MOD, "/mod" }, + /* 425 */ { ud_itab__425, UD_TAB__OPC_SSE, "/sse" }, + /* 426 */ { ud_itab__426, UD_TAB__OPC_MOD, "/mod" }, + /* 427 */ { ud_itab__427, UD_TAB__OPC_SSE, "/sse" }, + /* 428 */ { ud_itab__428, UD_TAB__OPC_MOD, "/mod" }, + /* 429 */ { ud_itab__429, UD_TAB__OPC_SSE, "/sse" }, + /* 430 */ { ud_itab__430, UD_TAB__OPC_MOD, "/mod" }, + /* 431 */ { ud_itab__431, UD_TAB__OPC_SSE, "/sse" }, + /* 432 */ { ud_itab__432, UD_TAB__OPC_MOD, "/mod" }, + /* 433 */ { ud_itab__433, UD_TAB__OPC_SSE, "/sse" }, + /* 434 */ { ud_itab__434, UD_TAB__OPC_MOD, "/mod" }, + /* 435 */ { ud_itab__435, UD_TAB__OPC_RM, "/rm" }, + /* 436 */ { ud_itab__436, UD_TAB__OPC_SSE, "/sse" }, + /* 437 */ { ud_itab__437, UD_TAB__OPC_MOD, "/mod" }, + /* 438 */ { ud_itab__438, UD_TAB__OPC_SSE, "/sse" }, + /* 439 */ { ud_itab__439, UD_TAB__OPC_MOD, "/mod" }, + /* 440 */ { ud_itab__440, UD_TAB__OPC_SSE, "/sse" }, + /* 441 */ { ud_itab__441, UD_TAB__OPC_MOD, "/mod" }, + /* 442 */ { ud_itab__442, UD_TAB__OPC_SSE, "/sse" }, + /* 443 */ { ud_itab__443, UD_TAB__OPC_MOD, "/mod" }, + /* 444 */ { ud_itab__444, UD_TAB__OPC_SSE, "/sse" }, + /* 445 */ { ud_itab__445, UD_TAB__OPC_MOD, "/mod" }, + /* 446 */ { ud_itab__446, UD_TAB__OPC_SSE, "/sse" }, + /* 447 */ { ud_itab__447, UD_TAB__OPC_MOD, "/mod" }, + /* 448 */ { ud_itab__448, UD_TAB__OPC_SSE, "/sse" }, + /* 449 */ { ud_itab__449, UD_TAB__OPC_MOD, "/mod" }, + /* 450 */ { ud_itab__450, UD_TAB__OPC_SSE, "/sse" }, + /* 451 */ { ud_itab__451, UD_TAB__OPC_MOD, "/mod" }, + /* 452 */ { ud_itab__452, UD_TAB__OPC_RM, "/rm" }, + /* 453 */ { ud_itab__453, UD_TAB__OPC_SSE, "/sse" }, + /* 454 */ { ud_itab__454, UD_TAB__OPC_MOD, "/mod" }, + /* 455 */ { ud_itab__455, UD_TAB__OPC_SSE, "/sse" }, + /* 456 */ { ud_itab__456, UD_TAB__OPC_MOD, "/mod" }, + /* 457 */ { ud_itab__457, UD_TAB__OPC_SSE, "/sse" }, + /* 458 */ { ud_itab__458, UD_TAB__OPC_MOD, "/mod" }, + /* 459 */ { ud_itab__459, UD_TAB__OPC_SSE, "/sse" }, + /* 460 */ { ud_itab__460, UD_TAB__OPC_MOD, "/mod" }, + /* 461 */ { ud_itab__461, UD_TAB__OPC_SSE, "/sse" }, + /* 462 */ { ud_itab__462, UD_TAB__OPC_MOD, "/mod" }, + /* 463 */ { ud_itab__463, UD_TAB__OPC_SSE, "/sse" }, + /* 464 */ { ud_itab__464, UD_TAB__OPC_MOD, "/mod" }, + /* 465 */ { ud_itab__465, UD_TAB__OPC_SSE, "/sse" }, + /* 466 */ { ud_itab__466, UD_TAB__OPC_MOD, "/mod" }, + /* 467 */ { ud_itab__467, UD_TAB__OPC_SSE, "/sse" }, + /* 468 */ { ud_itab__468, UD_TAB__OPC_MOD, "/mod" }, + /* 469 */ { ud_itab__469, UD_TAB__OPC_SSE, "/sse" }, + /* 470 */ { ud_itab__470, UD_TAB__OPC_SSE, "/sse" }, + /* 471 */ { ud_itab__471, UD_TAB__OPC_SSE, "/sse" }, + /* 472 */ { ud_itab__472, UD_TAB__OPC_SSE, "/sse" }, + /* 473 */ { ud_itab__473, UD_TAB__OPC_SSE, "/sse" }, + /* 474 */ { ud_itab__474, UD_TAB__OPC_SSE, "/sse" }, + /* 475 */ { ud_itab__475, UD_TAB__OPC_SSE, "/sse" }, + /* 476 */ { ud_itab__476, UD_TAB__OPC_SSE, "/sse" }, + /* 477 */ { ud_itab__477, UD_TAB__OPC_SSE, "/sse" }, + /* 478 */ { ud_itab__478, UD_TAB__OPC_SSE, "/sse" }, + /* 479 */ { ud_itab__479, UD_TAB__OPC_REG, "/reg" }, + /* 480 */ { ud_itab__480, UD_TAB__OPC_SSE, "/sse" }, + /* 481 */ { ud_itab__481, UD_TAB__OPC_SSE, "/sse" }, + /* 482 */ { ud_itab__482, UD_TAB__OPC_SSE, "/sse" }, + /* 483 */ { ud_itab__483, UD_TAB__OPC_SSE, "/sse" }, + /* 484 */ { ud_itab__484, UD_TAB__OPC_SSE, "/sse" }, + /* 485 */ { ud_itab__485, UD_TAB__OPC_SSE, "/sse" }, + /* 486 */ { ud_itab__486, UD_TAB__OPC_SSE, "/sse" }, + /* 487 */ { ud_itab__487, UD_TAB__OPC_SSE, "/sse" }, + /* 488 */ { ud_itab__488, UD_TAB__OPC_SSE, "/sse" }, + /* 489 */ { ud_itab__489, UD_TAB__OPC_SSE, "/sse" }, + /* 490 */ { ud_itab__490, UD_TAB__OPC_SSE, "/sse" }, + /* 491 */ { ud_itab__491, UD_TAB__OPC_SSE, "/sse" }, + /* 492 */ { ud_itab__492, UD_TAB__OPC_SSE, "/sse" }, + /* 493 */ { ud_itab__493, UD_TAB__OPC_SSE, "/sse" }, + /* 494 */ { ud_itab__494, UD_TAB__OPC_SSE, "/sse" }, + /* 495 */ { ud_itab__495, UD_TAB__OPC_SSE, "/sse" }, + /* 496 */ { ud_itab__496, UD_TAB__OPC_REG, "/reg" }, + /* 497 */ { ud_itab__497, UD_TAB__OPC_SSE, "/sse" }, + /* 498 */ { ud_itab__498, UD_TAB__OPC_OSIZE, "/o" }, + /* 499 */ { ud_itab__499, UD_TAB__OPC_SSE, "/sse" }, + /* 500 */ { ud_itab__500, UD_TAB__OPC_VENDOR, "intel" }, + /* 501 */ { ud_itab__501, UD_TAB__OPC_VENDOR, "intel" }, + /* 502 */ { ud_itab__502, UD_TAB__OPC_VENDOR, "intel" }, + /* 503 */ { ud_itab__503, UD_TAB__OPC_SSE, "/sse" }, + /* 504 */ { ud_itab__504, UD_TAB__OPC_VENDOR, "intel" }, + /* 505 */ { ud_itab__505, UD_TAB__OPC_SSE, "/sse" }, + /* 506 */ { ud_itab__506, UD_TAB__OPC_SSE, "/sse" }, + /* 507 */ { ud_itab__507, UD_TAB__OPC_SSE, "/sse" }, + /* 508 */ { ud_itab__508, UD_TAB__OPC_SSE, "/sse" }, + /* 509 */ { ud_itab__509, UD_TAB__OPC_SSE, "/sse" }, + /* 510 */ { ud_itab__510, UD_TAB__OPC_SSE, "/sse" }, + /* 511 */ { ud_itab__511, UD_TAB__OPC_SSE, "/sse" }, + /* 512 */ { ud_itab__512, UD_TAB__OPC_SSE, "/sse" }, + /* 513 */ { ud_itab__513, UD_TAB__OPC_SSE, "/sse" }, + /* 514 */ { ud_itab__514, UD_TAB__OPC_SSE, "/sse" }, + /* 515 */ { ud_itab__515, UD_TAB__OPC_SSE, "/sse" }, + /* 516 */ { ud_itab__516, UD_TAB__OPC_SSE, "/sse" }, + /* 517 */ { ud_itab__517, UD_TAB__OPC_SSE, "/sse" }, + /* 518 */ { ud_itab__518, UD_TAB__OPC_SSE, "/sse" }, + /* 519 */ { ud_itab__519, UD_TAB__OPC_SSE, "/sse" }, + /* 520 */ { ud_itab__520, UD_TAB__OPC_SSE, "/sse" }, + /* 521 */ { ud_itab__521, UD_TAB__OPC_SSE, "/sse" }, + /* 522 */ { ud_itab__522, UD_TAB__OPC_SSE, "/sse" }, + /* 523 */ { ud_itab__523, UD_TAB__OPC_SSE, "/sse" }, + /* 524 */ { ud_itab__524, UD_TAB__OPC_SSE, "/sse" }, + /* 525 */ { ud_itab__525, UD_TAB__OPC_SSE, "/sse" }, + /* 526 */ { ud_itab__526, UD_TAB__OPC_SSE, "/sse" }, + /* 527 */ { ud_itab__527, UD_TAB__OPC_SSE, "/sse" }, + /* 528 */ { ud_itab__528, UD_TAB__OPC_SSE, "/sse" }, + /* 529 */ { ud_itab__529, UD_TAB__OPC_SSE, "/sse" }, + /* 530 */ { ud_itab__530, UD_TAB__OPC_SSE, "/sse" }, + /* 531 */ { ud_itab__531, UD_TAB__OPC_SSE, "/sse" }, + /* 532 */ { ud_itab__532, UD_TAB__OPC_SSE, "/sse" }, + /* 533 */ { ud_itab__533, UD_TAB__OPC_SSE, "/sse" }, + /* 534 */ { ud_itab__534, UD_TAB__OPC_SSE, "/sse" }, + /* 535 */ { ud_itab__535, UD_TAB__OPC_SSE, "/sse" }, + /* 536 */ { ud_itab__536, UD_TAB__OPC_SSE, "/sse" }, + /* 537 */ { ud_itab__537, UD_TAB__OPC_SSE, "/sse" }, + /* 538 */ { ud_itab__538, UD_TAB__OPC_SSE, "/sse" }, + /* 539 */ { ud_itab__539, UD_TAB__OPC_SSE, "/sse" }, + /* 540 */ { ud_itab__540, UD_TAB__OPC_SSE, "/sse" }, + /* 541 */ { ud_itab__541, UD_TAB__OPC_SSE, "/sse" }, + /* 542 */ { ud_itab__542, UD_TAB__OPC_SSE, "/sse" }, + /* 543 */ { ud_itab__543, UD_TAB__OPC_SSE, "/sse" }, + /* 544 */ { ud_itab__544, UD_TAB__OPC_SSE, "/sse" }, + /* 545 */ { ud_itab__545, UD_TAB__OPC_SSE, "/sse" }, + /* 546 */ { ud_itab__546, UD_TAB__OPC_SSE, "/sse" }, + /* 547 */ { ud_itab__547, UD_TAB__OPC_SSE, "/sse" }, + /* 548 */ { ud_itab__548, UD_TAB__OPC_SSE, "/sse" }, + /* 549 */ { ud_itab__549, UD_TAB__OPC_SSE, "/sse" }, + /* 550 */ { ud_itab__550, UD_TAB__OPC_SSE, "/sse" }, + /* 551 */ { ud_itab__551, UD_TAB__OPC_SSE, "/sse" }, + /* 552 */ { ud_itab__552, UD_TAB__OPC_MOD, "/mod" }, + /* 553 */ { ud_itab__553, UD_TAB__OPC_SSE, "/sse" }, + /* 554 */ { ud_itab__554, UD_TAB__OPC_MOD, "/mod" }, + /* 555 */ { ud_itab__555, UD_TAB__OPC_MOD, "/mod" }, + /* 556 */ { ud_itab__556, UD_TAB__OPC_SSE, "/sse" }, + /* 557 */ { ud_itab__557, UD_TAB__OPC_SSE, "/sse" }, + /* 558 */ { ud_itab__558, UD_TAB__OPC_SSE, "/sse" }, + /* 559 */ { ud_itab__559, UD_TAB__OPC_SSE, "/sse" }, + /* 560 */ { ud_itab__560, UD_TAB__OPC_SSE, "/sse" }, + /* 561 */ { ud_itab__561, UD_TAB__OPC_SSE, "/sse" }, + /* 562 */ { ud_itab__562, UD_TAB__OPC_SSE, "/sse" }, + /* 563 */ { ud_itab__563, UD_TAB__OPC_MODE, "/m" }, + /* 564 */ { ud_itab__564, UD_TAB__OPC_MODE, "/m" }, + /* 565 */ { ud_itab__565, UD_TAB__OPC_MODE, "/m" }, + /* 566 */ { ud_itab__566, UD_TAB__OPC_MODE, "/m" }, + /* 567 */ { ud_itab__567, UD_TAB__OPC_MODE, "/m" }, + /* 568 */ { ud_itab__568, UD_TAB__OPC_MODE, "/m" }, + /* 569 */ { ud_itab__569, UD_TAB__OPC_MODE, "/m" }, + /* 570 */ { ud_itab__570, UD_TAB__OPC_MODE, "/m" }, + /* 571 */ { ud_itab__571, UD_TAB__OPC_OSIZE, "/o" }, + /* 572 */ { ud_itab__572, UD_TAB__OPC_MODE, "/m" }, + /* 573 */ { ud_itab__573, UD_TAB__OPC_MODE, "/m" }, + /* 574 */ { ud_itab__574, UD_TAB__OPC_OSIZE, "/o" }, + /* 575 */ { ud_itab__575, UD_TAB__OPC_MODE, "/m" }, + /* 576 */ { ud_itab__576, UD_TAB__OPC_MODE, "/m" }, + /* 577 */ { ud_itab__577, UD_TAB__OPC_MODE, "/m" }, + /* 578 */ { ud_itab__578, UD_TAB__OPC_MODE, "/m" }, + /* 579 */ { ud_itab__579, UD_TAB__OPC_OSIZE, "/o" }, + /* 580 */ { ud_itab__580, UD_TAB__OPC_OSIZE, "/o" }, + /* 581 */ { ud_itab__581, UD_TAB__OPC_REG, "/reg" }, + /* 582 */ { ud_itab__582, UD_TAB__OPC_REG, "/reg" }, + /* 583 */ { ud_itab__583, UD_TAB__OPC_REG, "/reg" }, + /* 584 */ { ud_itab__584, UD_TAB__OPC_MODE, "/m" }, + /* 585 */ { ud_itab__585, UD_TAB__OPC_MODE, "/m" }, + /* 586 */ { ud_itab__586, UD_TAB__OPC_MODE, "/m" }, + /* 587 */ { ud_itab__587, UD_TAB__OPC_MODE, "/m" }, + /* 588 */ { ud_itab__588, UD_TAB__OPC_MODE, "/m" }, + /* 589 */ { ud_itab__589, UD_TAB__OPC_MODE, "/m" }, + /* 590 */ { ud_itab__590, UD_TAB__OPC_MODE, "/m" }, + /* 591 */ { ud_itab__591, UD_TAB__OPC_MODE, "/m" }, + /* 592 */ { ud_itab__592, UD_TAB__OPC_REG, "/reg" }, + /* 593 */ { ud_itab__593, UD_TAB__OPC_REG, "/reg" }, + /* 594 */ { ud_itab__594, UD_TAB__OPC_OSIZE, "/o" }, + /* 595 */ { ud_itab__595, UD_TAB__OPC_OSIZE, "/o" }, + /* 596 */ { ud_itab__596, UD_TAB__OPC_MODE, "/m" }, + /* 597 */ { ud_itab__597, UD_TAB__OPC_OSIZE, "/o" }, + /* 598 */ { ud_itab__598, UD_TAB__OPC_MODE, "/m" }, + /* 599 */ { ud_itab__599, UD_TAB__OPC_MODE, "/m" }, + /* 600 */ { ud_itab__600, UD_TAB__OPC_MODE, "/m" }, + /* 601 */ { ud_itab__601, UD_TAB__OPC_OSIZE, "/o" }, + /* 602 */ { ud_itab__602, UD_TAB__OPC_MODE, "/m" }, + /* 603 */ { ud_itab__603, UD_TAB__OPC_MODE, "/m" }, + /* 604 */ { ud_itab__604, UD_TAB__OPC_MODE, "/m" }, + /* 605 */ { ud_itab__605, UD_TAB__OPC_OSIZE, "/o" }, + /* 606 */ { ud_itab__606, UD_TAB__OPC_OSIZE, "/o" }, + /* 607 */ { ud_itab__607, UD_TAB__OPC_OSIZE, "/o" }, + /* 608 */ { ud_itab__608, UD_TAB__OPC_OSIZE, "/o" }, + /* 609 */ { ud_itab__609, UD_TAB__OPC_OSIZE, "/o" }, + /* 610 */ { ud_itab__610, UD_TAB__OPC_REG, "/reg" }, + /* 611 */ { ud_itab__611, UD_TAB__OPC_REG, "/reg" }, + /* 612 */ { ud_itab__612, UD_TAB__OPC_MODE, "/m" }, + /* 613 */ { ud_itab__613, UD_TAB__OPC_MODE, "/m" }, + /* 614 */ { ud_itab__614, UD_TAB__OPC_REG, "/reg" }, + /* 615 */ { ud_itab__615, UD_TAB__OPC_REG, "/reg" }, + /* 616 */ { ud_itab__616, UD_TAB__OPC_MODE, "/m" }, + /* 617 */ { ud_itab__617, UD_TAB__OPC_OSIZE, "/o" }, + /* 618 */ { ud_itab__618, UD_TAB__OPC_REG, "/reg" }, + /* 619 */ { ud_itab__619, UD_TAB__OPC_REG, "/reg" }, + /* 620 */ { ud_itab__620, UD_TAB__OPC_REG, "/reg" }, + /* 621 */ { ud_itab__621, UD_TAB__OPC_REG, "/reg" }, + /* 622 */ { ud_itab__622, UD_TAB__OPC_MODE, "/m" }, + /* 623 */ { ud_itab__623, UD_TAB__OPC_MODE, "/m" }, + /* 624 */ { ud_itab__624, UD_TAB__OPC_MODE, "/m" }, + /* 625 */ { ud_itab__625, UD_TAB__OPC_MOD, "/mod" }, + /* 626 */ { ud_itab__626, UD_TAB__OPC_REG, "/reg" }, + /* 627 */ { ud_itab__627, UD_TAB__OPC_MOD, "/mod" }, + /* 628 */ { ud_itab__628, UD_TAB__OPC_MOD, "/mod" }, + /* 629 */ { ud_itab__629, UD_TAB__OPC_MOD, "/mod" }, + /* 630 */ { ud_itab__630, UD_TAB__OPC_MOD, "/mod" }, + /* 631 */ { ud_itab__631, UD_TAB__OPC_MOD, "/mod" }, + /* 632 */ { ud_itab__632, UD_TAB__OPC_MOD, "/mod" }, + /* 633 */ { ud_itab__633, UD_TAB__OPC_MOD, "/mod" }, + /* 634 */ { ud_itab__634, UD_TAB__OPC_MOD, "/mod" }, + /* 635 */ { ud_itab__635, UD_TAB__OPC_X87, "/x87" }, + /* 636 */ { ud_itab__636, UD_TAB__OPC_MOD, "/mod" }, + /* 637 */ { ud_itab__637, UD_TAB__OPC_MOD, "/mod" }, + /* 638 */ { ud_itab__638, UD_TAB__OPC_MOD, "/mod" }, + /* 639 */ { ud_itab__639, UD_TAB__OPC_MOD, "/mod" }, + /* 640 */ { ud_itab__640, UD_TAB__OPC_MOD, "/mod" }, + /* 641 */ { ud_itab__641, UD_TAB__OPC_MOD, "/mod" }, + /* 642 */ { ud_itab__642, UD_TAB__OPC_MOD, "/mod" }, + /* 643 */ { ud_itab__643, UD_TAB__OPC_MOD, "/mod" }, + /* 644 */ { ud_itab__644, UD_TAB__OPC_MOD, "/mod" }, + /* 645 */ { ud_itab__645, UD_TAB__OPC_MOD, "/mod" }, + /* 646 */ { ud_itab__646, UD_TAB__OPC_MOD, "/mod" }, + /* 647 */ { ud_itab__647, UD_TAB__OPC_MOD, "/mod" }, + /* 648 */ { ud_itab__648, UD_TAB__OPC_MOD, "/mod" }, + /* 649 */ { ud_itab__649, UD_TAB__OPC_MOD, "/mod" }, + /* 650 */ { ud_itab__650, UD_TAB__OPC_MOD, "/mod" }, + /* 651 */ { ud_itab__651, UD_TAB__OPC_MOD, "/mod" }, + /* 652 */ { ud_itab__652, UD_TAB__OPC_MOD, "/mod" }, + /* 653 */ { ud_itab__653, UD_TAB__OPC_MOD, "/mod" }, + /* 654 */ { ud_itab__654, UD_TAB__OPC_MOD, "/mod" }, + /* 655 */ { ud_itab__655, UD_TAB__OPC_MOD, "/mod" }, + /* 656 */ { ud_itab__656, UD_TAB__OPC_MOD, "/mod" }, + /* 657 */ { ud_itab__657, UD_TAB__OPC_MOD, "/mod" }, + /* 658 */ { ud_itab__658, UD_TAB__OPC_MOD, "/mod" }, + /* 659 */ { ud_itab__659, UD_TAB__OPC_MOD, "/mod" }, + /* 660 */ { ud_itab__660, UD_TAB__OPC_MOD, "/mod" }, + /* 661 */ { ud_itab__661, UD_TAB__OPC_MOD, "/mod" }, + /* 662 */ { ud_itab__662, UD_TAB__OPC_MOD, "/mod" }, + /* 663 */ { ud_itab__663, UD_TAB__OPC_MOD, "/mod" }, + /* 664 */ { ud_itab__664, UD_TAB__OPC_MOD, "/mod" }, + /* 665 */ { ud_itab__665, UD_TAB__OPC_MOD, "/mod" }, + /* 666 */ { ud_itab__666, UD_TAB__OPC_MOD, "/mod" }, + /* 667 */ { ud_itab__667, UD_TAB__OPC_MOD, "/mod" }, + /* 668 */ { ud_itab__668, UD_TAB__OPC_MOD, "/mod" }, + /* 669 */ { ud_itab__669, UD_TAB__OPC_MOD, "/mod" }, + /* 670 */ { ud_itab__670, UD_TAB__OPC_MOD, "/mod" }, + /* 671 */ { ud_itab__671, UD_TAB__OPC_MOD, "/mod" }, + /* 672 */ { ud_itab__672, UD_TAB__OPC_MOD, "/mod" }, + /* 673 */ { ud_itab__673, UD_TAB__OPC_MOD, "/mod" }, + /* 674 */ { ud_itab__674, UD_TAB__OPC_MOD, "/mod" }, + /* 675 */ { ud_itab__675, UD_TAB__OPC_MOD, "/mod" }, + /* 676 */ { ud_itab__676, UD_TAB__OPC_MOD, "/mod" }, + /* 677 */ { ud_itab__677, UD_TAB__OPC_MOD, "/mod" }, + /* 678 */ { ud_itab__678, UD_TAB__OPC_MOD, "/mod" }, + /* 679 */ { ud_itab__679, UD_TAB__OPC_MOD, "/mod" }, + /* 680 */ { ud_itab__680, UD_TAB__OPC_MOD, "/mod" }, + /* 681 */ { ud_itab__681, UD_TAB__OPC_MOD, "/mod" }, + /* 682 */ { ud_itab__682, UD_TAB__OPC_MOD, "/mod" }, + /* 683 */ { ud_itab__683, UD_TAB__OPC_MOD, "/mod" }, + /* 684 */ { ud_itab__684, UD_TAB__OPC_MOD, "/mod" }, + /* 685 */ { ud_itab__685, UD_TAB__OPC_MOD, "/mod" }, + /* 686 */ { ud_itab__686, UD_TAB__OPC_MOD, "/mod" }, + /* 687 */ { ud_itab__687, UD_TAB__OPC_MOD, "/mod" }, + /* 688 */ { ud_itab__688, UD_TAB__OPC_MOD, "/mod" }, + /* 689 */ { ud_itab__689, UD_TAB__OPC_MOD, "/mod" }, + /* 690 */ { ud_itab__690, UD_TAB__OPC_MOD, "/mod" }, + /* 691 */ { ud_itab__691, UD_TAB__OPC_MOD, "/mod" }, + /* 692 */ { ud_itab__692, UD_TAB__OPC_MOD, "/mod" }, + /* 693 */ { ud_itab__693, UD_TAB__OPC_MOD, "/mod" }, + /* 694 */ { ud_itab__694, UD_TAB__OPC_MOD, "/mod" }, + /* 695 */ { ud_itab__695, UD_TAB__OPC_MOD, "/mod" }, + /* 696 */ { ud_itab__696, UD_TAB__OPC_MOD, "/mod" }, + /* 697 */ { ud_itab__697, UD_TAB__OPC_MOD, "/mod" }, + /* 698 */ { ud_itab__698, UD_TAB__OPC_MOD, "/mod" }, + /* 699 */ { ud_itab__699, UD_TAB__OPC_MOD, "/mod" }, + /* 700 */ { ud_itab__700, UD_TAB__OPC_MOD, "/mod" }, + /* 701 */ { ud_itab__701, UD_TAB__OPC_REG, "/reg" }, + /* 702 */ { ud_itab__702, UD_TAB__OPC_MOD, "/mod" }, + /* 703 */ { ud_itab__703, UD_TAB__OPC_MOD, "/mod" }, + /* 704 */ { ud_itab__704, UD_TAB__OPC_MOD, "/mod" }, + /* 705 */ { ud_itab__705, UD_TAB__OPC_MOD, "/mod" }, + /* 706 */ { ud_itab__706, UD_TAB__OPC_MOD, "/mod" }, + /* 707 */ { ud_itab__707, UD_TAB__OPC_MOD, "/mod" }, + /* 708 */ { ud_itab__708, UD_TAB__OPC_MOD, "/mod" }, + /* 709 */ { ud_itab__709, UD_TAB__OPC_X87, "/x87" }, + /* 710 */ { ud_itab__710, UD_TAB__OPC_MOD, "/mod" }, + /* 711 */ { ud_itab__711, UD_TAB__OPC_MOD, "/mod" }, + /* 712 */ { ud_itab__712, UD_TAB__OPC_MOD, "/mod" }, + /* 713 */ { ud_itab__713, UD_TAB__OPC_MOD, "/mod" }, + /* 714 */ { ud_itab__714, UD_TAB__OPC_MOD, "/mod" }, + /* 715 */ { ud_itab__715, UD_TAB__OPC_MOD, "/mod" }, + /* 716 */ { ud_itab__716, UD_TAB__OPC_MOD, "/mod" }, + /* 717 */ { ud_itab__717, UD_TAB__OPC_MOD, "/mod" }, + /* 718 */ { ud_itab__718, UD_TAB__OPC_MOD, "/mod" }, + /* 719 */ { ud_itab__719, UD_TAB__OPC_MOD, "/mod" }, + /* 720 */ { ud_itab__720, UD_TAB__OPC_MOD, "/mod" }, + /* 721 */ { ud_itab__721, UD_TAB__OPC_MOD, "/mod" }, + /* 722 */ { ud_itab__722, UD_TAB__OPC_MOD, "/mod" }, + /* 723 */ { ud_itab__723, UD_TAB__OPC_MOD, "/mod" }, + /* 724 */ { ud_itab__724, UD_TAB__OPC_MOD, "/mod" }, + /* 725 */ { ud_itab__725, UD_TAB__OPC_MOD, "/mod" }, + /* 726 */ { ud_itab__726, UD_TAB__OPC_MOD, "/mod" }, + /* 727 */ { ud_itab__727, UD_TAB__OPC_MOD, "/mod" }, + /* 728 */ { ud_itab__728, UD_TAB__OPC_MOD, "/mod" }, + /* 729 */ { ud_itab__729, UD_TAB__OPC_MOD, "/mod" }, + /* 730 */ { ud_itab__730, UD_TAB__OPC_MOD, "/mod" }, + /* 731 */ { ud_itab__731, UD_TAB__OPC_MOD, "/mod" }, + /* 732 */ { ud_itab__732, UD_TAB__OPC_MOD, "/mod" }, + /* 733 */ { ud_itab__733, UD_TAB__OPC_MOD, "/mod" }, + /* 734 */ { ud_itab__734, UD_TAB__OPC_MOD, "/mod" }, + /* 735 */ { ud_itab__735, UD_TAB__OPC_MOD, "/mod" }, + /* 736 */ { ud_itab__736, UD_TAB__OPC_MOD, "/mod" }, + /* 737 */ { ud_itab__737, UD_TAB__OPC_MOD, "/mod" }, + /* 738 */ { ud_itab__738, UD_TAB__OPC_MOD, "/mod" }, + /* 739 */ { ud_itab__739, UD_TAB__OPC_MOD, "/mod" }, + /* 740 */ { ud_itab__740, UD_TAB__OPC_MOD, "/mod" }, + /* 741 */ { ud_itab__741, UD_TAB__OPC_MOD, "/mod" }, + /* 742 */ { ud_itab__742, UD_TAB__OPC_MOD, "/mod" }, + /* 743 */ { ud_itab__743, UD_TAB__OPC_MOD, "/mod" }, + /* 744 */ { ud_itab__744, UD_TAB__OPC_MOD, "/mod" }, + /* 745 */ { ud_itab__745, UD_TAB__OPC_MOD, "/mod" }, + /* 746 */ { ud_itab__746, UD_TAB__OPC_MOD, "/mod" }, + /* 747 */ { ud_itab__747, UD_TAB__OPC_MOD, "/mod" }, + /* 748 */ { ud_itab__748, UD_TAB__OPC_MOD, "/mod" }, + /* 749 */ { ud_itab__749, UD_TAB__OPC_MOD, "/mod" }, + /* 750 */ { ud_itab__750, UD_TAB__OPC_MOD, "/mod" }, + /* 751 */ { ud_itab__751, UD_TAB__OPC_MOD, "/mod" }, + /* 752 */ { ud_itab__752, UD_TAB__OPC_MOD, "/mod" }, + /* 753 */ { ud_itab__753, UD_TAB__OPC_MOD, "/mod" }, + /* 754 */ { ud_itab__754, UD_TAB__OPC_MOD, "/mod" }, + /* 755 */ { ud_itab__755, UD_TAB__OPC_MOD, "/mod" }, + /* 756 */ { ud_itab__756, UD_TAB__OPC_MOD, "/mod" }, + /* 757 */ { ud_itab__757, UD_TAB__OPC_MOD, "/mod" }, + /* 758 */ { ud_itab__758, UD_TAB__OPC_MOD, "/mod" }, + /* 759 */ { ud_itab__759, UD_TAB__OPC_MOD, "/mod" }, + /* 760 */ { ud_itab__760, UD_TAB__OPC_MOD, "/mod" }, + /* 761 */ { ud_itab__761, UD_TAB__OPC_MOD, "/mod" }, + /* 762 */ { ud_itab__762, UD_TAB__OPC_MOD, "/mod" }, + /* 763 */ { ud_itab__763, UD_TAB__OPC_REG, "/reg" }, + /* 764 */ { ud_itab__764, UD_TAB__OPC_MOD, "/mod" }, + /* 765 */ { ud_itab__765, UD_TAB__OPC_MOD, "/mod" }, + /* 766 */ { ud_itab__766, UD_TAB__OPC_MOD, "/mod" }, + /* 767 */ { ud_itab__767, UD_TAB__OPC_MOD, "/mod" }, + /* 768 */ { ud_itab__768, UD_TAB__OPC_MOD, "/mod" }, + /* 769 */ { ud_itab__769, UD_TAB__OPC_MOD, "/mod" }, + /* 770 */ { ud_itab__770, UD_TAB__OPC_MOD, "/mod" }, + /* 771 */ { ud_itab__771, UD_TAB__OPC_MOD, "/mod" }, + /* 772 */ { ud_itab__772, UD_TAB__OPC_X87, "/x87" }, + /* 773 */ { ud_itab__773, UD_TAB__OPC_MOD, "/mod" }, + /* 774 */ { ud_itab__774, UD_TAB__OPC_MOD, "/mod" }, + /* 775 */ { ud_itab__775, UD_TAB__OPC_MOD, "/mod" }, + /* 776 */ { ud_itab__776, UD_TAB__OPC_MOD, "/mod" }, + /* 777 */ { ud_itab__777, UD_TAB__OPC_MOD, "/mod" }, + /* 778 */ { ud_itab__778, UD_TAB__OPC_MOD, "/mod" }, + /* 779 */ { ud_itab__779, UD_TAB__OPC_MOD, "/mod" }, + /* 780 */ { ud_itab__780, UD_TAB__OPC_MOD, "/mod" }, + /* 781 */ { ud_itab__781, UD_TAB__OPC_MOD, "/mod" }, + /* 782 */ { ud_itab__782, UD_TAB__OPC_MOD, "/mod" }, + /* 783 */ { ud_itab__783, UD_TAB__OPC_MOD, "/mod" }, + /* 784 */ { ud_itab__784, UD_TAB__OPC_MOD, "/mod" }, + /* 785 */ { ud_itab__785, UD_TAB__OPC_MOD, "/mod" }, + /* 786 */ { ud_itab__786, UD_TAB__OPC_MOD, "/mod" }, + /* 787 */ { ud_itab__787, UD_TAB__OPC_MOD, "/mod" }, + /* 788 */ { ud_itab__788, UD_TAB__OPC_MOD, "/mod" }, + /* 789 */ { ud_itab__789, UD_TAB__OPC_MOD, "/mod" }, + /* 790 */ { ud_itab__790, UD_TAB__OPC_MOD, "/mod" }, + /* 791 */ { ud_itab__791, UD_TAB__OPC_MOD, "/mod" }, + /* 792 */ { ud_itab__792, UD_TAB__OPC_MOD, "/mod" }, + /* 793 */ { ud_itab__793, UD_TAB__OPC_MOD, "/mod" }, + /* 794 */ { ud_itab__794, UD_TAB__OPC_MOD, "/mod" }, + /* 795 */ { ud_itab__795, UD_TAB__OPC_MOD, "/mod" }, + /* 796 */ { ud_itab__796, UD_TAB__OPC_MOD, "/mod" }, + /* 797 */ { ud_itab__797, UD_TAB__OPC_MOD, "/mod" }, + /* 798 */ { ud_itab__798, UD_TAB__OPC_MOD, "/mod" }, + /* 799 */ { ud_itab__799, UD_TAB__OPC_MOD, "/mod" }, + /* 800 */ { ud_itab__800, UD_TAB__OPC_MOD, "/mod" }, + /* 801 */ { ud_itab__801, UD_TAB__OPC_MOD, "/mod" }, + /* 802 */ { ud_itab__802, UD_TAB__OPC_MOD, "/mod" }, + /* 803 */ { ud_itab__803, UD_TAB__OPC_MOD, "/mod" }, + /* 804 */ { ud_itab__804, UD_TAB__OPC_MOD, "/mod" }, + /* 805 */ { ud_itab__805, UD_TAB__OPC_MOD, "/mod" }, + /* 806 */ { ud_itab__806, UD_TAB__OPC_MOD, "/mod" }, + /* 807 */ { ud_itab__807, UD_TAB__OPC_REG, "/reg" }, + /* 808 */ { ud_itab__808, UD_TAB__OPC_MOD, "/mod" }, + /* 809 */ { ud_itab__809, UD_TAB__OPC_MOD, "/mod" }, + /* 810 */ { ud_itab__810, UD_TAB__OPC_MOD, "/mod" }, + /* 811 */ { ud_itab__811, UD_TAB__OPC_MOD, "/mod" }, + /* 812 */ { ud_itab__812, UD_TAB__OPC_MOD, "/mod" }, + /* 813 */ { ud_itab__813, UD_TAB__OPC_MOD, "/mod" }, + /* 814 */ { ud_itab__814, UD_TAB__OPC_X87, "/x87" }, + /* 815 */ { ud_itab__815, UD_TAB__OPC_MOD, "/mod" }, + /* 816 */ { ud_itab__816, UD_TAB__OPC_MOD, "/mod" }, + /* 817 */ { ud_itab__817, UD_TAB__OPC_MOD, "/mod" }, + /* 818 */ { ud_itab__818, UD_TAB__OPC_MOD, "/mod" }, + /* 819 */ { ud_itab__819, UD_TAB__OPC_MOD, "/mod" }, + /* 820 */ { ud_itab__820, UD_TAB__OPC_MOD, "/mod" }, + /* 821 */ { ud_itab__821, UD_TAB__OPC_MOD, "/mod" }, + /* 822 */ { ud_itab__822, UD_TAB__OPC_MOD, "/mod" }, + /* 823 */ { ud_itab__823, UD_TAB__OPC_MOD, "/mod" }, + /* 824 */ { ud_itab__824, UD_TAB__OPC_MOD, "/mod" }, + /* 825 */ { ud_itab__825, UD_TAB__OPC_MOD, "/mod" }, + /* 826 */ { ud_itab__826, UD_TAB__OPC_MOD, "/mod" }, + /* 827 */ { ud_itab__827, UD_TAB__OPC_MOD, "/mod" }, + /* 828 */ { ud_itab__828, UD_TAB__OPC_MOD, "/mod" }, + /* 829 */ { ud_itab__829, UD_TAB__OPC_MOD, "/mod" }, + /* 830 */ { ud_itab__830, UD_TAB__OPC_MOD, "/mod" }, + /* 831 */ { ud_itab__831, UD_TAB__OPC_MOD, "/mod" }, + /* 832 */ { ud_itab__832, UD_TAB__OPC_MOD, "/mod" }, + /* 833 */ { ud_itab__833, UD_TAB__OPC_MOD, "/mod" }, + /* 834 */ { ud_itab__834, UD_TAB__OPC_MOD, "/mod" }, + /* 835 */ { ud_itab__835, UD_TAB__OPC_MOD, "/mod" }, + /* 836 */ { ud_itab__836, UD_TAB__OPC_MOD, "/mod" }, + /* 837 */ { ud_itab__837, UD_TAB__OPC_MOD, "/mod" }, + /* 838 */ { ud_itab__838, UD_TAB__OPC_MOD, "/mod" }, + /* 839 */ { ud_itab__839, UD_TAB__OPC_MOD, "/mod" }, + /* 840 */ { ud_itab__840, UD_TAB__OPC_MOD, "/mod" }, + /* 841 */ { ud_itab__841, UD_TAB__OPC_MOD, "/mod" }, + /* 842 */ { ud_itab__842, UD_TAB__OPC_MOD, "/mod" }, + /* 843 */ { ud_itab__843, UD_TAB__OPC_MOD, "/mod" }, + /* 844 */ { ud_itab__844, UD_TAB__OPC_MOD, "/mod" }, + /* 845 */ { ud_itab__845, UD_TAB__OPC_MOD, "/mod" }, + /* 846 */ { ud_itab__846, UD_TAB__OPC_MOD, "/mod" }, + /* 847 */ { ud_itab__847, UD_TAB__OPC_MOD, "/mod" }, + /* 848 */ { ud_itab__848, UD_TAB__OPC_MOD, "/mod" }, + /* 849 */ { ud_itab__849, UD_TAB__OPC_MOD, "/mod" }, + /* 850 */ { ud_itab__850, UD_TAB__OPC_MOD, "/mod" }, + /* 851 */ { ud_itab__851, UD_TAB__OPC_MOD, "/mod" }, + /* 852 */ { ud_itab__852, UD_TAB__OPC_MOD, "/mod" }, + /* 853 */ { ud_itab__853, UD_TAB__OPC_MOD, "/mod" }, + /* 854 */ { ud_itab__854, UD_TAB__OPC_MOD, "/mod" }, + /* 855 */ { ud_itab__855, UD_TAB__OPC_MOD, "/mod" }, + /* 856 */ { ud_itab__856, UD_TAB__OPC_MOD, "/mod" }, + /* 857 */ { ud_itab__857, UD_TAB__OPC_MOD, "/mod" }, + /* 858 */ { ud_itab__858, UD_TAB__OPC_MOD, "/mod" }, + /* 859 */ { ud_itab__859, UD_TAB__OPC_MOD, "/mod" }, + /* 860 */ { ud_itab__860, UD_TAB__OPC_MOD, "/mod" }, + /* 861 */ { ud_itab__861, UD_TAB__OPC_MOD, "/mod" }, + /* 862 */ { ud_itab__862, UD_TAB__OPC_MOD, "/mod" }, + /* 863 */ { ud_itab__863, UD_TAB__OPC_MOD, "/mod" }, + /* 864 */ { ud_itab__864, UD_TAB__OPC_MOD, "/mod" }, + /* 865 */ { ud_itab__865, UD_TAB__OPC_MOD, "/mod" }, + /* 866 */ { ud_itab__866, UD_TAB__OPC_REG, "/reg" }, + /* 867 */ { ud_itab__867, UD_TAB__OPC_MOD, "/mod" }, + /* 868 */ { ud_itab__868, UD_TAB__OPC_MOD, "/mod" }, + /* 869 */ { ud_itab__869, UD_TAB__OPC_MOD, "/mod" }, + /* 870 */ { ud_itab__870, UD_TAB__OPC_MOD, "/mod" }, + /* 871 */ { ud_itab__871, UD_TAB__OPC_MOD, "/mod" }, + /* 872 */ { ud_itab__872, UD_TAB__OPC_MOD, "/mod" }, + /* 873 */ { ud_itab__873, UD_TAB__OPC_MOD, "/mod" }, + /* 874 */ { ud_itab__874, UD_TAB__OPC_MOD, "/mod" }, + /* 875 */ { ud_itab__875, UD_TAB__OPC_X87, "/x87" }, + /* 876 */ { ud_itab__876, UD_TAB__OPC_MOD, "/mod" }, + /* 877 */ { ud_itab__877, UD_TAB__OPC_MOD, "/mod" }, + /* 878 */ { ud_itab__878, UD_TAB__OPC_MOD, "/mod" }, + /* 879 */ { ud_itab__879, UD_TAB__OPC_MOD, "/mod" }, + /* 880 */ { ud_itab__880, UD_TAB__OPC_MOD, "/mod" }, + /* 881 */ { ud_itab__881, UD_TAB__OPC_MOD, "/mod" }, + /* 882 */ { ud_itab__882, UD_TAB__OPC_MOD, "/mod" }, + /* 883 */ { ud_itab__883, UD_TAB__OPC_MOD, "/mod" }, + /* 884 */ { ud_itab__884, UD_TAB__OPC_MOD, "/mod" }, + /* 885 */ { ud_itab__885, UD_TAB__OPC_MOD, "/mod" }, + /* 886 */ { ud_itab__886, UD_TAB__OPC_MOD, "/mod" }, + /* 887 */ { ud_itab__887, UD_TAB__OPC_MOD, "/mod" }, + /* 888 */ { ud_itab__888, UD_TAB__OPC_MOD, "/mod" }, + /* 889 */ { ud_itab__889, UD_TAB__OPC_MOD, "/mod" }, + /* 890 */ { ud_itab__890, UD_TAB__OPC_MOD, "/mod" }, + /* 891 */ { ud_itab__891, UD_TAB__OPC_MOD, "/mod" }, + /* 892 */ { ud_itab__892, UD_TAB__OPC_MOD, "/mod" }, + /* 893 */ { ud_itab__893, UD_TAB__OPC_MOD, "/mod" }, + /* 894 */ { ud_itab__894, UD_TAB__OPC_MOD, "/mod" }, + /* 895 */ { ud_itab__895, UD_TAB__OPC_MOD, "/mod" }, + /* 896 */ { ud_itab__896, UD_TAB__OPC_MOD, "/mod" }, + /* 897 */ { ud_itab__897, UD_TAB__OPC_MOD, "/mod" }, + /* 898 */ { ud_itab__898, UD_TAB__OPC_MOD, "/mod" }, + /* 899 */ { ud_itab__899, UD_TAB__OPC_MOD, "/mod" }, + /* 900 */ { ud_itab__900, UD_TAB__OPC_MOD, "/mod" }, + /* 901 */ { ud_itab__901, UD_TAB__OPC_MOD, "/mod" }, + /* 902 */ { ud_itab__902, UD_TAB__OPC_MOD, "/mod" }, + /* 903 */ { ud_itab__903, UD_TAB__OPC_MOD, "/mod" }, + /* 904 */ { ud_itab__904, UD_TAB__OPC_MOD, "/mod" }, + /* 905 */ { ud_itab__905, UD_TAB__OPC_MOD, "/mod" }, + /* 906 */ { ud_itab__906, UD_TAB__OPC_MOD, "/mod" }, + /* 907 */ { ud_itab__907, UD_TAB__OPC_MOD, "/mod" }, + /* 908 */ { ud_itab__908, UD_TAB__OPC_MOD, "/mod" }, + /* 909 */ { ud_itab__909, UD_TAB__OPC_MOD, "/mod" }, + /* 910 */ { ud_itab__910, UD_TAB__OPC_MOD, "/mod" }, + /* 911 */ { ud_itab__911, UD_TAB__OPC_MOD, "/mod" }, + /* 912 */ { ud_itab__912, UD_TAB__OPC_MOD, "/mod" }, + /* 913 */ { ud_itab__913, UD_TAB__OPC_MOD, "/mod" }, + /* 914 */ { ud_itab__914, UD_TAB__OPC_MOD, "/mod" }, + /* 915 */ { ud_itab__915, UD_TAB__OPC_MOD, "/mod" }, + /* 916 */ { ud_itab__916, UD_TAB__OPC_MOD, "/mod" }, + /* 917 */ { ud_itab__917, UD_TAB__OPC_MOD, "/mod" }, + /* 918 */ { ud_itab__918, UD_TAB__OPC_MOD, "/mod" }, + /* 919 */ { ud_itab__919, UD_TAB__OPC_MOD, "/mod" }, + /* 920 */ { ud_itab__920, UD_TAB__OPC_MOD, "/mod" }, + /* 921 */ { ud_itab__921, UD_TAB__OPC_MOD, "/mod" }, + /* 922 */ { ud_itab__922, UD_TAB__OPC_MOD, "/mod" }, + /* 923 */ { ud_itab__923, UD_TAB__OPC_MOD, "/mod" }, + /* 924 */ { ud_itab__924, UD_TAB__OPC_MOD, "/mod" }, + /* 925 */ { ud_itab__925, UD_TAB__OPC_MOD, "/mod" }, + /* 926 */ { ud_itab__926, UD_TAB__OPC_MOD, "/mod" }, + /* 927 */ { ud_itab__927, UD_TAB__OPC_MOD, "/mod" }, + /* 928 */ { ud_itab__928, UD_TAB__OPC_MOD, "/mod" }, + /* 929 */ { ud_itab__929, UD_TAB__OPC_MOD, "/mod" }, + /* 930 */ { ud_itab__930, UD_TAB__OPC_MOD, "/mod" }, + /* 931 */ { ud_itab__931, UD_TAB__OPC_MOD, "/mod" }, + /* 932 */ { ud_itab__932, UD_TAB__OPC_MOD, "/mod" }, + /* 933 */ { ud_itab__933, UD_TAB__OPC_MOD, "/mod" }, + /* 934 */ { ud_itab__934, UD_TAB__OPC_MOD, "/mod" }, + /* 935 */ { ud_itab__935, UD_TAB__OPC_MOD, "/mod" }, + /* 936 */ { ud_itab__936, UD_TAB__OPC_MOD, "/mod" }, + /* 937 */ { ud_itab__937, UD_TAB__OPC_MOD, "/mod" }, + /* 938 */ { ud_itab__938, UD_TAB__OPC_MOD, "/mod" }, + /* 939 */ { ud_itab__939, UD_TAB__OPC_MOD, "/mod" }, + /* 940 */ { ud_itab__940, UD_TAB__OPC_MOD, "/mod" }, + /* 941 */ { ud_itab__941, UD_TAB__OPC_REG, "/reg" }, + /* 942 */ { ud_itab__942, UD_TAB__OPC_MOD, "/mod" }, + /* 943 */ { ud_itab__943, UD_TAB__OPC_MOD, "/mod" }, + /* 944 */ { ud_itab__944, UD_TAB__OPC_MOD, "/mod" }, + /* 945 */ { ud_itab__945, UD_TAB__OPC_MOD, "/mod" }, + /* 946 */ { ud_itab__946, UD_TAB__OPC_MOD, "/mod" }, + /* 947 */ { ud_itab__947, UD_TAB__OPC_MOD, "/mod" }, + /* 948 */ { ud_itab__948, UD_TAB__OPC_MOD, "/mod" }, + /* 949 */ { ud_itab__949, UD_TAB__OPC_X87, "/x87" }, + /* 950 */ { ud_itab__950, UD_TAB__OPC_MOD, "/mod" }, + /* 951 */ { ud_itab__951, UD_TAB__OPC_MOD, "/mod" }, + /* 952 */ { ud_itab__952, UD_TAB__OPC_MOD, "/mod" }, + /* 953 */ { ud_itab__953, UD_TAB__OPC_MOD, "/mod" }, + /* 954 */ { ud_itab__954, UD_TAB__OPC_MOD, "/mod" }, + /* 955 */ { ud_itab__955, UD_TAB__OPC_MOD, "/mod" }, + /* 956 */ { ud_itab__956, UD_TAB__OPC_MOD, "/mod" }, + /* 957 */ { ud_itab__957, UD_TAB__OPC_MOD, "/mod" }, + /* 958 */ { ud_itab__958, UD_TAB__OPC_MOD, "/mod" }, + /* 959 */ { ud_itab__959, UD_TAB__OPC_MOD, "/mod" }, + /* 960 */ { ud_itab__960, UD_TAB__OPC_MOD, "/mod" }, + /* 961 */ { ud_itab__961, UD_TAB__OPC_MOD, "/mod" }, + /* 962 */ { ud_itab__962, UD_TAB__OPC_MOD, "/mod" }, + /* 963 */ { ud_itab__963, UD_TAB__OPC_MOD, "/mod" }, + /* 964 */ { ud_itab__964, UD_TAB__OPC_MOD, "/mod" }, + /* 965 */ { ud_itab__965, UD_TAB__OPC_MOD, "/mod" }, + /* 966 */ { ud_itab__966, UD_TAB__OPC_MOD, "/mod" }, + /* 967 */ { ud_itab__967, UD_TAB__OPC_MOD, "/mod" }, + /* 968 */ { ud_itab__968, UD_TAB__OPC_MOD, "/mod" }, + /* 969 */ { ud_itab__969, UD_TAB__OPC_MOD, "/mod" }, + /* 970 */ { ud_itab__970, UD_TAB__OPC_MOD, "/mod" }, + /* 971 */ { ud_itab__971, UD_TAB__OPC_MOD, "/mod" }, + /* 972 */ { ud_itab__972, UD_TAB__OPC_MOD, "/mod" }, + /* 973 */ { ud_itab__973, UD_TAB__OPC_MOD, "/mod" }, + /* 974 */ { ud_itab__974, UD_TAB__OPC_MOD, "/mod" }, + /* 975 */ { ud_itab__975, UD_TAB__OPC_MOD, "/mod" }, + /* 976 */ { ud_itab__976, UD_TAB__OPC_MOD, "/mod" }, + /* 977 */ { ud_itab__977, UD_TAB__OPC_MOD, "/mod" }, + /* 978 */ { ud_itab__978, UD_TAB__OPC_MOD, "/mod" }, + /* 979 */ { ud_itab__979, UD_TAB__OPC_MOD, "/mod" }, + /* 980 */ { ud_itab__980, UD_TAB__OPC_MOD, "/mod" }, + /* 981 */ { ud_itab__981, UD_TAB__OPC_MOD, "/mod" }, + /* 982 */ { ud_itab__982, UD_TAB__OPC_MOD, "/mod" }, + /* 983 */ { ud_itab__983, UD_TAB__OPC_MOD, "/mod" }, + /* 984 */ { ud_itab__984, UD_TAB__OPC_MOD, "/mod" }, + /* 985 */ { ud_itab__985, UD_TAB__OPC_MOD, "/mod" }, + /* 986 */ { ud_itab__986, UD_TAB__OPC_MOD, "/mod" }, + /* 987 */ { ud_itab__987, UD_TAB__OPC_MOD, "/mod" }, + /* 988 */ { ud_itab__988, UD_TAB__OPC_MOD, "/mod" }, + /* 989 */ { ud_itab__989, UD_TAB__OPC_MOD, "/mod" }, + /* 990 */ { ud_itab__990, UD_TAB__OPC_MOD, "/mod" }, + /* 991 */ { ud_itab__991, UD_TAB__OPC_MOD, "/mod" }, + /* 992 */ { ud_itab__992, UD_TAB__OPC_MOD, "/mod" }, + /* 993 */ { ud_itab__993, UD_TAB__OPC_MOD, "/mod" }, + /* 994 */ { ud_itab__994, UD_TAB__OPC_MOD, "/mod" }, + /* 995 */ { ud_itab__995, UD_TAB__OPC_MOD, "/mod" }, + /* 996 */ { ud_itab__996, UD_TAB__OPC_MOD, "/mod" }, + /* 997 */ { ud_itab__997, UD_TAB__OPC_MOD, "/mod" }, + /* 998 */ { ud_itab__998, UD_TAB__OPC_MOD, "/mod" }, + /* 999 */ { ud_itab__999, UD_TAB__OPC_REG, "/reg" }, + /* 1000 */ { ud_itab__1000, UD_TAB__OPC_MOD, "/mod" }, + /* 1001 */ { ud_itab__1001, UD_TAB__OPC_MOD, "/mod" }, + /* 1002 */ { ud_itab__1002, UD_TAB__OPC_MOD, "/mod" }, + /* 1003 */ { ud_itab__1003, UD_TAB__OPC_MOD, "/mod" }, + /* 1004 */ { ud_itab__1004, UD_TAB__OPC_MOD, "/mod" }, + /* 1005 */ { ud_itab__1005, UD_TAB__OPC_MOD, "/mod" }, + /* 1006 */ { ud_itab__1006, UD_TAB__OPC_MOD, "/mod" }, + /* 1007 */ { ud_itab__1007, UD_TAB__OPC_MOD, "/mod" }, + /* 1008 */ { ud_itab__1008, UD_TAB__OPC_X87, "/x87" }, + /* 1009 */ { ud_itab__1009, UD_TAB__OPC_MOD, "/mod" }, + /* 1010 */ { ud_itab__1010, UD_TAB__OPC_MOD, "/mod" }, + /* 1011 */ { ud_itab__1011, UD_TAB__OPC_MOD, "/mod" }, + /* 1012 */ { ud_itab__1012, UD_TAB__OPC_MOD, "/mod" }, + /* 1013 */ { ud_itab__1013, UD_TAB__OPC_MOD, "/mod" }, + /* 1014 */ { ud_itab__1014, UD_TAB__OPC_MOD, "/mod" }, + /* 1015 */ { ud_itab__1015, UD_TAB__OPC_MOD, "/mod" }, + /* 1016 */ { ud_itab__1016, UD_TAB__OPC_MOD, "/mod" }, + /* 1017 */ { ud_itab__1017, UD_TAB__OPC_MOD, "/mod" }, + /* 1018 */ { ud_itab__1018, UD_TAB__OPC_MOD, "/mod" }, + /* 1019 */ { ud_itab__1019, UD_TAB__OPC_MOD, "/mod" }, + /* 1020 */ { ud_itab__1020, UD_TAB__OPC_MOD, "/mod" }, + /* 1021 */ { ud_itab__1021, UD_TAB__OPC_MOD, "/mod" }, + /* 1022 */ { ud_itab__1022, UD_TAB__OPC_MOD, "/mod" }, + /* 1023 */ { ud_itab__1023, UD_TAB__OPC_MOD, "/mod" }, + /* 1024 */ { ud_itab__1024, UD_TAB__OPC_MOD, "/mod" }, + /* 1025 */ { ud_itab__1025, UD_TAB__OPC_MOD, "/mod" }, + /* 1026 */ { ud_itab__1026, UD_TAB__OPC_MOD, "/mod" }, + /* 1027 */ { ud_itab__1027, UD_TAB__OPC_MOD, "/mod" }, + /* 1028 */ { ud_itab__1028, UD_TAB__OPC_MOD, "/mod" }, + /* 1029 */ { ud_itab__1029, UD_TAB__OPC_MOD, "/mod" }, + /* 1030 */ { ud_itab__1030, UD_TAB__OPC_MOD, "/mod" }, + /* 1031 */ { ud_itab__1031, UD_TAB__OPC_MOD, "/mod" }, + /* 1032 */ { ud_itab__1032, UD_TAB__OPC_MOD, "/mod" }, + /* 1033 */ { ud_itab__1033, UD_TAB__OPC_MOD, "/mod" }, + /* 1034 */ { ud_itab__1034, UD_TAB__OPC_MOD, "/mod" }, + /* 1035 */ { ud_itab__1035, UD_TAB__OPC_MOD, "/mod" }, + /* 1036 */ { ud_itab__1036, UD_TAB__OPC_MOD, "/mod" }, + /* 1037 */ { ud_itab__1037, UD_TAB__OPC_MOD, "/mod" }, + /* 1038 */ { ud_itab__1038, UD_TAB__OPC_MOD, "/mod" }, + /* 1039 */ { ud_itab__1039, UD_TAB__OPC_MOD, "/mod" }, + /* 1040 */ { ud_itab__1040, UD_TAB__OPC_MOD, "/mod" }, + /* 1041 */ { ud_itab__1041, UD_TAB__OPC_MOD, "/mod" }, + /* 1042 */ { ud_itab__1042, UD_TAB__OPC_MOD, "/mod" }, + /* 1043 */ { ud_itab__1043, UD_TAB__OPC_MOD, "/mod" }, + /* 1044 */ { ud_itab__1044, UD_TAB__OPC_MOD, "/mod" }, + /* 1045 */ { ud_itab__1045, UD_TAB__OPC_MOD, "/mod" }, + /* 1046 */ { ud_itab__1046, UD_TAB__OPC_MOD, "/mod" }, + /* 1047 */ { ud_itab__1047, UD_TAB__OPC_MOD, "/mod" }, + /* 1048 */ { ud_itab__1048, UD_TAB__OPC_MOD, "/mod" }, + /* 1049 */ { ud_itab__1049, UD_TAB__OPC_MOD, "/mod" }, + /* 1050 */ { ud_itab__1050, UD_TAB__OPC_MOD, "/mod" }, + /* 1051 */ { ud_itab__1051, UD_TAB__OPC_MOD, "/mod" }, + /* 1052 */ { ud_itab__1052, UD_TAB__OPC_MOD, "/mod" }, + /* 1053 */ { ud_itab__1053, UD_TAB__OPC_MOD, "/mod" }, + /* 1054 */ { ud_itab__1054, UD_TAB__OPC_MOD, "/mod" }, + /* 1055 */ { ud_itab__1055, UD_TAB__OPC_MOD, "/mod" }, + /* 1056 */ { ud_itab__1056, UD_TAB__OPC_MOD, "/mod" }, + /* 1057 */ { ud_itab__1057, UD_TAB__OPC_MOD, "/mod" }, + /* 1058 */ { ud_itab__1058, UD_TAB__OPC_MOD, "/mod" }, + /* 1059 */ { ud_itab__1059, UD_TAB__OPC_MOD, "/mod" }, + /* 1060 */ { ud_itab__1060, UD_TAB__OPC_MOD, "/mod" }, + /* 1061 */ { ud_itab__1061, UD_TAB__OPC_MOD, "/mod" }, + /* 1062 */ { ud_itab__1062, UD_TAB__OPC_MOD, "/mod" }, + /* 1063 */ { ud_itab__1063, UD_TAB__OPC_MOD, "/mod" }, + /* 1064 */ { ud_itab__1064, UD_TAB__OPC_MOD, "/mod" }, + /* 1065 */ { ud_itab__1065, UD_TAB__OPC_MOD, "/mod" }, + /* 1066 */ { ud_itab__1066, UD_TAB__OPC_MOD, "/mod" }, + /* 1067 */ { ud_itab__1067, UD_TAB__OPC_REG, "/reg" }, + /* 1068 */ { ud_itab__1068, UD_TAB__OPC_MOD, "/mod" }, + /* 1069 */ { ud_itab__1069, UD_TAB__OPC_MOD, "/mod" }, + /* 1070 */ { ud_itab__1070, UD_TAB__OPC_MOD, "/mod" }, + /* 1071 */ { ud_itab__1071, UD_TAB__OPC_MOD, "/mod" }, + /* 1072 */ { ud_itab__1072, UD_TAB__OPC_MOD, "/mod" }, + /* 1073 */ { ud_itab__1073, UD_TAB__OPC_MOD, "/mod" }, + /* 1074 */ { ud_itab__1074, UD_TAB__OPC_MOD, "/mod" }, + /* 1075 */ { ud_itab__1075, UD_TAB__OPC_MOD, "/mod" }, + /* 1076 */ { ud_itab__1076, UD_TAB__OPC_X87, "/x87" }, + /* 1077 */ { ud_itab__1077, UD_TAB__OPC_MOD, "/mod" }, + /* 1078 */ { ud_itab__1078, UD_TAB__OPC_MOD, "/mod" }, + /* 1079 */ { ud_itab__1079, UD_TAB__OPC_MOD, "/mod" }, + /* 1080 */ { ud_itab__1080, UD_TAB__OPC_MOD, "/mod" }, + /* 1081 */ { ud_itab__1081, UD_TAB__OPC_MOD, "/mod" }, + /* 1082 */ { ud_itab__1082, UD_TAB__OPC_MOD, "/mod" }, + /* 1083 */ { ud_itab__1083, UD_TAB__OPC_MOD, "/mod" }, + /* 1084 */ { ud_itab__1084, UD_TAB__OPC_MOD, "/mod" }, + /* 1085 */ { ud_itab__1085, UD_TAB__OPC_MOD, "/mod" }, + /* 1086 */ { ud_itab__1086, UD_TAB__OPC_MOD, "/mod" }, + /* 1087 */ { ud_itab__1087, UD_TAB__OPC_MOD, "/mod" }, + /* 1088 */ { ud_itab__1088, UD_TAB__OPC_MOD, "/mod" }, + /* 1089 */ { ud_itab__1089, UD_TAB__OPC_MOD, "/mod" }, + /* 1090 */ { ud_itab__1090, UD_TAB__OPC_MOD, "/mod" }, + /* 1091 */ { ud_itab__1091, UD_TAB__OPC_MOD, "/mod" }, + /* 1092 */ { ud_itab__1092, UD_TAB__OPC_MOD, "/mod" }, + /* 1093 */ { ud_itab__1093, UD_TAB__OPC_MOD, "/mod" }, + /* 1094 */ { ud_itab__1094, UD_TAB__OPC_MOD, "/mod" }, + /* 1095 */ { ud_itab__1095, UD_TAB__OPC_MOD, "/mod" }, + /* 1096 */ { ud_itab__1096, UD_TAB__OPC_MOD, "/mod" }, + /* 1097 */ { ud_itab__1097, UD_TAB__OPC_MOD, "/mod" }, + /* 1098 */ { ud_itab__1098, UD_TAB__OPC_MOD, "/mod" }, + /* 1099 */ { ud_itab__1099, UD_TAB__OPC_MOD, "/mod" }, + /* 1100 */ { ud_itab__1100, UD_TAB__OPC_MOD, "/mod" }, + /* 1101 */ { ud_itab__1101, UD_TAB__OPC_MOD, "/mod" }, + /* 1102 */ { ud_itab__1102, UD_TAB__OPC_MOD, "/mod" }, + /* 1103 */ { ud_itab__1103, UD_TAB__OPC_MOD, "/mod" }, + /* 1104 */ { ud_itab__1104, UD_TAB__OPC_MOD, "/mod" }, + /* 1105 */ { ud_itab__1105, UD_TAB__OPC_MOD, "/mod" }, + /* 1106 */ { ud_itab__1106, UD_TAB__OPC_MOD, "/mod" }, + /* 1107 */ { ud_itab__1107, UD_TAB__OPC_MOD, "/mod" }, + /* 1108 */ { ud_itab__1108, UD_TAB__OPC_MOD, "/mod" }, + /* 1109 */ { ud_itab__1109, UD_TAB__OPC_MOD, "/mod" }, + /* 1110 */ { ud_itab__1110, UD_TAB__OPC_MOD, "/mod" }, + /* 1111 */ { ud_itab__1111, UD_TAB__OPC_MOD, "/mod" }, + /* 1112 */ { ud_itab__1112, UD_TAB__OPC_MOD, "/mod" }, + /* 1113 */ { ud_itab__1113, UD_TAB__OPC_MOD, "/mod" }, + /* 1114 */ { ud_itab__1114, UD_TAB__OPC_MOD, "/mod" }, + /* 1115 */ { ud_itab__1115, UD_TAB__OPC_MOD, "/mod" }, + /* 1116 */ { ud_itab__1116, UD_TAB__OPC_MOD, "/mod" }, + /* 1117 */ { ud_itab__1117, UD_TAB__OPC_MOD, "/mod" }, + /* 1118 */ { ud_itab__1118, UD_TAB__OPC_MOD, "/mod" }, + /* 1119 */ { ud_itab__1119, UD_TAB__OPC_MOD, "/mod" }, + /* 1120 */ { ud_itab__1120, UD_TAB__OPC_MOD, "/mod" }, + /* 1121 */ { ud_itab__1121, UD_TAB__OPC_MOD, "/mod" }, + /* 1122 */ { ud_itab__1122, UD_TAB__OPC_MOD, "/mod" }, + /* 1123 */ { ud_itab__1123, UD_TAB__OPC_MOD, "/mod" }, + /* 1124 */ { ud_itab__1124, UD_TAB__OPC_MOD, "/mod" }, + /* 1125 */ { ud_itab__1125, UD_TAB__OPC_MOD, "/mod" }, + /* 1126 */ { ud_itab__1126, UD_TAB__OPC_ASIZE, "/a" }, + /* 1127 */ { ud_itab__1127, UD_TAB__OPC_MODE, "/m" }, + /* 1128 */ { ud_itab__1128, UD_TAB__OPC_REG, "/reg" }, + /* 1129 */ { ud_itab__1129, UD_TAB__OPC_REG, "/reg" }, + /* 1130 */ { ud_itab__1130, UD_TAB__OPC_REG, "/reg" }, + /* 1131 */ { ud_itab__1131, UD_TAB__OPC_REG, "/reg" }, + /* 1132 */ { ud_itab__1132, UD_TAB__OPC_MODE, "/m" }, +}; + +/* itab entry operand definitions (for readability) */ +#define O_AL { OP_AL, SZ_B } +#define O_AX { OP_AX, SZ_W } +#define O_Av { OP_A, SZ_V } +#define O_C { OP_C, SZ_NA } +#define O_CL { OP_CL, SZ_B } +#define O_CS { OP_CS, SZ_NA } +#define O_CX { OP_CX, SZ_W } +#define O_D { OP_D, SZ_NA } +#define O_DL { OP_DL, SZ_B } +#define O_DS { OP_DS, SZ_NA } +#define O_DX { OP_DX, SZ_W } +#define O_E { OP_E, SZ_NA } +#define O_ES { OP_ES, SZ_NA } +#define O_Eb { OP_E, SZ_B } +#define O_Ed { OP_E, SZ_D } +#define O_Eq { OP_E, SZ_Q } +#define O_Ev { OP_E, SZ_V } +#define O_Ew { OP_E, SZ_W } +#define O_Ey { OP_E, SZ_Y } +#define O_Ez { OP_E, SZ_Z } +#define O_FS { OP_FS, SZ_NA } +#define O_Fv { OP_F, SZ_V } +#define O_G { OP_G, SZ_NA } +#define O_GS { OP_GS, SZ_NA } +#define O_Gb { OP_G, SZ_B } +#define O_Gd { OP_G, SZ_D } +#define O_Gq { OP_G, SZ_Q } +#define O_Gv { OP_G, SZ_V } +#define O_Gw { OP_G, SZ_W } +#define O_Gy { OP_G, SZ_Y } +#define O_Gz { OP_G, SZ_Z } +#define O_I1 { OP_I1, SZ_NA } +#define O_I3 { OP_I3, SZ_NA } +#define O_Ib { OP_I, SZ_B } +#define O_Iv { OP_I, SZ_V } +#define O_Iw { OP_I, SZ_W } +#define O_Iz { OP_I, SZ_Z } +#define O_Jb { OP_J, SZ_B } +#define O_Jv { OP_J, SZ_V } +#define O_Jz { OP_J, SZ_Z } +#define O_M { OP_M, SZ_NA } +#define O_Mb { OP_M, SZ_B } +#define O_MbRd { OP_MR, SZ_BD } +#define O_MbRv { OP_MR, SZ_BV } +#define O_Md { OP_M, SZ_D } +#define O_MdRy { OP_MR, SZ_DY } +#define O_MdU { OP_MU, SZ_DO } +#define O_Mo { OP_M, SZ_O } +#define O_Mq { OP_M, SZ_Q } +#define O_MqU { OP_MU, SZ_QO } +#define O_Ms { OP_M, SZ_W } +#define O_Mt { OP_M, SZ_T } +#define O_Mv { OP_M, SZ_V } +#define O_Mw { OP_M, SZ_W } +#define O_MwRd { OP_MR, SZ_WD } +#define O_MwRv { OP_MR, SZ_WV } +#define O_MwRy { OP_MR, SZ_WY } +#define O_MwU { OP_MU, SZ_WO } +#define O_N { OP_N, SZ_Q } +#define O_NONE { OP_NONE, SZ_NA } +#define O_Ob { OP_O, SZ_B } +#define O_Ov { OP_O, SZ_V } +#define O_Ow { OP_O, SZ_W } +#define O_P { OP_P, SZ_Q } +#define O_Q { OP_Q, SZ_Q } +#define O_R { OP_R, SZ_RDQ } +#define O_R0b { OP_R0, SZ_B } +#define O_R0v { OP_R0, SZ_V } +#define O_R0w { OP_R0, SZ_W } +#define O_R0y { OP_R0, SZ_Y } +#define O_R0z { OP_R0, SZ_Z } +#define O_R1b { OP_R1, SZ_B } +#define O_R1v { OP_R1, SZ_V } +#define O_R1w { OP_R1, SZ_W } +#define O_R1y { OP_R1, SZ_Y } +#define O_R1z { OP_R1, SZ_Z } +#define O_R2b { OP_R2, SZ_B } +#define O_R2v { OP_R2, SZ_V } +#define O_R2w { OP_R2, SZ_W } +#define O_R2y { OP_R2, SZ_Y } +#define O_R2z { OP_R2, SZ_Z } +#define O_R3b { OP_R3, SZ_B } +#define O_R3v { OP_R3, SZ_V } +#define O_R3w { OP_R3, SZ_W } +#define O_R3y { OP_R3, SZ_Y } +#define O_R3z { OP_R3, SZ_Z } +#define O_R4b { OP_R4, SZ_B } +#define O_R4v { OP_R4, SZ_V } +#define O_R4w { OP_R4, SZ_W } +#define O_R4y { OP_R4, SZ_Y } +#define O_R4z { OP_R4, SZ_Z } +#define O_R5b { OP_R5, SZ_B } +#define O_R5v { OP_R5, SZ_V } +#define O_R5w { OP_R5, SZ_W } +#define O_R5y { OP_R5, SZ_Y } +#define O_R5z { OP_R5, SZ_Z } +#define O_R6b { OP_R6, SZ_B } +#define O_R6v { OP_R6, SZ_V } +#define O_R6w { OP_R6, SZ_W } +#define O_R6y { OP_R6, SZ_Y } +#define O_R6z { OP_R6, SZ_Z } +#define O_R7b { OP_R7, SZ_B } +#define O_R7v { OP_R7, SZ_V } +#define O_R7w { OP_R7, SZ_W } +#define O_R7y { OP_R7, SZ_Y } +#define O_R7z { OP_R7, SZ_Z } +#define O_S { OP_S, SZ_NA } +#define O_SS { OP_SS, SZ_NA } +#define O_ST0 { OP_ST0, SZ_NA } +#define O_ST1 { OP_ST1, SZ_NA } +#define O_ST2 { OP_ST2, SZ_NA } +#define O_ST3 { OP_ST3, SZ_NA } +#define O_ST4 { OP_ST4, SZ_NA } +#define O_ST5 { OP_ST5, SZ_NA } +#define O_ST6 { OP_ST6, SZ_NA } +#define O_ST7 { OP_ST7, SZ_NA } +#define O_U { OP_U, SZ_O } +#define O_V { OP_V, SZ_O } +#define O_W { OP_W, SZ_O } +#define O_eAX { OP_eAX, SZ_Z } +#define O_eCX { OP_eCX, SZ_Z } +#define O_eDX { OP_eDX, SZ_Z } +#define O_rAX { OP_rAX, SZ_V } +#define O_rCX { OP_rCX, SZ_V } +#define O_rDX { OP_rDX, SZ_V } +#define O_sIb { OP_sI, SZ_B } +#define O_sIv { OP_sI, SZ_V } +#define O_sIz { OP_sI, SZ_Z } + +const struct ud_itab_entry ud_itab[] = { + /* 0000 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0001 */ { UD_Iadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0002 */ { UD_Iadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0003 */ { UD_Iadd, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0004 */ { UD_Iadd, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0005 */ { UD_Iadd, O_AL, O_Ib, O_NONE, P_none }, + /* 0006 */ { UD_Iadd, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0007 */ { UD_Ipush, O_ES, O_NONE, O_NONE, P_inv64 }, + /* 0008 */ { UD_Ipop, O_ES, O_NONE, O_NONE, P_inv64 }, + /* 0009 */ { UD_Ior, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0010 */ { UD_Ior, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0011 */ { UD_Ior, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0012 */ { UD_Ior, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0013 */ { UD_Ior, O_AL, O_Ib, O_NONE, P_none }, + /* 0014 */ { UD_Ior, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0015 */ { UD_Ipush, O_CS, O_NONE, O_NONE, P_inv64 }, + /* 0016 */ { UD_Isldt, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0017 */ { UD_Istr, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0018 */ { UD_Illdt, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0019 */ { UD_Iltr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0020 */ { UD_Iverr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0021 */ { UD_Iverw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0022 */ { UD_Isgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0023 */ { UD_Isidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0024 */ { UD_Ilgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0025 */ { UD_Ilidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0026 */ { UD_Ismsw, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0027 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0028 */ { UD_Iinvlpg, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0029 */ { UD_Ivmcall, O_NONE, O_NONE, O_NONE, P_none }, + /* 0030 */ { UD_Ivmlaunch, O_NONE, O_NONE, O_NONE, P_none }, + /* 0031 */ { UD_Ivmresume, O_NONE, O_NONE, O_NONE, P_none }, + /* 0032 */ { UD_Ivmxoff, O_NONE, O_NONE, O_NONE, P_none }, + /* 0033 */ { UD_Imonitor, O_NONE, O_NONE, O_NONE, P_none }, + /* 0034 */ { UD_Imwait, O_NONE, O_NONE, O_NONE, P_none }, + /* 0035 */ { UD_Ixgetbv, O_NONE, O_NONE, O_NONE, P_none }, + /* 0036 */ { UD_Ixsetbv, O_NONE, O_NONE, O_NONE, P_none }, + /* 0037 */ { UD_Ivmrun, O_NONE, O_NONE, O_NONE, P_none }, + /* 0038 */ { UD_Ivmmcall, O_NONE, O_NONE, O_NONE, P_none }, + /* 0039 */ { UD_Ivmload, O_NONE, O_NONE, O_NONE, P_none }, + /* 0040 */ { UD_Ivmsave, O_NONE, O_NONE, O_NONE, P_none }, + /* 0041 */ { UD_Istgi, O_NONE, O_NONE, O_NONE, P_none }, + /* 0042 */ { UD_Iclgi, O_NONE, O_NONE, O_NONE, P_none }, + /* 0043 */ { UD_Iskinit, O_NONE, O_NONE, O_NONE, P_none }, + /* 0044 */ { UD_Iinvlpga, O_NONE, O_NONE, O_NONE, P_none }, + /* 0045 */ { UD_Ismsw, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0046 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0047 */ { UD_Iswapgs, O_NONE, O_NONE, O_NONE, P_none }, + /* 0048 */ { UD_Irdtscp, O_NONE, O_NONE, O_NONE, P_none }, + /* 0049 */ { UD_Ilar, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0050 */ { UD_Ilsl, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0051 */ { UD_Isyscall, O_NONE, O_NONE, O_NONE, P_none }, + /* 0052 */ { UD_Iclts, O_NONE, O_NONE, O_NONE, P_none }, + /* 0053 */ { UD_Isysret, O_NONE, O_NONE, O_NONE, P_none }, + /* 0054 */ { UD_Iinvd, O_NONE, O_NONE, O_NONE, P_none }, + /* 0055 */ { UD_Iwbinvd, O_NONE, O_NONE, O_NONE, P_none }, + /* 0056 */ { UD_Iud2, O_NONE, O_NONE, O_NONE, P_none }, + /* 0057 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0058 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0059 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0060 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0061 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0062 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0063 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0064 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0065 */ { UD_Ifemms, O_NONE, O_NONE, O_NONE, P_none }, + /* 0066 */ { UD_Ipi2fw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0067 */ { UD_Ipi2fd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0068 */ { UD_Ipf2iw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0069 */ { UD_Ipf2id, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0070 */ { UD_Ipfnacc, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0071 */ { UD_Ipfpnacc, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0072 */ { UD_Ipfcmpge, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0073 */ { UD_Ipfmin, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0074 */ { UD_Ipfrcp, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0075 */ { UD_Ipfrsqrt, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0076 */ { UD_Ipfsub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0077 */ { UD_Ipfadd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0078 */ { UD_Ipfcmpgt, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0079 */ { UD_Ipfmax, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0080 */ { UD_Ipfrcpit1, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0081 */ { UD_Ipfrsqit1, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0082 */ { UD_Ipfsubr, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0083 */ { UD_Ipfacc, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0084 */ { UD_Ipfcmpeq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0085 */ { UD_Ipfmul, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0086 */ { UD_Ipfrcpit2, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0087 */ { UD_Ipmulhrw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0088 */ { UD_Ipswapd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0089 */ { UD_Ipavgusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0090 */ { UD_Imovups, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0091 */ { UD_Imovsd, O_V, O_W, O_NONE, P_str|P_aso|P_rexr|P_rexx|P_rexb }, + /* 0092 */ { UD_Imovss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0093 */ { UD_Imovupd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0094 */ { UD_Imovups, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0095 */ { UD_Imovsd, O_W, O_V, O_NONE, P_str|P_aso|P_rexr|P_rexx|P_rexb }, + /* 0096 */ { UD_Imovss, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0097 */ { UD_Imovupd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0098 */ { UD_Imovlps, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0099 */ { UD_Imovddup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0100 */ { UD_Imovsldup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0101 */ { UD_Imovlpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0102 */ { UD_Imovhlps, O_V, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0103 */ { UD_Imovddup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0104 */ { UD_Imovsldup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0105 */ { UD_Imovlps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0106 */ { UD_Imovlpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0107 */ { UD_Iunpcklps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0108 */ { UD_Iunpcklpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0109 */ { UD_Iunpckhps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0110 */ { UD_Iunpckhpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0111 */ { UD_Imovhps, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0112 */ { UD_Imovshdup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0113 */ { UD_Imovhpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0114 */ { UD_Imovlhps, O_V, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0115 */ { UD_Imovshdup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0116 */ { UD_Imovhps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0117 */ { UD_Imovhpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0118 */ { UD_Iprefetchnta, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0119 */ { UD_Iprefetcht0, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0120 */ { UD_Iprefetcht1, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0121 */ { UD_Iprefetcht2, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0122 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0123 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0124 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0125 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0126 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0127 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0128 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0129 */ { UD_Imov, O_R, O_C, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0130 */ { UD_Imov, O_R, O_D, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0131 */ { UD_Imov, O_C, O_R, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0132 */ { UD_Imov, O_D, O_R, O_NONE, P_rexr|P_rexw|P_rexb }, + /* 0133 */ { UD_Imovaps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0134 */ { UD_Imovapd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0135 */ { UD_Imovaps, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0136 */ { UD_Imovapd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0137 */ { UD_Icvtpi2ps, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0138 */ { UD_Icvtsi2sd, O_V, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0139 */ { UD_Icvtsi2ss, O_V, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0140 */ { UD_Icvtpi2pd, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0141 */ { UD_Imovntps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0142 */ { UD_Imovntpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0143 */ { UD_Icvttps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0144 */ { UD_Icvttsd2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0145 */ { UD_Icvttss2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0146 */ { UD_Icvttpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0147 */ { UD_Icvtps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0148 */ { UD_Icvtsd2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0149 */ { UD_Icvtss2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0150 */ { UD_Icvtpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0151 */ { UD_Iucomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0152 */ { UD_Iucomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0153 */ { UD_Icomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0154 */ { UD_Icomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0155 */ { UD_Iwrmsr, O_NONE, O_NONE, O_NONE, P_none }, + /* 0156 */ { UD_Irdtsc, O_NONE, O_NONE, O_NONE, P_none }, + /* 0157 */ { UD_Irdmsr, O_NONE, O_NONE, O_NONE, P_none }, + /* 0158 */ { UD_Irdpmc, O_NONE, O_NONE, O_NONE, P_none }, + /* 0159 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, P_none }, + /* 0160 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, P_none }, + /* 0161 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, P_none }, + /* 0162 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, P_none }, + /* 0163 */ { UD_Igetsec, O_NONE, O_NONE, O_NONE, P_none }, + /* 0164 */ { UD_Ipshufb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0165 */ { UD_Ipshufb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0166 */ { UD_Iphaddw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0167 */ { UD_Iphaddw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0168 */ { UD_Iphaddd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0169 */ { UD_Iphaddd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0170 */ { UD_Iphaddsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0171 */ { UD_Iphaddsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0172 */ { UD_Ipmaddubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0173 */ { UD_Ipmaddubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0174 */ { UD_Iphsubw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0175 */ { UD_Iphsubw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0176 */ { UD_Iphsubd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0177 */ { UD_Iphsubd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0178 */ { UD_Iphsubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0179 */ { UD_Iphsubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0180 */ { UD_Ipsignb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0181 */ { UD_Ipsignb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0182 */ { UD_Ipsignw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0183 */ { UD_Ipsignw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0184 */ { UD_Ipsignd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0185 */ { UD_Ipsignd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0186 */ { UD_Ipmulhrsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0187 */ { UD_Ipmulhrsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0188 */ { UD_Ipblendvb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0189 */ { UD_Iblendvps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0190 */ { UD_Iblendvpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0191 */ { UD_Iptest, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0192 */ { UD_Ipabsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0193 */ { UD_Ipabsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0194 */ { UD_Ipabsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0195 */ { UD_Ipabsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0196 */ { UD_Ipabsd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0197 */ { UD_Ipabsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0198 */ { UD_Ipmovsxbw, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0199 */ { UD_Ipmovsxbd, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0200 */ { UD_Ipmovsxbq, O_V, O_MwU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0201 */ { UD_Ipmovsxwd, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0202 */ { UD_Ipmovsxwq, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0203 */ { UD_Ipmovsxdq, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0204 */ { UD_Ipmuldq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0205 */ { UD_Ipcmpeqq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0206 */ { UD_Imovntdqa, O_V, O_Mo, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0207 */ { UD_Ipackusdw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0208 */ { UD_Ipmovzxbw, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0209 */ { UD_Ipmovzxbd, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0210 */ { UD_Ipmovzxbq, O_V, O_MwU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0211 */ { UD_Ipmovzxwd, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0212 */ { UD_Ipmovzxwq, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0213 */ { UD_Ipmovzxdq, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0214 */ { UD_Ipcmpgtq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0215 */ { UD_Ipminsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0216 */ { UD_Ipminsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0217 */ { UD_Ipminuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0218 */ { UD_Ipminud, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0219 */ { UD_Ipmaxsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0220 */ { UD_Ipmaxsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0221 */ { UD_Ipmaxuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0222 */ { UD_Ipmaxud, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0223 */ { UD_Ipmulld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0224 */ { UD_Iphminposuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0225 */ { UD_Iinvept, O_Gq, O_Mo, O_NONE, P_none }, + /* 0226 */ { UD_Iinvvpid, O_Gq, O_Mo, O_NONE, P_none }, + /* 0227 */ { UD_Iaesimc, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0228 */ { UD_Iaesenc, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0229 */ { UD_Iaesenclast, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0230 */ { UD_Iaesdec, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0231 */ { UD_Iaesdeclast, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0232 */ { UD_Imovbe, O_Gv, O_Mv, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0233 */ { UD_Icrc32, O_Gy, O_Eb, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0234 */ { UD_Imovbe, O_Mv, O_Gv, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0235 */ { UD_Icrc32, O_Gy, O_Ev, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0236 */ { UD_Iroundps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0237 */ { UD_Iroundpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0238 */ { UD_Iroundss, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0239 */ { UD_Iroundsd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0240 */ { UD_Iblendps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0241 */ { UD_Iblendpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0242 */ { UD_Ipblendw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0243 */ { UD_Ipalignr, O_P, O_Q, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0244 */ { UD_Ipalignr, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0245 */ { UD_Ipextrb, O_MbRv, O_V, O_Ib, P_aso|P_rexx|P_rexr|P_rexb|P_def64 }, + /* 0246 */ { UD_Ipextrw, O_MwRd, O_V, O_Ib, P_aso|P_rexx|P_rexr|P_rexb }, + /* 0247 */ { UD_Ipextrd, O_Ed, O_V, O_Ib, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, + /* 0248 */ { UD_Ipextrd, O_Ed, O_V, O_Ib, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, + /* 0249 */ { UD_Ipextrq, O_Eq, O_V, O_Ib, P_aso|P_rexr|P_rexw|P_rexb|P_def64 }, + /* 0250 */ { UD_Iextractps, O_MdRy, O_V, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0251 */ { UD_Ipinsrb, O_V, O_MbRd, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0252 */ { UD_Iinsertps, O_V, O_Md, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0253 */ { UD_Ipinsrd, O_V, O_Ed, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0254 */ { UD_Ipinsrd, O_V, O_Ed, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0255 */ { UD_Ipinsrq, O_V, O_Eq, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0256 */ { UD_Idpps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0257 */ { UD_Idppd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0258 */ { UD_Impsadbw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0259 */ { UD_Ipclmulqdq, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0260 */ { UD_Ipcmpestrm, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0261 */ { UD_Ipcmpestri, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0262 */ { UD_Ipcmpistrm, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0263 */ { UD_Ipcmpistri, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0264 */ { UD_Iaeskeygenassist, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0265 */ { UD_Icmovo, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0266 */ { UD_Icmovno, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0267 */ { UD_Icmovb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0268 */ { UD_Icmovae, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0269 */ { UD_Icmovz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0270 */ { UD_Icmovnz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0271 */ { UD_Icmovbe, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0272 */ { UD_Icmova, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0273 */ { UD_Icmovs, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0274 */ { UD_Icmovns, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0275 */ { UD_Icmovp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0276 */ { UD_Icmovnp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0277 */ { UD_Icmovl, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0278 */ { UD_Icmovge, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0279 */ { UD_Icmovle, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0280 */ { UD_Icmovg, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0281 */ { UD_Imovmskps, O_Gd, O_U, O_NONE, P_oso|P_rexr|P_rexb }, + /* 0282 */ { UD_Imovmskpd, O_Gd, O_U, O_NONE, P_oso|P_rexr|P_rexb }, + /* 0283 */ { UD_Isqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0284 */ { UD_Isqrtsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0285 */ { UD_Isqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0286 */ { UD_Isqrtpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0287 */ { UD_Irsqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0288 */ { UD_Irsqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0289 */ { UD_Ircpps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0290 */ { UD_Ircpss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0291 */ { UD_Iandps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0292 */ { UD_Iandpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0293 */ { UD_Iandnps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0294 */ { UD_Iandnpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0295 */ { UD_Iorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0296 */ { UD_Iorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0297 */ { UD_Ixorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0298 */ { UD_Ixorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0299 */ { UD_Iaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0300 */ { UD_Iaddsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0301 */ { UD_Iaddss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0302 */ { UD_Iaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0303 */ { UD_Imulps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0304 */ { UD_Imulsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0305 */ { UD_Imulss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0306 */ { UD_Imulpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0307 */ { UD_Icvtps2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0308 */ { UD_Icvtsd2ss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0309 */ { UD_Icvtss2sd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0310 */ { UD_Icvtpd2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0311 */ { UD_Icvtdq2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0312 */ { UD_Icvttps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0313 */ { UD_Icvtps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0314 */ { UD_Isubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0315 */ { UD_Isubsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0316 */ { UD_Isubss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0317 */ { UD_Isubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0318 */ { UD_Iminps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0319 */ { UD_Iminsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0320 */ { UD_Iminss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0321 */ { UD_Iminpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0322 */ { UD_Idivps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0323 */ { UD_Idivsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0324 */ { UD_Idivss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0325 */ { UD_Idivpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0326 */ { UD_Imaxps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0327 */ { UD_Imaxsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0328 */ { UD_Imaxss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0329 */ { UD_Imaxpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0330 */ { UD_Ipunpcklbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0331 */ { UD_Ipunpcklbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0332 */ { UD_Ipunpcklwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0333 */ { UD_Ipunpcklwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0334 */ { UD_Ipunpckldq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0335 */ { UD_Ipunpckldq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0336 */ { UD_Ipacksswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0337 */ { UD_Ipacksswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0338 */ { UD_Ipcmpgtb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0339 */ { UD_Ipcmpgtb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0340 */ { UD_Ipcmpgtw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0341 */ { UD_Ipcmpgtw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0342 */ { UD_Ipcmpgtd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0343 */ { UD_Ipcmpgtd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0344 */ { UD_Ipackuswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0345 */ { UD_Ipackuswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0346 */ { UD_Ipunpckhbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0347 */ { UD_Ipunpckhbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0348 */ { UD_Ipunpckhwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0349 */ { UD_Ipunpckhwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0350 */ { UD_Ipunpckhdq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0351 */ { UD_Ipunpckhdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0352 */ { UD_Ipackssdw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0353 */ { UD_Ipackssdw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0354 */ { UD_Ipunpcklqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0355 */ { UD_Ipunpckhqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0356 */ { UD_Imovd, O_P, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0357 */ { UD_Imovd, O_V, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0358 */ { UD_Imovq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0359 */ { UD_Imovdqu, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0360 */ { UD_Imovdqa, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0361 */ { UD_Ipshufw, O_P, O_Q, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0362 */ { UD_Ipshuflw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0363 */ { UD_Ipshufhw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0364 */ { UD_Ipshufd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0365 */ { UD_Ipsrlw, O_N, O_Ib, O_NONE, P_none }, + /* 0366 */ { UD_Ipsrlw, O_U, O_Ib, O_NONE, P_rexb }, + /* 0367 */ { UD_Ipsraw, O_N, O_Ib, O_NONE, P_none }, + /* 0368 */ { UD_Ipsraw, O_U, O_Ib, O_NONE, P_rexb }, + /* 0369 */ { UD_Ipsllw, O_N, O_Ib, O_NONE, P_none }, + /* 0370 */ { UD_Ipsllw, O_U, O_Ib, O_NONE, P_rexb }, + /* 0371 */ { UD_Ipsrld, O_N, O_Ib, O_NONE, P_none }, + /* 0372 */ { UD_Ipsrld, O_U, O_Ib, O_NONE, P_rexb }, + /* 0373 */ { UD_Ipsrad, O_N, O_Ib, O_NONE, P_none }, + /* 0374 */ { UD_Ipsrad, O_U, O_Ib, O_NONE, P_rexb }, + /* 0375 */ { UD_Ipslld, O_N, O_Ib, O_NONE, P_none }, + /* 0376 */ { UD_Ipslld, O_U, O_Ib, O_NONE, P_rexb }, + /* 0377 */ { UD_Ipsrlq, O_N, O_Ib, O_NONE, P_none }, + /* 0378 */ { UD_Ipsrlq, O_U, O_Ib, O_NONE, P_rexb }, + /* 0379 */ { UD_Ipsrldq, O_U, O_Ib, O_NONE, P_rexb }, + /* 0380 */ { UD_Ipsllq, O_N, O_Ib, O_NONE, P_none }, + /* 0381 */ { UD_Ipsllq, O_U, O_Ib, O_NONE, P_rexb }, + /* 0382 */ { UD_Ipslldq, O_U, O_Ib, O_NONE, P_rexb }, + /* 0383 */ { UD_Ipcmpeqb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0384 */ { UD_Ipcmpeqb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0385 */ { UD_Ipcmpeqw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0386 */ { UD_Ipcmpeqw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0387 */ { UD_Ipcmpeqd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0388 */ { UD_Ipcmpeqd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0389 */ { UD_Iemms, O_NONE, O_NONE, O_NONE, P_none }, + /* 0390 */ { UD_Ivmread, O_Ey, O_Gy, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 0391 */ { UD_Ivmwrite, O_Gy, O_Ey, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 0392 */ { UD_Ihaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0393 */ { UD_Ihaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0394 */ { UD_Ihsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0395 */ { UD_Ihsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0396 */ { UD_Imovd, O_Ey, O_P, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0397 */ { UD_Imovq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0398 */ { UD_Imovd, O_Ey, O_V, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0399 */ { UD_Imovq, O_Q, O_P, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0400 */ { UD_Imovdqu, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0401 */ { UD_Imovdqa, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0402 */ { UD_Ijo, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0403 */ { UD_Ijno, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0404 */ { UD_Ijb, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0405 */ { UD_Ijae, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0406 */ { UD_Ijz, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0407 */ { UD_Ijnz, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0408 */ { UD_Ijbe, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0409 */ { UD_Ija, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0410 */ { UD_Ijs, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0411 */ { UD_Ijns, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0412 */ { UD_Ijp, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0413 */ { UD_Ijnp, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0414 */ { UD_Ijl, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0415 */ { UD_Ijge, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0416 */ { UD_Ijle, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0417 */ { UD_Ijg, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0418 */ { UD_Iseto, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0419 */ { UD_Isetno, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0420 */ { UD_Isetb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0421 */ { UD_Isetae, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0422 */ { UD_Isetz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0423 */ { UD_Isetnz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0424 */ { UD_Isetbe, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0425 */ { UD_Iseta, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0426 */ { UD_Isets, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0427 */ { UD_Isetns, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0428 */ { UD_Isetp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0429 */ { UD_Isetnp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0430 */ { UD_Isetl, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0431 */ { UD_Isetge, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0432 */ { UD_Isetle, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0433 */ { UD_Isetg, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0434 */ { UD_Ipush, O_FS, O_NONE, O_NONE, P_none }, + /* 0435 */ { UD_Ipop, O_FS, O_NONE, O_NONE, P_none }, + /* 0436 */ { UD_Icpuid, O_NONE, O_NONE, O_NONE, P_none }, + /* 0437 */ { UD_Ibt, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0438 */ { UD_Ishld, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0439 */ { UD_Ishld, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0440 */ { UD_Imontmul, O_NONE, O_NONE, O_NONE, P_none }, + /* 0441 */ { UD_Ixsha1, O_NONE, O_NONE, O_NONE, P_none }, + /* 0442 */ { UD_Ixsha256, O_NONE, O_NONE, O_NONE, P_none }, + /* 0443 */ { UD_Ixstore, O_NONE, O_NONE, O_NONE, P_none }, + /* 0444 */ { UD_Ixcryptecb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0445 */ { UD_Ixcryptcbc, O_NONE, O_NONE, O_NONE, P_none }, + /* 0446 */ { UD_Ixcryptctr, O_NONE, O_NONE, O_NONE, P_none }, + /* 0447 */ { UD_Ixcryptcfb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0448 */ { UD_Ixcryptofb, O_NONE, O_NONE, O_NONE, P_none }, + /* 0449 */ { UD_Ipush, O_GS, O_NONE, O_NONE, P_none }, + /* 0450 */ { UD_Ipop, O_GS, O_NONE, O_NONE, P_none }, + /* 0451 */ { UD_Irsm, O_NONE, O_NONE, O_NONE, P_none }, + /* 0452 */ { UD_Ibts, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0453 */ { UD_Ishrd, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0454 */ { UD_Ishrd, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0455 */ { UD_Ifxsave, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0456 */ { UD_Ifxrstor, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0457 */ { UD_Ildmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0458 */ { UD_Istmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0459 */ { UD_Ixsave, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0460 */ { UD_Ixrstor, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0461 */ { UD_Iclflush, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0462 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0463 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0464 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0465 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0466 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0467 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0468 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0469 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0470 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0471 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0472 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0473 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0474 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0475 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0476 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0477 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0478 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0479 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0480 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0481 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0482 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0483 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0484 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0485 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, + /* 0486 */ { UD_Iimul, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0487 */ { UD_Icmpxchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0488 */ { UD_Icmpxchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0489 */ { UD_Ilss, O_Gv, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0490 */ { UD_Ibtr, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0491 */ { UD_Ilfs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0492 */ { UD_Ilgs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0493 */ { UD_Imovzx, O_Gv, O_Eb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0494 */ { UD_Imovzx, O_Gy, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0495 */ { UD_Ipopcnt, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, + /* 0496 */ { UD_Ibt, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0497 */ { UD_Ibts, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0498 */ { UD_Ibtr, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0499 */ { UD_Ibtc, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0500 */ { UD_Ibtc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0501 */ { UD_Ibsf, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0502 */ { UD_Ibsr, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0503 */ { UD_Imovsx, O_Gv, O_Eb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0504 */ { UD_Imovsx, O_Gy, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0505 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, + /* 0506 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0507 */ { UD_Icmpps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0508 */ { UD_Icmpsd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0509 */ { UD_Icmpss, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0510 */ { UD_Icmppd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0511 */ { UD_Imovnti, O_M, O_Gy, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0512 */ { UD_Ipinsrw, O_P, O_MwRy, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 0513 */ { UD_Ipinsrw, O_V, O_MwRy, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 0514 */ { UD_Ipextrw, O_Gd, O_N, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0515 */ { UD_Ipextrw, O_Gd, O_U, O_Ib, P_aso|P_rexr|P_rexb }, + /* 0516 */ { UD_Ishufps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0517 */ { UD_Ishufpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0518 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0519 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0520 */ { UD_Icmpxchg16b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0521 */ { UD_Ivmptrld, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0522 */ { UD_Ivmxon, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0523 */ { UD_Ivmclear, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0524 */ { UD_Ivmptrst, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0525 */ { UD_Ibswap, O_R0y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0526 */ { UD_Ibswap, O_R1y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0527 */ { UD_Ibswap, O_R2y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0528 */ { UD_Ibswap, O_R3y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0529 */ { UD_Ibswap, O_R4y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0530 */ { UD_Ibswap, O_R5y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0531 */ { UD_Ibswap, O_R6y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0532 */ { UD_Ibswap, O_R7y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0533 */ { UD_Iaddsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0534 */ { UD_Iaddsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0535 */ { UD_Ipsrlw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0536 */ { UD_Ipsrlw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0537 */ { UD_Ipsrld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0538 */ { UD_Ipsrld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0539 */ { UD_Ipsrlq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0540 */ { UD_Ipsrlq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0541 */ { UD_Ipaddq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0542 */ { UD_Ipaddq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0543 */ { UD_Ipmullw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0544 */ { UD_Ipmullw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0545 */ { UD_Imovdq2q, O_P, O_U, O_NONE, P_aso|P_rexb }, + /* 0546 */ { UD_Imovq2dq, O_V, O_N, O_NONE, P_aso|P_rexr }, + /* 0547 */ { UD_Imovq, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0548 */ { UD_Ipmovmskb, O_Gd, O_N, O_NONE, P_oso|P_rexr|P_rexb }, + /* 0549 */ { UD_Ipmovmskb, O_Gd, O_U, O_NONE, P_rexr|P_rexb }, + /* 0550 */ { UD_Ipsubusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0551 */ { UD_Ipsubusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0552 */ { UD_Ipsubusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0553 */ { UD_Ipsubusw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0554 */ { UD_Ipminub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0555 */ { UD_Ipminub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0556 */ { UD_Ipand, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0557 */ { UD_Ipand, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0558 */ { UD_Ipaddusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0559 */ { UD_Ipaddusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0560 */ { UD_Ipaddusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0561 */ { UD_Ipaddusw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0562 */ { UD_Ipmaxub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0563 */ { UD_Ipmaxub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0564 */ { UD_Ipandn, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0565 */ { UD_Ipandn, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0566 */ { UD_Ipavgb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0567 */ { UD_Ipavgb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0568 */ { UD_Ipsraw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0569 */ { UD_Ipsraw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0570 */ { UD_Ipsrad, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0571 */ { UD_Ipsrad, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0572 */ { UD_Ipavgw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0573 */ { UD_Ipavgw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0574 */ { UD_Ipmulhuw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0575 */ { UD_Ipmulhuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0576 */ { UD_Ipmulhw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0577 */ { UD_Ipmulhw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0578 */ { UD_Icvtpd2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0579 */ { UD_Icvtdq2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0580 */ { UD_Icvttpd2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0581 */ { UD_Imovntq, O_M, O_P, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0582 */ { UD_Imovntdq, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0583 */ { UD_Ipsubsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0584 */ { UD_Ipsubsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0585 */ { UD_Ipsubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0586 */ { UD_Ipsubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0587 */ { UD_Ipminsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0588 */ { UD_Ipminsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0589 */ { UD_Ipor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0590 */ { UD_Ipor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0591 */ { UD_Ipaddsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0592 */ { UD_Ipaddsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0593 */ { UD_Ipaddsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0594 */ { UD_Ipaddsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0595 */ { UD_Ipmaxsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0596 */ { UD_Ipmaxsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0597 */ { UD_Ipxor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0598 */ { UD_Ipxor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0599 */ { UD_Ilddqu, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0600 */ { UD_Ipsllw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0601 */ { UD_Ipsllw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0602 */ { UD_Ipslld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0603 */ { UD_Ipslld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0604 */ { UD_Ipsllq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0605 */ { UD_Ipsllq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0606 */ { UD_Ipmuludq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0607 */ { UD_Ipmuludq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0608 */ { UD_Ipmaddwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0609 */ { UD_Ipmaddwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0610 */ { UD_Ipsadbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0611 */ { UD_Ipsadbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0612 */ { UD_Imaskmovq, O_P, O_N, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0613 */ { UD_Imaskmovdqu, O_V, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0614 */ { UD_Ipsubb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0615 */ { UD_Ipsubb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0616 */ { UD_Ipsubw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0617 */ { UD_Ipsubw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0618 */ { UD_Ipsubd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0619 */ { UD_Ipsubd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0620 */ { UD_Ipsubq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0621 */ { UD_Ipsubq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0622 */ { UD_Ipaddb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0623 */ { UD_Ipaddb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0624 */ { UD_Ipaddw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0625 */ { UD_Ipaddw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0626 */ { UD_Ipaddd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0627 */ { UD_Ipaddd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0628 */ { UD_Iadc, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0629 */ { UD_Iadc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0630 */ { UD_Iadc, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0631 */ { UD_Iadc, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0632 */ { UD_Iadc, O_AL, O_Ib, O_NONE, P_none }, + /* 0633 */ { UD_Iadc, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0634 */ { UD_Ipush, O_SS, O_NONE, O_NONE, P_inv64 }, + /* 0635 */ { UD_Ipop, O_SS, O_NONE, O_NONE, P_inv64 }, + /* 0636 */ { UD_Isbb, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0637 */ { UD_Isbb, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0638 */ { UD_Isbb, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0639 */ { UD_Isbb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0640 */ { UD_Isbb, O_AL, O_Ib, O_NONE, P_none }, + /* 0641 */ { UD_Isbb, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0642 */ { UD_Ipush, O_DS, O_NONE, O_NONE, P_inv64 }, + /* 0643 */ { UD_Ipop, O_DS, O_NONE, O_NONE, P_inv64 }, + /* 0644 */ { UD_Iand, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0645 */ { UD_Iand, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0646 */ { UD_Iand, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0647 */ { UD_Iand, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0648 */ { UD_Iand, O_AL, O_Ib, O_NONE, P_none }, + /* 0649 */ { UD_Iand, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0650 */ { UD_Idaa, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 0651 */ { UD_Isub, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0652 */ { UD_Isub, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0653 */ { UD_Isub, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0654 */ { UD_Isub, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0655 */ { UD_Isub, O_AL, O_Ib, O_NONE, P_none }, + /* 0656 */ { UD_Isub, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0657 */ { UD_Idas, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 0658 */ { UD_Ixor, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0659 */ { UD_Ixor, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0660 */ { UD_Ixor, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0661 */ { UD_Ixor, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0662 */ { UD_Ixor, O_AL, O_Ib, O_NONE, P_none }, + /* 0663 */ { UD_Ixor, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0664 */ { UD_Iaaa, O_NONE, O_NONE, O_NONE, P_none }, + /* 0665 */ { UD_Icmp, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0666 */ { UD_Icmp, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0667 */ { UD_Icmp, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0668 */ { UD_Icmp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0669 */ { UD_Icmp, O_AL, O_Ib, O_NONE, P_none }, + /* 0670 */ { UD_Icmp, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0671 */ { UD_Iaas, O_NONE, O_NONE, O_NONE, P_none }, + /* 0672 */ { UD_Iinc, O_R0z, O_NONE, O_NONE, P_oso }, + /* 0673 */ { UD_Iinc, O_R1z, O_NONE, O_NONE, P_oso }, + /* 0674 */ { UD_Iinc, O_R2z, O_NONE, O_NONE, P_oso }, + /* 0675 */ { UD_Iinc, O_R3z, O_NONE, O_NONE, P_oso }, + /* 0676 */ { UD_Iinc, O_R4z, O_NONE, O_NONE, P_oso }, + /* 0677 */ { UD_Iinc, O_R5z, O_NONE, O_NONE, P_oso }, + /* 0678 */ { UD_Iinc, O_R6z, O_NONE, O_NONE, P_oso }, + /* 0679 */ { UD_Iinc, O_R7z, O_NONE, O_NONE, P_oso }, + /* 0680 */ { UD_Idec, O_R0z, O_NONE, O_NONE, P_oso }, + /* 0681 */ { UD_Idec, O_R1z, O_NONE, O_NONE, P_oso }, + /* 0682 */ { UD_Idec, O_R2z, O_NONE, O_NONE, P_oso }, + /* 0683 */ { UD_Idec, O_R3z, O_NONE, O_NONE, P_oso }, + /* 0684 */ { UD_Idec, O_R4z, O_NONE, O_NONE, P_oso }, + /* 0685 */ { UD_Idec, O_R5z, O_NONE, O_NONE, P_oso }, + /* 0686 */ { UD_Idec, O_R6z, O_NONE, O_NONE, P_oso }, + /* 0687 */ { UD_Idec, O_R7z, O_NONE, O_NONE, P_oso }, + /* 0688 */ { UD_Ipush, O_R0v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0689 */ { UD_Ipush, O_R1v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0690 */ { UD_Ipush, O_R2v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0691 */ { UD_Ipush, O_R3v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0692 */ { UD_Ipush, O_R4v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0693 */ { UD_Ipush, O_R5v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0694 */ { UD_Ipush, O_R6v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0695 */ { UD_Ipush, O_R7v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0696 */ { UD_Ipop, O_R0v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0697 */ { UD_Ipop, O_R1v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0698 */ { UD_Ipop, O_R2v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0699 */ { UD_Ipop, O_R3v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0700 */ { UD_Ipop, O_R4v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0701 */ { UD_Ipop, O_R5v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0702 */ { UD_Ipop, O_R6v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0703 */ { UD_Ipop, O_R7v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, + /* 0704 */ { UD_Ipusha, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 0705 */ { UD_Ipushad, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 0706 */ { UD_Ipopa, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 0707 */ { UD_Ipopad, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, + /* 0708 */ { UD_Ibound, O_Gv, O_M, O_NONE, P_aso|P_oso }, + /* 0709 */ { UD_Iarpl, O_Ew, O_Gw, O_NONE, P_aso }, + /* 0710 */ { UD_Imovsxd, O_Gq, O_Ed, O_NONE, P_aso|P_oso|P_rexw|P_rexx|P_rexr|P_rexb }, + /* 0711 */ { UD_Ipush, O_sIz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0712 */ { UD_Iimul, O_Gv, O_Ev, O_Iz, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0713 */ { UD_Ipush, O_sIb, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0714 */ { UD_Iimul, O_Gv, O_Ev, O_sIb, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0715 */ { UD_Iinsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0716 */ { UD_Iinsw, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0717 */ { UD_Iinsd, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0718 */ { UD_Ioutsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0719 */ { UD_Ioutsw, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0720 */ { UD_Ioutsd, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, + /* 0721 */ { UD_Ijo, O_Jb, O_NONE, O_NONE, P_none }, + /* 0722 */ { UD_Ijno, O_Jb, O_NONE, O_NONE, P_none }, + /* 0723 */ { UD_Ijb, O_Jb, O_NONE, O_NONE, P_none }, + /* 0724 */ { UD_Ijae, O_Jb, O_NONE, O_NONE, P_none }, + /* 0725 */ { UD_Ijz, O_Jb, O_NONE, O_NONE, P_none }, + /* 0726 */ { UD_Ijnz, O_Jb, O_NONE, O_NONE, P_none }, + /* 0727 */ { UD_Ijbe, O_Jb, O_NONE, O_NONE, P_none }, + /* 0728 */ { UD_Ija, O_Jb, O_NONE, O_NONE, P_none }, + /* 0729 */ { UD_Ijs, O_Jb, O_NONE, O_NONE, P_none }, + /* 0730 */ { UD_Ijns, O_Jb, O_NONE, O_NONE, P_none }, + /* 0731 */ { UD_Ijp, O_Jb, O_NONE, O_NONE, P_none }, + /* 0732 */ { UD_Ijnp, O_Jb, O_NONE, O_NONE, P_none }, + /* 0733 */ { UD_Ijl, O_Jb, O_NONE, O_NONE, P_none }, + /* 0734 */ { UD_Ijge, O_Jb, O_NONE, O_NONE, P_none }, + /* 0735 */ { UD_Ijle, O_Jb, O_NONE, O_NONE, P_none }, + /* 0736 */ { UD_Ijg, O_Jb, O_NONE, O_NONE, P_none }, + /* 0737 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0738 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0739 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0740 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0741 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0742 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0743 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0744 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0745 */ { UD_Iadd, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0746 */ { UD_Ior, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0747 */ { UD_Iadc, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0748 */ { UD_Isbb, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0749 */ { UD_Iand, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0750 */ { UD_Isub, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0751 */ { UD_Ixor, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0752 */ { UD_Icmp, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0753 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0754 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0755 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0756 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0757 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0758 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0759 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0760 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, + /* 0761 */ { UD_Iadd, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0762 */ { UD_Ior, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0763 */ { UD_Iadc, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0764 */ { UD_Isbb, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0765 */ { UD_Iand, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0766 */ { UD_Isub, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0767 */ { UD_Ixor, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0768 */ { UD_Icmp, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0769 */ { UD_Itest, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0770 */ { UD_Itest, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0771 */ { UD_Ixchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0772 */ { UD_Ixchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0773 */ { UD_Imov, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0774 */ { UD_Imov, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0775 */ { UD_Imov, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0776 */ { UD_Imov, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0777 */ { UD_Imov, O_MwRv, O_S, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0778 */ { UD_Ilea, O_Gv, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0779 */ { UD_Imov, O_S, O_MwRv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0780 */ { UD_Ipop, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 0781 */ { UD_Ixchg, O_R0v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0782 */ { UD_Ixchg, O_R1v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0783 */ { UD_Ixchg, O_R2v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0784 */ { UD_Ixchg, O_R3v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0785 */ { UD_Ixchg, O_R4v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0786 */ { UD_Ixchg, O_R5v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0787 */ { UD_Ixchg, O_R6v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0788 */ { UD_Ixchg, O_R7v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0789 */ { UD_Icbw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0790 */ { UD_Icwde, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0791 */ { UD_Icdqe, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0792 */ { UD_Icwd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0793 */ { UD_Icdq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0794 */ { UD_Icqo, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0795 */ { UD_Icall, O_Av, O_NONE, O_NONE, P_oso }, + /* 0796 */ { UD_Iwait, O_NONE, O_NONE, O_NONE, P_none }, + /* 0797 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0798 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, + /* 0799 */ { UD_Ipushfd, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0800 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, + /* 0801 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, + /* 0802 */ { UD_Ipopfw, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0803 */ { UD_Ipopfd, O_NONE, O_NONE, O_NONE, P_oso }, + /* 0804 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0805 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, + /* 0806 */ { UD_Isahf, O_NONE, O_NONE, O_NONE, P_none }, + /* 0807 */ { UD_Ilahf, O_NONE, O_NONE, O_NONE, P_none }, + /* 0808 */ { UD_Imov, O_AL, O_Ob, O_NONE, P_none }, + /* 0809 */ { UD_Imov, O_rAX, O_Ov, O_NONE, P_aso|P_oso|P_rexw }, + /* 0810 */ { UD_Imov, O_Ob, O_AL, O_NONE, P_none }, + /* 0811 */ { UD_Imov, O_Ov, O_rAX, O_NONE, P_aso|P_oso|P_rexw }, + /* 0812 */ { UD_Imovsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0813 */ { UD_Imovsw, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0814 */ { UD_Imovsd, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0815 */ { UD_Imovsq, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0816 */ { UD_Icmpsb, O_NONE, O_NONE, O_NONE, P_strz|P_seg }, + /* 0817 */ { UD_Icmpsw, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, + /* 0818 */ { UD_Icmpsd, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, + /* 0819 */ { UD_Icmpsq, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, + /* 0820 */ { UD_Itest, O_AL, O_Ib, O_NONE, P_none }, + /* 0821 */ { UD_Itest, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, + /* 0822 */ { UD_Istosb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0823 */ { UD_Istosw, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0824 */ { UD_Istosd, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0825 */ { UD_Istosq, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0826 */ { UD_Ilodsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, + /* 0827 */ { UD_Ilodsw, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0828 */ { UD_Ilodsd, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0829 */ { UD_Ilodsq, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, + /* 0830 */ { UD_Iscasb, O_NONE, O_NONE, O_NONE, P_strz }, + /* 0831 */ { UD_Iscasw, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, + /* 0832 */ { UD_Iscasd, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, + /* 0833 */ { UD_Iscasq, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, + /* 0834 */ { UD_Imov, O_R0b, O_Ib, O_NONE, P_rexb }, + /* 0835 */ { UD_Imov, O_R1b, O_Ib, O_NONE, P_rexb }, + /* 0836 */ { UD_Imov, O_R2b, O_Ib, O_NONE, P_rexb }, + /* 0837 */ { UD_Imov, O_R3b, O_Ib, O_NONE, P_rexb }, + /* 0838 */ { UD_Imov, O_R4b, O_Ib, O_NONE, P_rexb }, + /* 0839 */ { UD_Imov, O_R5b, O_Ib, O_NONE, P_rexb }, + /* 0840 */ { UD_Imov, O_R6b, O_Ib, O_NONE, P_rexb }, + /* 0841 */ { UD_Imov, O_R7b, O_Ib, O_NONE, P_rexb }, + /* 0842 */ { UD_Imov, O_R0v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0843 */ { UD_Imov, O_R1v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0844 */ { UD_Imov, O_R2v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0845 */ { UD_Imov, O_R3v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0846 */ { UD_Imov, O_R4v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0847 */ { UD_Imov, O_R5v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0848 */ { UD_Imov, O_R6v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0849 */ { UD_Imov, O_R7v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, + /* 0850 */ { UD_Irol, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0851 */ { UD_Iror, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0852 */ { UD_Ircl, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0853 */ { UD_Ircr, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0854 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0855 */ { UD_Ishr, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0856 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0857 */ { UD_Isar, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0858 */ { UD_Irol, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0859 */ { UD_Iror, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0860 */ { UD_Ircl, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0861 */ { UD_Ircr, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0862 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0863 */ { UD_Ishr, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0864 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0865 */ { UD_Isar, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0866 */ { UD_Iret, O_Iw, O_NONE, O_NONE, P_none }, + /* 0867 */ { UD_Iret, O_NONE, O_NONE, O_NONE, P_none }, + /* 0868 */ { UD_Iles, O_Gv, O_M, O_NONE, P_aso|P_oso }, + /* 0869 */ { UD_Ilds, O_Gv, O_M, O_NONE, P_aso|P_oso }, + /* 0870 */ { UD_Imov, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0871 */ { UD_Imov, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0872 */ { UD_Ienter, O_Iw, O_Ib, O_NONE, P_def64 }, + /* 0873 */ { UD_Ileave, O_NONE, O_NONE, O_NONE, P_none }, + /* 0874 */ { UD_Iretf, O_Iw, O_NONE, O_NONE, P_none }, + /* 0875 */ { UD_Iretf, O_NONE, O_NONE, O_NONE, P_none }, + /* 0876 */ { UD_Iint3, O_NONE, O_NONE, O_NONE, P_none }, + /* 0877 */ { UD_Iint, O_Ib, O_NONE, O_NONE, P_none }, + /* 0878 */ { UD_Iinto, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 0879 */ { UD_Iiretw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0880 */ { UD_Iiretd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0881 */ { UD_Iiretq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, + /* 0882 */ { UD_Irol, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0883 */ { UD_Iror, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0884 */ { UD_Ircl, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0885 */ { UD_Ircr, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0886 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0887 */ { UD_Ishr, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0888 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0889 */ { UD_Isar, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0890 */ { UD_Irol, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0891 */ { UD_Iror, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0892 */ { UD_Ircl, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0893 */ { UD_Ircr, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0894 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0895 */ { UD_Ishr, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0896 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0897 */ { UD_Isar, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0898 */ { UD_Irol, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0899 */ { UD_Iror, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0900 */ { UD_Ircl, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0901 */ { UD_Ircr, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0902 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0903 */ { UD_Ishr, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0904 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0905 */ { UD_Isar, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0906 */ { UD_Irol, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0907 */ { UD_Iror, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0908 */ { UD_Ircl, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0909 */ { UD_Ircr, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0910 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0911 */ { UD_Ishr, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0912 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0913 */ { UD_Isar, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 0914 */ { UD_Iaam, O_Ib, O_NONE, O_NONE, P_none }, + /* 0915 */ { UD_Iaad, O_Ib, O_NONE, O_NONE, P_none }, + /* 0916 */ { UD_Isalc, O_NONE, O_NONE, O_NONE, P_inv64 }, + /* 0917 */ { UD_Ixlatb, O_NONE, O_NONE, O_NONE, P_rexw|P_seg }, + /* 0918 */ { UD_Ifadd, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0919 */ { UD_Ifmul, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0920 */ { UD_Ifcom, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0921 */ { UD_Ifcomp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0922 */ { UD_Ifsub, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0923 */ { UD_Ifsubr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0924 */ { UD_Ifdiv, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0925 */ { UD_Ifdivr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0926 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, + /* 0927 */ { UD_Ifadd, O_ST0, O_ST1, O_NONE, P_none }, + /* 0928 */ { UD_Ifadd, O_ST0, O_ST2, O_NONE, P_none }, + /* 0929 */ { UD_Ifadd, O_ST0, O_ST3, O_NONE, P_none }, + /* 0930 */ { UD_Ifadd, O_ST0, O_ST4, O_NONE, P_none }, + /* 0931 */ { UD_Ifadd, O_ST0, O_ST5, O_NONE, P_none }, + /* 0932 */ { UD_Ifadd, O_ST0, O_ST6, O_NONE, P_none }, + /* 0933 */ { UD_Ifadd, O_ST0, O_ST7, O_NONE, P_none }, + /* 0934 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, + /* 0935 */ { UD_Ifmul, O_ST0, O_ST1, O_NONE, P_none }, + /* 0936 */ { UD_Ifmul, O_ST0, O_ST2, O_NONE, P_none }, + /* 0937 */ { UD_Ifmul, O_ST0, O_ST3, O_NONE, P_none }, + /* 0938 */ { UD_Ifmul, O_ST0, O_ST4, O_NONE, P_none }, + /* 0939 */ { UD_Ifmul, O_ST0, O_ST5, O_NONE, P_none }, + /* 0940 */ { UD_Ifmul, O_ST0, O_ST6, O_NONE, P_none }, + /* 0941 */ { UD_Ifmul, O_ST0, O_ST7, O_NONE, P_none }, + /* 0942 */ { UD_Ifcom, O_ST0, O_ST0, O_NONE, P_none }, + /* 0943 */ { UD_Ifcom, O_ST0, O_ST1, O_NONE, P_none }, + /* 0944 */ { UD_Ifcom, O_ST0, O_ST2, O_NONE, P_none }, + /* 0945 */ { UD_Ifcom, O_ST0, O_ST3, O_NONE, P_none }, + /* 0946 */ { UD_Ifcom, O_ST0, O_ST4, O_NONE, P_none }, + /* 0947 */ { UD_Ifcom, O_ST0, O_ST5, O_NONE, P_none }, + /* 0948 */ { UD_Ifcom, O_ST0, O_ST6, O_NONE, P_none }, + /* 0949 */ { UD_Ifcom, O_ST0, O_ST7, O_NONE, P_none }, + /* 0950 */ { UD_Ifcomp, O_ST0, O_ST0, O_NONE, P_none }, + /* 0951 */ { UD_Ifcomp, O_ST0, O_ST1, O_NONE, P_none }, + /* 0952 */ { UD_Ifcomp, O_ST0, O_ST2, O_NONE, P_none }, + /* 0953 */ { UD_Ifcomp, O_ST0, O_ST3, O_NONE, P_none }, + /* 0954 */ { UD_Ifcomp, O_ST0, O_ST4, O_NONE, P_none }, + /* 0955 */ { UD_Ifcomp, O_ST0, O_ST5, O_NONE, P_none }, + /* 0956 */ { UD_Ifcomp, O_ST0, O_ST6, O_NONE, P_none }, + /* 0957 */ { UD_Ifcomp, O_ST0, O_ST7, O_NONE, P_none }, + /* 0958 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, + /* 0959 */ { UD_Ifsub, O_ST0, O_ST1, O_NONE, P_none }, + /* 0960 */ { UD_Ifsub, O_ST0, O_ST2, O_NONE, P_none }, + /* 0961 */ { UD_Ifsub, O_ST0, O_ST3, O_NONE, P_none }, + /* 0962 */ { UD_Ifsub, O_ST0, O_ST4, O_NONE, P_none }, + /* 0963 */ { UD_Ifsub, O_ST0, O_ST5, O_NONE, P_none }, + /* 0964 */ { UD_Ifsub, O_ST0, O_ST6, O_NONE, P_none }, + /* 0965 */ { UD_Ifsub, O_ST0, O_ST7, O_NONE, P_none }, + /* 0966 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, + /* 0967 */ { UD_Ifsubr, O_ST0, O_ST1, O_NONE, P_none }, + /* 0968 */ { UD_Ifsubr, O_ST0, O_ST2, O_NONE, P_none }, + /* 0969 */ { UD_Ifsubr, O_ST0, O_ST3, O_NONE, P_none }, + /* 0970 */ { UD_Ifsubr, O_ST0, O_ST4, O_NONE, P_none }, + /* 0971 */ { UD_Ifsubr, O_ST0, O_ST5, O_NONE, P_none }, + /* 0972 */ { UD_Ifsubr, O_ST0, O_ST6, O_NONE, P_none }, + /* 0973 */ { UD_Ifsubr, O_ST0, O_ST7, O_NONE, P_none }, + /* 0974 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, + /* 0975 */ { UD_Ifdiv, O_ST0, O_ST1, O_NONE, P_none }, + /* 0976 */ { UD_Ifdiv, O_ST0, O_ST2, O_NONE, P_none }, + /* 0977 */ { UD_Ifdiv, O_ST0, O_ST3, O_NONE, P_none }, + /* 0978 */ { UD_Ifdiv, O_ST0, O_ST4, O_NONE, P_none }, + /* 0979 */ { UD_Ifdiv, O_ST0, O_ST5, O_NONE, P_none }, + /* 0980 */ { UD_Ifdiv, O_ST0, O_ST6, O_NONE, P_none }, + /* 0981 */ { UD_Ifdiv, O_ST0, O_ST7, O_NONE, P_none }, + /* 0982 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, + /* 0983 */ { UD_Ifdivr, O_ST0, O_ST1, O_NONE, P_none }, + /* 0984 */ { UD_Ifdivr, O_ST0, O_ST2, O_NONE, P_none }, + /* 0985 */ { UD_Ifdivr, O_ST0, O_ST3, O_NONE, P_none }, + /* 0986 */ { UD_Ifdivr, O_ST0, O_ST4, O_NONE, P_none }, + /* 0987 */ { UD_Ifdivr, O_ST0, O_ST5, O_NONE, P_none }, + /* 0988 */ { UD_Ifdivr, O_ST0, O_ST6, O_NONE, P_none }, + /* 0989 */ { UD_Ifdivr, O_ST0, O_ST7, O_NONE, P_none }, + /* 0990 */ { UD_Ifld, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0991 */ { UD_Ifst, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0992 */ { UD_Ifstp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0993 */ { UD_Ifldenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0994 */ { UD_Ifldcw, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0995 */ { UD_Ifnstenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0996 */ { UD_Ifnstcw, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 0997 */ { UD_Ifld, O_ST0, O_NONE, O_NONE, P_none }, + /* 0998 */ { UD_Ifld, O_ST1, O_NONE, O_NONE, P_none }, + /* 0999 */ { UD_Ifld, O_ST2, O_NONE, O_NONE, P_none }, + /* 1000 */ { UD_Ifld, O_ST3, O_NONE, O_NONE, P_none }, + /* 1001 */ { UD_Ifld, O_ST4, O_NONE, O_NONE, P_none }, + /* 1002 */ { UD_Ifld, O_ST5, O_NONE, O_NONE, P_none }, + /* 1003 */ { UD_Ifld, O_ST6, O_NONE, O_NONE, P_none }, + /* 1004 */ { UD_Ifld, O_ST7, O_NONE, O_NONE, P_none }, + /* 1005 */ { UD_Ifxch, O_ST0, O_ST0, O_NONE, P_none }, + /* 1006 */ { UD_Ifxch, O_ST0, O_ST1, O_NONE, P_none }, + /* 1007 */ { UD_Ifxch, O_ST0, O_ST2, O_NONE, P_none }, + /* 1008 */ { UD_Ifxch, O_ST0, O_ST3, O_NONE, P_none }, + /* 1009 */ { UD_Ifxch, O_ST0, O_ST4, O_NONE, P_none }, + /* 1010 */ { UD_Ifxch, O_ST0, O_ST5, O_NONE, P_none }, + /* 1011 */ { UD_Ifxch, O_ST0, O_ST6, O_NONE, P_none }, + /* 1012 */ { UD_Ifxch, O_ST0, O_ST7, O_NONE, P_none }, + /* 1013 */ { UD_Ifnop, O_NONE, O_NONE, O_NONE, P_none }, + /* 1014 */ { UD_Ifstp1, O_ST0, O_NONE, O_NONE, P_none }, + /* 1015 */ { UD_Ifstp1, O_ST1, O_NONE, O_NONE, P_none }, + /* 1016 */ { UD_Ifstp1, O_ST2, O_NONE, O_NONE, P_none }, + /* 1017 */ { UD_Ifstp1, O_ST3, O_NONE, O_NONE, P_none }, + /* 1018 */ { UD_Ifstp1, O_ST4, O_NONE, O_NONE, P_none }, + /* 1019 */ { UD_Ifstp1, O_ST5, O_NONE, O_NONE, P_none }, + /* 1020 */ { UD_Ifstp1, O_ST6, O_NONE, O_NONE, P_none }, + /* 1021 */ { UD_Ifstp1, O_ST7, O_NONE, O_NONE, P_none }, + /* 1022 */ { UD_Ifchs, O_NONE, O_NONE, O_NONE, P_none }, + /* 1023 */ { UD_Ifabs, O_NONE, O_NONE, O_NONE, P_none }, + /* 1024 */ { UD_Iftst, O_NONE, O_NONE, O_NONE, P_none }, + /* 1025 */ { UD_Ifxam, O_NONE, O_NONE, O_NONE, P_none }, + /* 1026 */ { UD_Ifld1, O_NONE, O_NONE, O_NONE, P_none }, + /* 1027 */ { UD_Ifldl2t, O_NONE, O_NONE, O_NONE, P_none }, + /* 1028 */ { UD_Ifldl2e, O_NONE, O_NONE, O_NONE, P_none }, + /* 1029 */ { UD_Ifldpi, O_NONE, O_NONE, O_NONE, P_none }, + /* 1030 */ { UD_Ifldlg2, O_NONE, O_NONE, O_NONE, P_none }, + /* 1031 */ { UD_Ifldln2, O_NONE, O_NONE, O_NONE, P_none }, + /* 1032 */ { UD_Ifldz, O_NONE, O_NONE, O_NONE, P_none }, + /* 1033 */ { UD_If2xm1, O_NONE, O_NONE, O_NONE, P_none }, + /* 1034 */ { UD_Ifyl2x, O_NONE, O_NONE, O_NONE, P_none }, + /* 1035 */ { UD_Ifptan, O_NONE, O_NONE, O_NONE, P_none }, + /* 1036 */ { UD_Ifpatan, O_NONE, O_NONE, O_NONE, P_none }, + /* 1037 */ { UD_Ifxtract, O_NONE, O_NONE, O_NONE, P_none }, + /* 1038 */ { UD_Ifprem1, O_NONE, O_NONE, O_NONE, P_none }, + /* 1039 */ { UD_Ifdecstp, O_NONE, O_NONE, O_NONE, P_none }, + /* 1040 */ { UD_Ifincstp, O_NONE, O_NONE, O_NONE, P_none }, + /* 1041 */ { UD_Ifprem, O_NONE, O_NONE, O_NONE, P_none }, + /* 1042 */ { UD_Ifyl2xp1, O_NONE, O_NONE, O_NONE, P_none }, + /* 1043 */ { UD_Ifsqrt, O_NONE, O_NONE, O_NONE, P_none }, + /* 1044 */ { UD_Ifsincos, O_NONE, O_NONE, O_NONE, P_none }, + /* 1045 */ { UD_Ifrndint, O_NONE, O_NONE, O_NONE, P_none }, + /* 1046 */ { UD_Ifscale, O_NONE, O_NONE, O_NONE, P_none }, + /* 1047 */ { UD_Ifsin, O_NONE, O_NONE, O_NONE, P_none }, + /* 1048 */ { UD_Ifcos, O_NONE, O_NONE, O_NONE, P_none }, + /* 1049 */ { UD_Ifiadd, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1050 */ { UD_Ifimul, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1051 */ { UD_Ificom, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1052 */ { UD_Ificomp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1053 */ { UD_Ifisub, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1054 */ { UD_Ifisubr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1055 */ { UD_Ifidiv, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1056 */ { UD_Ifidivr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1057 */ { UD_Ifcmovb, O_ST0, O_ST0, O_NONE, P_none }, + /* 1058 */ { UD_Ifcmovb, O_ST0, O_ST1, O_NONE, P_none }, + /* 1059 */ { UD_Ifcmovb, O_ST0, O_ST2, O_NONE, P_none }, + /* 1060 */ { UD_Ifcmovb, O_ST0, O_ST3, O_NONE, P_none }, + /* 1061 */ { UD_Ifcmovb, O_ST0, O_ST4, O_NONE, P_none }, + /* 1062 */ { UD_Ifcmovb, O_ST0, O_ST5, O_NONE, P_none }, + /* 1063 */ { UD_Ifcmovb, O_ST0, O_ST6, O_NONE, P_none }, + /* 1064 */ { UD_Ifcmovb, O_ST0, O_ST7, O_NONE, P_none }, + /* 1065 */ { UD_Ifcmove, O_ST0, O_ST0, O_NONE, P_none }, + /* 1066 */ { UD_Ifcmove, O_ST0, O_ST1, O_NONE, P_none }, + /* 1067 */ { UD_Ifcmove, O_ST0, O_ST2, O_NONE, P_none }, + /* 1068 */ { UD_Ifcmove, O_ST0, O_ST3, O_NONE, P_none }, + /* 1069 */ { UD_Ifcmove, O_ST0, O_ST4, O_NONE, P_none }, + /* 1070 */ { UD_Ifcmove, O_ST0, O_ST5, O_NONE, P_none }, + /* 1071 */ { UD_Ifcmove, O_ST0, O_ST6, O_NONE, P_none }, + /* 1072 */ { UD_Ifcmove, O_ST0, O_ST7, O_NONE, P_none }, + /* 1073 */ { UD_Ifcmovbe, O_ST0, O_ST0, O_NONE, P_none }, + /* 1074 */ { UD_Ifcmovbe, O_ST0, O_ST1, O_NONE, P_none }, + /* 1075 */ { UD_Ifcmovbe, O_ST0, O_ST2, O_NONE, P_none }, + /* 1076 */ { UD_Ifcmovbe, O_ST0, O_ST3, O_NONE, P_none }, + /* 1077 */ { UD_Ifcmovbe, O_ST0, O_ST4, O_NONE, P_none }, + /* 1078 */ { UD_Ifcmovbe, O_ST0, O_ST5, O_NONE, P_none }, + /* 1079 */ { UD_Ifcmovbe, O_ST0, O_ST6, O_NONE, P_none }, + /* 1080 */ { UD_Ifcmovbe, O_ST0, O_ST7, O_NONE, P_none }, + /* 1081 */ { UD_Ifcmovu, O_ST0, O_ST0, O_NONE, P_none }, + /* 1082 */ { UD_Ifcmovu, O_ST0, O_ST1, O_NONE, P_none }, + /* 1083 */ { UD_Ifcmovu, O_ST0, O_ST2, O_NONE, P_none }, + /* 1084 */ { UD_Ifcmovu, O_ST0, O_ST3, O_NONE, P_none }, + /* 1085 */ { UD_Ifcmovu, O_ST0, O_ST4, O_NONE, P_none }, + /* 1086 */ { UD_Ifcmovu, O_ST0, O_ST5, O_NONE, P_none }, + /* 1087 */ { UD_Ifcmovu, O_ST0, O_ST6, O_NONE, P_none }, + /* 1088 */ { UD_Ifcmovu, O_ST0, O_ST7, O_NONE, P_none }, + /* 1089 */ { UD_Ifucompp, O_NONE, O_NONE, O_NONE, P_none }, + /* 1090 */ { UD_Ifild, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1091 */ { UD_Ifisttp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1092 */ { UD_Ifist, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1093 */ { UD_Ifistp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1094 */ { UD_Ifld, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1095 */ { UD_Ifstp, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1096 */ { UD_Ifcmovnb, O_ST0, O_ST0, O_NONE, P_none }, + /* 1097 */ { UD_Ifcmovnb, O_ST0, O_ST1, O_NONE, P_none }, + /* 1098 */ { UD_Ifcmovnb, O_ST0, O_ST2, O_NONE, P_none }, + /* 1099 */ { UD_Ifcmovnb, O_ST0, O_ST3, O_NONE, P_none }, + /* 1100 */ { UD_Ifcmovnb, O_ST0, O_ST4, O_NONE, P_none }, + /* 1101 */ { UD_Ifcmovnb, O_ST0, O_ST5, O_NONE, P_none }, + /* 1102 */ { UD_Ifcmovnb, O_ST0, O_ST6, O_NONE, P_none }, + /* 1103 */ { UD_Ifcmovnb, O_ST0, O_ST7, O_NONE, P_none }, + /* 1104 */ { UD_Ifcmovne, O_ST0, O_ST0, O_NONE, P_none }, + /* 1105 */ { UD_Ifcmovne, O_ST0, O_ST1, O_NONE, P_none }, + /* 1106 */ { UD_Ifcmovne, O_ST0, O_ST2, O_NONE, P_none }, + /* 1107 */ { UD_Ifcmovne, O_ST0, O_ST3, O_NONE, P_none }, + /* 1108 */ { UD_Ifcmovne, O_ST0, O_ST4, O_NONE, P_none }, + /* 1109 */ { UD_Ifcmovne, O_ST0, O_ST5, O_NONE, P_none }, + /* 1110 */ { UD_Ifcmovne, O_ST0, O_ST6, O_NONE, P_none }, + /* 1111 */ { UD_Ifcmovne, O_ST0, O_ST7, O_NONE, P_none }, + /* 1112 */ { UD_Ifcmovnbe, O_ST0, O_ST0, O_NONE, P_none }, + /* 1113 */ { UD_Ifcmovnbe, O_ST0, O_ST1, O_NONE, P_none }, + /* 1114 */ { UD_Ifcmovnbe, O_ST0, O_ST2, O_NONE, P_none }, + /* 1115 */ { UD_Ifcmovnbe, O_ST0, O_ST3, O_NONE, P_none }, + /* 1116 */ { UD_Ifcmovnbe, O_ST0, O_ST4, O_NONE, P_none }, + /* 1117 */ { UD_Ifcmovnbe, O_ST0, O_ST5, O_NONE, P_none }, + /* 1118 */ { UD_Ifcmovnbe, O_ST0, O_ST6, O_NONE, P_none }, + /* 1119 */ { UD_Ifcmovnbe, O_ST0, O_ST7, O_NONE, P_none }, + /* 1120 */ { UD_Ifcmovnu, O_ST0, O_ST0, O_NONE, P_none }, + /* 1121 */ { UD_Ifcmovnu, O_ST0, O_ST1, O_NONE, P_none }, + /* 1122 */ { UD_Ifcmovnu, O_ST0, O_ST2, O_NONE, P_none }, + /* 1123 */ { UD_Ifcmovnu, O_ST0, O_ST3, O_NONE, P_none }, + /* 1124 */ { UD_Ifcmovnu, O_ST0, O_ST4, O_NONE, P_none }, + /* 1125 */ { UD_Ifcmovnu, O_ST0, O_ST5, O_NONE, P_none }, + /* 1126 */ { UD_Ifcmovnu, O_ST0, O_ST6, O_NONE, P_none }, + /* 1127 */ { UD_Ifcmovnu, O_ST0, O_ST7, O_NONE, P_none }, + /* 1128 */ { UD_Ifclex, O_NONE, O_NONE, O_NONE, P_none }, + /* 1129 */ { UD_Ifninit, O_NONE, O_NONE, O_NONE, P_none }, + /* 1130 */ { UD_Ifucomi, O_ST0, O_ST0, O_NONE, P_none }, + /* 1131 */ { UD_Ifucomi, O_ST0, O_ST1, O_NONE, P_none }, + /* 1132 */ { UD_Ifucomi, O_ST0, O_ST2, O_NONE, P_none }, + /* 1133 */ { UD_Ifucomi, O_ST0, O_ST3, O_NONE, P_none }, + /* 1134 */ { UD_Ifucomi, O_ST0, O_ST4, O_NONE, P_none }, + /* 1135 */ { UD_Ifucomi, O_ST0, O_ST5, O_NONE, P_none }, + /* 1136 */ { UD_Ifucomi, O_ST0, O_ST6, O_NONE, P_none }, + /* 1137 */ { UD_Ifucomi, O_ST0, O_ST7, O_NONE, P_none }, + /* 1138 */ { UD_Ifcomi, O_ST0, O_ST0, O_NONE, P_none }, + /* 1139 */ { UD_Ifcomi, O_ST0, O_ST1, O_NONE, P_none }, + /* 1140 */ { UD_Ifcomi, O_ST0, O_ST2, O_NONE, P_none }, + /* 1141 */ { UD_Ifcomi, O_ST0, O_ST3, O_NONE, P_none }, + /* 1142 */ { UD_Ifcomi, O_ST0, O_ST4, O_NONE, P_none }, + /* 1143 */ { UD_Ifcomi, O_ST0, O_ST5, O_NONE, P_none }, + /* 1144 */ { UD_Ifcomi, O_ST0, O_ST6, O_NONE, P_none }, + /* 1145 */ { UD_Ifcomi, O_ST0, O_ST7, O_NONE, P_none }, + /* 1146 */ { UD_Ifadd, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1147 */ { UD_Ifmul, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1148 */ { UD_Ifcom, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1149 */ { UD_Ifcomp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1150 */ { UD_Ifsub, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1151 */ { UD_Ifsubr, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1152 */ { UD_Ifdiv, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1153 */ { UD_Ifdivr, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1154 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, + /* 1155 */ { UD_Ifadd, O_ST1, O_ST0, O_NONE, P_none }, + /* 1156 */ { UD_Ifadd, O_ST2, O_ST0, O_NONE, P_none }, + /* 1157 */ { UD_Ifadd, O_ST3, O_ST0, O_NONE, P_none }, + /* 1158 */ { UD_Ifadd, O_ST4, O_ST0, O_NONE, P_none }, + /* 1159 */ { UD_Ifadd, O_ST5, O_ST0, O_NONE, P_none }, + /* 1160 */ { UD_Ifadd, O_ST6, O_ST0, O_NONE, P_none }, + /* 1161 */ { UD_Ifadd, O_ST7, O_ST0, O_NONE, P_none }, + /* 1162 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, + /* 1163 */ { UD_Ifmul, O_ST1, O_ST0, O_NONE, P_none }, + /* 1164 */ { UD_Ifmul, O_ST2, O_ST0, O_NONE, P_none }, + /* 1165 */ { UD_Ifmul, O_ST3, O_ST0, O_NONE, P_none }, + /* 1166 */ { UD_Ifmul, O_ST4, O_ST0, O_NONE, P_none }, + /* 1167 */ { UD_Ifmul, O_ST5, O_ST0, O_NONE, P_none }, + /* 1168 */ { UD_Ifmul, O_ST6, O_ST0, O_NONE, P_none }, + /* 1169 */ { UD_Ifmul, O_ST7, O_ST0, O_NONE, P_none }, + /* 1170 */ { UD_Ifcom2, O_ST0, O_NONE, O_NONE, P_none }, + /* 1171 */ { UD_Ifcom2, O_ST1, O_NONE, O_NONE, P_none }, + /* 1172 */ { UD_Ifcom2, O_ST2, O_NONE, O_NONE, P_none }, + /* 1173 */ { UD_Ifcom2, O_ST3, O_NONE, O_NONE, P_none }, + /* 1174 */ { UD_Ifcom2, O_ST4, O_NONE, O_NONE, P_none }, + /* 1175 */ { UD_Ifcom2, O_ST5, O_NONE, O_NONE, P_none }, + /* 1176 */ { UD_Ifcom2, O_ST6, O_NONE, O_NONE, P_none }, + /* 1177 */ { UD_Ifcom2, O_ST7, O_NONE, O_NONE, P_none }, + /* 1178 */ { UD_Ifcomp3, O_ST0, O_NONE, O_NONE, P_none }, + /* 1179 */ { UD_Ifcomp3, O_ST1, O_NONE, O_NONE, P_none }, + /* 1180 */ { UD_Ifcomp3, O_ST2, O_NONE, O_NONE, P_none }, + /* 1181 */ { UD_Ifcomp3, O_ST3, O_NONE, O_NONE, P_none }, + /* 1182 */ { UD_Ifcomp3, O_ST4, O_NONE, O_NONE, P_none }, + /* 1183 */ { UD_Ifcomp3, O_ST5, O_NONE, O_NONE, P_none }, + /* 1184 */ { UD_Ifcomp3, O_ST6, O_NONE, O_NONE, P_none }, + /* 1185 */ { UD_Ifcomp3, O_ST7, O_NONE, O_NONE, P_none }, + /* 1186 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, + /* 1187 */ { UD_Ifsubr, O_ST1, O_ST0, O_NONE, P_none }, + /* 1188 */ { UD_Ifsubr, O_ST2, O_ST0, O_NONE, P_none }, + /* 1189 */ { UD_Ifsubr, O_ST3, O_ST0, O_NONE, P_none }, + /* 1190 */ { UD_Ifsubr, O_ST4, O_ST0, O_NONE, P_none }, + /* 1191 */ { UD_Ifsubr, O_ST5, O_ST0, O_NONE, P_none }, + /* 1192 */ { UD_Ifsubr, O_ST6, O_ST0, O_NONE, P_none }, + /* 1193 */ { UD_Ifsubr, O_ST7, O_ST0, O_NONE, P_none }, + /* 1194 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, + /* 1195 */ { UD_Ifsub, O_ST1, O_ST0, O_NONE, P_none }, + /* 1196 */ { UD_Ifsub, O_ST2, O_ST0, O_NONE, P_none }, + /* 1197 */ { UD_Ifsub, O_ST3, O_ST0, O_NONE, P_none }, + /* 1198 */ { UD_Ifsub, O_ST4, O_ST0, O_NONE, P_none }, + /* 1199 */ { UD_Ifsub, O_ST5, O_ST0, O_NONE, P_none }, + /* 1200 */ { UD_Ifsub, O_ST6, O_ST0, O_NONE, P_none }, + /* 1201 */ { UD_Ifsub, O_ST7, O_ST0, O_NONE, P_none }, + /* 1202 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, + /* 1203 */ { UD_Ifdivr, O_ST1, O_ST0, O_NONE, P_none }, + /* 1204 */ { UD_Ifdivr, O_ST2, O_ST0, O_NONE, P_none }, + /* 1205 */ { UD_Ifdivr, O_ST3, O_ST0, O_NONE, P_none }, + /* 1206 */ { UD_Ifdivr, O_ST4, O_ST0, O_NONE, P_none }, + /* 1207 */ { UD_Ifdivr, O_ST5, O_ST0, O_NONE, P_none }, + /* 1208 */ { UD_Ifdivr, O_ST6, O_ST0, O_NONE, P_none }, + /* 1209 */ { UD_Ifdivr, O_ST7, O_ST0, O_NONE, P_none }, + /* 1210 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, + /* 1211 */ { UD_Ifdiv, O_ST1, O_ST0, O_NONE, P_none }, + /* 1212 */ { UD_Ifdiv, O_ST2, O_ST0, O_NONE, P_none }, + /* 1213 */ { UD_Ifdiv, O_ST3, O_ST0, O_NONE, P_none }, + /* 1214 */ { UD_Ifdiv, O_ST4, O_ST0, O_NONE, P_none }, + /* 1215 */ { UD_Ifdiv, O_ST5, O_ST0, O_NONE, P_none }, + /* 1216 */ { UD_Ifdiv, O_ST6, O_ST0, O_NONE, P_none }, + /* 1217 */ { UD_Ifdiv, O_ST7, O_ST0, O_NONE, P_none }, + /* 1218 */ { UD_Ifld, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1219 */ { UD_Ifisttp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1220 */ { UD_Ifst, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1221 */ { UD_Ifstp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1222 */ { UD_Ifrstor, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1223 */ { UD_Ifnsave, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1224 */ { UD_Ifnstsw, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1225 */ { UD_Iffree, O_ST0, O_NONE, O_NONE, P_none }, + /* 1226 */ { UD_Iffree, O_ST1, O_NONE, O_NONE, P_none }, + /* 1227 */ { UD_Iffree, O_ST2, O_NONE, O_NONE, P_none }, + /* 1228 */ { UD_Iffree, O_ST3, O_NONE, O_NONE, P_none }, + /* 1229 */ { UD_Iffree, O_ST4, O_NONE, O_NONE, P_none }, + /* 1230 */ { UD_Iffree, O_ST5, O_NONE, O_NONE, P_none }, + /* 1231 */ { UD_Iffree, O_ST6, O_NONE, O_NONE, P_none }, + /* 1232 */ { UD_Iffree, O_ST7, O_NONE, O_NONE, P_none }, + /* 1233 */ { UD_Ifxch4, O_ST0, O_NONE, O_NONE, P_none }, + /* 1234 */ { UD_Ifxch4, O_ST1, O_NONE, O_NONE, P_none }, + /* 1235 */ { UD_Ifxch4, O_ST2, O_NONE, O_NONE, P_none }, + /* 1236 */ { UD_Ifxch4, O_ST3, O_NONE, O_NONE, P_none }, + /* 1237 */ { UD_Ifxch4, O_ST4, O_NONE, O_NONE, P_none }, + /* 1238 */ { UD_Ifxch4, O_ST5, O_NONE, O_NONE, P_none }, + /* 1239 */ { UD_Ifxch4, O_ST6, O_NONE, O_NONE, P_none }, + /* 1240 */ { UD_Ifxch4, O_ST7, O_NONE, O_NONE, P_none }, + /* 1241 */ { UD_Ifst, O_ST0, O_NONE, O_NONE, P_none }, + /* 1242 */ { UD_Ifst, O_ST1, O_NONE, O_NONE, P_none }, + /* 1243 */ { UD_Ifst, O_ST2, O_NONE, O_NONE, P_none }, + /* 1244 */ { UD_Ifst, O_ST3, O_NONE, O_NONE, P_none }, + /* 1245 */ { UD_Ifst, O_ST4, O_NONE, O_NONE, P_none }, + /* 1246 */ { UD_Ifst, O_ST5, O_NONE, O_NONE, P_none }, + /* 1247 */ { UD_Ifst, O_ST6, O_NONE, O_NONE, P_none }, + /* 1248 */ { UD_Ifst, O_ST7, O_NONE, O_NONE, P_none }, + /* 1249 */ { UD_Ifstp, O_ST0, O_NONE, O_NONE, P_none }, + /* 1250 */ { UD_Ifstp, O_ST1, O_NONE, O_NONE, P_none }, + /* 1251 */ { UD_Ifstp, O_ST2, O_NONE, O_NONE, P_none }, + /* 1252 */ { UD_Ifstp, O_ST3, O_NONE, O_NONE, P_none }, + /* 1253 */ { UD_Ifstp, O_ST4, O_NONE, O_NONE, P_none }, + /* 1254 */ { UD_Ifstp, O_ST5, O_NONE, O_NONE, P_none }, + /* 1255 */ { UD_Ifstp, O_ST6, O_NONE, O_NONE, P_none }, + /* 1256 */ { UD_Ifstp, O_ST7, O_NONE, O_NONE, P_none }, + /* 1257 */ { UD_Ifucom, O_ST0, O_NONE, O_NONE, P_none }, + /* 1258 */ { UD_Ifucom, O_ST1, O_NONE, O_NONE, P_none }, + /* 1259 */ { UD_Ifucom, O_ST2, O_NONE, O_NONE, P_none }, + /* 1260 */ { UD_Ifucom, O_ST3, O_NONE, O_NONE, P_none }, + /* 1261 */ { UD_Ifucom, O_ST4, O_NONE, O_NONE, P_none }, + /* 1262 */ { UD_Ifucom, O_ST5, O_NONE, O_NONE, P_none }, + /* 1263 */ { UD_Ifucom, O_ST6, O_NONE, O_NONE, P_none }, + /* 1264 */ { UD_Ifucom, O_ST7, O_NONE, O_NONE, P_none }, + /* 1265 */ { UD_Ifucomp, O_ST0, O_NONE, O_NONE, P_none }, + /* 1266 */ { UD_Ifucomp, O_ST1, O_NONE, O_NONE, P_none }, + /* 1267 */ { UD_Ifucomp, O_ST2, O_NONE, O_NONE, P_none }, + /* 1268 */ { UD_Ifucomp, O_ST3, O_NONE, O_NONE, P_none }, + /* 1269 */ { UD_Ifucomp, O_ST4, O_NONE, O_NONE, P_none }, + /* 1270 */ { UD_Ifucomp, O_ST5, O_NONE, O_NONE, P_none }, + /* 1271 */ { UD_Ifucomp, O_ST6, O_NONE, O_NONE, P_none }, + /* 1272 */ { UD_Ifucomp, O_ST7, O_NONE, O_NONE, P_none }, + /* 1273 */ { UD_Ifiadd, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1274 */ { UD_Ifimul, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1275 */ { UD_Ificom, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1276 */ { UD_Ificomp, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1277 */ { UD_Ifisub, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1278 */ { UD_Ifisubr, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1279 */ { UD_Ifidiv, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1280 */ { UD_Ifidivr, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1281 */ { UD_Ifaddp, O_ST0, O_ST0, O_NONE, P_none }, + /* 1282 */ { UD_Ifaddp, O_ST1, O_ST0, O_NONE, P_none }, + /* 1283 */ { UD_Ifaddp, O_ST2, O_ST0, O_NONE, P_none }, + /* 1284 */ { UD_Ifaddp, O_ST3, O_ST0, O_NONE, P_none }, + /* 1285 */ { UD_Ifaddp, O_ST4, O_ST0, O_NONE, P_none }, + /* 1286 */ { UD_Ifaddp, O_ST5, O_ST0, O_NONE, P_none }, + /* 1287 */ { UD_Ifaddp, O_ST6, O_ST0, O_NONE, P_none }, + /* 1288 */ { UD_Ifaddp, O_ST7, O_ST0, O_NONE, P_none }, + /* 1289 */ { UD_Ifmulp, O_ST0, O_ST0, O_NONE, P_none }, + /* 1290 */ { UD_Ifmulp, O_ST1, O_ST0, O_NONE, P_none }, + /* 1291 */ { UD_Ifmulp, O_ST2, O_ST0, O_NONE, P_none }, + /* 1292 */ { UD_Ifmulp, O_ST3, O_ST0, O_NONE, P_none }, + /* 1293 */ { UD_Ifmulp, O_ST4, O_ST0, O_NONE, P_none }, + /* 1294 */ { UD_Ifmulp, O_ST5, O_ST0, O_NONE, P_none }, + /* 1295 */ { UD_Ifmulp, O_ST6, O_ST0, O_NONE, P_none }, + /* 1296 */ { UD_Ifmulp, O_ST7, O_ST0, O_NONE, P_none }, + /* 1297 */ { UD_Ifcomp5, O_ST0, O_NONE, O_NONE, P_none }, + /* 1298 */ { UD_Ifcomp5, O_ST1, O_NONE, O_NONE, P_none }, + /* 1299 */ { UD_Ifcomp5, O_ST2, O_NONE, O_NONE, P_none }, + /* 1300 */ { UD_Ifcomp5, O_ST3, O_NONE, O_NONE, P_none }, + /* 1301 */ { UD_Ifcomp5, O_ST4, O_NONE, O_NONE, P_none }, + /* 1302 */ { UD_Ifcomp5, O_ST5, O_NONE, O_NONE, P_none }, + /* 1303 */ { UD_Ifcomp5, O_ST6, O_NONE, O_NONE, P_none }, + /* 1304 */ { UD_Ifcomp5, O_ST7, O_NONE, O_NONE, P_none }, + /* 1305 */ { UD_Ifcompp, O_NONE, O_NONE, O_NONE, P_none }, + /* 1306 */ { UD_Ifsubrp, O_ST0, O_ST0, O_NONE, P_none }, + /* 1307 */ { UD_Ifsubrp, O_ST1, O_ST0, O_NONE, P_none }, + /* 1308 */ { UD_Ifsubrp, O_ST2, O_ST0, O_NONE, P_none }, + /* 1309 */ { UD_Ifsubrp, O_ST3, O_ST0, O_NONE, P_none }, + /* 1310 */ { UD_Ifsubrp, O_ST4, O_ST0, O_NONE, P_none }, + /* 1311 */ { UD_Ifsubrp, O_ST5, O_ST0, O_NONE, P_none }, + /* 1312 */ { UD_Ifsubrp, O_ST6, O_ST0, O_NONE, P_none }, + /* 1313 */ { UD_Ifsubrp, O_ST7, O_ST0, O_NONE, P_none }, + /* 1314 */ { UD_Ifsubp, O_ST0, O_ST0, O_NONE, P_none }, + /* 1315 */ { UD_Ifsubp, O_ST1, O_ST0, O_NONE, P_none }, + /* 1316 */ { UD_Ifsubp, O_ST2, O_ST0, O_NONE, P_none }, + /* 1317 */ { UD_Ifsubp, O_ST3, O_ST0, O_NONE, P_none }, + /* 1318 */ { UD_Ifsubp, O_ST4, O_ST0, O_NONE, P_none }, + /* 1319 */ { UD_Ifsubp, O_ST5, O_ST0, O_NONE, P_none }, + /* 1320 */ { UD_Ifsubp, O_ST6, O_ST0, O_NONE, P_none }, + /* 1321 */ { UD_Ifsubp, O_ST7, O_ST0, O_NONE, P_none }, + /* 1322 */ { UD_Ifdivrp, O_ST0, O_ST0, O_NONE, P_none }, + /* 1323 */ { UD_Ifdivrp, O_ST1, O_ST0, O_NONE, P_none }, + /* 1324 */ { UD_Ifdivrp, O_ST2, O_ST0, O_NONE, P_none }, + /* 1325 */ { UD_Ifdivrp, O_ST3, O_ST0, O_NONE, P_none }, + /* 1326 */ { UD_Ifdivrp, O_ST4, O_ST0, O_NONE, P_none }, + /* 1327 */ { UD_Ifdivrp, O_ST5, O_ST0, O_NONE, P_none }, + /* 1328 */ { UD_Ifdivrp, O_ST6, O_ST0, O_NONE, P_none }, + /* 1329 */ { UD_Ifdivrp, O_ST7, O_ST0, O_NONE, P_none }, + /* 1330 */ { UD_Ifdivp, O_ST0, O_ST0, O_NONE, P_none }, + /* 1331 */ { UD_Ifdivp, O_ST1, O_ST0, O_NONE, P_none }, + /* 1332 */ { UD_Ifdivp, O_ST2, O_ST0, O_NONE, P_none }, + /* 1333 */ { UD_Ifdivp, O_ST3, O_ST0, O_NONE, P_none }, + /* 1334 */ { UD_Ifdivp, O_ST4, O_ST0, O_NONE, P_none }, + /* 1335 */ { UD_Ifdivp, O_ST5, O_ST0, O_NONE, P_none }, + /* 1336 */ { UD_Ifdivp, O_ST6, O_ST0, O_NONE, P_none }, + /* 1337 */ { UD_Ifdivp, O_ST7, O_ST0, O_NONE, P_none }, + /* 1338 */ { UD_Ifild, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1339 */ { UD_Ifisttp, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1340 */ { UD_Ifist, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1341 */ { UD_Ifistp, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1342 */ { UD_Ifbld, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1343 */ { UD_Ifild, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1344 */ { UD_Ifbstp, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1345 */ { UD_Ifistp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, + /* 1346 */ { UD_Iffreep, O_ST0, O_NONE, O_NONE, P_none }, + /* 1347 */ { UD_Iffreep, O_ST1, O_NONE, O_NONE, P_none }, + /* 1348 */ { UD_Iffreep, O_ST2, O_NONE, O_NONE, P_none }, + /* 1349 */ { UD_Iffreep, O_ST3, O_NONE, O_NONE, P_none }, + /* 1350 */ { UD_Iffreep, O_ST4, O_NONE, O_NONE, P_none }, + /* 1351 */ { UD_Iffreep, O_ST5, O_NONE, O_NONE, P_none }, + /* 1352 */ { UD_Iffreep, O_ST6, O_NONE, O_NONE, P_none }, + /* 1353 */ { UD_Iffreep, O_ST7, O_NONE, O_NONE, P_none }, + /* 1354 */ { UD_Ifxch7, O_ST0, O_NONE, O_NONE, P_none }, + /* 1355 */ { UD_Ifxch7, O_ST1, O_NONE, O_NONE, P_none }, + /* 1356 */ { UD_Ifxch7, O_ST2, O_NONE, O_NONE, P_none }, + /* 1357 */ { UD_Ifxch7, O_ST3, O_NONE, O_NONE, P_none }, + /* 1358 */ { UD_Ifxch7, O_ST4, O_NONE, O_NONE, P_none }, + /* 1359 */ { UD_Ifxch7, O_ST5, O_NONE, O_NONE, P_none }, + /* 1360 */ { UD_Ifxch7, O_ST6, O_NONE, O_NONE, P_none }, + /* 1361 */ { UD_Ifxch7, O_ST7, O_NONE, O_NONE, P_none }, + /* 1362 */ { UD_Ifstp8, O_ST0, O_NONE, O_NONE, P_none }, + /* 1363 */ { UD_Ifstp8, O_ST1, O_NONE, O_NONE, P_none }, + /* 1364 */ { UD_Ifstp8, O_ST2, O_NONE, O_NONE, P_none }, + /* 1365 */ { UD_Ifstp8, O_ST3, O_NONE, O_NONE, P_none }, + /* 1366 */ { UD_Ifstp8, O_ST4, O_NONE, O_NONE, P_none }, + /* 1367 */ { UD_Ifstp8, O_ST5, O_NONE, O_NONE, P_none }, + /* 1368 */ { UD_Ifstp8, O_ST6, O_NONE, O_NONE, P_none }, + /* 1369 */ { UD_Ifstp8, O_ST7, O_NONE, O_NONE, P_none }, + /* 1370 */ { UD_Ifstp9, O_ST0, O_NONE, O_NONE, P_none }, + /* 1371 */ { UD_Ifstp9, O_ST1, O_NONE, O_NONE, P_none }, + /* 1372 */ { UD_Ifstp9, O_ST2, O_NONE, O_NONE, P_none }, + /* 1373 */ { UD_Ifstp9, O_ST3, O_NONE, O_NONE, P_none }, + /* 1374 */ { UD_Ifstp9, O_ST4, O_NONE, O_NONE, P_none }, + /* 1375 */ { UD_Ifstp9, O_ST5, O_NONE, O_NONE, P_none }, + /* 1376 */ { UD_Ifstp9, O_ST6, O_NONE, O_NONE, P_none }, + /* 1377 */ { UD_Ifstp9, O_ST7, O_NONE, O_NONE, P_none }, + /* 1378 */ { UD_Ifnstsw, O_AX, O_NONE, O_NONE, P_none }, + /* 1379 */ { UD_Ifucomip, O_ST0, O_ST0, O_NONE, P_none }, + /* 1380 */ { UD_Ifucomip, O_ST0, O_ST1, O_NONE, P_none }, + /* 1381 */ { UD_Ifucomip, O_ST0, O_ST2, O_NONE, P_none }, + /* 1382 */ { UD_Ifucomip, O_ST0, O_ST3, O_NONE, P_none }, + /* 1383 */ { UD_Ifucomip, O_ST0, O_ST4, O_NONE, P_none }, + /* 1384 */ { UD_Ifucomip, O_ST0, O_ST5, O_NONE, P_none }, + /* 1385 */ { UD_Ifucomip, O_ST0, O_ST6, O_NONE, P_none }, + /* 1386 */ { UD_Ifucomip, O_ST0, O_ST7, O_NONE, P_none }, + /* 1387 */ { UD_Ifcomip, O_ST0, O_ST0, O_NONE, P_none }, + /* 1388 */ { UD_Ifcomip, O_ST0, O_ST1, O_NONE, P_none }, + /* 1389 */ { UD_Ifcomip, O_ST0, O_ST2, O_NONE, P_none }, + /* 1390 */ { UD_Ifcomip, O_ST0, O_ST3, O_NONE, P_none }, + /* 1391 */ { UD_Ifcomip, O_ST0, O_ST4, O_NONE, P_none }, + /* 1392 */ { UD_Ifcomip, O_ST0, O_ST5, O_NONE, P_none }, + /* 1393 */ { UD_Ifcomip, O_ST0, O_ST6, O_NONE, P_none }, + /* 1394 */ { UD_Ifcomip, O_ST0, O_ST7, O_NONE, P_none }, + /* 1395 */ { UD_Iloopne, O_Jb, O_NONE, O_NONE, P_none }, + /* 1396 */ { UD_Iloope, O_Jb, O_NONE, O_NONE, P_none }, + /* 1397 */ { UD_Iloop, O_Jb, O_NONE, O_NONE, P_none }, + /* 1398 */ { UD_Ijcxz, O_Jb, O_NONE, O_NONE, P_aso }, + /* 1399 */ { UD_Ijecxz, O_Jb, O_NONE, O_NONE, P_aso }, + /* 1400 */ { UD_Ijrcxz, O_Jb, O_NONE, O_NONE, P_aso }, + /* 1401 */ { UD_Iin, O_AL, O_Ib, O_NONE, P_none }, + /* 1402 */ { UD_Iin, O_eAX, O_Ib, O_NONE, P_oso }, + /* 1403 */ { UD_Iout, O_Ib, O_AL, O_NONE, P_none }, + /* 1404 */ { UD_Iout, O_Ib, O_eAX, O_NONE, P_oso }, + /* 1405 */ { UD_Icall, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 1406 */ { UD_Ijmp, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, + /* 1407 */ { UD_Ijmp, O_Av, O_NONE, O_NONE, P_oso }, + /* 1408 */ { UD_Ijmp, O_Jb, O_NONE, O_NONE, P_def64 }, + /* 1409 */ { UD_Iin, O_AL, O_DX, O_NONE, P_none }, + /* 1410 */ { UD_Iin, O_eAX, O_DX, O_NONE, P_oso }, + /* 1411 */ { UD_Iout, O_DX, O_AL, O_NONE, P_none }, + /* 1412 */ { UD_Iout, O_DX, O_eAX, O_NONE, P_oso }, + /* 1413 */ { UD_Ilock, O_NONE, O_NONE, O_NONE, P_none }, + /* 1414 */ { UD_Iint1, O_NONE, O_NONE, O_NONE, P_none }, + /* 1415 */ { UD_Irepne, O_NONE, O_NONE, O_NONE, P_none }, + /* 1416 */ { UD_Irep, O_NONE, O_NONE, O_NONE, P_none }, + /* 1417 */ { UD_Ihlt, O_NONE, O_NONE, O_NONE, P_none }, + /* 1418 */ { UD_Icmc, O_NONE, O_NONE, O_NONE, P_none }, + /* 1419 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1420 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1421 */ { UD_Inot, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1422 */ { UD_Ineg, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1423 */ { UD_Imul, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1424 */ { UD_Iimul, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1425 */ { UD_Idiv, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1426 */ { UD_Iidiv, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1427 */ { UD_Itest, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1428 */ { UD_Itest, O_Ev, O_Iz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1429 */ { UD_Inot, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1430 */ { UD_Ineg, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1431 */ { UD_Imul, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1432 */ { UD_Iimul, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1433 */ { UD_Idiv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1434 */ { UD_Iidiv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1435 */ { UD_Iclc, O_NONE, O_NONE, O_NONE, P_none }, + /* 1436 */ { UD_Istc, O_NONE, O_NONE, O_NONE, P_none }, + /* 1437 */ { UD_Icli, O_NONE, O_NONE, O_NONE, P_none }, + /* 1438 */ { UD_Isti, O_NONE, O_NONE, O_NONE, P_none }, + /* 1439 */ { UD_Icld, O_NONE, O_NONE, O_NONE, P_none }, + /* 1440 */ { UD_Istd, O_NONE, O_NONE, O_NONE, P_none }, + /* 1441 */ { UD_Iinc, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1442 */ { UD_Idec, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1443 */ { UD_Iinc, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1444 */ { UD_Idec, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1445 */ { UD_Icall, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1446 */ { UD_Icall, O_Eq, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1447 */ { UD_Icall, O_Fv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1448 */ { UD_Ijmp, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, + /* 1449 */ { UD_Ijmp, O_Fv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, + /* 1450 */ { UD_Ipush, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, +}; + + +#ifndef __INSIDE_CYGWIN__ +const char * ud_mnemonics_str[] = { +"invalid", + "3dnow", + "none", + "db", + "pause", + "aaa", + "aad", + "aam", + "aas", + "adc", + "add", + "addpd", + "addps", + "addsd", + "addss", + "and", + "andpd", + "andps", + "andnpd", + "andnps", + "arpl", + "movsxd", + "bound", + "bsf", + "bsr", + "bswap", + "bt", + "btc", + "btr", + "bts", + "call", + "cbw", + "cwde", + "cdqe", + "clc", + "cld", + "clflush", + "clgi", + "cli", + "clts", + "cmc", + "cmovo", + "cmovno", + "cmovb", + "cmovae", + "cmovz", + "cmovnz", + "cmovbe", + "cmova", + "cmovs", + "cmovns", + "cmovp", + "cmovnp", + "cmovl", + "cmovge", + "cmovle", + "cmovg", + "cmp", + "cmppd", + "cmpps", + "cmpsb", + "cmpsw", + "cmpsd", + "cmpsq", + "cmpss", + "cmpxchg", + "cmpxchg8b", + "cmpxchg16b", + "comisd", + "comiss", + "cpuid", + "cvtdq2pd", + "cvtdq2ps", + "cvtpd2dq", + "cvtpd2pi", + "cvtpd2ps", + "cvtpi2ps", + "cvtpi2pd", + "cvtps2dq", + "cvtps2pi", + "cvtps2pd", + "cvtsd2si", + "cvtsd2ss", + "cvtsi2ss", + "cvtss2si", + "cvtss2sd", + "cvttpd2pi", + "cvttpd2dq", + "cvttps2dq", + "cvttps2pi", + "cvttsd2si", + "cvtsi2sd", + "cvttss2si", + "cwd", + "cdq", + "cqo", + "daa", + "das", + "dec", + "div", + "divpd", + "divps", + "divsd", + "divss", + "emms", + "enter", + "f2xm1", + "fabs", + "fadd", + "faddp", + "fbld", + "fbstp", + "fchs", + "fclex", + "fcmovb", + "fcmove", + "fcmovbe", + "fcmovu", + "fcmovnb", + "fcmovne", + "fcmovnbe", + "fcmovnu", + "fucomi", + "fcom", + "fcom2", + "fcomp3", + "fcomi", + "fucomip", + "fcomip", + "fcomp", + "fcomp5", + "fcompp", + "fcos", + "fdecstp", + "fdiv", + "fdivp", + "fdivr", + "fdivrp", + "femms", + "ffree", + "ffreep", + "ficom", + "ficomp", + "fild", + "fincstp", + "fninit", + "fiadd", + "fidivr", + "fidiv", + "fisub", + "fisubr", + "fist", + "fistp", + "fisttp", + "fld", + "fld1", + "fldl2t", + "fldl2e", + "fldpi", + "fldlg2", + "fldln2", + "fldz", + "fldcw", + "fldenv", + "fmul", + "fmulp", + "fimul", + "fnop", + "fpatan", + "fprem", + "fprem1", + "fptan", + "frndint", + "frstor", + "fnsave", + "fscale", + "fsin", + "fsincos", + "fsqrt", + "fstp", + "fstp1", + "fstp8", + "fstp9", + "fst", + "fnstcw", + "fnstenv", + "fnstsw", + "fsub", + "fsubp", + "fsubr", + "fsubrp", + "ftst", + "fucom", + "fucomp", + "fucompp", + "fxam", + "fxch", + "fxch4", + "fxch7", + "fxrstor", + "fxsave", + "fxtract", + "fyl2x", + "fyl2xp1", + "hlt", + "idiv", + "in", + "imul", + "inc", + "insb", + "insw", + "insd", + "int1", + "int3", + "int", + "into", + "invd", + "invept", + "invlpg", + "invlpga", + "invvpid", + "iretw", + "iretd", + "iretq", + "jo", + "jno", + "jb", + "jae", + "jz", + "jnz", + "jbe", + "ja", + "js", + "jns", + "jp", + "jnp", + "jl", + "jge", + "jle", + "jg", + "jcxz", + "jecxz", + "jrcxz", + "jmp", + "lahf", + "lar", + "lddqu", + "ldmxcsr", + "lds", + "lea", + "les", + "lfs", + "lgs", + "lidt", + "lss", + "leave", + "lfence", + "lgdt", + "lldt", + "lmsw", + "lock", + "lodsb", + "lodsw", + "lodsd", + "lodsq", + "loopne", + "loope", + "loop", + "lsl", + "ltr", + "maskmovq", + "maxpd", + "maxps", + "maxsd", + "maxss", + "mfence", + "minpd", + "minps", + "minsd", + "minss", + "monitor", + "montmul", + "mov", + "movapd", + "movaps", + "movd", + "movhpd", + "movhps", + "movlhps", + "movlpd", + "movlps", + "movhlps", + "movmskpd", + "movmskps", + "movntdq", + "movnti", + "movntpd", + "movntps", + "movntq", + "movq", + "movsb", + "movsw", + "movsd", + "movsq", + "movss", + "movsx", + "movupd", + "movups", + "movzx", + "mul", + "mulpd", + "mulps", + "mulsd", + "mulss", + "mwait", + "neg", + "nop", + "not", + "or", + "orpd", + "orps", + "out", + "outsb", + "outsw", + "outsd", + "packsswb", + "packssdw", + "packuswb", + "paddb", + "paddw", + "paddd", + "paddsb", + "paddsw", + "paddusb", + "paddusw", + "pand", + "pandn", + "pavgb", + "pavgw", + "pcmpeqb", + "pcmpeqw", + "pcmpeqd", + "pcmpgtb", + "pcmpgtw", + "pcmpgtd", + "pextrb", + "pextrd", + "pextrq", + "pextrw", + "pinsrb", + "pinsrw", + "pinsrd", + "pinsrq", + "pmaddwd", + "pmaxsw", + "pmaxub", + "pminsw", + "pminub", + "pmovmskb", + "pmulhuw", + "pmulhw", + "pmullw", + "pop", + "popa", + "popad", + "popfw", + "popfd", + "popfq", + "por", + "prefetch", + "prefetchnta", + "prefetcht0", + "prefetcht1", + "prefetcht2", + "psadbw", + "pshufw", + "psllw", + "pslld", + "psllq", + "psraw", + "psrad", + "psrlw", + "psrld", + "psrlq", + "psubb", + "psubw", + "psubd", + "psubsb", + "psubsw", + "psubusb", + "psubusw", + "punpckhbw", + "punpckhwd", + "punpckhdq", + "punpcklbw", + "punpcklwd", + "punpckldq", + "pi2fw", + "pi2fd", + "pf2iw", + "pf2id", + "pfnacc", + "pfpnacc", + "pfcmpge", + "pfmin", + "pfrcp", + "pfrsqrt", + "pfsub", + "pfadd", + "pfcmpgt", + "pfmax", + "pfrcpit1", + "pfrsqit1", + "pfsubr", + "pfacc", + "pfcmpeq", + "pfmul", + "pfrcpit2", + "pmulhrw", + "pswapd", + "pavgusb", + "push", + "pusha", + "pushad", + "pushfw", + "pushfd", + "pushfq", + "pxor", + "rcl", + "rcr", + "rol", + "ror", + "rcpps", + "rcpss", + "rdmsr", + "rdpmc", + "rdtsc", + "rdtscp", + "repne", + "rep", + "ret", + "retf", + "rsm", + "rsqrtps", + "rsqrtss", + "sahf", + "salc", + "sar", + "shl", + "shr", + "sbb", + "scasb", + "scasw", + "scasd", + "scasq", + "seto", + "setno", + "setb", + "setae", + "setz", + "setnz", + "setbe", + "seta", + "sets", + "setns", + "setp", + "setnp", + "setl", + "setge", + "setle", + "setg", + "sfence", + "sgdt", + "shld", + "shrd", + "shufpd", + "shufps", + "sidt", + "sldt", + "smsw", + "sqrtps", + "sqrtpd", + "sqrtsd", + "sqrtss", + "stc", + "std", + "stgi", + "sti", + "skinit", + "stmxcsr", + "stosb", + "stosw", + "stosd", + "stosq", + "str", + "sub", + "subpd", + "subps", + "subsd", + "subss", + "swapgs", + "syscall", + "sysenter", + "sysexit", + "sysret", + "test", + "ucomisd", + "ucomiss", + "ud2", + "unpckhpd", + "unpckhps", + "unpcklps", + "unpcklpd", + "verr", + "verw", + "vmcall", + "vmclear", + "vmxon", + "vmptrld", + "vmptrst", + "vmlaunch", + "vmresume", + "vmxoff", + "vmread", + "vmwrite", + "vmrun", + "vmmcall", + "vmload", + "vmsave", + "wait", + "wbinvd", + "wrmsr", + "xadd", + "xchg", + "xgetbv", + "xlatb", + "xor", + "xorpd", + "xorps", + "xcryptecb", + "xcryptcbc", + "xcryptctr", + "xcryptcfb", + "xcryptofb", + "xrstor", + "xsave", + "xsetbv", + "xsha1", + "xsha256", + "xstore", + "aesdec", + "aesdeclast", + "aesenc", + "aesenclast", + "aesimc", + "aeskeygenassist", + "pclmulqdq", + "getsec", + "movdqa", + "maskmovdqu", + "movdq2q", + "movdqu", + "movq2dq", + "paddq", + "psubq", + "pmuludq", + "pshufhw", + "pshuflw", + "pshufd", + "pslldq", + "psrldq", + "punpckhqdq", + "punpcklqdq", + "addsubpd", + "addsubps", + "haddpd", + "haddps", + "hsubpd", + "hsubps", + "movddup", + "movshdup", + "movsldup", + "pabsb", + "pabsw", + "pabsd", + "pshufb", + "phaddw", + "phaddd", + "phaddsw", + "pmaddubsw", + "phsubw", + "phsubd", + "phsubsw", + "psignb", + "psignd", + "psignw", + "pmulhrsw", + "palignr", + "pblendvb", + "pmuldq", + "pminsb", + "pminsd", + "pminuw", + "pminud", + "pmaxsb", + "pmaxsd", + "pmaxud", + "pmaxuw", + "pmulld", + "phminposuw", + "roundps", + "roundpd", + "roundss", + "roundsd", + "blendpd", + "pblendw", + "blendps", + "blendvpd", + "blendvps", + "dpps", + "dppd", + "mpsadbw", + "extractps", + "insertps", + "movntdqa", + "packusdw", + "pmovsxbw", + "pmovsxbd", + "pmovsxbq", + "pmovsxwd", + "pmovsxwq", + "pmovsxdq", + "pmovzxbw", + "pmovzxbd", + "pmovzxbq", + "pmovzxwd", + "pmovzxwq", + "pmovzxdq", + "pcmpeqq", + "popcnt", + "ptest", + "pcmpestri", + "pcmpestrm", + "pcmpgtq", + "pcmpistri", + "pcmpistrm", + "movbe", + "crc32" +}; +#endif /* __INSIDE_CYGWIN__ */ diff --git a/winsup/cygwin/udis86/itab.h b/winsup/cygwin/udis86/itab.h new file mode 100644 index 0000000..b6924b7 --- /dev/null +++ b/winsup/cygwin/udis86/itab.h @@ -0,0 +1,680 @@ +#ifndef UD_ITAB_H +#define UD_ITAB_H + +/* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */ + +/* ud_table_type -- lookup table types (see decode.c) */ +enum ud_table_type { + UD_TAB__OPC_TABLE, + UD_TAB__OPC_X87, + UD_TAB__OPC_MOD, + UD_TAB__OPC_VEX_M, + UD_TAB__OPC_VEX_P, + UD_TAB__OPC_RM, + UD_TAB__OPC_VENDOR, + UD_TAB__OPC_OSIZE, + UD_TAB__OPC_MODE, + UD_TAB__OPC_3DNOW, + UD_TAB__OPC_REG, + UD_TAB__OPC_ASIZE, + UD_TAB__OPC_SSE +}; + +/* ud_mnemonic -- mnemonic constants */ +enum ud_mnemonic_code { + UD_Iinvalid, + UD_I3dnow, + UD_Inone, + UD_Idb, + UD_Ipause, + UD_Iaaa, + UD_Iaad, + UD_Iaam, + UD_Iaas, + UD_Iadc, + UD_Iadd, + UD_Iaddpd, + UD_Iaddps, + UD_Iaddsd, + UD_Iaddss, + UD_Iand, + UD_Iandpd, + UD_Iandps, + UD_Iandnpd, + UD_Iandnps, + UD_Iarpl, + UD_Imovsxd, + UD_Ibound, + UD_Ibsf, + UD_Ibsr, + UD_Ibswap, + UD_Ibt, + UD_Ibtc, + UD_Ibtr, + UD_Ibts, + UD_Icall, + UD_Icbw, + UD_Icwde, + UD_Icdqe, + UD_Iclc, + UD_Icld, + UD_Iclflush, + UD_Iclgi, + UD_Icli, + UD_Iclts, + UD_Icmc, + UD_Icmovo, + UD_Icmovno, + UD_Icmovb, + UD_Icmovae, + UD_Icmovz, + UD_Icmovnz, + UD_Icmovbe, + UD_Icmova, + UD_Icmovs, + UD_Icmovns, + UD_Icmovp, + UD_Icmovnp, + UD_Icmovl, + UD_Icmovge, + UD_Icmovle, + UD_Icmovg, + UD_Icmp, + UD_Icmppd, + UD_Icmpps, + UD_Icmpsb, + UD_Icmpsw, + UD_Icmpsd, + UD_Icmpsq, + UD_Icmpss, + UD_Icmpxchg, + UD_Icmpxchg8b, + UD_Icmpxchg16b, + UD_Icomisd, + UD_Icomiss, + UD_Icpuid, + UD_Icvtdq2pd, + UD_Icvtdq2ps, + UD_Icvtpd2dq, + UD_Icvtpd2pi, + UD_Icvtpd2ps, + UD_Icvtpi2ps, + UD_Icvtpi2pd, + UD_Icvtps2dq, + UD_Icvtps2pi, + UD_Icvtps2pd, + UD_Icvtsd2si, + UD_Icvtsd2ss, + UD_Icvtsi2ss, + UD_Icvtss2si, + UD_Icvtss2sd, + UD_Icvttpd2pi, + UD_Icvttpd2dq, + UD_Icvttps2dq, + UD_Icvttps2pi, + UD_Icvttsd2si, + UD_Icvtsi2sd, + UD_Icvttss2si, + UD_Icwd, + UD_Icdq, + UD_Icqo, + UD_Idaa, + UD_Idas, + UD_Idec, + UD_Idiv, + UD_Idivpd, + UD_Idivps, + UD_Idivsd, + UD_Idivss, + UD_Iemms, + UD_Ienter, + UD_If2xm1, + UD_Ifabs, + UD_Ifadd, + UD_Ifaddp, + UD_Ifbld, + UD_Ifbstp, + UD_Ifchs, + UD_Ifclex, + UD_Ifcmovb, + UD_Ifcmove, + UD_Ifcmovbe, + UD_Ifcmovu, + UD_Ifcmovnb, + UD_Ifcmovne, + UD_Ifcmovnbe, + UD_Ifcmovnu, + UD_Ifucomi, + UD_Ifcom, + UD_Ifcom2, + UD_Ifcomp3, + UD_Ifcomi, + UD_Ifucomip, + UD_Ifcomip, + UD_Ifcomp, + UD_Ifcomp5, + UD_Ifcompp, + UD_Ifcos, + UD_Ifdecstp, + UD_Ifdiv, + UD_Ifdivp, + UD_Ifdivr, + UD_Ifdivrp, + UD_Ifemms, + UD_Iffree, + UD_Iffreep, + UD_Ificom, + UD_Ificomp, + UD_Ifild, + UD_Ifincstp, + UD_Ifninit, + UD_Ifiadd, + UD_Ifidivr, + UD_Ifidiv, + UD_Ifisub, + UD_Ifisubr, + UD_Ifist, + UD_Ifistp, + UD_Ifisttp, + UD_Ifld, + UD_Ifld1, + UD_Ifldl2t, + UD_Ifldl2e, + UD_Ifldpi, + UD_Ifldlg2, + UD_Ifldln2, + UD_Ifldz, + UD_Ifldcw, + UD_Ifldenv, + UD_Ifmul, + UD_Ifmulp, + UD_Ifimul, + UD_Ifnop, + UD_Ifpatan, + UD_Ifprem, + UD_Ifprem1, + UD_Ifptan, + UD_Ifrndint, + UD_Ifrstor, + UD_Ifnsave, + UD_Ifscale, + UD_Ifsin, + UD_Ifsincos, + UD_Ifsqrt, + UD_Ifstp, + UD_Ifstp1, + UD_Ifstp8, + UD_Ifstp9, + UD_Ifst, + UD_Ifnstcw, + UD_Ifnstenv, + UD_Ifnstsw, + UD_Ifsub, + UD_Ifsubp, + UD_Ifsubr, + UD_Ifsubrp, + UD_Iftst, + UD_Ifucom, + UD_Ifucomp, + UD_Ifucompp, + UD_Ifxam, + UD_Ifxch, + UD_Ifxch4, + UD_Ifxch7, + UD_Ifxrstor, + UD_Ifxsave, + UD_Ifxtract, + UD_Ifyl2x, + UD_Ifyl2xp1, + UD_Ihlt, + UD_Iidiv, + UD_Iin, + UD_Iimul, + UD_Iinc, + UD_Iinsb, + UD_Iinsw, + UD_Iinsd, + UD_Iint1, + UD_Iint3, + UD_Iint, + UD_Iinto, + UD_Iinvd, + UD_Iinvept, + UD_Iinvlpg, + UD_Iinvlpga, + UD_Iinvvpid, + UD_Iiretw, + UD_Iiretd, + UD_Iiretq, + UD_Ijo, + UD_Ijno, + UD_Ijb, + UD_Ijae, + UD_Ijz, + UD_Ijnz, + UD_Ijbe, + UD_Ija, + UD_Ijs, + UD_Ijns, + UD_Ijp, + UD_Ijnp, + UD_Ijl, + UD_Ijge, + UD_Ijle, + UD_Ijg, + UD_Ijcxz, + UD_Ijecxz, + UD_Ijrcxz, + UD_Ijmp, + UD_Ilahf, + UD_Ilar, + UD_Ilddqu, + UD_Ildmxcsr, + UD_Ilds, + UD_Ilea, + UD_Iles, + UD_Ilfs, + UD_Ilgs, + UD_Ilidt, + UD_Ilss, + UD_Ileave, + UD_Ilfence, + UD_Ilgdt, + UD_Illdt, + UD_Ilmsw, + UD_Ilock, + UD_Ilodsb, + UD_Ilodsw, + UD_Ilodsd, + UD_Ilodsq, + UD_Iloopne, + UD_Iloope, + UD_Iloop, + UD_Ilsl, + UD_Iltr, + UD_Imaskmovq, + UD_Imaxpd, + UD_Imaxps, + UD_Imaxsd, + UD_Imaxss, + UD_Imfence, + UD_Iminpd, + UD_Iminps, + UD_Iminsd, + UD_Iminss, + UD_Imonitor, + UD_Imontmul, + UD_Imov, + UD_Imovapd, + UD_Imovaps, + UD_Imovd, + UD_Imovhpd, + UD_Imovhps, + UD_Imovlhps, + UD_Imovlpd, + UD_Imovlps, + UD_Imovhlps, + UD_Imovmskpd, + UD_Imovmskps, + UD_Imovntdq, + UD_Imovnti, + UD_Imovntpd, + UD_Imovntps, + UD_Imovntq, + UD_Imovq, + UD_Imovsb, + UD_Imovsw, + UD_Imovsd, + UD_Imovsq, + UD_Imovss, + UD_Imovsx, + UD_Imovupd, + UD_Imovups, + UD_Imovzx, + UD_Imul, + UD_Imulpd, + UD_Imulps, + UD_Imulsd, + UD_Imulss, + UD_Imwait, + UD_Ineg, + UD_Inop, + UD_Inot, + UD_Ior, + UD_Iorpd, + UD_Iorps, + UD_Iout, + UD_Ioutsb, + UD_Ioutsw, + UD_Ioutsd, + UD_Ipacksswb, + UD_Ipackssdw, + UD_Ipackuswb, + UD_Ipaddb, + UD_Ipaddw, + UD_Ipaddd, + UD_Ipaddsb, + UD_Ipaddsw, + UD_Ipaddusb, + UD_Ipaddusw, + UD_Ipand, + UD_Ipandn, + UD_Ipavgb, + UD_Ipavgw, + UD_Ipcmpeqb, + UD_Ipcmpeqw, + UD_Ipcmpeqd, + UD_Ipcmpgtb, + UD_Ipcmpgtw, + UD_Ipcmpgtd, + UD_Ipextrb, + UD_Ipextrd, + UD_Ipextrq, + UD_Ipextrw, + UD_Ipinsrb, + UD_Ipinsrw, + UD_Ipinsrd, + UD_Ipinsrq, + UD_Ipmaddwd, + UD_Ipmaxsw, + UD_Ipmaxub, + UD_Ipminsw, + UD_Ipminub, + UD_Ipmovmskb, + UD_Ipmulhuw, + UD_Ipmulhw, + UD_Ipmullw, + UD_Ipop, + UD_Ipopa, + UD_Ipopad, + UD_Ipopfw, + UD_Ipopfd, + UD_Ipopfq, + UD_Ipor, + UD_Iprefetch, + UD_Iprefetchnta, + UD_Iprefetcht0, + UD_Iprefetcht1, + UD_Iprefetcht2, + UD_Ipsadbw, + UD_Ipshufw, + UD_Ipsllw, + UD_Ipslld, + UD_Ipsllq, + UD_Ipsraw, + UD_Ipsrad, + UD_Ipsrlw, + UD_Ipsrld, + UD_Ipsrlq, + UD_Ipsubb, + UD_Ipsubw, + UD_Ipsubd, + UD_Ipsubsb, + UD_Ipsubsw, + UD_Ipsubusb, + UD_Ipsubusw, + UD_Ipunpckhbw, + UD_Ipunpckhwd, + UD_Ipunpckhdq, + UD_Ipunpcklbw, + UD_Ipunpcklwd, + UD_Ipunpckldq, + UD_Ipi2fw, + UD_Ipi2fd, + UD_Ipf2iw, + UD_Ipf2id, + UD_Ipfnacc, + UD_Ipfpnacc, + UD_Ipfcmpge, + UD_Ipfmin, + UD_Ipfrcp, + UD_Ipfrsqrt, + UD_Ipfsub, + UD_Ipfadd, + UD_Ipfcmpgt, + UD_Ipfmax, + UD_Ipfrcpit1, + UD_Ipfrsqit1, + UD_Ipfsubr, + UD_Ipfacc, + UD_Ipfcmpeq, + UD_Ipfmul, + UD_Ipfrcpit2, + UD_Ipmulhrw, + UD_Ipswapd, + UD_Ipavgusb, + UD_Ipush, + UD_Ipusha, + UD_Ipushad, + UD_Ipushfw, + UD_Ipushfd, + UD_Ipushfq, + UD_Ipxor, + UD_Ircl, + UD_Ircr, + UD_Irol, + UD_Iror, + UD_Ircpps, + UD_Ircpss, + UD_Irdmsr, + UD_Irdpmc, + UD_Irdtsc, + UD_Irdtscp, + UD_Irepne, + UD_Irep, + UD_Iret, + UD_Iretf, + UD_Irsm, + UD_Irsqrtps, + UD_Irsqrtss, + UD_Isahf, + UD_Isalc, + UD_Isar, + UD_Ishl, + UD_Ishr, + UD_Isbb, + UD_Iscasb, + UD_Iscasw, + UD_Iscasd, + UD_Iscasq, + UD_Iseto, + UD_Isetno, + UD_Isetb, + UD_Isetae, + UD_Isetz, + UD_Isetnz, + UD_Isetbe, + UD_Iseta, + UD_Isets, + UD_Isetns, + UD_Isetp, + UD_Isetnp, + UD_Isetl, + UD_Isetge, + UD_Isetle, + UD_Isetg, + UD_Isfence, + UD_Isgdt, + UD_Ishld, + UD_Ishrd, + UD_Ishufpd, + UD_Ishufps, + UD_Isidt, + UD_Isldt, + UD_Ismsw, + UD_Isqrtps, + UD_Isqrtpd, + UD_Isqrtsd, + UD_Isqrtss, + UD_Istc, + UD_Istd, + UD_Istgi, + UD_Isti, + UD_Iskinit, + UD_Istmxcsr, + UD_Istosb, + UD_Istosw, + UD_Istosd, + UD_Istosq, + UD_Istr, + UD_Isub, + UD_Isubpd, + UD_Isubps, + UD_Isubsd, + UD_Isubss, + UD_Iswapgs, + UD_Isyscall, + UD_Isysenter, + UD_Isysexit, + UD_Isysret, + UD_Itest, + UD_Iucomisd, + UD_Iucomiss, + UD_Iud2, + UD_Iunpckhpd, + UD_Iunpckhps, + UD_Iunpcklps, + UD_Iunpcklpd, + UD_Iverr, + UD_Iverw, + UD_Ivmcall, + UD_Ivmclear, + UD_Ivmxon, + UD_Ivmptrld, + UD_Ivmptrst, + UD_Ivmlaunch, + UD_Ivmresume, + UD_Ivmxoff, + UD_Ivmread, + UD_Ivmwrite, + UD_Ivmrun, + UD_Ivmmcall, + UD_Ivmload, + UD_Ivmsave, + UD_Iwait, + UD_Iwbinvd, + UD_Iwrmsr, + UD_Ixadd, + UD_Ixchg, + UD_Ixgetbv, + UD_Ixlatb, + UD_Ixor, + UD_Ixorpd, + UD_Ixorps, + UD_Ixcryptecb, + UD_Ixcryptcbc, + UD_Ixcryptctr, + UD_Ixcryptcfb, + UD_Ixcryptofb, + UD_Ixrstor, + UD_Ixsave, + UD_Ixsetbv, + UD_Ixsha1, + UD_Ixsha256, + UD_Ixstore, + UD_Iaesdec, + UD_Iaesdeclast, + UD_Iaesenc, + UD_Iaesenclast, + UD_Iaesimc, + UD_Iaeskeygenassist, + UD_Ipclmulqdq, + UD_Igetsec, + UD_Imovdqa, + UD_Imaskmovdqu, + UD_Imovdq2q, + UD_Imovdqu, + UD_Imovq2dq, + UD_Ipaddq, + UD_Ipsubq, + UD_Ipmuludq, + UD_Ipshufhw, + UD_Ipshuflw, + UD_Ipshufd, + UD_Ipslldq, + UD_Ipsrldq, + UD_Ipunpckhqdq, + UD_Ipunpcklqdq, + UD_Iaddsubpd, + UD_Iaddsubps, + UD_Ihaddpd, + UD_Ihaddps, + UD_Ihsubpd, + UD_Ihsubps, + UD_Imovddup, + UD_Imovshdup, + UD_Imovsldup, + UD_Ipabsb, + UD_Ipabsw, + UD_Ipabsd, + UD_Ipshufb, + UD_Iphaddw, + UD_Iphaddd, + UD_Iphaddsw, + UD_Ipmaddubsw, + UD_Iphsubw, + UD_Iphsubd, + UD_Iphsubsw, + UD_Ipsignb, + UD_Ipsignd, + UD_Ipsignw, + UD_Ipmulhrsw, + UD_Ipalignr, + UD_Ipblendvb, + UD_Ipmuldq, + UD_Ipminsb, + UD_Ipminsd, + UD_Ipminuw, + UD_Ipminud, + UD_Ipmaxsb, + UD_Ipmaxsd, + UD_Ipmaxud, + UD_Ipmaxuw, + UD_Ipmulld, + UD_Iphminposuw, + UD_Iroundps, + UD_Iroundpd, + UD_Iroundss, + UD_Iroundsd, + UD_Iblendpd, + UD_Ipblendw, + UD_Iblendps, + UD_Iblendvpd, + UD_Iblendvps, + UD_Idpps, + UD_Idppd, + UD_Impsadbw, + UD_Iextractps, + UD_Iinsertps, + UD_Imovntdqa, + UD_Ipackusdw, + UD_Ipmovsxbw, + UD_Ipmovsxbd, + UD_Ipmovsxbq, + UD_Ipmovsxwd, + UD_Ipmovsxwq, + UD_Ipmovsxdq, + UD_Ipmovzxbw, + UD_Ipmovzxbd, + UD_Ipmovzxbq, + UD_Ipmovzxwd, + UD_Ipmovzxwq, + UD_Ipmovzxdq, + UD_Ipcmpeqq, + UD_Ipopcnt, + UD_Iptest, + UD_Ipcmpestri, + UD_Ipcmpestrm, + UD_Ipcmpgtq, + UD_Ipcmpistri, + UD_Ipcmpistrm, + UD_Imovbe, + UD_Icrc32, + UD_MAX_MNEMONIC_CODE +} UD_ATTR_PACKED; + +#ifndef __INSIDE_CYGWIN__ +extern const char * ud_mnemonics_str[]; +#endif /* __INSIDE_CYGWIN__ */ + +#endif /* UD_ITAB_H */ diff --git a/winsup/cygwin/udis86/types.h b/winsup/cygwin/udis86/types.h new file mode 100644 index 0000000..2d2dc68 --- /dev/null +++ b/winsup/cygwin/udis86/types.h @@ -0,0 +1,260 @@ +/* udis86 - libudis86/types.h + * + * Copyright (c) 2002-2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * + * 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 OWNER 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 UD_TYPES_H +#define UD_TYPES_H + +#ifdef __KERNEL__ + /* -D__KERNEL__ is automatically passed on the command line when + building something as part of the Linux kernel */ +# include <linux/kernel.h> +# include <linux/string.h> +# ifndef __UD_STANDALONE__ +# define __UD_STANDALONE__ 1 +#endif +#endif /* __KERNEL__ */ + +#ifdef __INSIDE_CYGWIN__ +# include <inttypes.h> +# ifndef __UD_STANDALONE__ +# define __UD_STANDALONE__ 1 +# endif +#endif /* __INSIDE_CYGWIN__ */ + + +#if defined(_MSC_VER) || defined(__BORLANDC__) +# include <stdint.h> +# include <stdio.h> +# define inline __inline /* MS Visual Studio requires __inline + instead of inline for C code */ +#elif !defined(__UD_STANDALONE__) +# include <stdio.h> +# include <inttypes.h> +#endif /* !__UD_STANDALONE__ */ + +/* gcc specific extensions */ +#ifdef __GNUC__ +# define UD_ATTR_PACKED __attribute__((packed)) +#else +# define UD_ATTR_PACKED +#endif /* UD_ATTR_PACKED */ + + +/* ----------------------------------------------------------------------------- + * All possible "types" of objects in udis86. Order is Important! + * ----------------------------------------------------------------------------- + */ +enum ud_type +{ + UD_NONE, + + /* 8 bit GPRs */ + UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, + UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, + UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, + UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, + UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, + + /* 16 bit GPRs */ + UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, + UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, + UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, + UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, + + /* 32 bit GPRs */ + UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, + UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, + UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, + UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, + + /* 64 bit GPRs */ + UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, + UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, + UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, + UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, + + /* segment registers */ + UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, + UD_R_FS, UD_R_GS, + + /* control registers*/ + UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, + UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, + UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, + UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, + + /* debug registers */ + UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, + UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, + UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, + UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, + + /* mmx registers */ + UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, + UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, + + /* x87 registers */ + UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, + UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, + + /* extended multimedia registers */ + UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, + UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, + UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, + UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, + + UD_R_RIP, + + /* Operand Types */ + UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, + UD_OP_JIMM, UD_OP_CONST +}; + +#include "itab.h" + +union ud_lval { + int8_t sbyte; + uint8_t ubyte; + int16_t sword; + uint16_t uword; + int32_t sdword; + uint32_t udword; + int64_t sqword; + uint64_t uqword; + struct { + uint16_t seg; + uint32_t off; + } ptr; +}; + +/* ----------------------------------------------------------------------------- + * struct ud_operand - Disassembled instruction Operand. + * ----------------------------------------------------------------------------- + */ +struct ud_operand { + enum ud_type type; + uint8_t size; + enum ud_type base; + enum ud_type index; + uint8_t scale; + uint8_t offset; + union ud_lval lval; + /* + * internal use only + */ + uint64_t _legacy; /* this will be removed in 1.8 */ + uint8_t _oprcode; +}; + +/* ----------------------------------------------------------------------------- + * struct ud - The udis86 object. + * ----------------------------------------------------------------------------- + */ +struct ud +{ + /* + * input buffering + */ + int (*inp_hook) (struct ud*); +#ifndef __UD_STANDALONE__ + FILE* inp_file; +#endif + const uint8_t* inp_buf; + size_t inp_buf_size; + size_t inp_buf_index; + uint8_t inp_curr; + size_t inp_ctr; + uint8_t inp_sess[64]; + int inp_end; + + void (*translator)(struct ud*); + uint64_t insn_offset; + char insn_hexcode[64]; + + /* + * Assembly output buffer + */ + char *asm_buf; + size_t asm_buf_size; + size_t asm_buf_fill; + char asm_buf_int[128]; + + /* + * Symbol resolver for use in the translation phase. + */ + const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset); + + uint8_t dis_mode; + uint64_t pc; + uint8_t vendor; + enum ud_mnemonic_code mnemonic; + struct ud_operand operand[3]; + uint8_t error; + uint8_t pfx_rex; + uint8_t pfx_seg; + uint8_t pfx_opr; + uint8_t pfx_adr; + uint8_t pfx_lock; + uint8_t pfx_str; + uint8_t pfx_rep; + uint8_t pfx_repe; + uint8_t pfx_repne; + uint8_t opr_mode; + uint8_t adr_mode; + uint8_t br_far; + uint8_t br_near; + uint8_t have_modrm; + uint8_t modrm; + uint8_t primary_opcode; + void * user_opaque_data; + const struct ud_itab_entry * itab_entry; + const struct ud_lookup_table_list_entry *le; +}; + +/* ----------------------------------------------------------------------------- + * Type-definitions + * ----------------------------------------------------------------------------- + */ +typedef enum ud_type ud_type_t; +typedef enum ud_mnemonic_code ud_mnemonic_code_t; + +typedef struct ud ud_t; +typedef struct ud_operand ud_operand_t; + +#ifndef __INSIDE_CYGWIN__ +#define UD_SYN_INTEL ud_translate_intel +#define UD_SYN_ATT ud_translate_att +#endif /* __INSIDE_CYGWIN__ */ +#define UD_EOI (-1) +#define UD_INP_CACHE_SZ 32 +#define UD_VENDOR_AMD 0 +#define UD_VENDOR_INTEL 1 +#define UD_VENDOR_ANY 2 + +#endif + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/winsup/cygwin/udis86/udint.h b/winsup/cygwin/udis86/udint.h new file mode 100644 index 0000000..2969547 --- /dev/null +++ b/winsup/cygwin/udis86/udint.h @@ -0,0 +1,91 @@ +/* udis86 - libudis86/udint.h -- definitions for internal use only + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * + * 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 OWNER 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 _UDINT_H_ +#define _UDINT_H_ + +#ifndef __INSIDE_CYGWIN__ +# ifdef HAVE_CONFIG_H +# include <config.h> +# endif /* HAVE_CONFIG_H */ +#endif /* __INSIDE_CYGWIN__ */ + +#if defined(UD_DEBUG) && HAVE_ASSERT_H +# include <assert.h> +# define UD_ASSERT(_x) assert(_x) +#else +# define UD_ASSERT(_x) +#endif /* !HAVE_ASSERT_H */ + +#if defined(UD_DEBUG) + #define UDERR(u, msg) \ + do { \ + (u)->error = 1; \ + fprintf(stderr, "decode-error: %s:%d: %s", \ + __FILE__, __LINE__, (msg)); \ + } while (0) +#else + #define UDERR(u, m) \ + do { \ + (u)->error = 1; \ + } while (0) +#endif /* !LOGERR */ + +#define UD_RETURN_ON_ERROR(u) \ + do { \ + if ((u)->error != 0) { \ + return (u)->error; \ + } \ + } while (0) + +#define UD_RETURN_WITH_ERROR(u, m) \ + do { \ + UDERR(u, m); \ + return (u)->error; \ + } while (0) + +#ifndef __UD_STANDALONE__ +# define UD_NON_STANDALONE(x) x +#else +# define UD_NON_STANDALONE(x) +#endif + +/* printf formatting int64 specifier */ +#ifdef FMT64 +# undef FMT64 +#endif +#if defined(_MSC_VER) || defined(__BORLANDC__) +# define FMT64 "I64" +#else +# if defined(__APPLE__) +# define FMT64 "ll" +# elif defined(__amd64__) || defined(__x86_64__) +# define FMT64 "l" +# else +# define FMT64 "ll" +# endif /* !x64 */ +#endif + +#endif /* _UDINT_H_ */ diff --git a/winsup/cygwin/udis86/udis86.c b/winsup/cygwin/udis86/udis86.c new file mode 100644 index 0000000..53db032 --- /dev/null +++ b/winsup/cygwin/udis86/udis86.c @@ -0,0 +1,464 @@ +/* udis86 - libudis86/udis86.c + * + * Copyright (c) 2002-2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * + * 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 OWNER 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 "winsup.h" +#include "extern.h" +#include "udint.h" +#include "decode.h" + +#if !defined(__UD_STANDALONE__) +# if HAVE_STRING_H +# include <string.h> +# endif +#endif /* !__UD_STANDALONE__ */ + +#ifdef __INSIDE_CYGWIN__ +#define sprintf __small_sprintf +#endif /* __INSIDE_CYGWIN__ */ + +static void ud_inp_init(struct ud *u); + +/* ============================================================================= + * ud_init + * Initializes ud_t object. + * ============================================================================= + */ +extern void +ud_init(struct ud* u) +{ + memset((void*)u, 0, sizeof(struct ud)); + ud_set_mode(u, 16); + u->mnemonic = UD_Iinvalid; + ud_set_pc(u, 0); +#ifndef __UD_STANDALONE__ + ud_set_input_file(u, stdin); +#endif /* __UD_STANDALONE__ */ + + ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); +} + + +/* ============================================================================= + * ud_disassemble + * Disassembles one instruction and returns the number of + * bytes disassembled. A zero means end of disassembly. + * ============================================================================= + */ +extern unsigned int +ud_disassemble(struct ud* u) +{ + int len; + if (u->inp_end) { + return 0; + } + if ((len = ud_decode(u)) > 0) { + if (u->translator != NULL) { + u->asm_buf[0] = '\0'; + u->translator(u); + } + } + return len; +} + + +/* ============================================================================= + * ud_set_mode() - Set Disassemly Mode. + * ============================================================================= + */ +extern void +ud_set_mode(struct ud* u, uint8_t m) +{ + switch(m) { + case 16: + case 32: + case 64: u->dis_mode = m ; return; + default: u->dis_mode = 16; return; + } +} + +/* ============================================================================= + * ud_set_vendor() - Set vendor. + * ============================================================================= + */ +extern void +ud_set_vendor(struct ud* u, unsigned v) +{ + switch(v) { + case UD_VENDOR_INTEL: + u->vendor = v; + break; + case UD_VENDOR_ANY: + u->vendor = v; + break; + default: + u->vendor = UD_VENDOR_AMD; + } +} + +/* ============================================================================= + * ud_set_pc() - Sets code origin. + * ============================================================================= + */ +extern void +ud_set_pc(struct ud* u, uint64_t o) +{ + u->pc = o; +} + +/* ============================================================================= + * ud_set_syntax() - Sets the output syntax. + * ============================================================================= + */ +extern void +ud_set_syntax(struct ud* u, void (*t)(struct ud*)) +{ + u->translator = t; +} + +/* ============================================================================= + * ud_insn() - returns the disassembled instruction + * ============================================================================= + */ +const char* +ud_insn_asm(const struct ud* u) +{ + return u->asm_buf; +} + +/* ============================================================================= + * ud_insn_offset() - Returns the offset. + * ============================================================================= + */ +uint64_t +ud_insn_off(const struct ud* u) +{ + return u->insn_offset; +} + + +/* ============================================================================= + * ud_insn_hex() - Returns hex form of disassembled instruction. + * ============================================================================= + */ +const char* +ud_insn_hex(struct ud* u) +{ + u->insn_hexcode[0] = 0; + if (!u->error) { + unsigned int i; + const unsigned char *src_ptr = ud_insn_ptr(u); + char* src_hex; + src_hex = (char*) u->insn_hexcode; + /* for each byte used to decode instruction */ + for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; + ++i, ++src_ptr) { + sprintf(src_hex, "%02x", *src_ptr & 0xFF); + src_hex += 2; + } + } + return u->insn_hexcode; +} + + +/* ============================================================================= + * ud_insn_ptr + * Returns a pointer to buffer containing the bytes that were + * disassembled. + * ============================================================================= + */ +extern const uint8_t* +ud_insn_ptr(const struct ud* u) +{ + return (u->inp_buf == NULL) ? + u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); +} + + +/* ============================================================================= + * ud_insn_len + * Returns the count of bytes disassembled. + * ============================================================================= + */ +extern unsigned int +ud_insn_len(const struct ud* u) +{ + return u->inp_ctr; +} + + +/* ============================================================================= + * ud_insn_get_opr + * Return the operand struct representing the nth operand of + * the currently disassembled instruction. Returns NULL if + * there's no such operand. + * ============================================================================= + */ +const struct ud_operand* +ud_insn_opr(const struct ud *u, unsigned int n) +{ + if (n > 2 || u->operand[n].type == UD_NONE) { + return NULL; + } else { + return &u->operand[n]; + } +} + + +/* ============================================================================= + * ud_opr_is_sreg + * Returns non-zero if the given operand is of a segment register type. + * ============================================================================= + */ +int +ud_opr_is_sreg(const struct ud_operand *opr) +{ + return opr->type == UD_OP_REG && + opr->base >= UD_R_ES && + opr->base <= UD_R_GS; +} + + +/* ============================================================================= + * ud_opr_is_sreg + * Returns non-zero if the given operand is of a general purpose + * register type. + * ============================================================================= + */ +int +ud_opr_is_gpr(const struct ud_operand *opr) +{ + return opr->type == UD_OP_REG && + opr->base >= UD_R_AL && + opr->base <= UD_R_R15; +} + + +/* ============================================================================= + * ud_set_user_opaque_data + * ud_get_user_opaque_data + * Get/set user opaqute data pointer + * ============================================================================= + */ +void +ud_set_user_opaque_data(struct ud * u, void* opaque) +{ + u->user_opaque_data = opaque; +} + +void* +ud_get_user_opaque_data(const struct ud *u) +{ + return u->user_opaque_data; +} + + +/* ============================================================================= + * ud_set_asm_buffer + * Allow the user to set an assembler output buffer. If `buf` is NULL, + * we switch back to the internal buffer. + * ============================================================================= + */ +void +ud_set_asm_buffer(struct ud *u, char *buf, size_t size) +{ + if (buf == NULL) { + ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); + } else { + u->asm_buf = buf; + u->asm_buf_size = size; + } +} + + +/* ============================================================================= + * ud_set_sym_resolver + * Set symbol resolver for relative targets used in the translation + * phase. + * + * The resolver is a function that takes a uint64_t address and returns a + * symbolic name for the that address. The function also takes a second + * argument pointing to an integer that the client can optionally set to a + * non-zero value for offsetted targets. (symbol+offset) The function may + * also return NULL, in which case the translator only prints the target + * address. + * + * The function pointer maybe NULL which resets symbol resolution. + * ============================================================================= + */ +void +ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, + uint64_t addr, + int64_t *offset)) +{ + u->sym_resolver = resolver; +} + + +/* ============================================================================= + * ud_insn_mnemonic + * Return the current instruction mnemonic. + * ============================================================================= + */ +enum ud_mnemonic_code +ud_insn_mnemonic(const struct ud *u) +{ + return u->mnemonic; +} + + +#ifndef __INSIDE_CYGWIN__ +/* ============================================================================= + * ud_lookup_mnemonic + * Looks up mnemonic code in the mnemonic string table. + * Returns NULL if the mnemonic code is invalid. + * ============================================================================= + */ +const char* +ud_lookup_mnemonic(enum ud_mnemonic_code c) +{ + if (c < UD_MAX_MNEMONIC_CODE) { + return ud_mnemonics_str[c]; + } else { + return NULL; + } +} +#endif /* __INSIDE_CYGWIN__ */ + + +/* + * ud_inp_init + * Initializes the input system. + */ +static void +ud_inp_init(struct ud *u) +{ + u->inp_hook = NULL; + u->inp_buf = NULL; + u->inp_buf_size = 0; + u->inp_buf_index = 0; + u->inp_curr = 0; + u->inp_ctr = 0; + u->inp_end = 0; + UD_NON_STANDALONE(u->inp_file = NULL); +} + + +/* ============================================================================= + * ud_inp_set_hook + * Sets input hook. + * ============================================================================= + */ +void +ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) +{ + ud_inp_init(u); + u->inp_hook = hook; +} + +/* ============================================================================= + * ud_inp_set_buffer + * Set buffer as input. + * ============================================================================= + */ +void +ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) +{ + ud_inp_init(u); + u->inp_buf = buf; + u->inp_buf_size = len; + u->inp_buf_index = 0; +} + + +#ifndef __UD_STANDALONE__ +/* ============================================================================= + * ud_input_set_file + * Set FILE as input. + * ============================================================================= + */ +static int +inp_file_hook(struct ud* u) +{ + return fgetc(u->inp_file); +} + +void +ud_set_input_file(register struct ud* u, FILE* f) +{ + ud_inp_init(u); + u->inp_hook = inp_file_hook; + u->inp_file = f; +} +#endif /* __UD_STANDALONE__ */ + + +/* ============================================================================= + * ud_input_skip + * Skip n input bytes. + * ============================================================================ + */ +void +ud_input_skip(struct ud* u, size_t n) +{ + if (u->inp_end) { + return; + } + if (u->inp_buf == NULL) { + while (n--) { + int c = u->inp_hook(u); + if (c == UD_EOI) { + goto eoi; + } + } + return; + } else { + if (n > u->inp_buf_size || + u->inp_buf_index > u->inp_buf_size - n) { + u->inp_buf_index = u->inp_buf_size; + goto eoi; + } + u->inp_buf_index += n; + return; + } +eoi: + u->inp_end = 1; + UDERR(u, "cannot skip, eoi received\b"); + return; +} + + +/* ============================================================================= + * ud_input_end + * Returns non-zero on end-of-input. + * ============================================================================= + */ +int +ud_input_end(const struct ud *u) +{ + return u->inp_end; +} + +/* vim:set ts=2 sw=2 expandtab */ diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 27dc289..ffe71ee 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -1983,6 +1983,23 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap) break; case SID_arg: sid = *arg.sid; + + /* SIDs we want to filter out before hitting LookupAccountSidW. + If the latency of the AD connection is high, LookupAccountSidW + might take a long time before returning with ERROR_NONE_MAPPED. */ + + /* Capability SIDs, just drop out, we don't handle them */ + if (sid_id_auth (sid) == 15 /* SECURITY_APP_PACKAGE_AUTHORITY */ + && sid_sub_auth (sid, 0) == SECURITY_CAPABILITY_BASE_RID) + return NULL; + /* IIS APPPOOL */ + if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */ + && sid_sub_auth (sid, 0) == SECURITY_APPPOOL_ID_BASE_RID) + break; + /* Samba user/group SIDs */ + if (sid_id_auth (sid) == 22) + break; + ret = LookupAccountSidW (NULL, sid, name, &nlen, dom, &dlen, &acc_type); if (!ret && cygheap->dom.member_machine () diff --git a/winsup/cygwin/x86_64/fastcwd.cc b/winsup/cygwin/x86_64/fastcwd.cc new file mode 100644 index 0000000..f5a8755 --- /dev/null +++ b/winsup/cygwin/x86_64/fastcwd.cc @@ -0,0 +1,200 @@ +/* x86_64/fastcwd.cc: find fast cwd pointer on x86_64 hosts. + + This file is part of Cygwin. + + This software is a copyrighted work licensed under the terms of the + Cygwin license. Please consult the file "CYGWIN_LICENSE" for + details. */ + +#include "winsup.h" +#include <assert.h> +#include "udis86/types.h" +#include "udis86/extern.h" + +class fcwd_access_t; + +/* Helper function to get the absolute address of an rip-relative instruction + by summing the current instruction's pc (rip), the current instruction's + length, and the signed 32-bit displacement in the operand. Optionally, an + additional offset is subtracted to deal with the case where a member of a + struct is being referenced by the instruction but the address of the struct + is desired. +*/ +static inline const void * +rip_rel_offset (const ud_t *ud_obj, const ud_operand_t *opr, int sub_off=0) +{ + assert ((opr->type == UD_OP_JIMM && opr->size == 32) || + (opr->type == UD_OP_MEM && opr->base == UD_R_RIP && + opr->index == UD_NONE && opr->scale == 0 && opr->offset == 32)); + + return (const void *) (ud_insn_off (ud_obj) + ud_insn_len (ud_obj) + + opr->lval.sdword - sub_off); +} + +/* This function scans the code in ntdll.dll to find the address of the + global variable used to access the CWD. While the pointer is global, + it's not exported from the DLL, unfortunately. Therefore we have to + use some knowledge to figure out the address. */ + +fcwd_access_t ** +find_fast_cwd_pointer_x86_64 () +{ + /* Fetch entry points of relevant functions in ntdll.dll. */ + HMODULE ntdll = GetModuleHandle ("ntdll.dll"); + if (!ntdll) + return NULL; + const uint8_t *get_dir = (const uint8_t *) + GetProcAddress (ntdll, "RtlGetCurrentDirectory_U"); + const uint8_t *ent_crit = (const uint8_t *) + GetProcAddress (ntdll, "RtlEnterCriticalSection"); + if (!get_dir || !ent_crit) + return NULL; + /* Initialize udis86 */ + ud_t ud_obj; + ud_init (&ud_obj); + /* Set 64-bit mode */ + ud_set_mode (&ud_obj, 64); + ud_set_input_buffer (&ud_obj, get_dir, 80); + /* Set pc (rip) so that subsequent calls to ud_insn_off will return the pc of + the instruction, saving us the hassle of tracking it ourselves */ + ud_set_pc (&ud_obj, (uint64_t) get_dir); + const ud_operand_t *opr, *opr0; + ud_mnemonic_code_t insn; + ud_type_t reg = UD_NONE; + /* Search first relative call instruction in RtlGetCurrentDirectory_U. */ + const uint8_t *use_cwd = NULL; + while (ud_disassemble (&ud_obj) && + (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret && + insn != UD_Ijmp) + { + if (insn == UD_Icall) + { + opr = ud_insn_opr (&ud_obj, 0); + if (opr->type == UD_OP_JIMM && opr->size == 32) + { + /* Fetch offset from instruction and compute address of called + function. This function actually fetches the current FAST_CWD + instance and performs some other actions, not important to us. + */ + use_cwd = (const uint8_t *) rip_rel_offset (&ud_obj, opr); + break; + } + } + } + if (!use_cwd) + return NULL; + ud_set_input_buffer (&ud_obj, use_cwd, 120); + ud_set_pc (&ud_obj, (uint64_t) use_cwd); + + /* Next we search for the locking mechanism and perform a sanity check. + we basically look for the RtlEnterCriticalSection call and test if the + code uses the FastPebLock. */ + PRTL_CRITICAL_SECTION lockaddr = NULL; + + while (ud_disassemble (&ud_obj) && + (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret && + insn != UD_Ijmp) + { + if (insn == UD_Ilea) + { + /* udis86 seems to follow intel syntax, in that operand 0 is the + dest and 1 is the src */ + opr0 = ud_insn_opr (&ud_obj, 0); + opr = ud_insn_opr (&ud_obj, 1); + if (opr->type == UD_OP_MEM && opr->base == UD_R_RIP && + opr->index == UD_NONE && opr->scale == 0 && opr->offset == 32 && + opr0->type == UD_OP_REG && opr0->size == 64) + { + lockaddr = (PRTL_CRITICAL_SECTION) rip_rel_offset (&ud_obj, opr); + reg = opr0->base; + break; + } + } + } + + /* Test if lock address is FastPebLock. */ + if (lockaddr != NtCurrentTeb ()->Peb->FastPebLock) + return NULL; + + /* Find where the lock address is loaded into rcx as the first parameter of + a function call */ + bool found = false; + if (reg != UD_R_RCX) + { + while (ud_disassemble (&ud_obj) && + (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret && + insn != UD_Ijmp) + { + if (insn == UD_Imov) + { + opr0 = ud_insn_opr (&ud_obj, 0); + opr = ud_insn_opr (&ud_obj, 1); + if (opr->type == UD_OP_REG && opr->size == 64 && + opr->base == reg && opr0->type == UD_OP_REG && + opr0->size == 64 && opr0->base == UD_R_RCX) + { + found = true; + break; + } + } + } + if (!found) + return NULL; + } + + /* Next is the `callq RtlEnterCriticalSection' */ + found = false; + while (ud_disassemble (&ud_obj) && + (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret && + insn != UD_Ijmp) + { + if (insn == UD_Icall) + { + opr = ud_insn_opr (&ud_obj, 0); + if (opr->type == UD_OP_JIMM && opr->size == 32) + { + if (ent_crit != rip_rel_offset (&ud_obj, opr)) + return NULL; + found = true; + break; + } + } + } + if (!found) + return NULL; + + fcwd_access_t **f_cwd_ptr = NULL; + /* now we're looking for a mov rel(%rip), %<reg64> */ + while (ud_disassemble (&ud_obj) && + (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret && + insn != UD_Ijmp) + { + if (insn == UD_Imov) + { + opr0 = ud_insn_opr (&ud_obj, 0); + opr = ud_insn_opr (&ud_obj, 1); + if (opr->type == UD_OP_MEM && opr->size == 64 && + opr->base == UD_R_RIP && opr->index == UD_NONE && + opr->scale == 0 && opr->offset == 32 && + opr0->type == UD_OP_REG && opr0->size == 64) + { + f_cwd_ptr = (fcwd_access_t **) rip_rel_offset (&ud_obj, opr); + reg = opr0->base; + break; + } + } + } + /* Check that the next instruction is a test. */ + if (!f_cwd_ptr || !ud_disassemble (&ud_obj) || + ud_insn_mnemonic (&ud_obj) != UD_Itest) + return NULL; + + /* ... and that it's testing the same register that the mov above loaded the + f_cwd_ptr into against itself */ + opr0 = ud_insn_opr (&ud_obj, 0); + opr = ud_insn_opr (&ud_obj, 1); + if (opr->type != UD_OP_REG || opr->size != 64 || opr->base != reg || + opr0->type != opr->type || opr0->size != 64 || opr0->base != opr->base) + return NULL; + return f_cwd_ptr; +} diff --git a/winsup/doc/dll.xml b/winsup/doc/dll.xml index f036976..66d65f7 100644 --- a/winsup/doc/dll.xml +++ b/winsup/doc/dll.xml @@ -19,26 +19,53 @@ variables, etc. All these are merged together, like if you were building one big object files, and put into the dll. They are not put into your .exe at all.</para> -<para>The exports contains a list of functions and variables that the +<para>The exports is a list of functions and variables that the dll makes available to other programs. Think of this as the list of -"global" symbols, the rest being hidden. Normally, you'd create this -list by hand with a text editor, but it's possible to do it -automatically from the list of functions in your code. The -<filename>dlltool</filename> program creates the exports section of -the dll from your text file of exported symbols.</para> - -<para>The import library is a regular UNIX-like -<filename>.a</filename> library, but it only contains the tiny bit of -information needed to tell the OS how your program interacts with -("imports") the dll. This information is linked into your -<filename>.exe</filename>. This is also generated by -<filename>dlltool</filename>.</para> +"public" symbols, the rest being hidden. + +<footnote> + <para> + Note that <filename>ld</filename>'s default behaviour is to export all + global symbols, if there otherwise wouldn't be any exported symbols + (i.e. because you haven't specified a def file or made any export + annotations). (See <code>--export-all-symbols</code> in the + <filename>ld</filename> man page for more details.) + </para> +</footnote> + +This list can be in a module definition (.def) file, which you can write by hand +with a text editor, but it's also possible to have it generated automatically +from the functions and variables in your code, by annotating the declarations +with <code>__attribute__ ((dllexport))</code>. + +<footnote> + <para> + If you're making these annotations on the declarations in a header which is + also installed to be included by users of your library, you probably want to + use macros to do the right thing and increase portability. See <ulink + url="https://gcc.gnu.org/wiki/Visibility">this example</ulink> for details. + </para> +</footnote> + +</para> + +<para>The import library is a regular UNIX-like <filename>.a</filename> library, +but it only contains the tiny bit of information ("a stub") needed to tell the +OS how your program interacts with ("imports") the dll. This information is +linked into your <filename>.exe</filename>. +</para> + +<para> + Refer to the <ulink + url="https://sourceware.org/binutils/docs/ld/WIN32.html">section of the ld + manual</ulink> discussing Win32 PE specifics for more details. +</para> <sect2 id="dll-build"><title>Building DLLs</title> -<para>This page gives only a few simple examples of gcc's DLL-building +<para>This page gives only a few simple examples of gcc's DLL-building capabilities. To begin an exploration of the many additional options, -see the gcc documentation and website, currently at +see the gcc documentation and website, currently at <ulink url="http://gcc.gnu.org/">http://gcc.gnu.org/</ulink> </para> @@ -49,8 +76,8 @@ For this example, we'll use a single file <filename>mydll.c</filename> for the contents of the dll (<filename>mydll.dll</filename>).</para> -<para>Fortunately, with the latest gcc and binutils the process for building a dll -is now pretty simple. Say you want to build this minimal function in mydll.c:</para> +<para>Say you want to build this minimal function in +<filename>mydll.c</filename>:</para> <screen> #include <stdio.h> @@ -59,28 +86,44 @@ int hello() { printf ("Hello World!\n"); -} +} </screen> -<para>First compile mydll.c to object code:</para> +<para>First compile <filename>mydll.c</filename> to the object +<filename>mydll.o</filename>:</para> <screen>gcc -c mydll.c</screen> <para>Then, tell gcc that it is building a shared library:</para> -<screen>gcc -shared -o mydll.dll mydll.o</screen> +<screen>gcc -shared -o mydll.dll mydll.o -Wl,--out-implib libmydll.a</screen> + +<para> + That's it! You now have the dll (<filename>mydll.dll</filename>) and the + import library (<filename>libmydll.a</filename>). + +<footnote> + <para> + In fact, <code>--out-implib</code> is optional in this simple example, + because <filename>ld</filename> can automatically generate import stubs when + told to link directly to a .dll. (See <code>--enable-auto-import</code> in + the <filename>ld</filename> man page for more details.) + </para> +</footnote> + +</para> <para> -That's it! To finish up the example, you can now link to the -dll with a simple program: +To finish up the example, you can now link to the dll with a simple program, +<filename>myprog.c</filename>: </para> <screen> -int +int main () { hello (); -} +} </screen> <para> @@ -89,35 +132,84 @@ Then link to your dll with a command like: <screen>gcc -o myprog myprog.c -L./ -lmydll</screen> -<para>However, if you are building a dll as an export library, -you will probably want to use the complete syntax:</para> +<para> + Try it out: +</para> + +<screen> +$ ./myprog +Hello World! +</screen> + +<para>However, if you are building a dll for installation, +you will probably want to use a more complex syntax:</para> <screen>gcc -shared -o cyg${module}.dll \ -Wl,--out-implib=lib${module}.dll.a \ - -Wl,--export-all-symbols \ - -Wl,--enable-auto-import \ - -Wl,--whole-archive ${old_libs} \ - -Wl,--no-whole-archive ${dependency_libs}</screen> + -Wl,--whole-archive ${objs_libs} -Wl,--no-whole-archive \ + ${dependency_libs}</screen> -<para> +<itemizedlist spacing="compact"> +<listitem> The name of your library is <literal>${module}</literal>, prefixed with <literal>cyg</literal> for the DLL and <literal>lib</literal> for the -import library. Cygwin DLLs use the <literal>cyg</literal> prefix to -differentiate them from native-Windows MinGW DLLs, see -<ulink url="http://mingw.org">the MinGW website</ulink> for more details. -<literal>${old_libs}</literal> are all -your object files, bundled together in static libs or single object -files and the <literal>${dependency_libs}</literal> are import libs you -need to link against, e.g -<userinput>'-lpng -lz -L/usr/local/special -lmyspeciallib'</userinput>. +import library. Cygwin DLLs use the <literal>cyg</literal> prefix to +differentiate them from native-Windows MinGW DLLs. +</listitem> +<listitem> +<literal>${objs_libs}</literal> are all your object files, bundled together in +static libs or single object files +</listitem> +<listitem> +<literal>${dependency_libs}</literal> are static or import libs you need to link +against, e.g <userinput>'-lpng -lz -L/usr/local/special -lmyspeciallib' +</userinput>. +</listitem> +</itemizedlist> + +<para> + When the import library is installed into <filename>/usr/lib</filename>, it + can be linked to with just <code>-l${module}</code>. The dll itself is + installed into <filename>/usr/bin</filename> so it can be found on + <code>PATH</code> by the loader when a linked .exe is run. +</para> + +</sect2> + +<sect2 id="dll-tool"><title>dlltool</title> + +<para> +Historically, the process for building a dll with <filename>gcc</filename> and +<filename>binutils</filename> wasn't so simple, and the +<filename>dlltool</filename> tool was used: </para> + +<itemizedlist spacing="compact"> + <listitem> + <para> + To create the exports section of the dll, from the module definition file + or by scanning object files. + </para> + </listitem> + + <listitem> + <para> + To generate the import library. + </para> + </listitem> +</itemizedlist> + +<para> + (See the <filename>dlltool</filename> man page for more details.) +</para> + </sect2> -<sect2 id="dll-link"><title>Linking Against DLLs</title> +<sect2 id="dll-link"><title>Linking Against Foreign DLLs</title> <para>If you have an existing DLL already, you need to build a Cygwin-compatible import library. If you have the source to compile -the DLL, see <xref linkend="dll-build"></xref> for details on having +the DLL, see <xref linkend="dll-build"></xref> for details on having <filename>gcc</filename> build one for you. If you do not have the source or a supplied working import library, you can get most of the way by creating a .def file with these commands (you might need to diff --git a/winsup/doc/faq-programming.xml b/winsup/doc/faq-programming.xml index a834298..39610b9 100644 --- a/winsup/doc/faq-programming.xml +++ b/winsup/doc/faq-programming.xml @@ -676,17 +676,18 @@ rewriting the runtime library in question from specs... <answer> <para>First, you need to make sure you have the necessary build tools -installed; you at least need <literal>gcc-g++</literal>, -<literal>make</literal>, <literal>automake</literal>, -<literal>autoconf</literal>, <literal>git</literal>, <literal>perl</literal>, -<literal>cocom</literal> and <literal>patch</literal>. +installed; you at least need <literal>autoconf</literal>, +<literal>automake</literal>, <literal>cocom</literal>, +<literal>gcc-g++</literal>, <literal>git</literal>, +<literal>libtool</literal>, <literal>make</literal>, +<literal>patch</literal>, and <literal>perl</literal>. </para> <para> Additionally, building the <code>dumper</code> utility requires -<literal>gettext-devel</literal>, <literal>libiconv-devel</literal>, <literal>libzstd-devel</literal> and -<literal>zlib-devel</literal>. Building this program can be disabled with the -<literal>--disable-dumper</literal> option to <literal>configure</literal>. +<literal>gettext-devel</literal>, <literal>libiconv</literal>, +<literal>libiconv-devel</literal>, <literal>libiconv2</literal>, +<literal>libzstd-devel</literal>, and <literal>zlib-devel</literal>. </para> <para> @@ -702,14 +703,27 @@ option to <literal>configure</literal>. <para> Building the documentation also requires the <literal>dblatex</literal>, -<literal>docbook2X</literal>, <literal>docbook-xml45</literal>, -<literal>docbook-xsl</literal>, and <literal>xmlto</literal> packages. Building -the documentation can be disabled with the <literal>--disable-doc</literal> -option to <literal>configure</literal>. +<literal>docbook-utils</literal>, <literal>docbook-xml45</literal>, +<literal>docbook-xsl</literal>, <literal>docbook2X</literal>, +<literal>perl-XML-SAX-Expat</literal>, and <literal>xmlto</literal> +packages. Building the documentation can be disabled with the +<literal>--disable-doc</literal> option to <literal>configure</literal>. +</para> + +<para> +Below are ready-made commands to download the required +packages. When you reach the <emphasis>Select Packages</emphasis> screen, +these packages should be amongst the search results. </para> +<screen> +$ setup-x86_64.exe -P autoconf,automake,cocom,gcc-g++,git,libtool,make,patch,perl # download build tool packages +$ setup-x86_64.exe -P gettext-devel,libiconv,libiconv-devel,libiconv2,libzstd-devel,zlib-devel # download dumper packages +$ setup-x86_64.exe -P mingw64-x86_64-gcc-g++,mingw64-x86_64-zlib # download utility packages +$ setup-x86_64.exe -P dblatex,docbook-utils,docbook-xml45,docbook-xsl,docbook2X,perl-XML-SAX-Expat,xmlto # download documentation packages +</screen> <para>Next, check out the Cygwin sources from the -<ulink url="https://cygwin.com/git.html">Cygwin GIT source repository</ulink>). +<ulink url="https://cygwin.com/git.html">Cygwin GIT source repository</ulink>. This is the <emphasis>preferred method</emphasis> for acquiring the sources. Otherwise, if you are trying to duplicate a cygwin release then you should download the corresponding source package diff --git a/winsup/doc/faq-using.xml b/winsup/doc/faq-using.xml index 4dc462a..111702c 100644 --- a/winsup/doc/faq-using.xml +++ b/winsup/doc/faq-using.xml @@ -855,6 +855,11 @@ possible to preset the sparse attribute with <literal>chattr</literal>. ---a-S-------- 2/is_sparse ---a-S-------- 2/maybe_sparse ---a-S-------- 2/not_sparse + $ lssparse -H 0/is_sparse # from cygutils-extra package + Hole range[1]: offset=0x0, length=0x100000 + Data range[2]: offset=0x100000, length=0x4 + $ lssparse -H 0/not_sparse + Data range[1]: offset=0x0, length=0x100004 </screen> <para>With <literal>sparse</literal> mount option or a SSD, all <literal>?/maybe_sparse</literal> files would be sparse. @@ -956,6 +961,26 @@ contents are exempt from scanning. In a default installation, this would be <literal>C:\cygwin\bin</literal>. Obviously, this could be exploited by a hostile non-Cygwin program, so do this at your own risk. </para> +<para>Anti-virus software typically reduce the speed of Windows +<literal>CreateProcess</literal> calls which are used by Cygwin to provide +<literal>fork()</literal> and <literal>exec()</literal>. This in particular +slows down shell scripts. In the simple speed test shown below, the first +column shows the number of <literal>date</literal> commands run per second. +Anti-virus was turned off at the line marked with <literal>***</literal>. +</para> +<screen> + bash$ while :; do date +%s; done | uniq -c + ... + 122 1741712430 + 118 1741712431 + 118 1741712432 + 121 1741712433 + 142 1741712434 *** + 140 1741712435 + 141 1741712436 + 144 1741712437 + ... +</screen> <para>See also <xref linkend="faq.using.bloda"></xref> for a list of applications that have been known, at one time or another, to interfere with the normal functioning of Cygwin. diff --git a/winsup/doc/path.xml b/winsup/doc/path.xml index f56614b..9665f6b 100644 --- a/winsup/doc/path.xml +++ b/winsup/doc/path.xml @@ -33,12 +33,12 @@ <refsect1 id="func-cygwin-conv-path-desc"> <title>Description</title> -<para>Use this function to convert POSIX paths in -<parameter>from</parameter> to Win32 paths in <parameter>to</parameter> -or, vice versa, Win32 paths in <parameter>from</parameter> to POSIX paths -in <parameter>to</parameter>. <parameter>what</parameter> -defines the direction of this conversion and can be any of the below -values.</para> +<para>Use this function to convert NUL-terminated POSIX paths in +<parameter>from</parameter> to NUL-terminated Win32 paths in +<parameter>to</parameter> or, vice versa, NUL-terminated Win32 paths in +<parameter>from</parameter> to NUL-terminated POSIX paths in +<parameter>to</parameter>. <parameter>what</parameter> defines the +direction of this conversion and can be any of the below values.</para> <programlisting> CCP_POSIX_TO_WIN_A /* from is char *posix, to is char *win32 */ @@ -62,7 +62,8 @@ default.</para> <para><parameter>size</parameter> is the size of the buffer pointed to by <parameter>to</parameter> in bytes. If <parameter>size</parameter> -is 0, <function>cygwin_conv_path</function> just returns the required +is 0, <parameter>to</parameter> may be NULL and +<function>cygwin_conv_path</function> just returns the required buffer size in bytes. Otherwise, it returns 0 on success, or -1 on error and errno is set to one of the below values.</para> @@ -73,6 +74,12 @@ error and errno is set to one of the below values.</para> of what == CCP_POSIX_TO_WIN_A, longer than MAX_PATH. ENOSPC size is less than required for the conversion. </programlisting> + +<para>In the event of an error, the memory at <parameter>to</parameter> is +not modified unless the error is <constant>EFAULT</constant> writing to +the memory at <parameter>to</parameter>, which may happen if +<parameter>size</parameter> is incorrectly specified.</para> + </refsect1> <refsect1 id="func-cygwin-conv-path-example"> diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml index bb5f414..cec7ee3 100644 --- a/winsup/doc/posix.xml +++ b/winsup/doc/posix.xml @@ -1614,9 +1614,9 @@ ISO®/IEC DIS 9945 Information technology _toupper (SUSv4) acl_add_perm (POSIX.1e draft) acl_calc_mask (POSIX.1e draft) - acl_check (POSIX.1e draft) + acl_check (libacl) acl_clear_perms (POSIX.1e draft) - acl_cmp (POSIX.1e draft) + acl_cmp (libacl) acl_copy_entry (POSIX.1e draft) acl_copy_ext (POSIX.1e draft) acl_copy_int (POSIX.1e draft) @@ -1625,30 +1625,37 @@ ISO®/IEC DIS 9945 Information technology acl_delete_entry (POSIX.1e draft) acl_delete_perm (POSIX.1e draft) acl_dup (POSIX.1e draft) - acl_entries (POSIX.1e draft) - acl_equiv_mode (POSIX.1e draft) + acl_entries (libacl) + acl_equiv_mode (libacl) acl_error (POSIX.1e draft) - acl_extended_fd (POSIX.1e draft) - acl_extended_file (POSIX.1e draft) - acl_extended_file_nofollow (POSIX.1e draft) + acl_extended_fd (libacl) + acl_extended_file (libacl) + acl_extended_file_nofollow (libacl) acl_free (POSIX.1e draft) - acl_from_mode (POSIX.1e draft) + acl_from_mode (libacl) acl_from_text (POSIX.1e draft) acl_get_entry (POSIX.1e draft) acl_get_fd (POSIX.1e draft) + acl_get_fd_np (FreeBSD, NetBSD) acl_get_file (POSIX.1e draft) - acl_get_perm (POSIX.1e draft) + acl_get_link_np (FreeBSD, NetBSD) + acl_get_perm (libacl) + acl_get_perm_np (FreeBSD, NetBSD) acl_get_permset (POSIX.1e draft) acl_get_qualifier (POSIX.1e draft) acl_get_tag_type (POSIX.1e draft) acl_init (POSIX.1e draft) + acl_is_trivial_np (FreeBSD, NetBSD) acl_set_fd (POSIX.1e draft) + acl_set_fd_np (FreeBSD, NetBSD) acl_set_file (POSIX.1e draft) + acl_set_link_np (FreeBSD, NetBSD) acl_set_permset (POSIX.1e draft) acl_set_qualifier (POSIX.1e draft) acl_set_tag_type (POSIX.1e draft) acl_size (POSIX.1e draft) - acl_to_any_text (POSIX.1e draft) + acl_strip_np (FreeBSD, NetBSD) + acl_to_any_text (libacl) acl_to_text (POSIX.1e draft) acl_valid (POSIX.1e draft) atoff (AIX) diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am index 8f2967a..20e06b9 100644 --- a/winsup/testsuite/Makefile.am +++ b/winsup/testsuite/Makefile.am @@ -311,6 +311,12 @@ check_PROGRAMS = \ winsup.api/pthread/self2 \ winsup.api/pthread/threadidafterfork \ winsup.api/pthread/tsd1 \ + winsup.api/posix_spawn/chdir \ + winsup.api/posix_spawn/errors \ + winsup.api/posix_spawn/fds \ + winsup.api/posix_spawn/signals \ + winsup.api/posix_spawn/spawnp \ + winsup.api/posix_spawn/win32 \ winsup.api/samples/sample-fail \ winsup.api/samples/sample-pass # winsup.api/ltp/ulimit01 is omitted as we don't have <ulimit.h> @@ -344,7 +350,7 @@ XFAIL_TESTS = \ LOG_COMPILER = $(srcdir)/cygrun.sh export runtime_root=$(abs_builddir)/testinst/bin -export cygrun=$(builddir)/mingw/cygrun +export mingwtestdir=$(builddir)/mingw # Set up things in the Cygwin 'installation' at testsuite/testinst/ to provide # things which tests need to work diff --git a/winsup/testsuite/cygrun.sh b/winsup/testsuite/cygrun.sh index bf1d5cc..f1673e4 100755 --- a/winsup/testsuite/cygrun.sh +++ b/winsup/testsuite/cygrun.sh @@ -11,7 +11,7 @@ export PATH="$runtime_root:${PATH}" if [ "$1" = "./mingw/cygload" ] then windows_runtime_root=$(cygpath -m $runtime_root) - $cygrun "$exe -v -cygwin $windows_runtime_root/cygwin1.dll" + $mingwtestdir/cygrun "$exe -v -cygwin $windows_runtime_root/cygwin1.dll" else - cygdrop $cygrun $exe + cygdrop $mingwtestdir/cygrun $exe fi diff --git a/winsup/testsuite/mingw/Makefile.am b/winsup/testsuite/mingw/Makefile.am index 772e734..25300a1 100644 --- a/winsup/testsuite/mingw/Makefile.am +++ b/winsup/testsuite/mingw/Makefile.am @@ -16,7 +16,7 @@ override CC = @MINGW_CC@ override CXX = @MINGW_CXX@ AM_CPPFLAGS = -noinst_PROGRAMS = cygrun cygload +noinst_PROGRAMS = cygrun cygload winchild cygrun_SOURCES = \ ../cygrun.c @@ -24,3 +24,8 @@ cygrun_SOURCES = \ cygload_SOURCES = \ ../winsup.api/cygload.cc cygload_LDFLAGS=-static -Wl,-e,cygloadCRTStartup + +winchild_SOURCES = \ + ../winsup.api/posix_spawn/winchild.c +winchild_LDFLAGS=-municode +winchild_LDADD=-lntdll diff --git a/winsup/testsuite/stress/cygstress b/winsup/testsuite/stress/cygstress new file mode 100755 index 0000000..55412ef --- /dev/null +++ b/winsup/testsuite/stress/cygstress @@ -0,0 +1,613 @@ +#!/bin/bash +# +# Run stress-ng on Cygwin +# +# Copyright 2025 Christian Franke +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set -e -o pipefail # pipefail is required + +usage() +{ + cat <<EOF +Usage: ${0##*/} [OPTION...] {CI|WORK|FAIL|test...} + + -n print commands only (dry-run) + -f force execution of tests tagged 'heavy' or 'admin' + -c LIST set CPU affinity to LIST + -s PATH stress-ng executable [default: stress-ng] + -t N run each test for at least N seconds [default: 5] + -v print stress-ng output always [default: on error only] + -w N start N workers for each test [default: 2] + + CI run all tests tagged CI + WORK run all tests tagged WORKS + FAIL run all tests tagged FAILS + test... run individual test(s) (may require '-f') +EOF + exit 1 +} + +# Tags: +# WORKS: works on Cygwin (3.7.0-0.51.gd35cc82b5ec1) +# WORKS,CI: possibly suitable subset for Cygwin CI test. +# FAILS: fails on Cygwin, see "TODO Cygwin" for details. +# heavy: heavy resource usage, may work, hang, freeze desktop, require reset, ... +# admin: requires administrator, may work or not, may be 'heavy' or not. +# -----: unsupported due to missing API, library, declaration, ... + +stress_tests=' +# TEST [ARGS] # Tag # Comment + access # FAILS # TODO undecided: "access 004 on chmod mode 400 failed: 13 (Permission denied)" + acl # WORKS,CI # (fixed in stress-ng 0.18.12) + affinity # WORKS + af-alg # ----- # requires AF_ALG + aio # WORKS + aiol # ----- # requires io_setup(2), io_submit(2), ... + alarm # WORKS,CI + apparmor # ----- + atomic # WORKS + + bad-altstack # WORKS + bad-ioctl # ----- + besselmath # WORKS + bigheap # heavy + binderfs # ----- + bind-mount # ----- + bitonicsort # WORKS + bitops # WORKS + branch # WORKS + brk # heavy # allocates memory until OOM + bsearch # WORKS + bubblesort # WORKS + + cache # WORKS + cacheline # WORKS + cachehammer # WORKS + cap # ----- + cgroup # ----- + chattr # ----- + chdir # WORKS,CI + chmod # WORKS,CI + chown # FAILS # TODO undecided: "fchown failed, errno=22 (Invalid argument)" + chroot # admin + clock # WORKS,CI # (fixed in stress-ng 0.18.12: "timer_create failed for timer ... + # ... ''CLOCK_THREAD_CPUTIME_ID'', errno=134") + clone # ----- + close # FAILS # TODO Cygwin: close(2) is not thread-safe + context # WORKS,CI # (fixed in Cygwin 3.6.0: signals lost after swapcontext) + copy-file # ----- + cpu # WORKS + cpu-online # ----- + cpu-sched # FAILS # TODO undecided: "child died: signal 9 ''SIGKILL''" + # (fixed in Cygwin 3.6.0: signals lost after SIGSTOP) + crypt # WORKS # uses libcrypt + cyclic # admin + + daemon # WORKS + dccp # ----- + dekker # WORKS + dentry # WORKS + dev # FAILS # TODO Cygwin: "*** fatal error in forked process - pthread_mutex::_fixup_after_fork () ... + # ... doesn''t understand PROCESS_SHARED mutex''s" + dev-shm # ----- + dfp # WORKS + dir # WORKS + dirdeep # heavy # creates deep dir tree + dirmany # heavy # creates many dirs/files + dnotify # ----- + dup # WORKS,CI + dynlib # ----- + + easy-opcode # WORKS + eigen # WORKS + efivar # ----- + enosys # ----- + env # heavy # creates very large environment until OOM + epoll # ----- + eventfd # ----- + exec # WORKS,CI + exit-group # ----- + expmath # WORKS + + factor # WORKS # uses libgmp + fallocate # WORKS,CI + fanotify # ----- + far-branch # WORKS + fault # WORKS + fcntl # FAILS # TODO this script: fixed in stress-ng >0.18.12: "F_SETLKW (F_WRLCK) failed: ... + # ... errno=45 (Resource deadlock avoided)" + # (fixed in Cygwin 3.6.1: "ftruncate failed, errno=21 (Is a directory)") + fd-fork # WORKS,CI + fd-race # ----- # TODO stress-ng: drop restriction to Linux + # TODO Cygwin: close(2) is not thread-safe, see also "close" + fibsearch # WORKS + fiemap # ----- + fifo # WORKS + file-ioctl # WORKS,CI + filename # FAILS # TODO Cygwin: creates files Cygwin cannot remove later, please see: + # https://sourceware.org/pipermail/cygwin/2024-September/256451.html + filename --filename-opts posix # WORKS,CI # restricts filenames to POSIX charset +# filerace # WORKS # TODO this script: added in stress-ng >0.18.12 + flipflop # WORKS + flock # WORKS,CI + flushcache # WORKS + fma # WORKS + fork # WORKS,CI + forkheavy # heavy # forks until process table is full + fp # WORKS,CI + fp-error # WORKS,CI + fpunch # FAILS # TODO this script: fixed in stress-ng >0.18.12 + fractal # WORKS + fsize # heavy # creates large files until disk is full + fstat # WORKS,CI + full # ----- # requires pread/pwrite() working on /dev/full + funccall # WORKS + funcret # WORKS + futex # ----- + + get # WORKS + getdent # ----- + getrandom # ----- + goto # WORKS + gpu # ----- + + handle # ----- # requires name/open_by_handle_at(2) + hash # WORKS + hdd # WORKS + heapsort # WORKS # uses libbsd + hrtimers # WORKS,CI # (fixed in Cygwin 3.5.7: "timer_delete failed") + hsearch # WORKS + hyperbolic # WORKS + + icache # WORKS + icmp-flood # ----- # requires "struct icmphdr", ... in <netinet/*.h> + idle-page # ----- # requires /sys/kernel/mm/page_idle/bitmap + inode-flags # ----- + inotify # ----- # requires inotify_*(2) + insertionsort # WORKS + intmath # WORKS + io # WORKS + iomix # WORKS + ioport # ----- + ioprio # ----- + io-uring # ----- + ipsec-mb # ----- # requires libipsec-mb + itimer # WORKS,CI + + jpeg # WORKS # uses libjpeg + judy # ----- # requires libJudy (ORPHANED) + + kcmp # ----- + key # ----- + kill # WORKS,CI + klog # ----- + kvm # ----- + + l1cache # ----- # requires /sys/devices/system/cpu + l1cache --l1cache-line-size 32768 --l1cache-ways 8 --l1cache-sets 1 # WORKS + landlock # ----- + lease # ----- + led # ----- + link # WORKS,CI + list # WORKS + llc-affinity # WORKS + loadavg # WORKS + locka # WORKS + lockbus # WORKS + lockf # WORKS,CI # (fixed in Cygwin 3.5.5: "NtCreateEvent(lock): 0xC000003" and ... + # "can''t handle more than 910 locks per file") + lockmix # WORKS + lockofd # ----- + logmath # WORKS,CI # (fixed in Cygwin 3.5.5: signal handler destroys long double values) + longjmp # WORKS,CI # (fixed in Cygwin 3.5.5: signals lost during setjmp or longjmp) + loop # ----- + lsearch # WORKS + lsm # ----- + + madvise # WORKS + malloc # WORKS,CI + matrix # WORKS + matrix-3d # WORKS + mcontend # WORKS + membarrier # ----- + memcpy # WORKS,CI # (fixed in Cygwin 3.6.1: crash due to set DF in signal handler) + memfd # ----- + memhotplug # ----- + memrate # WORKS + memthrash # WORKS + mergesort # WORKS # uses libbsd + metamix # FAILS # TODO Cygwin: "fdatasync on ./tmp-stress-ng-metamix-*/... failed, errno=13" + mincore # ----- + min-nanosleep # WORKS + misaligned # WORKS + mknod # ----- + mlock # WORKS + mlockmany # heavy # requires --pathological + mmap # WORKS,CI + mmapaddr # WORKS + mmapfork # WORKS + mmapfiles # WORKS + mmapfixed # WORKS + mmaphuge # ----- + mmapmany # WORKS + mmaptorture # heavy + module # ----- + monte-carlo # WORKS + mpfr # WORKS # uses libmpfr + mprotect # FAILS # TODO Cygwin: crashes or hangs and then ignores SIGKILL + mq # FAILS # TODO undecided: "fail: ... mq_[timed]receive failed, errno=1" + # (fixed in Cygwin 3.5.6: crash on invalid mq fd) + mremap # ----- + mseal # ----- + msg # WORKS + msync # WORKS + msyncmany # WORKS + mtx # WORKS + munmap # ----- + mutex # WORKS + + nanosleep # FAILS # TODO undecided: "detected 1 unexpected nanosleep underruns" + netdev # ----- + netlink-proc # ----- + netlink-task # ----- + nice # heavy # TODO Cygwin: may change nice value of other processes + nop # WORKS + null # WORKS + numa # ----- + + oom-pipe # ----- + opcode # ----- + open # WORKS,CI + + pagemove # ----- + pageswap # ----- + pci # ----- + personality # ----- + peterson # WORKS + physmmap # ----- + physpage # ----- + pidfd # ----- + ping-sock # ----- + pipe # WORKS,CI + pipeherd # heavy # many forks, may freeze desktop + pkey # ----- + plugin # ----- + poll # WORKS + powmath # WORKS + prctl # ----- + prefetch # WORKS + prime # WORKS # uses libgmp + prio-inv # ----- # requires <pthread_nt.h> + priv-instr # FAILS # TODO Cygwin: crashes or hangs, please see: + # https://sourceware.org/pipermail/cygwin/2025-March/257726.html + procfs # ----- # TODO stress-ng: support /proc subset of Cygwin + pseek # WORKS,CI # (fixed in Cygwin 3.5.5: "pread: Bad file descriptor") + pthread # WORKS,CI + ptr-chase # WORKS + ptrace # ----- + pty # WORKS,CI # (fixed in Cygwin 3.7.0: implement tcdrain/tcflow/TIOCINQ for pty) + # (fixed in Cygwin 3.6.1: "No pty allocated, errno=0") + qsort # WORKS + quota # ----- + + race-sched # WORKS + radixsort # WORKS # uses libbsd + ramfs # ----- + rawdev # ----- + randlist # WORKS + rawsock # ----- + rawpkt # ----- # requires <linux/if_packet.h>, ... + rawudp # ----- + rdrand # WORKS + readahead # ----- + reboot # ----- + regex # WORKS + regs # WORKS + remap # ----- + rename # WORKS,CI + resched # heavy + resources # heavy + revio # WORKS + ring-pipe # WORKS + rlimit # heavy + rmap # WORKS + rotate # WORKS + rseq # ----- + rtc # ----- # requires /dev/rtc + + schedmix # WORKS + schedpolicy # WORKS,CI + sctp # ----- + seal # ----- + seccomp # ----- + secretmem # ----- + seek # WORKS,CI + sem # FAILS # TODO Cygwin: "instance 0 corrupted bogo-ops counter, 556328 vs 556327" + sem-sysv # FAILS # TODO Cygwin: "aborted early, out of system resources" + sendfile # ----- # requires sendfile(2) + session # WORKS + set # FAILS # TODO stress-ng: "setrlimit failed, ..., expected -EPERM, instead got errno=22 (Invalid argument)" + shellsort # WORKS + shm # WORKS,CI + shm-sysv # ----- # requires shmat(2), smdt(2) + sigabrt # WORKS,CI + sigbus # FAILS # TODO Cygwin: "ftruncate file to a single page failed, errno=13 (Permission denied)" + sigchld # FAILS # TODO Cygwin: hangs + sigfd # ----- # TODO Cygwin: "stressor terminated with unexpected signal 11 ''SIGSEGV''" + # (fixed in stress-ng >0.18.12: drop restriction to glibc) + sigfpe # FAILS # TODO undecided: "got SIGFPE error 15 (FPE_INTDEV), expecting 20 (FPE_FLTRES)" + sighup # WORKS,CI + sigill # FAILS # TODO Cygwin: "terminated on signal: 11", possibly similar to "priv-instr" + sigio # ----- # requires O_ASYNC + signal # WORKS,CI + signest # FAILS # TODO Cygwin: "terminated on signal: 11" + sigpending # WORKS,CI + sigpipe # WORKS,CI + sigq # WORKS,CI + sigrt # WORKS,CI + sigsegv # FAILS # TODO Cygwin: crashes or hangs, possibly similar to "priv-instr" + sigsuspend # WORKS,CI + sigtrap # WORKS,CI + sigurg # WORKS,CI + sigvtalrm # WORKS,CI + sigxcpu # FAILS # TODO stress-ng: "setrlimit failed, errno=22 (Invalid argument)" + sigxfsz # FAILS # TODO stress-ng: "setrlimit failed, errno=22 (Invalid argument)" + skiplist # WORKS + sleep # WORKS,CI + smi # ----- + sock # WORKS + sockabuse # FAILS # TODO undecided: "recv failed, errno=113 (Software caused connection abort)" + sockdiag # ----- + sockfd # ----- + sockmany # heavy + sockpair # WORKS + softlockup # admin + sparsematrix # WORKS + spawn # heavy # TODO Cygwin: "NNN spawns failed (100.00%)", may crash other processes + spinmem # WORKS + splice # ----- + stack # heavy + stackmmap # WORKS + statmount # ----- + str # WORKS + stream # WORKS # (fixed in stress-ng >0.18.12: --stream-l3-size set correctly) + swap # ----- + switch # WORKS + symlink # WORKS,CI + sync-file # ----- + syncload # WORKS + sysbadaddr # heavy + syscall # FAILS # TODO Cygwin: "terminated on signal: 11" + sysinfo # WORKS + sysinval # ----- + sysfs # ----- + + tee # ----- # requires tee(2) + timer # WORKS,CI # TODO undecided: "1 timer settime calls failed" + timerfd # heavy # TODO undecided: may freeze desktop + time-warp # WORKS + tlb-shootdown # heavy + tmpfs # ----- # requires tmpfs filesystem + touch # WORKS + tree # WORKS # (fixed in Cygwin 3.6.1: crash due to set DF in signal handler, see also "memcpy") + trig # WORKS + tsc # WORKS + tsearch # WORKS + tun # ----- + + udp # WORKS + udp-flood # ----- # requires AF_PACKET + umask # WORKS + umount # ----- + unlink # WORKS,CI + unshare # ----- + uprobe # ----- + urandom # WORKS + userfaultfd # ----- + usersyscall # ----- + utime # WORKS,CI + + vdso # ----- + veccmp # WORKS + vecfp # WORKS + vecmath # WORKS + vecshuf # WORKS + vecwide # WORKS + verity # ----- + vfork # WORKS + vforkmany # heavy # forks until process table is full + vm # WORKS,CI + vm-addr # WORKS + vm-rw # ----- + vm-segv # WORKS + vm-splice # ----- + vma # WORKS + vnni # WORKS + + wait # FAILS # TODO Cygwin: hangs in few cases + waitcpu # WORKS + watchdog # ----- + wcs # WORKS + workload # WORKS,CI # (fixed in Cygwin 3.5.5: hang in mq_send/receive) + + x86cpuid # WORKS + x86syscall # ----- + xattr # FAILS # TODO Cygwin: "fsetxattr succeeded unexpectedly, created ... + # "... attribute with size greater than permitted size, errno=61" + yield # WORKS + + zero # WORKS,CI + zlib # WORKS # uses libz + zombie # WORKS,CI +' + +stress_ng="stress-ng" +timeout=5; workers=2 +dryrun=false; force=false; verbose=false +taskset= + +while :; do case $1 in + -c) shift; taskset=$1 ;; + -f) force=true ;; + -n) dryrun=true ;; + -s) shift; stress_ng=$1 ;; + -t) shift; timeout=$1 ;; + -v) verbose=true ;; + -w) shift; workers=$1 ;; + -*) usage ;; + *) break ;; +esac; shift || usage; done + +run_ci=false; run_work=false; run_fail=false +run_tests= + +while [ $# -ge 1 ]; do case $1 in + CI) run_ci=true ;; WORK) run_work=true ;; FAIL) run_fail=true ;; + [a-z]*[a-z]) run_tests+=" $1" ;; + *) usage ;; +esac; shift; done +$run_ci || $run_work || $run_fail || [ ${run_tests:+t} ] || usage + +command -V "$stress_ng" >/dev/null || exit 1 + +# SIGKILL may not work if stress-ng hangs. +# Use Windows 'taskkill' as no 'killall --force' is available. +command -V taskkill >/dev/null || exit 1 + +stress_ng_name=${stress_ng##*/} +tempdir=${TMP:-/tmp} +logdir=${LOGDIR:-/tmp/logdir} + +mkdir -p "$logdir" + +find_stress() +{ + local p=$(procps -C "$stress_ng_name" -o pid,ppid,s,pri,ni,tt,start,time,args --sort pid) + test "$(wc -l <<< "$p")" -gt 1 || return 1 + echo "$p" +} + +stop_stress() +{ + echo '$' taskkill /F /T /IM "${stress_ng_name}.exe" + taskkill /F /T /IM "${stress_ng_name}.exe" ||: +} + +total=0 +fails=0 + +# stress TEST [OPTION...] +stress() +{ + local name=$1 + shift || return 1 + + local td="$tempdir/stress-ng.$$.$total.d" + local logfile="$logdir/$name" + local cmd=("$stress_ng" -v -M --oomable --timestamp --verify --temp-path "$td" -t "$timeout") + test -z "$taskset" || cmd+=(--taskset "$taskset") + cmd+=(--"$name" "$workers" "$@") + + if $dryrun || $verbose; then + echo '$' "${cmd[@]}" + ! $dryrun || return 0 + fi + + ( + t=$(date +%s); : $((t += timeout + 30)); sleep 1 + while [ "$(date +%s)" -lt "$t" ]; do sleep 1; done + # Another delay to let 'exit 0' occur before 'kill $watchdog' + ( sleep 1; stop_stress ) & + exit 0 + ) & + local watchdog=$! + trap "kill $watchdog 2>/dev/null ||:; exit 130" SIGINT SIGTERM + + mkdir "$td" + local rc=0 + if $verbose; then + # This requires '-o pipefail' + "${cmd[@]}" 2>&1 | tee "$logfile" || rc=$? + else + "${cmd[@]}" >"$logfile" 2>&1 || rc=$? + fi + + kill $watchdog 2>/dev/null ||: + trap - SIGINT SIGTERM + + local errs= + if wait $watchdog; then + sleep 2 + errs=", command hangs" + fi + + local p + if p=$(find_stress); then + errs+=", processes left" + stop_stress + sleep 2 + fi + + rmdir "$td" 2>/dev/null || errs+=", files left in '$td'" + + ! grep -Eqv '^(stress-ng|info):' "$logfile" || errs+=", unexpected output" + + if [ "${rc}${errs:+t}" != "0" ]; then + $verbose || cat "$logfile" + echo ">>> FAILURE: $name" "$@" "(exit status ${rc}${errs})" + ! [ ${p:+t} ] || echo "$p" + echo + return 1 + fi + echo ">>> SUCCESS: $name" "$@" + ! $verbose || echo + return 0 +} + +if p=$(find_stress); then + echo "*** Other $stress_ng_name processes are still running:" + echo "$p" + $dryrun || exit 1 +fi + +while read; do + args=${REPLY#*|} + name=${args%% *} + run_this=false + for t in $run_tests; do if [ "$t" = "$name" ]; then + run_this=true; break + fi; done + + tag=${REPLY%%|*} + case $tag in + FAILS) $run_this || $run_fail || continue ;; + WORKS) $run_this || $run_work || continue ;; + WORKS,CI) $run_this || $run_work || $run_ci || continue ;; + -----) $run_this || continue ;; + admin|heavy) + $run_this || continue + if ! $force; then + echo ">>> SKIPPED: $name (tagged '$tag', use '-f' to override)"; echo + continue + fi ;; + *) echo "*** syntax error: '$REPLY'"; exit 1 ;; + esac + + : $((++total)) + stress $args ||: $((++fails)) +done <<<"$( + sed -E \ + -e 's/^ *([-0-9a-z]+)( +-[^#]*[^ #])? +# *(FAILS|WORKS(,CI)?|admin|heavy|-----) *(#.*)?$/\3|\1\2/' \ + -e '/^ *(#.*)?$/d' \ + <<<"$stress_tests" +)" + +if [ $fails -ne 0 ]; then + echo ">>> FAILURE: $fails of $total stress test(s) failed" + exit 1 +fi +echo ">>> SUCCESS: All $total stress test(s) succeeded" +exit 0 diff --git a/winsup/testsuite/winsup.api/cygload.cc b/winsup/testsuite/winsup.api/cygload.cc index afd3ee9..08372a3 100644 --- a/winsup/testsuite/winsup.api/cygload.cc +++ b/winsup/testsuite/winsup.api/cygload.cc @@ -82,6 +82,13 @@ cygwin::padding::padding () "movl %%fs:4, %0" :"=r"(stackbase) ); +# elif __aarch64__ + // x18 register points to TEB. See _TEB structure definition in + // winsup\cygwin\local_includes\ntdll.h + __asm__ volatile ( + "ldr %0, [x18, #0x8]" + :"=r" (stackbase) + ); # else # error Unknown architecture # endif diff --git a/winsup/testsuite/winsup.api/ltp/alarm01.c b/winsup/testsuite/winsup.api/ltp/alarm01.c index 187e488..2ee1929 100644 --- a/winsup/testsuite/winsup.api/ltp/alarm01.c +++ b/winsup/testsuite/winsup.api/ltp/alarm01.c @@ -188,7 +188,7 @@ main(int ac, char **av) void setup() { - void trapper(); + void trapper(int sig); /* capture signals */ tst_sig(NOFORK, DEF_HANDLER, cleanup); @@ -218,8 +218,7 @@ cleanup() } /* End cleanup() */ void -trapper(sig) -int sig; +trapper(int sig) { signal(SIGALRM, trapper); } diff --git a/winsup/testsuite/winsup.api/ltp/alarm02.c b/winsup/testsuite/winsup.api/ltp/alarm02.c index 03a41b4..6ef7552 100644 --- a/winsup/testsuite/winsup.api/ltp/alarm02.c +++ b/winsup/testsuite/winsup.api/ltp/alarm02.c @@ -99,7 +99,7 @@ void setup(); void cleanup(void) __attribute__((noreturn)); -void alarm_received(); +void alarm_received(int sig); @@ -232,7 +232,7 @@ cleanup() tst_exit(); } -void alarm_received() +void alarm_received(int sig) { received_alarm = 1; } diff --git a/winsup/testsuite/winsup.api/ltp/alarm03.c b/winsup/testsuite/winsup.api/ltp/alarm03.c index 871f6fa..f7d0c15 100644 --- a/winsup/testsuite/winsup.api/ltp/alarm03.c +++ b/winsup/testsuite/winsup.api/ltp/alarm03.c @@ -191,7 +191,7 @@ main(int ac, char **av) void setup() { - void trapper(); + void trapper(int sig); /* capture signals */ tst_sig(FORK, DEF_HANDLER, cleanup); @@ -221,8 +221,7 @@ cleanup() } /* End cleanup() */ void -trapper(sig) -int sig; +trapper(int sig) { signal(SIGALRM, trapper); } diff --git a/winsup/testsuite/winsup.api/ltp/exit02.c b/winsup/testsuite/winsup.api/ltp/exit02.c index 1503106..b6c741e 100644 --- a/winsup/testsuite/winsup.api/ltp/exit02.c +++ b/winsup/testsuite/winsup.api/ltp/exit02.c @@ -45,6 +45,7 @@ #include <signal.h> #include <fcntl.h> #include <sys/wait.h> +#include <string.h> #include "test.h" #include "usctest.h" @@ -69,7 +70,6 @@ main(int ac, char **av) char wbuf[BUFSIZ], rbuf[BUFSIZ]; int len, rlen; int rval = 0; - char *strcpy(); int lc; /* loop counter */ const char *msg; /* message returned from parse_opts */ diff --git a/winsup/testsuite/winsup.api/ltp/fcntl07.c b/winsup/testsuite/winsup.api/ltp/fcntl07.c index e0082df..8d93873 100644 --- a/winsup/testsuite/winsup.api/ltp/fcntl07.c +++ b/winsup/testsuite/winsup.api/ltp/fcntl07.c @@ -142,7 +142,7 @@ #include "usctest.h" #include "search_path.h" -void setup(); +void setup(char *path); void cleanup(void) __attribute__((noreturn)); void help(); diff --git a/winsup/testsuite/winsup.api/ltp/fcntl07B.c b/winsup/testsuite/winsup.api/ltp/fcntl07B.c index db866fd..3d61e48 100644 --- a/winsup/testsuite/winsup.api/ltp/fcntl07B.c +++ b/winsup/testsuite/winsup.api/ltp/fcntl07B.c @@ -142,7 +142,7 @@ #include "usctest.h" #include "search_path.h" -void setup(); +void setup(char *path); void cleanup(void) __attribute__((noreturn)); void help(); diff --git a/winsup/testsuite/winsup.api/ltp/kill02.c b/winsup/testsuite/winsup.api/ltp/kill02.c index eba47cc..d4af44a 100644 --- a/winsup/testsuite/winsup.api/ltp/kill02.c +++ b/winsup/testsuite/winsup.api/ltp/kill02.c @@ -185,19 +185,19 @@ int alarm_flag = FALSE; /*This flag indicates an alarm time out. */ char who_am_i = '0'; /*This indicates which process is which when using */ /*interrupt routine usr1_rout. */ -void notify_timeout(); /*Signal handler that the parent enters if it times out */ +void notify_timeout(int sig); /*Signal handler that the parent enters if it times out */ /*waiting for the child to indicate its set up status. */ void parent_rout(); /*This is the parents routine. */ void child1_rout(); /*This is child 1's routine. */ void child2_rout(); /*This is child 2's routine. */ void childA_rout(); /*This is child A's routine. */ void childB_rout(); /*This is child B's routine. */ -void usr1_rout(); /*This routine is used by all children to indicate that */ +void usr1_rout(int sig); /*This routine is used by all children to indicate that */ /*they have caught signal SIGUSR1. */ void par_kill(); /*This routine is called by the original parent to */ /*remove child 2 and to indicate to child 1 to */ /*remove its children. */ -void chld1_kill(); /*This routine is used by child 1 to remove itself and */ +void chld1_kill(int sig); /*This routine is used by child 1 to remove itself and */ /*its children A and B. */ void setup(); @@ -515,7 +515,7 @@ void child1_rout() if (signal(SIGUSR2,chld1_kill) == SIG_ERR) { tst_brkm(TBROK,NULL,"Could not set to catch the parents signal."); (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); - (void) chld1_kill(); + (void) chld1_kill(SIGUSR1); exit(0); } @@ -525,7 +525,7 @@ void child1_rout() if (signal(SIGALRM,notify_timeout) == SIG_ERR) { tst_brkm(TBROK,NULL,"Could not set to catch the childs time out alarm."); (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); - (void) chld1_kill(); + (void) chld1_kill(SIGUSR1); exit(0); } @@ -550,7 +550,7 @@ void child1_rout() */ if (alarm_flag == TRUE) { tst_brkm(TBROK,NULL,"The set up of the children failed by timing out."); - (void) chld1_kill(); + (void) chld1_kill(SIGUSR1); (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); exit(0); } @@ -740,7 +740,7 @@ setup() /*********************************************************** * This routine indicates that the process caught SIGUSR1. **********************************************************/ -void usr1_rout() +void usr1_rout(int sig) { char mesg[MAXMESG]; /*Used to buffer messages for tst_res. */ @@ -772,7 +772,7 @@ void usr1_rout() * which occurs when the child fails to notify the parent * the status of set up. **********************************************************/ -void notify_timeout() +void notify_timeout(int sig) { alarm_flag = TRUE; @@ -810,7 +810,7 @@ void par_kill() * This routine is executed by child 1 when the parent tells it to * remove it's children and itself. ********************************************************************/ -void chld1_kill() +void chld1_kill(int sig) { char mesg[MAXMESG]; /*Used to buffer messages for tst_resm. */ diff --git a/winsup/testsuite/winsup.api/ltp/mmap05.c b/winsup/testsuite/winsup.api/ltp/mmap05.c index 600cd76..23a6589 100644 --- a/winsup/testsuite/winsup.api/ltp/mmap05.c +++ b/winsup/testsuite/winsup.api/ltp/mmap05.c @@ -97,7 +97,7 @@ sigjmp_buf env; /* environment for sigsetjmp/siglongjmp */ void setup(); /* Main setup function of test */ void cleanup(void) __attribute__((noreturn)); /* cleanup function for the test */ -void sig_handler(); /* signal handler to catch SIGSEGV */ +void sig_handler(int sig); /* signal handler to catch SIGSEGV */ int main(int ac, char **av) diff --git a/winsup/testsuite/winsup.api/ltp/munmap01.c b/winsup/testsuite/winsup.api/ltp/munmap01.c index 0527201..91e06c5 100644 --- a/winsup/testsuite/winsup.api/ltp/munmap01.c +++ b/winsup/testsuite/winsup.api/ltp/munmap01.c @@ -88,7 +88,7 @@ unsigned int map_len; /* length of the region to be mapped */ void setup(); /* Main setup function of test */ void cleanup(void); /* cleanup function for the test */ -void sig_handler(); /* signal catching function */ +void sig_handler(int sig); /* signal catching function */ int main(int ac, char **av) @@ -244,7 +244,7 @@ setup() * cleanup function and exit the program. */ void -sig_handler() +sig_handler(int sig) { tst_resm(TPASS, "Functionality of munmap() successful"); diff --git a/winsup/testsuite/winsup.api/ltp/munmap02.c b/winsup/testsuite/winsup.api/ltp/munmap02.c index 7345e73..ddd9626 100644 --- a/winsup/testsuite/winsup.api/ltp/munmap02.c +++ b/winsup/testsuite/winsup.api/ltp/munmap02.c @@ -90,7 +90,7 @@ unsigned int map_len; /* length of the region to be mapped */ void setup(); /* Main setup function of test */ void cleanup(void); /* cleanup function for the test */ -void sig_handler(); /* signal catching function */ +void sig_handler(int sig); /* signal catching function */ int main(int ac, char **av) @@ -255,7 +255,7 @@ setup() * cleanup function and exit the program. */ void -sig_handler() +sig_handler(int sig) { tst_resm(TPASS, "Functionality of munmap() successful"); diff --git a/winsup/testsuite/winsup.api/ltp/pause01.c b/winsup/testsuite/winsup.api/ltp/pause01.c index 1c3b946..fbdc028 100644 --- a/winsup/testsuite/winsup.api/ltp/pause01.c +++ b/winsup/testsuite/winsup.api/ltp/pause01.c @@ -124,7 +124,7 @@ int TST_TOTAL=1; /* Total number of test cases. */ extern int Tst_count; /* Test Case counter for tst_* routines */ int exp_enos[]={EINTR, 0}; -void go(); +void go(int sig); int main(int ac, char **av) @@ -224,6 +224,6 @@ cleanup() /* routine to catch the alarm signal */ void -go() +go(int sig) { } diff --git a/winsup/testsuite/winsup.api/ltp/pipe01.c b/winsup/testsuite/winsup.api/ltp/pipe01.c index cc01cc9..2035071 100644 --- a/winsup/testsuite/winsup.api/ltp/pipe01.c +++ b/winsup/testsuite/winsup.api/ltp/pipe01.c @@ -44,6 +44,7 @@ * NONE */ #include <errno.h> +#include <string.h> #include "test.h" #include "usctest.h" @@ -64,7 +65,6 @@ main(int ac, char **av) char wrbuf[BUFSIZ], rebuf[BUFSIZ]; int red, written; /* no. of chars read/written to pipe */ int greater, length; - char *strcpy(); /* parse standard options */ if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL){ diff --git a/winsup/testsuite/winsup.api/ltp/sbrk01.c b/winsup/testsuite/winsup.api/ltp/sbrk01.c index 700fb6b..ed30338 100644 --- a/winsup/testsuite/winsup.api/ltp/sbrk01.c +++ b/winsup/testsuite/winsup.api/ltp/sbrk01.c @@ -140,7 +140,7 @@ main(int ac, char **av) ***************************************************************/ if ( (msg=parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *) NULL ) { tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); - tst_exit(0); + tst_exit(); } /*************************************************************** diff --git a/winsup/testsuite/winsup.api/ltp/signal03.c b/winsup/testsuite/winsup.api/ltp/signal03.c index 2a0923c..5a55ade 100644 --- a/winsup/testsuite/winsup.api/ltp/signal03.c +++ b/winsup/testsuite/winsup.api/ltp/signal03.c @@ -170,9 +170,9 @@ void setup(); void cleanup(void) __attribute__((noreturn)); -void do_test(); +void do_test(int test_case, int Tst_count); void sigdfl_test(); -void update_timings(); +void update_timings(struct tblock atblock); #if defined(linux) # define SIG_PF sig_t /* This might need to be sighandler_t on some systems */ @@ -222,9 +222,7 @@ long Tret; * M A I N ***********************************************************************/ int -main(argc, argv) -int argc; -char **argv; +main(int argc, char *argv[]) { int lc; const char *msg; @@ -278,18 +276,16 @@ char **argv; * ***********************************************************************/ void -do_test(test_case, tst_count) -int test_case; -int tst_count; +do_test(int test_case, int tst_count) { int term_stat; /* Termination status of the child returned to */ /* the parent. */ char string[30]; int fd1[2]; /* ipc */ int rd_sz; /* size of read */ - void p_timeout_handler(); + void p_timeout_handler(int sig); void c_timeout_handler(); - void catchsig(); + void catchsig(int sig); Tst_count = tst_count; @@ -620,7 +616,7 @@ cleanup() * call cleanup. ***********************************************************************/ void -p_timeout_handler() +p_timeout_handler(int sig) { kill(Pid, SIGKILL); cleanup(); @@ -643,7 +639,7 @@ c_timeout_handler() * if called. ***********************************************************************/ void -catchsig() +catchsig(int sig) { exit_val = SIG_CAUGHT; return; @@ -653,8 +649,7 @@ catchsig() * Update timing information ***********************************************************************/ void -update_timings(atblock) -struct tblock atblock; +update_timings(struct tblock atblock) { tblock.tb_max += atblock.tb_max; tblock.tb_min += atblock.tb_min; diff --git a/winsup/testsuite/winsup.api/ltp/symlink01.c b/winsup/testsuite/winsup.api/ltp/symlink01.c index 186a85b..a1441c6 100644 --- a/winsup/testsuite/winsup.api/ltp/symlink01.c +++ b/winsup/testsuite/winsup.api/ltp/symlink01.c @@ -288,26 +288,27 @@ #include "test.h" #include "usctest.h" +struct all_test_cases; void setup(); void cleanup(void) __attribute__((noreturn)); void help(); -void delete_files(); -void do_EEXIST(); -void do_ENOENT(); -void do_ELOOP(); -void do_ENOTDIR(); -void do_EXDEV(); -void do_ENAMETOOLONG(); -void do_EINVAL(); -void do_readlink(); -void do_stat(); -void do_chdir(); -void do_link(); -void do_unlink(); -void do_chmod(); -void do_utime(); -void do_rename(); -void do_open(); +void delete_files(char *path1, char *path2); +void do_EEXIST(struct all_test_cases *tc_ptr); +void do_ENOENT(struct all_test_cases *tc_ptr); +void do_ELOOP(struct all_test_cases *tc_ptr); +void do_ENOTDIR(struct all_test_cases *tc_ptr); +void do_EXDEV(struct all_test_cases *tc_ptr); +void do_ENAMETOOLONG(struct all_test_cases *tc_ptr); +void do_EINVAL(struct all_test_cases *tc_ptr); +void do_readlink(struct all_test_cases *tc_ptr); +void do_stat(struct all_test_cases *tc_ptr); +void do_chdir(struct all_test_cases *tc_ptr); +void do_link(struct all_test_cases *tc_ptr); +void do_unlink(struct all_test_cases *tc_ptr); +void do_chmod(struct all_test_cases *tc_ptr); +void do_utime(struct all_test_cases *tc_ptr); +void do_rename(struct all_test_cases *tc_ptr); +void do_open(struct all_test_cases *tc_ptr); #define S_FILE "symbolic" /* Name of symbolic link file */ #define O_FILE "object" /* Name of object file */ @@ -378,8 +379,14 @@ const char *msgs[] = { /* * Define test object setup and validation functions */ -int creat_both(), creat_symlink(), creat_path_max(), ck_symlink(), - creat_object(), ck_object(), ck_both(), ck_path_max(); +int creat_both(const char *path1, const char *path2, const char *path3); +int creat_symlink(const char *path1, const char *path2, const char *unused); +int creat_path_max(const char *path1, const char *path2, const char *path3); +int creat_object(const char *path1, const char *unused1, const char *unused2); +int ck_symlink(const char *path1, const char *path2, const char *path3); +int ck_object(const char *path1, const char *path2, const char *path3); +int ck_both(const char *path1, const char *path2, const char *path3); +int ck_path_max(const char *path1, const char *path2, const char *path3); /* @@ -391,10 +398,10 @@ struct all_test_cases int test_fail; int errno_val; int pass_msg; - int (*test_setup)(); - int (*ck_test)(); + int (*test_setup)(const char *, const char *, const char *); + int (*ck_test)(const char *, const char *, const char *); const char *fn_arg[3]; - + } test_objects[] = { {SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {"%bc+eFhi!k", S_FILE, NULL}}, {SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}}, @@ -491,7 +498,6 @@ char test_msg[BUFMAX]; char full_path[PATH_MAX+1+1]; /* Add one for '\0' and another to exceed the PATH_MAX limit, see creat_path_max() */ extern int Tst_count; extern char *TESTDIR; -extern char *strrchr(); extern int errno; struct stat asymlink, statter; @@ -511,8 +517,8 @@ option_t Options[] = { int main(int argc, char *argv[]) { - struct tcses *tcs_ptr, *get_tcs_info(); - int do_syscalltests(); + struct tcses *tcs_ptr, *get_tcs_info(char *ptr); + int do_syscalltests(struct tcses *tcs); void cleanup(); int lc; /* loop counter */ const char *msg; /* message returned from parse_opts */ @@ -589,8 +595,7 @@ main(int argc, char *argv[]) * * Argument is path to program name. ***********************************************************************/ -struct tcses *get_tcs_info(ptr) -char *ptr; +struct tcses *get_tcs_info(char *ptr) { unsigned ctr; struct tcses *tcs_ptr; @@ -605,16 +610,14 @@ char *ptr; } #endif - for(ctr=0; ctr < (sizeof(all_tcses)/sizeof(struct tcses)); ctr++) { - if ( strcmp(ptr, all_tcses[ctr].tcid) == 0 || + if ( strcmp(ptr, all_tcses[ctr].tcid) == 0 || strcmp(ptr, all_tcses[ctr].syscall) == 0 ) { tcs_ptr = &all_tcses[ctr]; TCID = all_tcses[ctr].tcid; TST_TOTAL=tcs_ptr->test_cases; return(tcs_ptr); } - } return(NULL); } @@ -628,8 +631,7 @@ char *ptr; * link file and a minus one if the path doesn't point at a file. ***********************************************************************/ int -see_if_a_symlink(path) -char *path; +see_if_a_symlink(const char *path) { if (lstat(path, &asymlink) < 0) return(-1); @@ -644,8 +646,7 @@ char *path; * This function performs without any hesitation, file(s) deletions ***********************************************************************/ void -delete_files(path1, path2) -char *path1, *path2; +delete_files(char *path1, char *path2) { unlink(path1); unlink(path2); @@ -660,8 +661,7 @@ char *path1, *path2; * ***********************************************************************/ int -creat_symlink(path1, path2) -char *path1, *path2; +creat_symlink(const char *path1, const char *path2, const char *unused) { TEST( symlink(path1, path2) ); errno=TEST_ERRNO; @@ -671,7 +671,7 @@ char *path1, *path2; "symlink(2) Failure when creating setup %s object file: errno:%d %s", path1, errno, strerror(errno)); return(0); - } + } else { sprintf(Buf, "symlink(%s, %s) was succesful.\n", path1, path2); strcat(Buffer, Buf); @@ -690,8 +690,7 @@ char *path1, *path2; * ***********************************************************************/ int -creat_object(path1) -char *path1; +creat_object(const char *path1, const char *unused1, const char *unused2) { int fd; if ((fd=creat(path1, MODE)) == -1) { @@ -700,7 +699,7 @@ char *path1; "creat(2) Failure when creating setup %s object file: errno:%d %s", path1, errno, strerror(errno)); return(0); - } + } else { sprintf(Buf, "creat(%s, %#o) was succesful.\n", path1, MODE); strcat(Buffer, Buf); @@ -728,12 +727,11 @@ char *path1; * ***********************************************************************/ int -creat_both(path1, path2, path3) -char *path1, *path2, *path3; +creat_both(const char *path1, const char *path2, const char *path3) { - if (creat_symlink(path1, path2) == -1) + if (creat_symlink(path1, path2, NULL) == -1) return(0); - else if (creat_object(path3) == -1) + else if (creat_object(path3, NULL, NULL) == -1) return(0); return(1); } @@ -748,8 +746,7 @@ char *path1, *path2, *path3; * ***********************************************************************/ int -ck_symlink(path1, path2, path3) -char *path1, *path2, *path3; +ck_symlink(const char *path1, const char *path2, const char *path3) { int ret; @@ -780,8 +777,7 @@ char *path1, *path2, *path3; * ***********************************************************************/ int -ck_both(path1, path2, path3) -char *path1, *path2, *path3; +ck_both(const char *path1, const char *path2, const char *path3) { if (ck_symlink(path1, path2, path3) == 0) return(0); @@ -804,7 +800,6 @@ char *path1, *path2, *path3; return(0); } return(1); - } /*********************************************************************** @@ -816,8 +811,7 @@ char *path1, *path2, *path3; * Argument three is regular file name ***********************************************************************/ int -creat_path_max(path1, path2, path3) -char *path1, *path2, *path3; +creat_path_max(const char *path1, const char *path2, const char *path3) { int ctr, to_go, size, whole_chunks; char buf [PATH_MAX]; @@ -858,8 +852,7 @@ char *path1, *path2, *path3; * Argument three is regular file name ***********************************************************************/ int -ck_path_max(path1, path2, path3) -char *path1, *path2, *path3; +ck_path_max(const char *path1, const char *path2, const char *path3) { if (strlen(full_path) == (PATH_MAX+1)) return(1); @@ -884,8 +877,7 @@ char *path1, *path2, *path3; * ***********************************************************************/ int -ck_object(path1, path2, path3) -char *path1, *path2, *path3; +ck_object(const char *path1, const char *path2, const char *path3) { int ret; @@ -897,7 +889,7 @@ char *path1, *path2, *path3; } else if (ret == 1) { TEST_RESULT=TFAIL; - sprintf(test_msg, + sprintf(test_msg, "lstat(2) detected a regular object file as a symbolic link file"); return(0); } @@ -912,7 +904,6 @@ char *path1, *path2, *path3; sprintf(test_msg, "lstat(2) and stat(2) do not return same inode information for an object file"); return(0); - } return(1); } @@ -923,8 +914,7 @@ char *path1, *path2, *path3; * Argument is a ptr into the all_tcses array of structures of type tcses ***********************************************************************/ int -do_syscalltests(tcs) -struct tcses *tcs; +do_syscalltests(struct tcses *tcs) { int ctr, ret; struct all_test_cases *tc_ptr; @@ -957,20 +947,20 @@ struct tcses *tcs; } TEST_RESULT=TPASS; delete_files(S_FILE, O_FILE); - /* + /* * Perform test case setup */ ret = (tc_ptr->test_setup)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1], - tc_ptr->fn_arg[2], tc_ptr->errno_val); + tc_ptr->fn_arg[2]); /* If an expected error, try it out */ if (tc_ptr->test_fail) { - /* + /* * Try to perform test verification function */ if (! (tc_ptr->ck_test)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1], - tc_ptr->fn_arg[2], tc_ptr->errno_val)) + tc_ptr->fn_arg[2])) tst_resm(TEST_RESULT, test_msg); else if (tc_ptr->errno_val == EEXIST) do_EEXIST(tc_ptr); @@ -990,22 +980,22 @@ struct tcses *tcs; tst_resm(TBROK, "Test Case Declaration Error"); } else if (ret == 1) { /* No setup function error */ - + if (tc_ptr->errno_val != 0) tst_resm(TBROK, "Test Case Declaration Error"); else { - /* + /* * Perform test verification function */ ret=(tc_ptr->ck_test)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1], - tc_ptr->fn_arg[2], tc_ptr->errno_val); + tc_ptr->fn_arg[2]); /* Perform requested symbolic link system call test */ if ((cktcsid(tc_ptr->tcid, SYMLINK)) || (cktcsid(tc_ptr->tcid, LSTAT))) { if (ret == 1) - tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]); + tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]); else tst_resm(TEST_RESULT, test_msg); } @@ -1047,8 +1037,7 @@ struct tcses *tcs; * all_test_cases ***********************************************************************/ void -do_EEXIST(tc_ptr) -struct all_test_cases *tc_ptr; +do_EEXIST(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, SYMLINK)) { @@ -1109,8 +1098,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ENOENT(tc_ptr) -struct all_test_cases *tc_ptr; +do_ENOENT(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, STAT)) { @@ -1204,8 +1192,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ELOOP(tc_ptr) -struct all_test_cases *tc_ptr; +do_ELOOP(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, STAT)) { @@ -1314,8 +1301,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ENOTDIR(tc_ptr) -struct all_test_cases *tc_ptr; +do_ENOTDIR(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, RMDIR)) { @@ -1350,8 +1336,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_EXDEV(tc_ptr) -struct all_test_cases *tc_ptr; +do_EXDEV(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, RENAME)) { @@ -1388,8 +1373,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_ENAMETOOLONG(tc_ptr) -struct all_test_cases *tc_ptr; +do_ENAMETOOLONG(struct all_test_cases *tc_ptr) { int ret; @@ -1440,8 +1424,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_EINVAL(tc_ptr) -struct all_test_cases *tc_ptr; +do_EINVAL(struct all_test_cases *tc_ptr) { if (cktcsid(tc_ptr->tcid, READLINK)) { TEST( readlink(tc_ptr->fn_arg[0], test_msg, BUFMAX) ); @@ -1473,8 +1456,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_readlink(tc_ptr) -struct all_test_cases *tc_ptr; +do_readlink(struct all_test_cases *tc_ptr) { char scratch[PATH_MAX]; int ret; @@ -1514,8 +1496,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_stat(tc_ptr) -struct all_test_cases *tc_ptr; +do_stat(struct all_test_cases *tc_ptr) { if (statter.st_dev != asymlink.st_dev) tst_resm(TFAIL, @@ -1575,8 +1556,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_chdir(tc_ptr) -struct all_test_cases *tc_ptr; +do_chdir(struct all_test_cases *tc_ptr) { if (mkdir(tc_ptr->fn_arg[2],MODE) == -1) tst_resm(TFAIL, "Could not create a setup directory file"); @@ -1626,8 +1606,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_link(tc_ptr) -struct all_test_cases *tc_ptr; +do_link(struct all_test_cases *tc_ptr) { struct stat stbuf; @@ -1688,8 +1667,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_unlink(tc_ptr) -struct all_test_cases *tc_ptr; +do_unlink(struct all_test_cases *tc_ptr) { if (stat(tc_ptr->fn_arg[2], &asymlink) == -1) tst_resm(TBROK, @@ -1730,8 +1708,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_chmod(tc_ptr) -struct all_test_cases *tc_ptr; +do_chmod(struct all_test_cases *tc_ptr) { if (stat(tc_ptr->fn_arg[2], &asymlink) == -1) tst_resm(TBROK, @@ -1772,8 +1749,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_utime(tc_ptr) -struct all_test_cases *tc_ptr; +do_utime(struct all_test_cases *tc_ptr) { struct utimbuf utimes; @@ -1828,8 +1804,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_rename(tc_ptr) -struct all_test_cases *tc_ptr; +do_rename(struct all_test_cases *tc_ptr) { int pts_at_object = 0; @@ -1870,8 +1845,7 @@ struct all_test_cases *tc_ptr; * all_test_cases ***********************************************************************/ void -do_open(tc_ptr) -struct all_test_cases *tc_ptr; +do_open(struct all_test_cases *tc_ptr) { int fd = -1; int ret, pts_at_object = 0; diff --git a/winsup/testsuite/winsup.api/ltp/unlink08.c b/winsup/testsuite/winsup.api/ltp/unlink08.c index e793b46..367b13d 100644 --- a/winsup/testsuite/winsup.api/ltp/unlink08.c +++ b/winsup/testsuite/winsup.api/ltp/unlink08.c @@ -129,15 +129,15 @@ extern int Tst_count; /* Test Case counter for tst_* routines */ int exp_enos[]={0, 0}; -int unwrite_dir_setup(); -int unsearch_dir_setup(); -int dir_setup(); -int no_setup(); +int unwrite_dir_setup(int flag); +int unsearch_dir_setup(int flag); +int dir_setup(int flag); +int no_setup(int flag); struct test_case_t { const char *pathname; const char *desc; - int (*setupfunc)(); + int (*setupfunc)(int flag); int exp_ret; /* -1 means error, 0 means != -1 */ int exp_errno; } Test_cases[] = { @@ -306,8 +306,7 @@ cleanup() * ******************************************************************/ int -unwrite_dir_setup(flag) -int flag; +unwrite_dir_setup(int flag) { int fd; @@ -358,8 +357,7 @@ int flag; * ******************************************************************/ int -unsearch_dir_setup(flag) -int flag; +unsearch_dir_setup(int flag) { int fd; @@ -410,8 +408,7 @@ int flag; * ******************************************************************/ int -dir_setup(flag) -int flag; +dir_setup(int flag) { if (mkdir("regdir", 0777) == -1 ) { tst_brkm(TBROK, cleanup, @@ -425,8 +422,7 @@ int flag; * ******************************************************************/ int -no_setup(flag) -int flag; +no_setup(int flag) { return 0; } diff --git a/winsup/testsuite/winsup.api/posix_spawn/chdir.c b/winsup/testsuite/winsup.api/posix_spawn/chdir.c new file mode 100644 index 0000000..0951d2d --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/chdir.c @@ -0,0 +1,158 @@ +#include "test.h" +#include <fcntl.h> +#include <limits.h> +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* Linux is behind the times a bit (also needs the *chdir_np functions) */ +#ifndef O_SEARCH +# define O_SEARCH O_PATH +#endif + +int handle_child (char *expected) +{ + char buf[PATH_MAX + 1]; + + nullError (getcwd (buf, sizeof (buf))); + testAssertMsg (!strcmp (buf, expected), "cwd '%s' != expected '%s'", + buf, expected); + + return 0; +} + +int handle_childfds (char *expectedcwd, char *expectedfd0, char *expectedfd1) +{ + char buf[PATH_MAX + 1]; + ssize_t ret; + + testAssert (handle_child (expectedcwd) == 0); + + negError (ret = readlink ("/dev/fd/0", buf, PATH_MAX)); + testAssertMsg (ret < PATH_MAX, "Path too long for PATH_MAX buffer"); + buf[ret] = '\0'; + testAssertMsg (!strcmp (buf, expectedfd0), "fd 0 '%s' != expected '%s'", + buf, expectedfd0); + + negError (ret = readlink ("/dev/fd/1", buf, PATH_MAX)); + testAssertMsg (ret < PATH_MAX, "Path too long for PATH_MAX buffer"); + buf[ret] = '\0'; + testAssertMsg (!strcmp (buf, expectedfd1), "fd 1 '%s' != expected '%s'", + buf, expectedfd1); + + return 0; +} + +static char tmpcwd[] = "tmpcwd.XXXXXX"; +static char tmppath[] = "tmpfile.XXXXXX"; +static char tmppath2[sizeof (tmpcwd) + 9] = {0}; + +static void cleanup_tmpfiles (void) +{ + if (tmppath2[0]) + unlink (tmppath2); + rmdir (tmpcwd); + unlink (tmppath); +} + +int main (int argc, char **argv) +{ + posix_spawn_file_actions_t fa; + pid_t pid; + int status; + int fd; + char buf[PATH_MAX + 1]; + char buffd0[PATH_MAX + 1]; + char buffd1[PATH_MAX + 1]; + char *childargv[] = {"chdir", "--child", buf, NULL, NULL, NULL}; + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + if (argc == 3 && !strcmp (argv[1], "--child")) + return handle_child (argv[2]); + else if (argc == 5 && !strcmp (argv[1], "--child")) + return handle_childfds (argv[2], argv[3], argv[4]); + + /* make a directory and a couple of files for testing */ + nullError (mkdtemp (tmpcwd)); + atexit (cleanup_tmpfiles); + + negError (fd = mkstemp (tmppath)); + negError (close (fd)); + + stpcpy (stpcpy (stpcpy (tmppath2, tmpcwd), "/"), "tmpfile2"); + negError (fd = open (tmppath2, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)); + negError (close (fd)); + + + /* ensure cwd is inherited by default */ + nullError (getcwd (buf, sizeof (buf))); + stpcpy (stpcpy (stpcpy (buffd0, buf), "/"), tmppath); + errCode (posix_spawn (&pid, MYSELF, NULL, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + + /* test posix_spawn_file_actions_addchdir */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addchdir_np (&fa, tmpcwd)); + + strcat (buf, "/"); + strcat (buf, tmpcwd); + stpcpy (stpcpy (stpcpy (buffd1, buf), "/"), "tmpfile2"); + + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_addfchdir */ + negError (fd = open (tmpcwd, O_SEARCH|O_DIRECTORY|O_CLOEXEC, 0755)); + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addfchdir_np (&fa, fd)); + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + negError (close (fd)); + + /* test posix_spawn_file_actions_addchdir + addopen */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 0, tmppath, O_RDONLY, 0644)); + errCode (posix_spawn_file_actions_addchdir_np (&fa, tmpcwd)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 0644)); + childargv[3] = buffd0; + childargv[4] = buffd1; + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_addfchdir + addopen */ + negError (fd = open (tmpcwd, O_SEARCH|O_DIRECTORY|O_CLOEXEC, 0755)); + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 0, tmppath, O_RDONLY, 0644)); + errCode (posix_spawn_file_actions_addfchdir_np (&fa, fd)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 0644)); + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_addfchdir + adddup2 of directory fd */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_adddup2 (&fa, fd, 0)); + errCode (posix_spawn_file_actions_addfchdir_np (&fa, fd)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 0644)); + childargv[3] = buf; + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + negError (close (fd)); + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/errors.c b/winsup/testsuite/winsup.api/posix_spawn/errors.c new file mode 100644 index 0000000..3fbc2cb --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/errors.c @@ -0,0 +1,66 @@ +#include "test.h" +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +static char tmppath[] = "pspawn.XXXXXX"; +static const char exit0[] = "exit 0\n"; + +void cleanup_tmpfile (void) +{ + unlink (tmppath); +} + +int main (void) +{ + posix_spawn_file_actions_t fa; + pid_t pid; + int fd; + char *childargv[] = {"ls", NULL}; + char tmpsub[sizeof (tmppath) + 3]; + char *p; + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + negError (fd = mkstemp (tmppath)); + atexit (cleanup_tmpfile); + negError (write (fd, exit0, sizeof (exit0) - 1)); + negError (close (fd)); + + /* expected ENOENT: posix_spawn without full path */ + errCodeExpected (ENOENT, + posix_spawn (&pid, childargv[0], NULL, NULL, childargv, environ)); + + /* expected EACCES: posix_spawn with path to non-executable file */ + errCodeExpected (EACCES, + posix_spawn (&pid, tmppath, NULL, NULL, childargv, environ)); + + negError (chmod (tmppath, 0755)); + + /* expected ENOEXEC: posix_spawn with unrecognized file format */ + errCodeExpected (ENOEXEC, + posix_spawn (&pid, tmppath, NULL, NULL, childargv, environ)); + + p = stpcpy (tmpsub, tmppath); + p = stpcpy (p, "/ls"); + +#ifndef __CYGWIN__ + /* Cygwin returns ENOENT rather than ENOTDIR here */ + /* expected ENOTDIR: posix_spawn with file as non-leaf entry in path */ + errCodeExpected (ENOTDIR, + posix_spawn (&pid, tmpsub, NULL, NULL, childargv, environ)); +#endif + + /* expected ENOENT: relative path after chdir */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addchdir_np (&fa, "/tmp")); + errCodeExpected (ENOENT, + posix_spawn (&pid, tmppath, &fa, NULL, childargv, environ)); + errCode (posix_spawn_file_actions_destroy (&fa)); + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/fds.c b/winsup/testsuite/winsup.api/posix_spawn/fds.c new file mode 100644 index 0000000..98ce36f --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/fds.c @@ -0,0 +1,124 @@ +#include "test.h" +#include <fcntl.h> +#include <limits.h> +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int handle_child (char *devfd, char *target) +{ + char buf[PATH_MAX]; + ssize_t ret; + + ret = readlink (devfd, buf, PATH_MAX); + if (ret < 0) + { + int err = errno; + if (err == ENOENT && !strcmp (target, "<ENOENT>")) + return 0; + error_at_line (1, err, __FILE__, __LINE__ - 6, + "ret = readlink (devfd, buf, PATH_MAX)"); + } + testAssertMsg (ret < PATH_MAX, "Path too long for PATH_MAX buffer"); + buf[ret] = '\0'; + if (strcmp (target, buf)) + error_at_line (1, 0, __FILE__, __LINE__ - 12, + "Target '%s' != expected '%s'", buf, target); + + return 0; +} + +int main (int argc, char **argv) +{ + posix_spawn_file_actions_t fa; + pid_t pid; + int status; + int fd, fdcloexec; + char buf[16]; + char *childargv[] = {"fds", "--child", buf, "", NULL}; + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + if (argc == 4 && !strcmp (argv[1], "--child")) + return handle_child (argv[2], argv[3]); + + /* open file descriptors to test inheritance */ + negError (fd = open ("/dev/null", O_RDONLY, 0644)); + negError (fdcloexec = open ("/dev/full", O_RDONLY|O_CLOEXEC, 0644)); + + /* ensure fd is inherited by default */ + sprintf (buf, "/dev/fd/%d", fd); + childargv[3] = "/dev/null"; + errCode (posix_spawn (&pid, MYSELF, NULL, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + + /* ensure CLOEXEC fd is closed */ + sprintf (buf, "/dev/fd/%d", fdcloexec); + childargv[3] = "<ENOENT>"; + errCode (posix_spawn (&pid, MYSELF, NULL, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + + /* test posix_spawn_file_actions_addopen */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 0, "/dev/zero", O_RDONLY, + 0644)); + strcpy (buf, "/dev/fd/0"); + childargv[3] = "/dev/zero"; + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_adddup2 */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_adddup2 (&fa, fd, 0)); + childargv[3] = "/dev/null"; + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_adddup2 with CLOEXEC fd */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_adddup2 (&fa, fdcloexec, 0)); + childargv[3] = "/dev/full"; + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_adddup2 with out to err */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "/dev/zero", O_WRONLY, + 0644)); + errCode (posix_spawn_file_actions_adddup2 (&fa, 1, 2)); + strcpy (buf, "/dev/fd/2"); + childargv[3] = "/dev/zero"; + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_addclose */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addclose (&fa, fd)); + sprintf (buf, "/dev/fd/%d", fd); + childargv[3] = "<ENOENT>"; + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* TODO: test new fds (open or dup2) not 0 through 2 */ + /* TODO: test error cases */ + + negError (close (fd)); + negError (close (fdcloexec)); + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/signals.c b/winsup/testsuite/winsup.api/posix_spawn/signals.c new file mode 100644 index 0000000..f64404d --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/signals.c @@ -0,0 +1,82 @@ +#include "test.h" +#include <signal.h> +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int handle_child (char *arg) +{ + struct sigaction sa; + sigset_t mask; + int ret; + + negError (sigaction (SIGUSR1, NULL, &sa)); + negError (sigprocmask (SIG_SETMASK, NULL, &mask)); + negError (ret = sigismember (&mask, SIGUSR2)); + + if (!strcmp (arg, "inherited")) + { + testAssert (sa.sa_handler == SIG_IGN); + testAssertMsg (ret, "SIGUSR2 not masked"); + } + else + { + testAssert (sa.sa_handler == SIG_DFL); + testAssertMsg (!ret, "SIGUSR2 masked"); + } + + return 0; +} + +int main (int argc, char **argv) +{ + posix_spawnattr_t sa; + pid_t pid; + int status; + sigset_t sigusr1mask, sigusr2mask, emptymask; + char *childargv[] = {"signal", "--child", "inherited", NULL}; + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + if (argc == 3 && !strcmp (argv[1], "--child")) + return handle_child (argv[2]); + + negError (sigemptyset (&sigusr1mask)); + negError (sigaddset (&sigusr1mask, SIGUSR1)); + negError (sigemptyset (&sigusr2mask)); + negError (sigaddset (&sigusr2mask, SIGUSR2)); + negError (sigemptyset (&emptymask)); + + /* set all signals to default */ + for (int i = 1; i < NSIG; ++i) + if (i != SIGKILL && i != SIGSTOP) + signal (i, SIG_DFL); + + /* change some signal states to test signal-related posix_spawn flags */ + sigError (signal (SIGUSR1, SIG_IGN)); + negError (sigprocmask (SIG_SETMASK, &sigusr2mask, NULL)); + + /* ensure ignored and blocked signals are inherited by default */ + errCode (posix_spawn (&pid, MYSELF, NULL, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + + errCode (posix_spawnattr_init (&sa)); + errCode (posix_spawnattr_setsigmask (&sa, &emptymask)); + errCode (posix_spawnattr_setsigdefault (&sa, &sigusr1mask)); + errCode (posix_spawnattr_setflags (&sa, + POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK)); + + /* ensure setsigmask and setsigdefault work */ + childargv[2] = "spawnattr"; + errCode (posix_spawn (&pid, MYSELF, NULL, &sa, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + + errCode (posix_spawnattr_destroy (&sa)); + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/spawnp.c b/winsup/testsuite/winsup.api/posix_spawn/spawnp.c new file mode 100644 index 0000000..c7bee87 --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/spawnp.c @@ -0,0 +1,25 @@ +#include "test.h" +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main (void) +{ + pid_t pid; + int status; + /* the test installation has very limited binaries on the PATH, but sh is one + of them and 'true' should be a builtin */ + char *childargv[] = {"sh", "-c", "true", NULL}; + char *childenv[] = {NULL}; + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + /* can posix_spawnp find a program even with an empty environment? */ + errCode (posix_spawnp (&pid, childargv[0], NULL, NULL, childargv, childenv)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/test.h b/winsup/testsuite/winsup.api/posix_spawn/test.h new file mode 100644 index 0000000..5c56ed1 --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/test.h @@ -0,0 +1,53 @@ +#ifndef _POSIX_SPAWN_TEST_H_ +#define _POSIX_SPAWN_TEST_H_ + +#define _GNU_SOURCE +#include <errno.h> +#include <error.h> +#include <signal.h> +#include <sys/wait.h> + +#define negError(x) do { \ + if ((x) < 0) \ + error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \ +} while (0) + +#define nullError(x) do { \ + if (!(x)) \ + error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \ +} while (0) + +#define sigError(x) do { \ + if ((x) == SIG_ERR) \ + error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \ +} while (0) + +#define errCodeExpected(expected, x) do { \ + int _errcode = (x); \ + if (_errcode != (expected)) \ + error_at_line(1, _errcode, __FILE__, __LINE__, "%s", #x); \ +} while (0) + +#define errCode(x) errCodeExpected(0, x) + +#define exitStatus(status, expectedExitCode) do { \ + if (WIFSIGNALED ((status))) \ + error_at_line (128 + WTERMSIG ((status)), 0, __FILE__, __LINE__ - 2, \ + "child terminated with signal %d", WTERMSIG ((status))); \ + else if (WIFEXITED ((status)) && WEXITSTATUS ((status)) != (expectedExitCode)) \ + error_at_line (WEXITSTATUS ((status)), 0, __FILE__, __LINE__ - 2, \ + "child exited with code %d", WEXITSTATUS ((status))); \ +} while (0) + +/* first vararg to testAssertMsg must be string msg */ +#define testAssertMsg(cond, ...) do { \ + if (!(cond)) \ + error_at_line (1, 0, __FILE__, __LINE__, __VA_ARGS__); \ +} while (0); + +#define testAssert(cond) testAssertMsg(cond, "%s", #cond) + +#define MYSELF "/proc/self/exe" + +#endif /* _POSIX_SPAWN_TEST_H_ */ + diff --git a/winsup/testsuite/winsup.api/posix_spawn/win32.c b/winsup/testsuite/winsup.api/posix_spawn/win32.c new file mode 100644 index 0000000..8998c43 --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/win32.c @@ -0,0 +1,181 @@ +#include "test.h" +#include <dlfcn.h> +#include <fcntl.h> +#include <limits.h> +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/cygwin.h> +#include <unistd.h> + +char * find_winchild (void) +{ + static const char winchild[] = "/winchild"; + char *mingwtestdir = getenv ("mingwtestdir"); + if (!mingwtestdir) + { + Dl_info dli; + if (dladdr (&find_winchild, &dli)) + { + ssize_t i = strlen (dli.dli_fname) - 1; + for (int slashes = 0; i >= 0 && slashes < 3; --i) + if (dli.dli_fname[i] == '/') + slashes++; + stpcpy (stpcpy (dli.dli_fname + i + 1, "/mingw"), winchild); + return realpath (dli.dli_fname, NULL); + } + else + { + return realpath ("../../mingw/winchild", NULL); + } + } + else + { + char *ret, *tmp = malloc (strlen (mingwtestdir) + sizeof (winchild)); + stpcpy (stpcpy (tmp, mingwtestdir), winchild); + ret = realpath (tmp, NULL); + free (tmp); + return ret; + } +} + +static char tmppath[] = "pspawn.XXXXXX"; +static char tmpcwd[] = "tmpcwd.XXXXXX"; +static char tmppath2[sizeof (tmpcwd) + 9] = {0}; + +static void cleanup_tmpfiles (void) +{ + if (tmppath2[0]) + unlink (tmppath2); + rmdir (tmpcwd); + unlink (tmppath); +} + +int main (void) +{ + posix_spawn_file_actions_t fa; + pid_t pid; + int status; + int fd, fdcloexec, cwdfd; + char *childargv[] = {"winchild", NULL, NULL, NULL}; + char *winchild = find_winchild (); + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + /* temp regular file */ + negError (fd = mkstemp (tmppath)); + atexit (cleanup_tmpfiles); + negError (close (fd)); + + /* temp directory */ + nullError (mkdtemp (tmpcwd)); + + /* temp file within temp directory */ + stpcpy (stpcpy (stpcpy (tmppath2, tmpcwd), "/"), "tmpfile2"); + negError (fd = open (tmppath2, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)); + negError (close (fd)); + + /* open file descriptors to test inheritance */ + negError (fd = open ("/dev/null", O_RDONLY, 0644)); + negError (fdcloexec = open ("/dev/full", O_RDONLY|O_CLOEXEC, 0644)); + + /* test posix_spawn_file_actions_addopen */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 0, "/dev/zero", O_RDONLY, + 0644)); + childargv[1] = "0"; + childargv[2] = "\\Device\\Null"; + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_adddup2 */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_adddup2 (&fa, fd, 0)); + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_adddup2 with CLOEXEC fd */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_adddup2 (&fa, fdcloexec, 0)); + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_adddup2 with out to err */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "/dev/zero", O_WRONLY, + 0644)); + errCode (posix_spawn_file_actions_adddup2 (&fa, 1, 2)); + childargv[1] = "2"; + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_addopen with real file */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, tmppath, O_WRONLY, 0644)); + childargv[1] = "1"; + childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmppath); + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + free (childargv[2]); + + /* test posix_spawn_file_actions_addchdir */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addchdir (&fa, tmpcwd)); + childargv[1] = "CWD"; + childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmpcwd); + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + + /* test posix_spawn_file_actions_addfchdir */ + negError (cwdfd = open (tmpcwd, O_SEARCH|O_DIRECTORY|O_CLOEXEC, 0755)); + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addfchdir (&fa, cwdfd)); + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + free (childargv[2]); + + /* test posix_spawn_file_actions_addfchdir followed by addopen */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addfchdir (&fa, cwdfd)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 0644)); + childargv[1] = "1"; + childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmppath2); + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + free (childargv[2]); + + /* test posix_spawn_file_actions_adddup2 of directory handle */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_adddup2 (&fa, cwdfd, 0)); + childargv[1] = "0"; + childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmpcwd); + errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + free (childargv[2]); + + negError (close (cwdfd)); + negError (close (fd)); + negError (close (fdcloexec)); + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/winchild.c b/winsup/testsuite/winsup.api/posix_spawn/winchild.c new file mode 100644 index 0000000..6fdfa00 --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/winchild.c @@ -0,0 +1,130 @@ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winternl.h> +#include <ctype.h> +#include <stdio.h> + + +int wmain (int argc, wchar_t **argv) +{ + if (argc != 3) + { + fwprintf (stderr, L"Usage: %ls handle expected\n", argv[0]); + return 1; + } + + if (!wcscmp (argv[1], L"CWD")) + { + LPWSTR buffer; + DWORD len = GetCurrentDirectoryW (0, NULL); + if (len == 0) + { + fwprintf (stderr, L"%ls: GetCurrentDirectory failed with error %lu\n", + argv[0], GetLastError ()); + return 2; + } + buffer = malloc (len * sizeof (WCHAR)); + if (GetCurrentDirectoryW (len, buffer) != len - 1) + { + fwprintf (stderr, L"%ls: GetCurrentDirectory failed with error %lu\n", + argv[0], GetLastError ()); + return 2; + } + if (wcscmp (argv[2], buffer)) + { + fwprintf (stderr, L"%ls: CWD '%ls' != expected '%ls'\n", + argv[0], buffer, argv[2]); + free (buffer); + return 4; + } + free (buffer); + } + else if (iswdigit (argv[1][0]) && !argv[1][1]) + { + HANDLE stdhandle; + DWORD nStdHandle; + switch (argv[1][0]) + { + case L'0': + nStdHandle = STD_INPUT_HANDLE; + break; + case L'1': + nStdHandle = STD_OUTPUT_HANDLE; + break; + case L'2': + nStdHandle = STD_ERROR_HANDLE; + break; + default: + fwprintf (stderr, L"%ls: Unknown handle '%ls'\n", argv[0], argv[1]); + return 1; + } + + stdhandle = GetStdHandle (nStdHandle); + if (stdhandle == INVALID_HANDLE_VALUE) + { + fwprintf (stderr, L"%ls: Failed getting standard handle %ls: %lu\n", + argv[0], argv[1], GetLastError ()); + return 2; + } + else if (stdhandle == NULL) + { + if (wcscmp (argv[2], L"<CLOSED>")) + { + fwprintf (stderr, + L"%ls: Handle %ls name '%ls' != expected '%ls'\n", + argv[0], argv[1], L"<CLOSED>", argv[2]); + return 4; + } + } + else + { + LPWSTR buf, win32path; + buf = malloc (65536); + if (!GetFinalPathNameByHandleW (stdhandle, buf, + 65536 / sizeof (WCHAR), + FILE_NAME_OPENED|VOLUME_NAME_DOS)) + { + POBJECT_NAME_INFORMATION pinfo = (POBJECT_NAME_INFORMATION) buf; + DWORD err = GetLastError (); + ULONG len; + NTSTATUS status = NtQueryObject (stdhandle, ObjectNameInformation, + pinfo, 65536, &len); + if (!NT_SUCCESS (status)) + { + fwprintf (stderr, + L"%ls: NtQueryObject for handle %ls failed: 0x%08x\n", + argv[0], argv[1], status); + free (buf); + return 3; + } + + pinfo->Name.Buffer[pinfo->Name.Length / sizeof (WCHAR)] = L'\0'; + win32path = pinfo->Name.Buffer; + } + else + { + static const WCHAR prefix[] = L"\\\\?\\"; + win32path = buf; + if (!wcsncmp (win32path, prefix, + sizeof (prefix) / sizeof (WCHAR) - 1)) + win32path += sizeof (prefix) / sizeof (WCHAR) - 1; + } + + if (wcscmp (win32path, argv[2])) + { + fwprintf (stderr, + L"%ls: Handle %ls name '%ls' != expected '%ls'\n", + argv[0], argv[1], win32path, argv[2]); + free (buf); + return 4; + } + free (buf); + } + } + else + { + fwprintf (stderr, L"%ls: Unknown handle '%ls'\n", argv[0], argv[1]); + return 1; + } + return 0; +} diff --git a/winsup/testsuite/winsup.api/pthread/cancel3.c b/winsup/testsuite/winsup.api/pthread/cancel3.c index 8ed7d52..18caf23 100644 --- a/winsup/testsuite/winsup.api/pthread/cancel3.c +++ b/winsup/testsuite/winsup.api/pthread/cancel3.c @@ -40,6 +40,7 @@ */ #include "test.h" +#include "cpu_relax.h" /* * Create NUMTHREADS threads in addition to the Main thread. @@ -88,7 +89,7 @@ mythread(void * arg) { int i; for (i = 0; i < 1E7; i++) - __asm__ volatile ("pause":::); + CPU_RELAX(); } } diff --git a/winsup/testsuite/winsup.api/pthread/cancel5.c b/winsup/testsuite/winsup.api/pthread/cancel5.c index dd5be7b..05b8ef9 100644 --- a/winsup/testsuite/winsup.api/pthread/cancel5.c +++ b/winsup/testsuite/winsup.api/pthread/cancel5.c @@ -38,12 +38,13 @@ *
* Fail Criteria:
* - Process returns non-zero exit status.
- */
-
-#include "test.h"
-
-/*
- * Create NUMTHREADS threads in addition to the Main thread.
+ */ + +#include "test.h" +#include "cpu_relax.h" + +/* + * Create NUMTHREADS threads in addition to the Main thread. */
enum {
NUMTHREADS = 10
@@ -89,7 +90,7 @@ mythread(void * arg) {
int i;
for (i = 0; i < 1E7; i++)
- __asm__ volatile ("pause":::);
+ CPU_RELAX();
}
}
diff --git a/winsup/testsuite/winsup.api/pthread/cpu_relax.h b/winsup/testsuite/winsup.api/pthread/cpu_relax.h new file mode 100644 index 0000000..c31ef8c --- /dev/null +++ b/winsup/testsuite/winsup.api/pthread/cpu_relax.h @@ -0,0 +1,13 @@ +#ifndef CPU_RELAX_H +#define CPU_RELAX_H + +#if defined(__x86_64__) || defined(__i386__) // Check for x86 architectures + #define CPU_RELAX() __asm__ volatile ("pause" :::) +#elif defined(__aarch64__) || defined(__arm__) // Check for ARM architectures + #define CPU_RELAX() __asm__ volatile ("dmb ishst\n" \ + "yield" :::) +#else + #error unimplemented for this target +#endif + +#endif diff --git a/winsup/utils/kill.cc b/winsup/utils/kill.cc index bcabcd4..1e6ab5c 100644 --- a/winsup/utils/kill.cc +++ b/winsup/utils/kill.cc @@ -372,7 +372,9 @@ main (int argc, char **argv) case '?': if (gotasig) /* this is a negative pid, go ahead */ { - --optind; + /* Reset optind because it points to the next argument if and + only if the pid has one digit. */ + optind = av - argv; goto out; } optreset = 1; |