├── Module.manifest ├── .gitignore ├── screenshot.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── extension.properties ├── data └── languages │ ├── xtensa.pspec │ ├── xtensa.dwarf │ ├── xtensa.opinion │ ├── xtensa.ldefs │ ├── xtensa.slaspec │ ├── xtensa.cspec │ ├── xtensaTodo.sinc │ ├── xtensa.sinc │ └── xtensaInstructions.sinc ├── mkindex.pl ├── README.md ├── LICENSE ├── Makefile ├── src └── main │ └── java │ └── ghidra │ └── app │ └── util │ └── bin │ └── format │ └── elf │ └── relocation │ ├── Xtensa_ElfRelocationConstants.java │ └── Xtensa_ElfRelocationHandler.java ├── gradlew.bat └── gradlew /Module.manifest: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | xtensa.sla 3 | data/manuals/ 4 | release/ 5 | release.zip 6 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yath/ghidra-xtensa/HEAD/screenshot.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yath/ghidra-xtensa/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /extension.properties: -------------------------------------------------------------------------------- 1 | name=Xtensa 2 | description=Xtensa CPU plugin 3 | author=Sebastian Schmidt 4 | createdOn= 5 | version=@extversion@ 6 | -------------------------------------------------------------------------------- /data/languages/xtensa.pspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /data/languages/xtensa.dwarf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /data/languages/xtensa.opinion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /mkindex.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use constant PAGEOFFSET => 24; 5 | 6 | print "\@xtensa.pdf[Xtensa® Instruction Set Architecture (ISA) Reference Manual, April 2010]\n\n"; 7 | 8 | my $last; 9 | 10 | while (<>) { 11 | if (/^# (\S+) .*?pg\. (\d+)/) { 12 | my ($o, $p) = (lc $1, $2+PAGEOFFSET); 13 | print "$o, $p\n"; 14 | $last = $o; 15 | } 16 | 17 | if (/^:(\S+)/ && $last && $last ne $1) { 18 | warn "Constructor for opcode $1 is preceded by comment for $last"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tensilica Xtensa module for Ghidra 2 | 3 | ![Screenshot](/screenshot.png?raw=true) 4 | 5 | # Installation 6 | 7 | ``` 8 | $ cd ghidra_9.1.X/Ghidra/Processors 9 | $ git clone https://github.com/yath/ghidra-xtensa Xtensa 10 | $ cd Xtensa 11 | $ make 12 | $ 13 | ``` 14 | 15 | Or download a pre-built release and unzip it to `Ghidra/Processors`. 16 | 17 | # Bugs 18 | 19 | * Probably a lot in instructions I did not yet happen to encouter. Pull requests 20 | appreciated. 21 | 22 | # TODO 23 | 24 | * Windowed Register Option 25 | * MAC16 Option 26 | * Loop Option 27 | * ESP8266/ESP32 image loaders? 28 | -------------------------------------------------------------------------------- /data/languages/xtensa.ldefs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | Tensilica Xtensa 32-bit little-endian 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /data/languages/xtensa.slaspec: -------------------------------------------------------------------------------- 1 | @include "xtensa.sinc" 2 | 3 | # NOTE: This is quite a big hack; a real processor will compare nextPC to LEND on every ifetch. 4 | # As we only inject the branch-back check on addresses marked by loop insns, we may miss 5 | # strange things like loop registers being written directly or loop registers being overwritten 6 | # by a "nested" loop instruction. We also don't check CLOOPENABLE (PS.EXCM). 7 | # For code that hasn't been intentially crafted for anti-analysis this should be fine. 8 | :^instruction is phase=0 & loopEnd=1 & instruction [phase=1;] { 9 | if (LCOUNT == 0) goto ; 10 | LCOUNT = LCOUNT - 1; 11 | goto [LBEG]; 12 | 13 | build instruction; 14 | } 15 | 16 | :^instruction is phase=0 & loopEnd=0 & instruction [phase=1;] { 17 | build instruction; 18 | } 19 | 20 | with : phase=1 { 21 | @include "xtensaInstructions.sinc" 22 | @include "xtensaTodo.sinc" 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Sebastian Schmidt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Assume we are in Ghidra/Processors/subdir 2 | GHIDRA_DIR ?= $(shell readlink -f $(CURDIR)/../../..) 3 | SLEIGH ?= $(GHIDRA_DIR)/support/sleigh 4 | PERL ?= perl 5 | 6 | # -x turns on parser debugging (SleighCompile) 7 | # -u print warnings for unnecessary pcode instructions (SleighCompile) 8 | # -l report pattern conflicts (SleighCompile) 9 | # -n print warnings for all NOP constructors (SleighCompile) 10 | # -t print warnings for dead temporaries (SleighCompile) 11 | # -e enforce use of 'local' keyword for temporaries (SleighCompile) 12 | # -f print warnings for unused token fields (SleighCompile) 13 | SLEIGH_ARGS := -x -u -l -n -t -e -f 14 | 15 | LANGDIR := data/languages 16 | 17 | # Must start with slaspec. 18 | SLA_SRCS := $(LANGDIR)/xtensa.slaspec $(wildcard $(LANGDIR)/xtensa*.sinc) 19 | SLA := $(LANGDIR)/xtensa.sla 20 | 21 | MANDIR := data/manuals 22 | IDX := $(MANDIR)/xtensa.idx 23 | 24 | # Targets 25 | 26 | .PHONY: all 27 | all: check-ghidra $(SLA) $(IDX) 28 | 29 | .PHONY: check-ghidra 30 | check-ghidra: 31 | @if [ ! -d $(GHIDRA_DIR)/Ghidra ]; then \ 32 | echo "Your Ghidra installation directory could not be determined." >&2; \ 33 | echo "Please re-run make with GHIDRA_DIR set to the root of your Ghidra installation." >&2; \ 34 | exit 1; \ 35 | fi 36 | 37 | $(SLA): $(SLA_SRCS) 38 | $(SLEIGH) $(SLEIGH_ARGS) $< $@ 39 | 40 | $(IDX): $(SLA_SRCS) 41 | mkdir -p $(MANDIR) 42 | $(PERL) mkindex.pl $^ > $@ 43 | 44 | release.zip: clean all 45 | mkdir -p release/Xtensa/$(LANGDIR) 46 | cp -r $(LANGDIR)/xtensa* release/Xtensa/$(LANGDIR) 47 | mkdir -p release/Xtensa/$(MANDIR) 48 | cp -r $(MANDIR)/*.idx release/Xtensa/$(MANDIR) 49 | cp Module.manifest release/Xtensa 50 | cd release && zip -r ../$@ . 51 | 52 | .PHONY: clean 53 | clean: 54 | rm -rf $(SLA) $(IDX) release release.zip 55 | -------------------------------------------------------------------------------- /src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java: -------------------------------------------------------------------------------- 1 | package ghidra.app.util.bin.format.elf.relocation; 2 | 3 | public class Xtensa_ElfRelocationConstants { 4 | /* Xtensa processor ELF architecture-magic number */ 5 | 6 | // EM_XTENSA is already definded 7 | public static final int EM_XTENSA_OLD = 0xABC7; 8 | 9 | /* Xtensa relocations defined by the ABIs */ 10 | 11 | public static final int R_XTENSA_NONE = 0; 12 | public static final int R_XTENSA_32 = 1; 13 | public static final int R_XTENSA_RTLD = 2; 14 | public static final int R_XTENSA_GLOB_DAT = 3; 15 | public static final int R_XTENSA_JMP_SLOT = 4; 16 | public static final int R_XTENSA_RELATIVE = 5; 17 | public static final int R_XTENSA_PLT = 6; 18 | public static final int R_XTENSA_OP0 = 8; 19 | public static final int R_XTENSA_OP1 = 9; 20 | public static final int R_XTENSA_OP2 = 10; 21 | public static final int R_XTENSA_ASM_EXPAND = 11; 22 | public static final int R_XTENSA_ASM_SIMPLIFY = 12; 23 | public static final int R_XTENSA_GNU_VTINHERIT = 15; 24 | public static final int R_XTENSA_GNU_VTENTRY = 16; 25 | public static final int R_XTENSA_DIFF8 = 17; 26 | public static final int R_XTENSA_DIFF16 = 18; 27 | public static final int R_XTENSA_DIFF32 = 19; 28 | public static final int R_XTENSA_SLOT0_OP = 20; 29 | public static final int R_XTENSA_SLOT1_OP = 21; 30 | public static final int R_XTENSA_SLOT2_OP = 22; 31 | public static final int R_XTENSA_SLOT3_OP = 23; 32 | public static final int R_XTENSA_SLOT4_OP = 24; 33 | public static final int R_XTENSA_SLOT5_OP = 25; 34 | public static final int R_XTENSA_SLOT6_OP = 26; 35 | public static final int R_XTENSA_SLOT7_OP = 27; 36 | public static final int R_XTENSA_SLOT8_OP = 28; 37 | public static final int R_XTENSA_SLOT9_OP = 29; 38 | public static final int R_XTENSA_SLOT10_OP = 30; 39 | public static final int R_XTENSA_SLOT11_OP = 31; 40 | public static final int R_XTENSA_SLOT12_OP = 32; 41 | public static final int R_XTENSA_SLOT13_OP = 33; 42 | public static final int R_XTENSA_SLOT14_OP = 34; 43 | public static final int R_XTENSA_SLOT0_ALT = 35; 44 | public static final int R_XTENSA_SLOT1_ALT = 36; 45 | public static final int R_XTENSA_SLOT2_ALT = 37; 46 | public static final int R_XTENSA_SLOT3_ALT = 38; 47 | public static final int R_XTENSA_SLOT4_ALT = 39; 48 | public static final int R_XTENSA_SLOT5_ALT = 40; 49 | public static final int R_XTENSA_SLOT6_ALT = 41; 50 | public static final int R_XTENSA_SLOT7_ALT = 42; 51 | public static final int R_XTENSA_SLOT8_ALT = 43; 52 | public static final int R_XTENSA_SLOT9_ALT = 44; 53 | public static final int R_XTENSA_SLOT10_ALT = 45; 54 | public static final int R_XTENSA_SLOT11_ALT = 46; 55 | public static final int R_XTENSA_SLOT12_ALT = 47; 56 | public static final int R_XTENSA_SLOT13_ALT = 48; 57 | public static final int R_XTENSA_SLOT14_ALT = 49; 58 | } 59 | -------------------------------------------------------------------------------- /data/languages/xtensa.cspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /data/languages/xtensaTodo.sinc: -------------------------------------------------------------------------------- 1 | ## Windowed Register Option ## 2 | 3 | # CALL4 - Call PC-relative, Rotate Window by 4, pg. 298. 4 | :call4 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b01 & op0 = 0b0101 unimpl 5 | 6 | # CALL8 - Call PC-relative, Rotate Window by 8, pg. 300. 7 | :call8 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b10 & op0 = 0b0101 unimpl 8 | 9 | # CALL12 - Call PC-relative, Rotate Window by 12, pg. 302. 10 | :call12 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b11 & op0 = 0b0101 unimpl 11 | 12 | # CALLX4 - Call Register, Rotate Window by 4, pg. 305. 13 | :callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b01 & op0 = 0 unimpl 14 | 15 | # CALLX8 - Call Register, Rotate Window by 8, pg. 307. 16 | :callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b10 & op0 = 0 unimpl 17 | 18 | # CALLX12 - Call Register, Rotate Window by 12, pg. 308. 19 | :callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b11 & op0 = 0 unimpl 20 | 21 | # ENTRY - Subroutine Entry, pg. 340. 22 | :entry as, u15_12.23_sb3 is u15_12.23_sb3 & as & u2_6.7 = 0b00 & u2_4.5 = 0b11 & op0 = 0b0110 unimpl 23 | 24 | # L32E - Load 32-bit for Window Exceptions, pg. 376. 25 | :l32e at, as, s5_12.15_oex is op2 = 0 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl 26 | 27 | # MOVSP - Move to Stack Pointer, pg. 427. 28 | :movsp at, as is op2 = 0 & op1 = 0 & ar = 0b0001 & as & at & op0 = 0 unimpl 29 | 30 | # RETW - Windowed Return, pg. 480. 31 | :retw is op2 = 0 & ar = 0 & as = 0 & at = 0 & u2_18.19 = 0b10 & u2_16.17 = 0b01 & op0 = 0 unimpl 32 | 33 | # RETW.N - Narrow Windowed Return, pg. 482. 34 | :retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 unimpl 35 | 36 | # ROTW - Rotate Window, pg. 496. 37 | :rotw s4_4.7 is op2 = 0b0100 & op1 = 0 & ar = 0b1000 & as = 0 & s4_4.7 & op0 = 0 unimpl 38 | 39 | # S32E - Store 32-bit for Window Exceptions, pg. 508. 40 | :s32e at, as, s5_12.15_oex is op2 = 0b0100 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl 41 | 42 | 43 | ## MAC16 option ## 44 | 45 | # LDDEC - Load with Autodecrement, pg. 386. 46 | :lddec "MAC16_REGS[" u2_12.13 "]", as is op2 = 0b1001 & op1 = 0 & u2_14.15 = 0 & u2_12.13 & as & at = 0 & op0 = 0b0100 unimpl 47 | 48 | # LDINC - Load with Autoincrement, pg. 387. 49 | :ldinc "MAC16_REGS[" u2_12.13 "]", as is op2 = 0b1000 & op1 = 0 & u2_14.15 = 0 & u2_12.13 & as & at = 0 & op0 = 0b0100 unimpl 50 | 51 | # MULA.AA.* - Signed Multiply, pg. 431. 52 | :mula.aa.* as, at is op2 = 0b0001 & u2_18.19 = 0b01 & ar = 0 & as & at & op0 = 0b0100 unimpl 53 | 54 | # FIXME: Add remaining MUL.* opcodes. 55 | 56 | 57 | # TODO this produces correct pcode, tho it would be nicer to display the float in disasm as well 58 | # +0.0 +1.0 +2.0 +0.5 59 | const.s_imm: tmp is as=0 [ tmp = 0x00000000; ] { export *[const]:4 tmp; } 60 | const.s_imm: tmp is as=1 [ tmp = 0x3F800000; ] { export *[const]:4 tmp; } 61 | const.s_imm: tmp is as=2 [ tmp = 0x40000000; ] { export *[const]:4 tmp; } 62 | const.s_imm: tmp is as=3 [ tmp = 0x3F000000; ] { export *[const]:4 tmp; } 63 | 64 | :const.s fr, const.s_imm is op2=0b1111 & op1=0b1010 & fr & const.s_imm & at=0b0011 & op0=0 { 65 | fr = float2float(const.s_imm); 66 | } 67 | 68 | 69 | # Stub out some insns which mainly appear in boilerplate library functions... 70 | :div0.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b0111 & op0=0 unimpl 71 | :sqrt0.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1001 & op0=0 unimpl 72 | :nexp01.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1011 & op0=0 unimpl 73 | :mksadj.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1100 & op0=0 unimpl 74 | :mkdadj.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1101 & op0=0 unimpl 75 | :addexp.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1110 & op0=0 unimpl 76 | :addexpm.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1111 & op0=0 unimpl 77 | :maddn.s fr, fs, ft is op2=0b0110 & op1=0b1010 & fr & fs & ft & op0=0 unimpl 78 | :divn.s fr, fs, ft is op2=0b0111 & op1=0b1010 & fr & fs & ft & op0=0 unimpl 79 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Use "xargs" to parse quoted args. 209 | # 210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 | # 212 | # In Bash we could simply go: 213 | # 214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 | # set -- "${ARGS[@]}" "$@" 216 | # 217 | # but POSIX shell has neither arrays nor command substitution, so instead we 218 | # post-process each arg (as a line of input to sed) to backslash-escape any 219 | # character that might be a shell metacharacter, then use eval to reverse 220 | # that process (while maintaining the separation between arguments), and wrap 221 | # the whole thing up as a single "set" statement. 222 | # 223 | # This will of course break if any of these variables contains a newline or 224 | # an unmatched quote. 225 | # 226 | 227 | eval "set -- $( 228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 | xargs -n1 | 230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 | tr '\n' ' ' 232 | )" '"$@"' 233 | 234 | exec "$JAVACMD" "$@" 235 | -------------------------------------------------------------------------------- /src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java: -------------------------------------------------------------------------------- 1 | package ghidra.app.util.bin.format.elf.relocation; 2 | 3 | import ghidra.app.util.bin.format.elf.ElfConstants; 4 | import ghidra.app.util.bin.format.elf.ElfHeader; 5 | import ghidra.app.util.bin.format.elf.ElfRelocation; 6 | import ghidra.app.util.bin.format.elf.ElfSymbol; 7 | import ghidra.program.model.address.Address; 8 | import ghidra.program.model.listing.Program; 9 | import ghidra.program.model.mem.Memory; 10 | import ghidra.program.model.mem.MemoryAccessException; 11 | import ghidra.util.exception.NotFoundException; 12 | 13 | public class Xtensa_ElfRelocationHandler extends ElfRelocationHandler { 14 | 15 | @Override 16 | public boolean canRelocate(ElfHeader elf) { 17 | return elf.e_machine() == ElfConstants.EM_XTENSA || 18 | elf.e_machine() == Xtensa_ElfRelocationConstants.EM_XTENSA_OLD; 19 | } 20 | 21 | @Override 22 | public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation, Address relocationAddress) 23 | throws MemoryAccessException, NotFoundException { 24 | ElfHeader elf = elfRelocationContext.getElfHeader(); 25 | if (!canRelocate(elf)) { 26 | return; 27 | } 28 | 29 | int type=relocation.getType(); 30 | if (Xtensa_ElfRelocationConstants.R_XTENSA_NONE == type) { 31 | return; 32 | } 33 | 34 | Program program = elfRelocationContext.getProgram(); 35 | Memory memory = program.getMemory(); 36 | 37 | long addend = relocation.hasAddend() ? relocation.getAddend() : memory.getInt(relocationAddress); 38 | long offset = relocationAddress.getOffset(); 39 | long base = elfRelocationContext.getImageBaseWordAdjustmentOffset(); 40 | ElfSymbol sym = null; 41 | long symbolValue = 0; 42 | String symbolName = null; 43 | 44 | int symbolIndex = relocation.getSymbolIndex(); 45 | if (symbolIndex != 0) { 46 | sym = elfRelocationContext.getSymbol(symbolIndex); 47 | } 48 | 49 | if (null != sym) { 50 | symbolValue = elfRelocationContext.getSymbolValue(sym); 51 | symbolName = sym.getNameAsString(); 52 | } 53 | 54 | switch(type) { 55 | case Xtensa_ElfRelocationConstants.R_XTENSA_32: 56 | markAsWarning(program, relocationAddress, "R_XTENSA_32", 57 | symbolName, symbolIndex, "TODO, needs support ", 58 | elfRelocationContext.getLog()); 59 | break; 60 | case Xtensa_ElfRelocationConstants.R_XTENSA_RTLD: 61 | markAsWarning(program, relocationAddress, "R_XTENSA_RTLD", 62 | symbolName, symbolIndex, "TODO, needs support ", 63 | elfRelocationContext.getLog()); 64 | break; 65 | case Xtensa_ElfRelocationConstants.R_XTENSA_GLOB_DAT: 66 | markAsWarning(program, relocationAddress, "R_XTENSA_GLOB_DAT", 67 | symbolName, symbolIndex, "TODO, needs support ", 68 | elfRelocationContext.getLog()); 69 | break; 70 | case Xtensa_ElfRelocationConstants.R_XTENSA_JMP_SLOT: 71 | markAsWarning(program, relocationAddress, "R_XTENSA_JMP_SLOT", 72 | symbolName, symbolIndex, "TODO, needs support ", 73 | elfRelocationContext.getLog()); 74 | break; 75 | case Xtensa_ElfRelocationConstants.R_XTENSA_RELATIVE: 76 | markAsWarning(program, relocationAddress, "R_XTENSA_RELATIVE", 77 | symbolName, symbolIndex, "TODO, needs support ", 78 | elfRelocationContext.getLog()); 79 | break; 80 | case Xtensa_ElfRelocationConstants.R_XTENSA_PLT: 81 | markAsWarning(program, relocationAddress, "R_XTENSA_PLT", 82 | symbolName, symbolIndex, "TODO, needs support ", 83 | elfRelocationContext.getLog()); 84 | break; 85 | case Xtensa_ElfRelocationConstants.R_XTENSA_OP0: 86 | markAsWarning(program, relocationAddress, "R_XTENSA_OP0", 87 | symbolName, symbolIndex, "TODO, needs support ", 88 | elfRelocationContext.getLog()); 89 | break; 90 | case Xtensa_ElfRelocationConstants.R_XTENSA_OP1: 91 | markAsWarning(program, relocationAddress, "R_XTENSA_OP1", 92 | symbolName, symbolIndex, "TODO, needs support ", 93 | elfRelocationContext.getLog()); 94 | break; 95 | case Xtensa_ElfRelocationConstants.R_XTENSA_OP2: 96 | markAsWarning(program, relocationAddress, "R_XTENSA_OP2", 97 | symbolName, symbolIndex, "TODO, needs support ", 98 | elfRelocationContext.getLog()); 99 | break; 100 | case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_EXPAND: 101 | markAsWarning(program, relocationAddress, "R_XTENSA_ASM_EXPAND", 102 | symbolName, symbolIndex, "TODO, needs support ", 103 | elfRelocationContext.getLog()); 104 | break; 105 | case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_SIMPLIFY: 106 | markAsWarning(program, relocationAddress, "R_XTENSA_ASM_SIMPLIFY", 107 | symbolName, symbolIndex, "TODO, needs support ", 108 | elfRelocationContext.getLog()); 109 | break; 110 | case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTINHERIT: 111 | markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTINHERIT", 112 | symbolName, symbolIndex, "TODO, needs support ", 113 | elfRelocationContext.getLog()); 114 | break; 115 | case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTENTRY: 116 | markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTENTRY", 117 | symbolName, symbolIndex, "TODO, needs support ", 118 | elfRelocationContext.getLog()); 119 | break; 120 | case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF8: 121 | markAsWarning(program, relocationAddress, "R_XTENSA_DIFF8", 122 | symbolName, symbolIndex, "TODO, needs support ", 123 | elfRelocationContext.getLog()); 124 | break; 125 | case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF16: 126 | markAsWarning(program, relocationAddress, "R_XTENSA_DIFF16", 127 | symbolName, symbolIndex, "TODO, needs support ", 128 | elfRelocationContext.getLog()); 129 | break; 130 | case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF32: 131 | markAsWarning(program, relocationAddress, "R_XTENSA_DIFF32", 132 | symbolName, symbolIndex, "TODO, needs support ", 133 | elfRelocationContext.getLog()); 134 | break; 135 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_OP: 136 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_OP", 137 | symbolName, symbolIndex, "TODO, needs support ", 138 | elfRelocationContext.getLog()); 139 | break; 140 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_OP: 141 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_OP", 142 | symbolName, symbolIndex, "TODO, needs support ", 143 | elfRelocationContext.getLog()); 144 | break; 145 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_OP: 146 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_OP", 147 | symbolName, symbolIndex, "TODO, needs support ", 148 | elfRelocationContext.getLog()); 149 | break; 150 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_OP: 151 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_OP", 152 | symbolName, symbolIndex, "TODO, needs support ", 153 | elfRelocationContext.getLog()); 154 | break; 155 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_OP: 156 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_OP", 157 | symbolName, symbolIndex, "TODO, needs support ", 158 | elfRelocationContext.getLog()); 159 | break; 160 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_OP: 161 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_OP", 162 | symbolName, symbolIndex, "TODO, needs support ", 163 | elfRelocationContext.getLog()); 164 | break; 165 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_OP: 166 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_OP", 167 | symbolName, symbolIndex, "TODO, needs support ", 168 | elfRelocationContext.getLog()); 169 | break; 170 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_OP: 171 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_OP", 172 | symbolName, symbolIndex, "TODO, needs support ", 173 | elfRelocationContext.getLog()); 174 | break; 175 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_OP: 176 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_OP", 177 | symbolName, symbolIndex, "TODO, needs support ", 178 | elfRelocationContext.getLog()); 179 | break; 180 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_OP: 181 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_OP", 182 | symbolName, symbolIndex, "TODO, needs support ", 183 | elfRelocationContext.getLog()); 184 | break; 185 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_OP: 186 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_OP", 187 | symbolName, symbolIndex, "TODO, needs support ", 188 | elfRelocationContext.getLog()); 189 | break; 190 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_OP: 191 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_OP", 192 | symbolName, symbolIndex, "TODO, needs support ", 193 | elfRelocationContext.getLog()); 194 | break; 195 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_OP: 196 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_OP", 197 | symbolName, symbolIndex, "TODO, needs support ", 198 | elfRelocationContext.getLog()); 199 | break; 200 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_OP: 201 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_OP", 202 | symbolName, symbolIndex, "TODO, needs support ", 203 | elfRelocationContext.getLog()); 204 | break; 205 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_OP: 206 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_OP", 207 | symbolName, symbolIndex, "TODO, needs support ", 208 | elfRelocationContext.getLog()); 209 | break; 210 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_ALT: 211 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_ALT", 212 | symbolName, symbolIndex, "TODO, needs support ", 213 | elfRelocationContext.getLog()); 214 | break; 215 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_ALT: 216 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_ALT", 217 | symbolName, symbolIndex, "TODO, needs support ", 218 | elfRelocationContext.getLog()); 219 | break; 220 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_ALT: 221 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_ALT", 222 | symbolName, symbolIndex, "TODO, needs support ", 223 | elfRelocationContext.getLog()); 224 | break; 225 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_ALT: 226 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_ALT", 227 | symbolName, symbolIndex, "TODO, needs support ", 228 | elfRelocationContext.getLog()); 229 | break; 230 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_ALT: 231 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_ALT", 232 | symbolName, symbolIndex, "TODO, needs support ", 233 | elfRelocationContext.getLog()); 234 | break; 235 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_ALT: 236 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_ALT", 237 | symbolName, symbolIndex, "TODO, needs support ", 238 | elfRelocationContext.getLog()); 239 | break; 240 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_ALT: 241 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_ALT", 242 | symbolName, symbolIndex, "TODO, needs support ", 243 | elfRelocationContext.getLog()); 244 | break; 245 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_ALT: 246 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_ALT", 247 | symbolName, symbolIndex, "TODO, needs support ", 248 | elfRelocationContext.getLog()); 249 | break; 250 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_ALT: 251 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_ALT", 252 | symbolName, symbolIndex, "TODO, needs support ", 253 | elfRelocationContext.getLog()); 254 | break; 255 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_ALT: 256 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_ALT", 257 | symbolName, symbolIndex, "TODO, needs support ", 258 | elfRelocationContext.getLog()); 259 | break; 260 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_ALT: 261 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_ALT", 262 | symbolName, symbolIndex, "TODO, needs support ", 263 | elfRelocationContext.getLog()); 264 | break; 265 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_ALT: 266 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_ALT", 267 | symbolName, symbolIndex, "TODO, needs support ", 268 | elfRelocationContext.getLog()); 269 | break; 270 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_ALT: 271 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_ALT", 272 | symbolName, symbolIndex, "TODO, needs support ", 273 | elfRelocationContext.getLog()); 274 | break; 275 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_ALT: 276 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_ALT", 277 | symbolName, symbolIndex, "TODO, needs support ", 278 | elfRelocationContext.getLog()); 279 | break; 280 | case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_ALT: 281 | markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_ALT", 282 | symbolName, symbolIndex, "TODO, needs support ", 283 | elfRelocationContext.getLog()); 284 | break; 285 | default: 286 | markAsUnhandled(program, relocationAddress, type, symbolIndex, 287 | symbolName, elfRelocationContext.getLog()); 288 | break; 289 | } 290 | } 291 | 292 | } 293 | -------------------------------------------------------------------------------- /data/languages/xtensa.sinc: -------------------------------------------------------------------------------- 1 | define endian=little; 2 | define alignment=1; 3 | 4 | define space ram type=ram_space size=4 default; 5 | define space register type=register_space size=4; 6 | 7 | # Special registers (SR). Not all are actually 32 bit, but for the sake of 8 | # simplicity they are here. 9 | define register offset=0x00 size=4 [ LBEG LEND LCOUNT SAR BR LITBASE ]; 10 | define register offset=0x30 size=4 [ SCOMPARE1 ]; 11 | define register offset=0x40 size=4 [ ACCLO ACCHI ]; 12 | define register offset=0x80 size=4 [ M0 M1 M2 M3 ]; 13 | define register offset=0x120 size=4 [ WindowBase WindowStart ]; 14 | define register offset=0x14c size=4 [ PTEVADDR ]; 15 | define register offset=0x164 size=4 [ MMID RASID ITLBCFG DTLBCFG ]; 16 | define register offset=0x180 size=4 [ IBREAKENABLE ]; 17 | define register offset=0x184 size=4 [ MEMCTL ]; 18 | define register offset=0x188 size=4 [ CACHEATTR ATOMCTL ]; 19 | define register offset=0x1a0 size=4 [ DDR ]; 20 | define register offset=0x1a8 size=4 [ MEPC MEPS MESAVE MESR MECR MEVADDR ]; 21 | define register offset=0x200 size=4 [ IBREAKA0 IBREAKA1 ]; 22 | define register offset=0x240 size=4 [ DBREAKA0 DBREAKA1 ]; 23 | define register offset=0x280 size=4 [ DBREAKC0 DBREAKC1 ]; 24 | define register offset=0x2c4 size=4 [ EPC1 EPC2 EPC3 EPC4 EPC5 EPC6 EPC7 ]; 25 | define register offset=0x300 size=4 [ DEPC ]; 26 | define register offset=0x308 size=4 [ EPS2 EPS3 EPS4 EPS5 EPS6 EPS7 ]; 27 | define register offset=0x344 size=4 [ EXCSAVE1 EXCSAVE2 EXCSAVE3 EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 ]; 28 | define register offset=0x380 size=4 [ CPENABLE ]; 29 | define register offset=0x384 size=4 [ INTERRUPT INTSET INTCLEAR INTENABLE ]; 30 | define register offset=0x398 size=4 [ PS VECBASE EXCCAUSE DEBUGCAUSE CCOUNT PRID ICOUNT ICOUNTLEVEL EXCVADDR ]; 31 | define register offset=0x3c0 size=4 [ CCOMPARE0 CCOMPARE1 CCOMPARE2 ]; 32 | define register offset=0x3d0 size=4 [ MISC0 MISC1 MISC2 MISC3 ]; 33 | 34 | # Address registers (AR). 35 | define register offset=0x8000 size=4 [ 36 | a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 37 | ]; 38 | 39 | # Floating Point registers (FR + FCR (control) + FSR (status)). 40 | # TODO: FCR and FSR seem unused? 41 | define register offset=0x8100 size=4 [ 42 | f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 43 | fcr fsr 44 | ]; 45 | 46 | # Boolean registers (BR). 47 | define register offset=0x8200 size=1 [ 48 | b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 49 | ]; 50 | 51 | # Program counter. 52 | define register offset=0x8300 size=4 [ pc ]; 53 | 54 | 55 | define register offset=0x8400 size=4 contextreg; 56 | define context contextreg 57 | phase=(0,0) 58 | loopEnd=(1,1) noflow 59 | ; 60 | 61 | # Regular 24-bit instruction. 62 | define token insn(24) 63 | # Named opcode/register fields. 64 | op2 = (20,23) 65 | ar = (12,15) 66 | fr = (12,15) 67 | br = (12,15) 68 | as = (8,11) 69 | fs = (8,11) 70 | bs = (8,11) 71 | sr = (8,15) 72 | at = (4,7) 73 | ft = (4,7) 74 | bt = (4,7) 75 | op1 = (16,19) 76 | op0 = (0,3) 77 | 78 | # Signed and unsigned immediates. Named [us]N_L.M, where u and s denote signedness, L and M the 79 | # least and most significant bit of the immediate in the instruction word, and N the length 80 | # (i.e. M-L+1). 81 | u3_21.23 = (21,23) 82 | u4_20.23 = (20,23) 83 | s8_16.23 = (16,23) signed 84 | u8_16.23 = (16,23) 85 | u12_12.23 = (12,23) 86 | s12_12.23 = (12,23) signed 87 | u16_8.23 = (8,23) 88 | s8_6.23 = (6,23) signed 89 | u1_20 = (20,20) 90 | u2_18.19 = (18,19) 91 | u3_17.19 = (17,19) 92 | u2_16.17 = (16,17) 93 | u1_16 = (16,16) 94 | u2_14.15 = (14,15) 95 | u3_13.15 = (13,15) 96 | u4_12.15 = (12,15) 97 | u8_8.15 = (8,15) 98 | u2_12.13 = (12,13) 99 | u1_12 = (12,12) 100 | u4_8.11 = (8,11) 101 | u8_4.11 = (4,11) 102 | s4_8.11 = (8,11) signed 103 | u2_6.7 = (6,7) 104 | u3_5.7 = (5,7) 105 | u4_4.7 = (4,7) 106 | s4_4.7 = (4,7) 107 | u2_4.5 = (4,5) 108 | u1_4 = (4,4) 109 | ; 110 | 111 | # Narrow 16-bit instructions; fields are always prefixed with n_. 112 | define token narrowinsn(16) 113 | n_ar = (12,15) 114 | n_as = (8,11) 115 | n_at = (4,7) 116 | n_op0 = (0, 3) 117 | 118 | n_u4_12.15 = (12,15) 119 | n_s4_12.15 = (12,15) signed 120 | n_u4_8.11 = (8,11) 121 | n_u1_7 = (7,7) 122 | n_u2_6.7 = (6,7) 123 | n_u4_4.7 = (4,7) 124 | n_s3_4.6 = (4,6) 125 | n_u2_4.5 = (4,5) 126 | 127 | ; 128 | 129 | attach variables [ sr ] [ 130 | # 0x...0 0x...4 0x...8 0x...c 131 | LBEG LEND LCOUNT SAR # 0x0_ 132 | BR LITBASE _ _ # 0x1_ 133 | _ _ _ _ # 0x2_ 134 | SCOMPARE1 _ _ _ # 0x3_ 135 | ACCLO ACCHI _ _ # 0x4_ 136 | _ _ _ _ # 0x5_ 137 | _ _ _ _ # 0x6_ 138 | _ _ _ _ # 0x7_ 139 | M0 M1 M2 M3 # 0x8_ 140 | _ _ _ _ # 0x9_ 141 | _ _ _ _ # 0xa_ 142 | _ _ _ _ # 0xb_ 143 | _ _ _ _ # 0xc_ 144 | _ _ _ _ # 0xd_ 145 | _ _ _ _ # 0xe_ 146 | _ _ _ _ # 0xf_ 147 | # 0x...0 0x...4 0x...8 0x...c 148 | _ _ _ _ # 0x10_ 149 | _ _ _ _ # 0x11_ 150 | WindowBase WindowStart _ _ # 0x12_ 151 | _ _ _ _ # 0x13_ 152 | _ _ _ PTEVADDR # 0x14_ 153 | _ _ _ _ # 0x15_ 154 | _ MMID RASID ITLBCFG # 0x16_ 155 | DTLBCFG _ _ _ # 0x17_ 156 | IBREAKENABLE MEMCTL CACHEATTR ATOMCTL # 0x18_ 157 | _ _ _ _ # 0x19_ 158 | DDR _ MEPC MEPS # 0x1a_ 159 | MESAVE MESR MECR MEVADDR # 0x1b_ 160 | _ _ _ _ # 0x1c_ 161 | _ _ _ _ # 0x1d_ 162 | _ _ _ _ # 0x1e_ 163 | _ _ _ _ # 0x1f_ 164 | # 0x...0 0x...4 0x...8 0x...c 165 | IBREAKA0 IBREAKA1 _ _ # 0x20_ 166 | _ _ _ _ # 0x21_ 167 | _ _ _ _ # 0x22_ 168 | _ _ _ _ # 0x23_ 169 | DBREAKA0 DBREAKA1 _ _ # 0x24_ 170 | _ _ _ _ # 0x25_ 171 | _ _ _ _ # 0x26_ 172 | _ _ _ _ # 0x27_ 173 | DBREAKC0 DBREAKC1 _ _ # 0x28_ 174 | _ _ _ _ # 0x29_ 175 | _ _ _ _ # 0x2a_ 176 | _ _ _ _ # 0x2b_ 177 | _ EPC1 EPC2 EPC3 # 0x2c_ 178 | EPC4 EPC5 EPC6 EPC7 # 0x2d_ 179 | _ _ _ _ # 0x2e_ 180 | _ _ _ _ # 0x2f_ 181 | # 0x...0 0x...4 0x...8 0x...c 182 | DEPC _ EPS2 EPS3 # 0x30_ 183 | EPS4 EPS5 EPS6 EPS7 # 0x31_ 184 | _ _ _ _ # 0x32_ 185 | _ _ _ _ # 0x33_ 186 | _ EXCSAVE1 EXCSAVE2 EXCSAVE3 # 0x34_ 187 | EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 # 0x35_ 188 | _ _ _ _ # 0x36_ 189 | _ _ _ _ # 0x37_ 190 | CPENABLE INTERRUPT INTSET INTCLEAR # 0x38_ 191 | INTENABLE _ PS VECBASE # 0x39_ 192 | EXCCAUSE DEBUGCAUSE CCOUNT PRID # 0x3a_ 193 | ICOUNT ICOUNTLEVEL EXCVADDR _ # 0x3b_ 194 | CCOMPARE0 CCOMPARE1 CCOMPARE2 _ # 0x3c_ 195 | MISC0 MISC1 MISC2 MISC3 # 0x3d_ 196 | _ _ _ _ # 0x3e_ 197 | _ _ _ _ # 0x3f_ 198 | # 0x...0 0x...4 0x...8 0x...c 199 | ]; 200 | 201 | attach variables [ ar as at n_ar n_as n_at ] [ 202 | a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 203 | ]; 204 | 205 | attach variables [ fr fs ft ] [ 206 | f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 207 | ]; 208 | 209 | attach variables [ br bs bt ] [ 210 | b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 211 | ]; 212 | 213 | # Various 32-bit pointers relative to PC. Any operands that are split across non-consecutive 214 | # bits are named foo_LL.LM_ML.MM, where LL is the least significant bits of the least 215 | # singificant operand half, LM the most significant bits of the least significant operand half, etc. 216 | 217 | urel_16.23: rel is u8_16.23 [ rel = inst_start + u8_16.23 + 4; ] { export *:4 rel; } 218 | 219 | srel_16.23: rel is s8_16.23 [ rel = inst_start + s8_16.23 + 4; ] { export *:4 rel; } 220 | 221 | srel_12.23: rel is s12_12.23 [ rel = inst_start + s12_12.23 + 4; ] { export *:4 rel; } 222 | 223 | srel_6.23: rel is s8_6.23 [ rel = inst_start + s8_6.23 + 4; ] { export *:4 rel; } 224 | 225 | urel_12.15_4.5: rel is n_u2_4.5 & n_u4_12.15 [ 226 | rel = inst_start + ((n_u2_4.5 << 4) | n_u4_12.15) + 4; 227 | ] { export *:4 rel; } 228 | 229 | srel_6.23_sb2: rel is s8_6.23 [ 230 | rel = (inst_start & ~3) + ( s8_6.23 << 2 ) + 4; 231 | ] { export *:4 rel; } 232 | 233 | srel_8.23_oex_sb2: rel is u16_8.23 [ 234 | rel = ((inst_start + 3) & ~3) + ((u16_8.23 | 0xffff0000) << 2); 235 | ] { export *:4 rel; } 236 | 237 | # Immediates split across the instruction. 238 | u5_8.11_20: tmp is u1_20 & u4_8.11 [ tmp = (u1_20 << 4) | u4_8.11; ] { export *[const]:1 tmp; } 239 | u5_4.7_20: tmp is u1_20 & u4_4.7 [ tmp = (u1_20 << 4) | u4_4.7; ] { export *[const]:1 tmp; } 240 | u5_8.11_16: tmp is u1_16 & u4_8.11 [ tmp = (u1_16 << 4) | u4_8.11; ] { export *[const]:1 tmp; } 241 | u5_4.7_12: tmp is u1_12 & u4_4.7 [ tmp = (u1_12 << 4) | u4_4.7; ] { export *[const]:1 tmp; } 242 | u5_8.11_4: tmp is u1_4 & u4_8.11 [ tmp = (u1_4 << 4) | u4_8.11; ] { export *[const]:1 tmp; } 243 | 244 | # Signed 12-bit (extended to 16) immediate, used by MOVI. 245 | s16_16.23_8.11: tmp is s4_8.11 & u8_16.23 [ 246 | tmp = (s4_8.11 << 8) | u8_16.23; 247 | ] { export *[const]:2 tmp; } 248 | 249 | # An “asymmetric” immediate from -32..95, used by MOVI.N. 250 | n_s8_12.15_4.6_asymm: tmp is n_s3_4.6 & n_s4_12.15 [ 251 | tmp = ((((n_s3_4.6 & 7) << 4) | (n_s4_12.15 & 15)) | 252 | ((((n_s3_4.6 >> 2) & 1) & ((n_s3_4.6 >> 1) & 1)) << 7)); 253 | ] { export *[const]:1 tmp; } 254 | 255 | # Immediates shifted or with offset. 256 | s16_16.23_sb8: tmp is s8_16.23 [ tmp = s8_16.23 << 8; ] { export *[const]:2 tmp; } 257 | u15_12.23_sb3: tmp is u12_12.23 [ tmp = u12_12.23 << 3; ] { export *[const]:2 tmp; } 258 | u10_16.23_sb2: tmp is u8_16.23 [ tmp = u8_16.23 << 2; ] { export *[const]:2 tmp; } 259 | u9_16.23_sb1: tmp is u8_16.23 [ tmp = u8_16.23 << 1; ] { export *[const]:2 tmp; } 260 | u5_20.23_plus1: tmp is u4_20.23 [ tmp = u4_20.23 + 1; ] { export *[const]:1 tmp; } 261 | u8_20.23_sb4: tmp is u4_20.23 [ tmp = u4_20.23 << 4; ] { export *[const]:1 tmp; } 262 | u5_4.7_plus7: tmp is u4_4.7 [ tmp = u4_4.7 + 7; ] { export *[const]:1 tmp; } 263 | 264 | n_u6_12.15_sb2: tmp is n_u4_12.15 [ tmp = n_u4_12.15 << 2; ] { export *[const]:1 tmp; } 265 | 266 | # One-extended. FIXME: Verify this. Only used by [LS]32E (window extension), which aren’t yet 267 | # implemented. 268 | s5_12.15_oex: tmp is u4_12.15 [ tmp = (2 << u4_12.15) * -1; ] { export *[const]:2 tmp; } 269 | 270 | # Some 4-bit immediates with mappings that can’t be (easily) expressed in a single disassembly action. 271 | 272 | # n_u4_4.7 with 0 being -1, used by ADDI.N. 273 | n_s4_4.7_nozero: tmp is n_u4_4.7 = 0 [ tmp = -1; ] { export *[const]:4 tmp; } 274 | n_s4_4.7_nozero: tmp is n_u4_4.7 [ tmp = n_u4_4.7+0; ] { export *[const]:4 tmp; } 275 | 276 | # imm stored in sa for slli is 32-shift. 277 | # TODO why can't we use subtable output for this instead of repeating u5_4.7_20 calc? 278 | u5_4.7_20_slli: tmp is u1_20 & u4_4.7 [ tmp = 32 - ((u1_20 << 4) | u4_4.7); ] { export *[const]:1 tmp; } 279 | 280 | # B4CONST(ar) (Branch Immediate) encodings, pg. 41 f. 281 | r_b4const: tmp is ar = 0 [ tmp = 0xffffffff; ] { export *[const]:4 tmp; } 282 | r_b4const: tmp is ar = 1 [ tmp = 0x1; ] { export *[const]:4 tmp; } 283 | r_b4const: tmp is ar = 2 [ tmp = 0x2; ] { export *[const]:4 tmp; } 284 | r_b4const: tmp is ar = 3 [ tmp = 0x3; ] { export *[const]:4 tmp; } 285 | r_b4const: tmp is ar = 4 [ tmp = 0x4; ] { export *[const]:4 tmp; } 286 | r_b4const: tmp is ar = 5 [ tmp = 0x5; ] { export *[const]:4 tmp; } 287 | r_b4const: tmp is ar = 6 [ tmp = 0x6; ] { export *[const]:4 tmp; } 288 | r_b4const: tmp is ar = 7 [ tmp = 0x7; ] { export *[const]:4 tmp; } 289 | r_b4const: tmp is ar = 8 [ tmp = 0x8; ] { export *[const]:4 tmp; } 290 | r_b4const: tmp is ar = 9 [ tmp = 0xa; ] { export *[const]:4 tmp; } 291 | r_b4const: tmp is ar = 10 [ tmp = 0xc; ] { export *[const]:4 tmp; } 292 | r_b4const: tmp is ar = 11 [ tmp = 0x10; ] { export *[const]:4 tmp; } 293 | r_b4const: tmp is ar = 12 [ tmp = 0x20; ] { export *[const]:4 tmp; } 294 | r_b4const: tmp is ar = 13 [ tmp = 0x40; ] { export *[const]:4 tmp; } 295 | r_b4const: tmp is ar = 14 [ tmp = 0x80; ] { export *[const]:4 tmp; } 296 | r_b4const: tmp is ar = 15 [ tmp = 0x100; ] { export *[const]:4 tmp; } 297 | 298 | # B4CONSTU(ar) (Branch Unsigned Immediate) encodings, pg. 42. 299 | r_b4constu: tmp is ar = 0 [ tmp = 0x8000; ] { export *[const]:4 tmp; } 300 | r_b4constu: tmp is ar = 1 [ tmp = 0x1000; ] { export *[const]:4 tmp; } 301 | r_b4constu: tmp is ar = 2 [ tmp = 0x2; ] { export *[const]:4 tmp; } 302 | r_b4constu: tmp is ar = 3 [ tmp = 0x3; ] { export *[const]:4 tmp; } 303 | r_b4constu: tmp is ar = 4 [ tmp = 0x4; ] { export *[const]:4 tmp; } 304 | r_b4constu: tmp is ar = 5 [ tmp = 0x5; ] { export *[const]:4 tmp; } 305 | r_b4constu: tmp is ar = 6 [ tmp = 0x6; ] { export *[const]:4 tmp; } 306 | r_b4constu: tmp is ar = 7 [ tmp = 0x7; ] { export *[const]:4 tmp; } 307 | r_b4constu: tmp is ar = 8 [ tmp = 0x8; ] { export *[const]:4 tmp; } 308 | r_b4constu: tmp is ar = 9 [ tmp = 0xa; ] { export *[const]:4 tmp; } 309 | r_b4constu: tmp is ar = 10 [ tmp = 0xc; ] { export *[const]:4 tmp; } 310 | r_b4constu: tmp is ar = 11 [ tmp = 0x10; ] { export *[const]:4 tmp; } 311 | r_b4constu: tmp is ar = 12 [ tmp = 0x20; ] { export *[const]:4 tmp; } 312 | r_b4constu: tmp is ar = 13 [ tmp = 0x40; ] { export *[const]:4 tmp; } 313 | r_b4constu: tmp is ar = 14 [ tmp = 0x80; ] { export *[const]:4 tmp; } 314 | r_b4constu: tmp is ar = 15 [ tmp = 0x100; ] { export *[const]:4 tmp; } 315 | 316 | define pcodeop breakpoint; 317 | define pcodeop dhi; 318 | define pcodeop dhu; 319 | define pcodeop dhwb; 320 | define pcodeop dhwbi; 321 | define pcodeop dii; 322 | define pcodeop diu; 323 | define pcodeop diwb; 324 | define pcodeop diwbi; 325 | define pcodeop dpfl; 326 | define pcodeop dpfr; 327 | define pcodeop dpfro; 328 | define pcodeop dpfw; 329 | define pcodeop dpfwo; 330 | define pcodeop dsync; 331 | define pcodeop esync; 332 | define pcodeop excw; 333 | define pcodeop extw; 334 | define pcodeop idtlb; 335 | define pcodeop ihi; 336 | define pcodeop ihu; 337 | define pcodeop iii; 338 | define pcodeop iitlb; 339 | define pcodeop iiu; 340 | define pcodeop ill; 341 | define pcodeop ipf; 342 | define pcodeop ipfl; 343 | define pcodeop isync; 344 | define pcodeop acquire; 345 | define pcodeop ldct; 346 | define pcodeop lict; 347 | define pcodeop licw; 348 | define pcodeop memw; 349 | define pcodeop nsa; 350 | define pcodeop pdtlb; 351 | define pcodeop pitlb; 352 | define pcodeop rdtlb0; 353 | define pcodeop rdtlb1; 354 | define pcodeop rer; 355 | define pcodeop rfdd; 356 | define pcodeop rfde; 357 | define pcodeop rfdo; 358 | define pcodeop rfe; 359 | define pcodeop rfi; 360 | define pcodeop rfme; 361 | define pcodeop rfue; 362 | define pcodeop rfwo; 363 | define pcodeop rfwu; 364 | define pcodeop ritlb0; 365 | define pcodeop ritlb1; 366 | define pcodeop rsil; 367 | define pcodeop rsync; 368 | define pcodeop rur; 369 | define pcodeop s32c1i; 370 | define pcodeop release; 371 | define pcodeop sdct; 372 | define pcodeop sict; 373 | define pcodeop sicw; 374 | define pcodeop simcall; 375 | define pcodeop syscall; 376 | define pcodeop waiti; 377 | define pcodeop wdtlb; 378 | define pcodeop wer; 379 | define pcodeop witlb; 380 | define pcodeop wur; 381 | define pcodeop xsr; 382 | -------------------------------------------------------------------------------- /data/languages/xtensaInstructions.sinc: -------------------------------------------------------------------------------- 1 | # ABS - Absolute Value (RRR), pg. 246. 2 | :abs ar, at is op2 = 0b0110 & op1 = 0 & ar & as = 0b0001 & at & op0 = 0 { 3 | ar = at; 4 | if (ar s> 0) 5 | goto inst_next; 6 | ar = -ar; 7 | } 8 | 9 | # ABS.S - Absolute Single Value (RRR), pg. 247. 10 | :abs.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0b0001 & op0 = 0b0000 { 11 | fr = abs(fs); 12 | } 13 | 14 | # ADD - Add (RRR), pg. 248. 15 | :add ar, as, at is op2 = 0b1000 & op1 = 0 & ar & as & at & op0 = 0 { 16 | ar = as + at; 17 | } 18 | 19 | # ADD.N - Narrow Add (RRRN), pg. 249. 20 | :add.n n_ar, n_as, n_at is n_ar & n_as & n_at & n_op0 = 0b1010 { 21 | n_ar = n_as + n_at; 22 | } 23 | 24 | # ADD.S - Add Single (RRR), pg. 250. 25 | :add.s fr, fs, ft is op2 = 0 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { 26 | fr = fs f+ ft; 27 | } 28 | 29 | # ADDI - Add Immediate (RRI8), pg. 251. 30 | :addi at, as, s8_16.23 is s8_16.23 & ar = 0b1100 & as & at & op0 = 0b0010 { 31 | at = as + sext(s8_16.23:1); 32 | } 33 | 34 | # ADDI.N - Narrow Add Immediate (RRRN), pg. 252. 35 | :addi.n n_ar, n_as, n_s4_4.7_nozero is n_ar & n_as & n_s4_4.7_nozero & n_op0 = 0b1011 { 36 | n_ar = n_as + n_s4_4.7_nozero; 37 | } 38 | 39 | # ADDMI - Add Immediate with Shift by 8, pg. 253. 40 | :addmi at, as, s16_16.23_sb8 is s16_16.23_sb8 & ar = 0b1101 & as & at & op0 = 0b0010 { 41 | at = as + sext(s16_16.23_sb8); 42 | } 43 | 44 | # ADDX2 - Add with Shift by 1, pg. 254. 45 | :addx2 ar, as, at is op2 = 0b1001 & op1 = 0 & ar & as & at & op0 = 0 { 46 | ar = (as << 1) + at; 47 | } 48 | 49 | # ADDX4 - Add with Shift by 2, pg. 255. 50 | :addx4 ar, as, at is op2 = 0b1010 & op1 = 0 & ar & as & at & op0 = 0 { 51 | ar = (as << 2) + at; 52 | } 53 | 54 | # ADDX8 - Add with Shift by 4, pg. 256. 55 | :addx8 ar, as, at is op2 = 0b1011 & op1 = 0 & ar & as & at & op0 = 0 { 56 | ar = (as << 3) + at; 57 | } 58 | 59 | # ALL4 - All 4 Booleans True, pg. 257. 60 | :all4 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1001 & bs & bt & op0 = 0 { 61 | local b = *[register]:1 &:4 bs+1; 62 | local c = *[register]:1 &:4 bs+2; 63 | local d = *[register]:1 &:4 bs+3; 64 | bt = bs && b && c && d; 65 | } 66 | 67 | # ALL8 - All 8 Booleans True, pg. 258. 68 | :all8 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1011 & bs & bt & op0 = 0 { 69 | local b = *[register]:1 &:4 bs+1; 70 | local c = *[register]:1 &:4 bs+2; 71 | local d = *[register]:1 &:4 bs+3; 72 | local e = *[register]:1 &:4 bs+4; 73 | local f = *[register]:1 &:4 bs+5; 74 | local g = *[register]:1 &:4 bs+6; 75 | local h = *[register]:1 &:4 bs+7; 76 | bt = bs && b && c && d && e && f && g && h; 77 | } 78 | 79 | # AND - Bitwise Logical And, pg. 259. 80 | :and ar, as, at is op2 = 0b0001 & op1 = 0 & ar & as & at & op0 = 0 { 81 | ar = as & at; 82 | } 83 | 84 | # ANDB - Boolean And, pg. 260. 85 | :andb br, bs, bt is op2 = 0 & op1 = 0b0010 & br & bs & bt & op0 = 0 { 86 | br = bs && bt; 87 | } 88 | 89 | # ANDBC - Boolean And with Complement, pg. 261. 90 | :andbc br, bs, bt is op2 = 0b0001 & op1 = 0b0010 & br & bs & bt & op0 = 0 { 91 | br = bs && !bt; 92 | } 93 | 94 | # ANY4 - Any 4 Booleans True, pg. 262. 95 | :any4 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1000 & bs & bt & op0 = 0 { 96 | local b = *[register]:1 &:4 bs+1; 97 | local c = *[register]:1 &:4 bs+2; 98 | local d = *[register]:1 &:4 bs+3; 99 | bt = bs || b || c || d; 100 | } 101 | 102 | # ANY8 - Any 8 Booleans True, pg. 263. 103 | :any8 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1010 & bs & bt & op0 = 0 { 104 | local b = *[register]:1 &:4 bs+1; 105 | local c = *[register]:1 &:4 bs+2; 106 | local d = *[register]:1 &:4 bs+3; 107 | local e = *[register]:1 &:4 bs+4; 108 | local f = *[register]:1 &:4 bs+5; 109 | local g = *[register]:1 &:4 bs+6; 110 | local h = *[register]:1 &:4 bs+7; 111 | bt = bs || b || c || d || e || f || g || h; 112 | } 113 | 114 | # BALL - Branch if All Bits Set, pg. 264. 115 | :ball srel_16.23, as, at is srel_16.23 & ar = 0b0100 & as & at & op0 = 0b0111 { 116 | if ((~as & at) == 0) 117 | goto srel_16.23; 118 | } 119 | 120 | # BANY - Branch if Any Bit Set, pg. 265. 121 | :bany srel_16.23, as, at, is srel_16.23 & ar = 0b1000 & as & at & op0 = 0b0111 { 122 | if ((as & at) != 0) 123 | goto srel_16.23; 124 | } 125 | 126 | macro extract_bit(val, bit, result) { 127 | result = (val >> bit)&1; 128 | } 129 | 130 | # BBC - Branch if Bit Clear, pg. 266. 131 | :bbc as, at, srel_16.23 is srel_16.23 & ar = 0b0101 & as & at & op0 = 0b0111 { 132 | local bval; 133 | extract_bit(as, at[0,5], bval); 134 | if (bval == 0) 135 | goto srel_16.23; 136 | } 137 | 138 | # BBCI - Branch if Bit Clear immediate, pg. 267 139 | :bbci as, u5_4.7_12, srel_16.23 is srel_16.23 & u3_13.15 = 0b011 & as & u5_4.7_12 & op0 = 0b0111 { 140 | local bval; 141 | extract_bit(as, u5_4.7_12, bval); 142 | if (bval == 0) 143 | goto srel_16.23; 144 | } 145 | 146 | # BBS - Branch if Bit Set, pg. 269. 147 | :bbs as, at, srel_16.23 is srel_16.23 & ar = 0b1101 & as & at & op0 = 0b0111 { 148 | local bval; 149 | extract_bit(as, at[0,5], bval); 150 | if (bval != 0) 151 | goto srel_16.23; 152 | } 153 | 154 | # BBSI - Branch if Bit Set immediate, pg. 270. 155 | :bbsi as, u5_4.7_12, srel_16.23 is srel_16.23 & u3_13.15 = 0b111 & as & u5_4.7_12 & op0 = 0b0111 { 156 | local bval; 157 | extract_bit(as, u5_4.7_12, bval); 158 | if (bval != 0) 159 | goto srel_16.23; 160 | } 161 | 162 | # BEQ - Branch if Equal, pg. 272. 163 | :beq as, at, srel_16.23 is srel_16.23 & ar = 0b0001 & as & at & op0 = 0b0111 { 164 | if (as == at) 165 | goto srel_16.23; 166 | } 167 | 168 | # BEQI - Branch if Equal Immediate, pg. 273. 169 | :beqi as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0 & u2_4.5 = 0b10 & op0 = 0b0110 { 170 | if (as == r_b4const) 171 | goto srel_16.23; 172 | } 173 | 174 | # BEQZ - Branch if Equal Zero, pg. 274. 175 | :beqz as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0 & u2_4.5 = 0b01 & op0 = 0b0110 { 176 | if (as == 0) 177 | goto srel_12.23; 178 | } 179 | 180 | # BEQZ.N - Narrow Branch if Equal Zero, pg. 275. 181 | :beqz.n n_as, urel_12.15_4.5 is urel_12.15_4.5 & n_as & n_u2_6.7 = 0b10 & n_op0 = 0b1100 { 182 | if (n_as == 0) 183 | goto urel_12.15_4.5; 184 | } 185 | 186 | # BF - Branch if False, pg. 276. 187 | :bf bs, srel_16.23 is srel_16.23 & ar = 0 & bs & at = 0b0111 & op0 = 0b0110 { 188 | if (!bs) 189 | goto srel_16.23; 190 | } 191 | 192 | # BGE - Branch if Greater Than or Equal, pg. 277. 193 | :bge as, at, srel_16.23 is srel_16.23 & ar = 0b1010 & as & at & op0 = 0b0111 { 194 | if (as s>= at) 195 | goto srel_16.23; 196 | } 197 | 198 | # BGEI - Branch if Greater Than or Equal Immediate, pg. 278. 199 | :bgei as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0b11 & u2_4.5 = 0b10 & op0 = 0b0110 { 200 | if (as s>= r_b4const) 201 | goto srel_16.23; 202 | } 203 | 204 | # BGEU - Branch if Greater Than or Equal Unsigned, pg. 279. 205 | :bgeu as, at, srel_16.23 is srel_16.23 & ar = 0b1011 & as & at & op0 = 0b0111 { 206 | if (as >= at) 207 | goto srel_16.23; 208 | } 209 | 210 | # BGEUI - Branch if Greater Than or Equal Unsigned Immediate, pg. 280. 211 | :bgeui as, r_b4constu, srel_16.23 is srel_16.23 & r_b4constu & as & u2_6.7 = 0b11 & u2_4.5 = 0b11 & op0 = 0b0110 { 212 | if (as >= r_b4constu) 213 | goto srel_16.23; 214 | } 215 | 216 | # BGEZ - Branch if Greater Than or Equal Zero, pg. 281. 217 | :bgez as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0b11 & u2_4.5 = 0b01 & op0 = 0b0110 { 218 | if (as s>= 0) 219 | goto srel_12.23; 220 | } 221 | 222 | # BLT - Branch if Less Than, pg. 282. 223 | :blt as, at, srel_16.23 is srel_16.23 & ar = 0b0010 & as & at & op0 = 0b0111 { 224 | if (as s< at) 225 | goto srel_16.23; 226 | } 227 | 228 | # BLTI - Branch if Less Than Immediate, pg. 283. 229 | :blti as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0b10 & u2_4.5 = 0b10 & op0 = 0b0110 { 230 | if (as s< r_b4const) 231 | goto srel_16.23; 232 | } 233 | 234 | # BLTU - Branch if Less Than Unsigned, pg. 284. 235 | :bltu as, at, srel_16.23 is srel_16.23 & ar = 0b0011 & as & at & op0 = 0b0111 { 236 | if (as < at) 237 | goto srel_16.23; 238 | } 239 | 240 | # BLTUI - Branch if Less Than Unsigned Immediate, pg. 285. 241 | :bltui as, r_b4constu, srel_16.23 is srel_16.23 & r_b4constu & as & u2_6.7 = 0b10 & u2_4.5 = 0b11 & op0 = 0b0110 { 242 | if (as < r_b4constu) 243 | goto srel_16.23; 244 | } 245 | 246 | # BLTZ - Branch if Less Than Zero, pg. 286. 247 | :bltz as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0b10 & u2_4.5 = 0b01 & op0 = 0b0110 { 248 | if (as s< 0) 249 | goto srel_12.23; 250 | } 251 | 252 | # BNALL - Branch if Not-All Bits Set, pg. 287. 253 | :bnall srel_16.23, as, at is srel_16.23 & ar = 0b1100 & as & at & op0 = 0b0111 { 254 | if ((~as & at) != 0) 255 | goto srel_16.23; 256 | } 257 | 258 | # BNE - Branch if Not Equal, pg. 288. 259 | :bne as, at, srel_16.23 is srel_16.23 & ar = 0b1001 & as & at & op0 = 0b0111 { 260 | if (as != at) 261 | goto srel_16.23; 262 | } 263 | 264 | # BNEI - Branch if Not EquaL Immediate, pg. 289. 265 | :bnei as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0b01 & u2_4.5 = 0b10 & op0 = 0b0110 { 266 | if (as != r_b4const) 267 | goto srel_16.23; 268 | } 269 | 270 | # BNEZ - Branch if Not Equal Zero, pg. 290. 271 | :bnez as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0b01 & u2_4.5 = 0b01 & op0 = 0b0110 { 272 | if (as != 0) 273 | goto srel_12.23; 274 | } 275 | 276 | # BNEZ.N - Narrow Branch if Not Equal Zero, pg. 291. 277 | :bnez.n n_as, urel_12.15_4.5 is urel_12.15_4.5 & n_as & n_u2_6.7 = 0b11 & n_op0 = 0b1100 { 278 | if (n_as != 0) 279 | goto urel_12.15_4.5; 280 | } 281 | 282 | # BNONE - Branch if No Bit Set, pg. 292. 283 | :bnone srel_16.23, as, at, is srel_16.23 & ar = 0 & as & at & op0 = 0b0111 { 284 | if ((as & at) == 0) 285 | goto srel_16.23; 286 | } 287 | 288 | # BREAK - Breakpoint, pg. 293. 289 | :break u4_8.11, u4_4.7 is op2 = 0 & op1 = 0 & ar = 0b0100 & u4_8.11 & u4_4.7 & op0 = 0 { 290 | breakpoint(0x001000:4, u4_8.11:1, u4_4.7:1); 291 | } 292 | 293 | # BREAK.N - Narrow Breakpoint, pg. 295. 294 | :break.n n_u4_8.11 is n_ar = 0b1111 & n_u4_8.11 & n_at = 0b0010 & n_op0 = 0b1101 { 295 | breakpoint(0x010000:4, n_u4_8.11:1, 0:1); 296 | } 297 | 298 | # BT - Branch if True, pg. 296. 299 | :bt bs, srel_16.23 is srel_16.23 & ar = 0b0001 & bs & at = 0b0111 & op0 = 0b0110 { 300 | if (bs) 301 | goto srel_16.23; 302 | } 303 | 304 | # CALL0 - Non-windowed Call, pg. 297. 305 | :call0 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0 & op0 = 0b0101 { 306 | a0 = inst_start + 3; 307 | call srel_6.23_sb2; 308 | } 309 | 310 | # CALLX0 - Non-windowed Call Register, pg. 304. 311 | :callx0 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0 & op0 = 0 { 312 | local dst = as; 313 | a0 = inst_start + 3; 314 | call [dst]; 315 | } 316 | 317 | # CEIL.S - Ceiling Single to Fixed, pg. 311. 318 | :ceil.s ar, fs, u4_4.7 is op2 = 0b1011 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 { 319 | local scale:4 = int2float(1:1 << u4_4.7:1); 320 | ar = ceil(fs f* scale); 321 | } 322 | 323 | # CLAMPS - Signed Clamp, pg. 312. 324 | :clamps ar, as, u5_4.7_plus7 is op2 = 0b0011 & op1 = 0b0011 & ar & as & u5_4.7_plus7 & op0 = 0 { 325 | # ar ← min(max(as, -2^{u5_4.7_plus7}), 2^{u5_4.7_plus7}-1) 326 | local maxval:4 = (1 << u5_4.7_plus7) - 1; 327 | local minval:4 = -(1 << u5_4.7_plus7); 328 | if (as s< minval) 329 | goto ; 330 | if (as s> maxval) 331 | goto ; 332 | 333 | ar = as; 334 | goto inst_next; 335 | 336 | 337 | ar = minval; 338 | goto inst_next; 339 | 340 | 341 | ar = maxval; 342 | # fallthrough inst_next 343 | } 344 | 345 | # DHI - Data Cache Hit Invalidate, pg. 313. 346 | :dhi as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0110 & op0 = 0b0010 { 347 | dhi(as + zext(u10_16.23_sb2)); 348 | } 349 | 350 | # DHU - Data Cache Hit Unlock, pg. 315. 351 | :dhu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { 352 | dhu(as + zext(u8_20.23_sb4)); 353 | } 354 | 355 | # DHWB - Data Cache Hit Writeback, pg. 317. 356 | :dhwb as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0100 & op0 = 0b0010 { 357 | dhwb(as + zext(u10_16.23_sb2)); 358 | } 359 | 360 | # DHWBI - Data Cache Hit Writeback Invalidate, pg. 319. 361 | :dhwbi as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0101 & op0 = 0b0010 { 362 | dhwbi(as + zext(u10_16.23_sb2)); 363 | } 364 | 365 | # DII - Data Cache Index Invalidate, pg. 321. 366 | :dii as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0111 & op0 = 0b0010 { 367 | dii(as + zext(u10_16.23_sb2)); 368 | } 369 | 370 | # DIU - Data Cache Index Unlock, pg. 323. 371 | :diu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { 372 | diu(as + zext(u8_20.23_sb4)); 373 | } 374 | 375 | # DIWB - Data Cache Index Write Back, pg. 325. 376 | :diwb as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0100 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { 377 | diwb(as + zext(u8_20.23_sb4)); 378 | } 379 | 380 | # DIWBI - Data Cache Index Write Back Invalidate, pg. 327. 381 | :diwbi as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0101 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { 382 | diwbi(as + zext(u8_20.23_sb4)); 383 | } 384 | 385 | # DPFL - Data Cache Prefetch and Lock, pg. 329. 386 | :dpfl as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { 387 | dpfl(as + zext(u8_20.23_sb4)); 388 | } 389 | 390 | # DPFR - Data Cache Prefetch for Read, pg. 331. 391 | :dpfr as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0 & op0 = 0b0010 { 392 | dpfr(as + zext(u10_16.23_sb2)); 393 | } 394 | 395 | # DPFRO - Data Cache Prefetch for Read Once, pg. 333. 396 | :dpfro as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0010 & op0 = 0b0010 { 397 | dpfro(as + zext(u10_16.23_sb2)); 398 | } 399 | 400 | # DPFW - Data Cache Prefetch for Write, pg. 335. 401 | :dpfw as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0001 & op0 = 0b0010 { 402 | dpfw(as + zext(u10_16.23_sb2)); 403 | } 404 | 405 | # DPFWO - Data Cache Prefetch for Write Once, pg. 337. 406 | :dpfwo as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0011 & op0 = 0b0010 { 407 | dpfwo(as + zext(u10_16.23_sb2)); 408 | } 409 | 410 | # DSYNC - Load/Store Synchronize, pg. 339. 411 | :dsync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0011 & op0 = 0 { 412 | dsync(); 413 | } 414 | 415 | # ESYNC - Execute Synchronize, pg. 342. 416 | :esync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0010 & op0 = 0 { 417 | esync(); 418 | } 419 | 420 | # EXCW - Exception Wait, pg. 343. 421 | :excw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1000 & op0 = 0 { 422 | excw(); 423 | } 424 | 425 | # EXTUI - Extract Unsigned Immediate, pg. 344. 426 | :extui ar, at, u5_8.11_16, u5_20.23_plus1 is u5_20.23_plus1 & u3_17.19 = 0b010 & u5_8.11_16 & ar & at & op0 = 0 { 427 | local shifted:4 = at >> u5_8.11_16; 428 | local mask:4 = (1:4 << (u5_20.23_plus1))-1; 429 | ar = shifted & mask; 430 | } 431 | 432 | # EXTW - External Wait, pg. 345. 433 | :extw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1101 & op0 = 0 { 434 | extw(); 435 | } 436 | 437 | # FLOAT.S - Convert Fixed to Single, pg. 346. 438 | :float.s fr, as, u4_4.7 is op2 = 0b1100 & op1 = 0b1010 & fr & as & u4_4.7 & op0 = 0 { 439 | local f = int2float(as); 440 | local d = int2float(1:2 << u4_4.7:2); 441 | fr = d f/ f; 442 | } 443 | 444 | # FLOOR.S - Floor Single to Fixed, pg. 347. 445 | :floor.s ar, fs, u4_4.7 is op2 = 0b1010 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 { 446 | local scale:4 = int2float(1:2 << u4_4.7:2); 447 | ar = floor(fs f* scale); 448 | } 449 | 450 | # IDTLB - Invalidate Data TLB Entry, pg. 348. 451 | :idtlb as is op2 = 0b0101 & op1 = 0 & ar = 0b1100 & as & at = 0 & op0 = 0 { 452 | idtlb(); 453 | } 454 | 455 | # IHI - Instruction Cache Hit Invalidate, pg. 349. 456 | :ihi as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b1110 & op0 = 0b0010 { 457 | ihi(as + zext(u10_16.23_sb2)); 458 | } 459 | 460 | # IHU - Instruction Cache Hit Unlock, pg. 351. 461 | :ihu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { 462 | ihu(as + zext(u8_20.23_sb4)); 463 | } 464 | 465 | # III - Instruction Cache Index Invalidate, pg. 353. 466 | :iii as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b1111 & op0 = 0b0010 { 467 | iii(as + zext(u10_16.23_sb2)); 468 | } 469 | 470 | # IITLB - Invalidate Instruction TLB Entry, pg. 355. 471 | :iitlb as is op2 = 0b0101 & op1 = 0 & ar = 0b0100 & as & at = 0 & op0 = 0 { 472 | iitlb(as); 473 | } 474 | 475 | # IIU - Instruction Cache Index Unlock, pg. 356. 476 | :iiu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { 477 | iiu(as + zext(u8_20.23_sb4)); 478 | } 479 | 480 | # ILL - Illegal Instruction, pg. 358. 481 | :ill is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & at = 0 & op0 = 0 { 482 | ill(); 483 | goto inst_start; 484 | } 485 | 486 | # ILL.N - Narrow Illegal Instruction, pg. 359. 487 | :ill.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0110 & n_op0 = 0b1101 { 488 | ill(); 489 | goto inst_start; 490 | } 491 | 492 | # IPF - Instruction Cache Prefetch, pg. 360. 493 | :ipf as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b1100 & op0 = 0b0010 { 494 | ipf(as + zext(u10_16.23_sb2)); 495 | } 496 | 497 | # IPFL - Instruction Cache Prefetch and Lock, pg. 362. 498 | :ipfl as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { 499 | ipfl(as + zext(u8_20.23_sb4)); 500 | } 501 | 502 | # ISYNC - Instruction Fetch Synchronize, pg. 364. 503 | :isync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0 & op0 = 0 { 504 | isync(); 505 | } 506 | 507 | # J - Unconditional Jump, pg. 366. 508 | :j srel_6.23 is srel_6.23 & u2_4.5 = 0 & op0 = 0b0110 { 509 | goto srel_6.23; 510 | } 511 | 512 | # J.L is a macro. 513 | 514 | # RET (JX A0) - Non-Windowed Return, pg. 478. 515 | :ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6.7 = 0b10 & u2_4.5 = 0b10 & op0 = 0 { 516 | return [a0]; 517 | } 518 | 519 | # The manual suggests that RET is equivalent to JX A0, yet RET has bit 5 unset, JX doesn’t. 520 | :ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6.7 = 0b10 & u2_4.5 = 0b00 & op0 = 0 { 521 | return [a0]; 522 | } 523 | 524 | # JX - Uncoditional Jump Register, pg. 368. 525 | :jx as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b10 & u2_4.5 = 0b10 & op0 = 0 { 526 | goto [as]; 527 | } 528 | 529 | # L8UI - Load 8-bit Unsigned, pg. 369. 530 | :l8ui at, as, u8_16.23 is u8_16.23 & ar = 0 & as & at & op0 = 0b0010 { 531 | local addr:4 = as + zext(u8_16.23:1); 532 | at = zext(*:1 addr); 533 | } 534 | 535 | # L16SI - Load 16-bit Signed, pg. 370. 536 | :l16si at, as, u9_16.23_sb1 is u9_16.23_sb1 & ar = 0b1001 & as & at & op0 = 0b0010 { 537 | local addr:4 = as + zext(u9_16.23_sb1); 538 | at = sext(*:2 addr); 539 | } 540 | 541 | # L16UI - Load 16-bit Unsigned, pg. 372. 542 | :l16ui at, as, u9_16.23_sb1 is u9_16.23_sb1 & ar = 0b001 & as & at & op0 = 0b0010 { 543 | local addr:4 = as + zext(u9_16.23_sb1); 544 | at = zext(*:2 addr); 545 | } 546 | 547 | # L32AI - Load 32-bit Acquire, pg. 374. 548 | :l32ai at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1011 & as & at & op0 = 0b0010 { 549 | local addr:4 = as + zext(u10_16.23_sb2); 550 | at = *:4 addr; 551 | acquire(addr); 552 | } 553 | 554 | # L32I - Load 32-bit, pg. 378. 555 | :l32i at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0010 & as & at & op0 = 0b0010 { 556 | local addr:4 = as + zext(u10_16.23_sb2); 557 | at = *:4 addr; 558 | } 559 | 560 | # L32I.N - Narrow Load 32-bit, pg. 380. 561 | :l32i.n n_at, n_as, n_u6_12.15_sb2 is n_u6_12.15_sb2 & n_as & n_at & n_op0 = 0b1000 { 562 | local addr:4 = n_as + zext(n_u6_12.15_sb2); 563 | n_at = *:4 addr; 564 | } 565 | 566 | # L32R - Load 32-bit PC-relative, pg. 382. 567 | :l32r at, srel_8.23_oex_sb2 is srel_8.23_oex_sb2 & at & op0 = 0b0001 { 568 | at = srel_8.23_oex_sb2; 569 | } 570 | 571 | # LDCT - Load Data Cache Tag, pg. 384. 572 | :ldct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1000 & as & at & op0 = 0 { 573 | at = ldct(as); 574 | } 575 | 576 | # LICT - Load Instruction Cache Tag, pg. 388. 577 | :lict at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0 & as & at & op0 = 0 { 578 | at = lict(as); 579 | } 580 | 581 | # LICW - Load Instruction Cache Word, pg. 390. 582 | :licw at, as is op2 = 0b1111 & op1 = 0b0010 & ar = 0 & as & at & op0 = 0 { 583 | at = licw(as); 584 | } 585 | 586 | macro loopSetup(as, end, doit) { 587 | LCOUNT = as - 1; 588 | LBEG = inst_next; 589 | #LEND = end; 590 | if (doit) goto ; 591 | goto end; 592 | 593 | } 594 | 595 | # LOOP - Loop, pg. 392. 596 | :loop as, urel_16.23 is urel_16.23 & ar=0b1000 & as & at=0b0111 & op0=0b0110 597 | [loopEnd=1; globalset(urel_16.23, loopEnd);] { 598 | loopSetup(as, urel_16.23, 1:1); 599 | } 600 | 601 | # LOOPGTZ - Loop if Greater Than Zero, pg. 394. 602 | :loopgtz as, urel_16.23 is urel_16.23 & ar=0b1010 & as & at=0b0111 & op0=0b0110 603 | [loopEnd=1; globalset(urel_16.23, loopEnd);] { 604 | loopSetup(as, urel_16.23, as s> 0); 605 | } 606 | 607 | # LOOPNEZ - Loop if Not Equal Zero, pg. 396. 608 | :loopnez as, urel_16.23 is urel_16.23 & ar=0b1001 & as & at=0b0111 & op0=0b0110 609 | [loopEnd=1; globalset(urel_16.23, loopEnd);] { 610 | loopSetup(as, urel_16.23, as != 0); 611 | } 612 | 613 | # LSI - Load Single Immediate, pg. 398. 614 | :lsi ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0 & as & ft & op0 = 0b0011 { 615 | local addr:4 = as + zext(u10_16.23_sb2); 616 | ft = *:4 addr; 617 | } 618 | 619 | # LSIU - Load Single Immediate with Update, pg. 400. 620 | :lsiu ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1000 & as & ft & op0 = 0b0011 { 621 | local addr:4 = as + zext(u10_16.23_sb2); 622 | ft = *:4 addr; 623 | as = addr; 624 | } 625 | 626 | # LSX - Load Single Indexed, pg. 402. 627 | :lsx fr, as, at is op2 = 0 & op1 = 0b1000 & fr & as & at & op0 = 0 { 628 | local addr:4 = as+at; 629 | fr = *:4 addr; 630 | } 631 | 632 | # LSXU - Load Single Indexed with Update, pg. 404. 633 | :lsxu fr, as, at is op2 = 0b0001 & op1 = 0b1000 & fr & as & at & op0 = 0 { 634 | local addr:4 = as+at; 635 | fr = *:4 addr; 636 | as = addr; 637 | } 638 | 639 | # MADD.S - Multiply and Add Single, pg. 406. 640 | :madd.s fr, fs, ft is op2 = 0b0100 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { 641 | fr = fr f+ (fs f* ft); 642 | } 643 | 644 | # MAX - Maximum Value, pg. 407. 645 | :max ar, as, at is op2 = 0b0101 & op1 = 0b0011 & ar & as & at & op0 = 0 { 646 | if (as s> at) 647 | goto ; 648 | ar = at; 649 | goto inst_next; 650 | 651 | ar = as; 652 | } 653 | 654 | # MAXU - Maximum Value Unsigned, pg. 408. 655 | :maxu ar, as, at is op2 = 0b0111 & op1 = 0b0011 & ar & as & at & op0 = 0 { 656 | if (as > at) 657 | goto ; 658 | ar = at; 659 | goto inst_next; 660 | 661 | ar = as; 662 | } 663 | 664 | # MEMW - Memory Wait, pg. 409. 665 | :memw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1100 & op0 = 0 { 666 | memw(); 667 | } 668 | 669 | # MIN - Minimum Value, pg. 410. 670 | :min ar, as, at is op2 = 0b0100 & op1 = 0b0011 & ar & as & at & op0 = 0 { 671 | if (as s< at) 672 | goto ; 673 | ar = at; 674 | goto inst_next; 675 | 676 | ar = as; 677 | } 678 | 679 | # MINU - Minimum Value Unsigned, pg. 411. 680 | :minu ar, as, at is op2 = 0b0110 & op1 = 0b0011 & ar & as & at & op0 = 0 { 681 | if (as < at) 682 | goto ; 683 | ar = at; 684 | goto inst_next; 685 | 686 | ar = as; 687 | } 688 | 689 | # MOV.N - Narrow Move, pg. 413. 690 | :mov.n n_at, n_as is n_ar = 0 & n_as & n_at & n_op0 = 0b1101 { 691 | n_at = n_as; 692 | } 693 | 694 | # MOV.S - Move Single, pg. 414. 695 | :mov.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0 & op0 = 0 { 696 | fr = fs; 697 | } 698 | 699 | # MOVEQZ - Move if Equal to Zero, pg. 415. 700 | :moveqz ar, as, at is op2 = 0b1000 & op1 = 0b0011 & ar & as & at & op0 = 0 { 701 | if (at != 0) 702 | goto inst_next; 703 | ar = as; 704 | } 705 | 706 | # MOVEQZ.S - Move Single if Equal to Zero, pg. 416. 707 | :moveqz.s fr, fs, at is op2 = 0b1000 & op1 = 0b1011 & fr & fs & at & op0 = 0 { 708 | if (at != 0) 709 | goto inst_next; 710 | fr = fs; 711 | } 712 | 713 | # MOVF - Move if False, pg. 417. 714 | :movf ar, as, bt is op2 = 0b1100 & op1 = 0b0011 & ar & as & bt & op0 = 0 { 715 | if (bt) 716 | goto inst_next; 717 | ar = as; 718 | } 719 | 720 | # MOVF.S - Move Single if False, pg. 418. 721 | :movf.s fr, fs, bt is op2 = 0b1100 & op1 = 0b1011 & fr & fs & bt & op0 = 0 { 722 | if (bt) 723 | goto inst_next; 724 | fr = fs; 725 | } 726 | 727 | # MOVGEZ - Move if Greater Than or Equal to Zero, pg. 419. 728 | :movgez ar, as, at is op2 = 0b1011 & op1 = 0b0011 & ar & as & at & op0 = 0 { 729 | if (at s< 0) 730 | goto inst_next; 731 | ar = as; 732 | } 733 | 734 | # MOVGEZ.S - Move Single if Greater Than or Equal to Zero, pg. 420. 735 | :movgez.s fr, fs, at is op2 = 0b1011 & op1 = 0b1011 & fr & fs & at & op0 = 0 { 736 | if (at s< 0) 737 | goto inst_next; 738 | fr = fs; 739 | } 740 | 741 | # MOVI - Move Immediate, pg. 421. 742 | :movi at, s16_16.23_8.11 is s16_16.23_8.11 & ar = 0b1010 & at & op0 = 0b0010 { 743 | local val:4 = sext(s16_16.23_8.11); 744 | at = val; 745 | } 746 | 747 | 748 | # MOVI.N - Narrow Move Immediate, pg. 422. 749 | :movi.n n_as, n_s8_12.15_4.6_asymm is n_s8_12.15_4.6_asymm & n_as & n_u1_7 = 0 & n_op0 = 0b1100 { 750 | local val:4 = sext(n_s8_12.15_4.6_asymm); 751 | n_as = val; 752 | } 753 | 754 | # MOVLTZ - Move if Less Than Zero, pg. 423. 755 | :movltz ar, as, at is op2 = 0b1010 & op1 = 0b0011 & ar & as & at & op0 = 0 { 756 | if (at s>= 0) 757 | goto inst_next; 758 | ar = as; 759 | } 760 | 761 | # MOVLTZ.S - Move Single if Less Than Zero, pg. 424. 762 | :movltz.s fr, fs, at is op2 = 0b1010 & op1 = 0b1011 & fr & fs & at & op0 = 0 { 763 | if (at s>= 0) 764 | goto inst_next; 765 | fr = fs; 766 | } 767 | 768 | # MOVNEZ - Move if Not Equal to Zero, pg. 425. 769 | :movnez ar, as, at is op2 = 0b1001 & op1 = 0b0011 & ar & as & at & op0 = 0 { 770 | if (at == 0) 771 | goto inst_next; 772 | ar = as; 773 | } 774 | 775 | # MOVNEZ.S - Move Single if Not Equal to Zero, pg. 426. 776 | :movnez.s fr, fs, at is op2 = 0b1001 & op1 = 0b1011 & fr & fs & at & op0 = 0 { 777 | if (at == 0) 778 | goto inst_next; 779 | fr = fs; 780 | } 781 | 782 | # MOVT - Move if True, pg. 428. 783 | :movt ar, as, bt is op2 = 0b1101 & op1 = 0b0011 & ar & as & bt & op0 = 0 { 784 | if (!bt) 785 | goto inst_next; 786 | ar = as; 787 | } 788 | 789 | # MOVT.S - Move Single if True, pg. 429. 790 | :movt.s fr, fs, bt is op2 = 0b1101 & op1 = 0b1011 & fr & fs & bt & op0 = 0 { 791 | if (!bt) 792 | goto inst_next; 793 | fr = fs; 794 | } 795 | 796 | # MSUB.S - Multiply and Subtract Single, pg. 430. 797 | :msub.s fr, fs, ft is op2 = 0b0101 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { 798 | fr = fr f- (fs f* ft); 799 | } 800 | 801 | # MUL.S - Multiply Single, pg. 435. 802 | :mul.s fr, fs, ft is op2 = 0b0010 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { 803 | fr = fs f* ft; 804 | } 805 | 806 | # MUL16S - Multiply 16-bit Signed, pg. 436. 807 | :mul16s ar, as, at is op2 = 0b1101 & op1 = 0b0001 & ar & as & at & op0 = 0 { 808 | ar = sext(as:2) * sext(at:2); 809 | } 810 | 811 | # MUL16U - Multiply 16-bit Unsigned, pg. 437. 812 | :mul16u ar, as, at is op2 = 0b1100 & op1 = 0b0001 & ar & as & at & op0 = 0 { 813 | ar = zext(as:2) * zext(at:2); 814 | } 815 | 816 | # MULL - Multiply Low, pg. 450. 817 | :mull ar, as, at is op2 = 0b1000 & op1 = 0b0010 & ar & as & at & op0 = 0 { 818 | ar = as * at; 819 | } 820 | 821 | # MULSH - Multiply Signed High, pg. 455. 822 | :mulsh ar, as, at is op2 = 0b1011 & op1 = 0b0010 & ar & as & at & op0 = 0 { 823 | local s64:8 = sext(as); 824 | local t64:8 = sext(at); 825 | local p:8 = (s64 * t64); 826 | ar = p(4); 827 | } 828 | 829 | # MULUH - Multiply Unsigned High, pg. 456. 830 | :muluh ar, as, at is op2 = 0b1010 & op1 = 0b0010 & ar & as & at & op0 = 0 { 831 | local s64:8 = zext(as); 832 | local t64:8 = zext(at); 833 | local p:8 = (s64 * t64); 834 | ar = p(4); 835 | } 836 | 837 | # NEG - Negate, pg. 457. 838 | :neg ar, at is op2 = 0b0110 & op1 = 0 & ar & as = 0 & at & op0 = 0 { 839 | ar = -at; 840 | } 841 | 842 | # NEG.S - Negate Single, pg. 458. 843 | :neg.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0b0110 & op0 = 0 { 844 | fr = f- fs; 845 | } 846 | 847 | # NOP - No Operation, pg. 459. 848 | :nop is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1111 & op0 = 0 { } 849 | 850 | # NOP.N - Narrow No Operation, pg. 460. 851 | :nop.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0011 & n_op0 = 0b1101 { } 852 | 853 | # NSA - Normalization Shift Amount, pg. 461. 854 | :nsa at, as is op2 = 0b0100 & op1 = 0 & ar = 0b1110 & as & at & op0 = 0 { 855 | # https://stackoverflow.com/questions/54772520/normalizing-a-two-complement-number 856 | at = nsa(as); 857 | } 858 | 859 | # NSAU - Normalization Shift Amount Unsigned, pg. 462. (Count leading zeros) 860 | :nsau at, as is op2 = 0b0100 & op1 = 0 & ar = 0b1111 & as & at & op0 = 0 { 861 | local z4 = as[16,16] == 0; 862 | 863 | local t3 = zext(z4)*as[0,16] + zext(!z4)*as[16,16]; 864 | local z3 = t3[8,8] == 0; 865 | 866 | local t2 = (z3)*t3[0,8] + (!z3)*t3[8,8]; 867 | local z2 = t2[4,4] == 0; 868 | 869 | local t1 = (z2)*t2[0,4] + (!z2)*t2[4,4]; 870 | local z1 = t1[2,2] == 0; 871 | 872 | local z0 = (z1)*(t1[1,1] == 0) + (!z1)*(t1[3,1] == 0); 873 | local all0 = as == 0; 874 | 875 | at = zext((all0)*32 + (!all0)*(z4<<4 | z3<<3 | z2<<2 | z1<<1 | z0)); 876 | } 877 | 878 | # OEQ.S - Compare Single Equal, pg. 463. 879 | :oeq.s br, fs, ft is op2 = 0b0010 & op1 = 0b1011 & br & fs & ft & op0 = 0 { 880 | br = !nan(fs) && !nan(ft) && fs f== ft; 881 | } 882 | 883 | # OLE.S - Compare Single Ordered and Less Than or Equal, pg. 464 884 | :ole.s br, fs, ft is op2 = 0b0110 & op1 = 0b1011 & br & fs & ft & op0 = 0 { 885 | br = !nan(fs) && !nan(ft) && fs f<= ft; 886 | } 887 | 888 | # OLT.S - Compare Single Ordered and Less Than, pg. 465. 889 | :olt.s br, fs, ft is op2 = 0b0100 & op1 = 0b1011 & br & fs & ft & op0 = 0 { 890 | br = !nan(fs) && !nan(ft) && fs f< ft; 891 | } 892 | 893 | # MOV - Move, pg. 412. Special case of OR as, at, at. 894 | :mov ar, as is op2 = 0b0010 & op1 = 0 & ar & as & as = at & op0 = 0 { 895 | ar = as; 896 | } 897 | 898 | # OR - Bitwise Logical Or, pg. 466. 899 | :or ar, as, at is op2 = 0b0010 & op1 = 0 & ar & as & at & op0 = 0 { 900 | ar = as | at; 901 | } 902 | 903 | # ORB - Boolean Or, pg. 467. 904 | :orb br, bs, bt is op2 = 0b0010 & op1 = 0b0010 & br & bs & bt & op0 = 0 { 905 | br = bs || bt; 906 | } 907 | 908 | # ORBC - Boolean Or with Complement, pg. 468. 909 | :orbc br, bs, bt is op2 = 0b0011 & op1 = 0b0010 & br & bs & bt & op0 = 0 { 910 | br = bs || !bt; 911 | } 912 | 913 | # PDTLB - Probe Data TLB, pg. 469. 914 | :pdtlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1101 & as & at & op0 = 0 { 915 | at = pdtlb(as); 916 | } 917 | 918 | # PITLB - Probe Instruction TLB, pg. 470. 919 | :pitlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0101 & as & at & op0 = 0 { 920 | at = pitlb(as); 921 | } 922 | 923 | # QUOS - Quotient Signed, pg. 471. 924 | :quos ar, as, at is op2 = 0b1101 & op1 = 0b0010 & ar & as & at & op0 = 0 { 925 | ar = as s/ at; 926 | } 927 | 928 | # QUOU - Quotient Unsigned, pg. 472. 929 | :quou ar, as, at is op2 = 0b1100 & op1 = 0b0010 & ar & as & at & op0 = 0 { 930 | ar = as / at; 931 | } 932 | 933 | # RDTLB0 - Read Data TLB Virtual Entry, pg. 473. 934 | :rdtlb0 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1011 & as & at & op0 = 0 { 935 | at = rdtlb0(as); 936 | } 937 | 938 | # RDTLB1 - Read Data TLB Entry Translation, pg. 474. 939 | :rdtlb1 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1111 & as & at & op0 = 0 { 940 | at = rdtlb1(as); 941 | } 942 | 943 | # REMS - Remainder Signed, pg. 475. 944 | :rems ar, as, at, is op2 = 0b1111 & op1 = 0b0010 & ar & as & at & op0 = 0 { 945 | ar = as s% at; 946 | } 947 | 948 | # REMU - Remainder Unsigned, pg. 476. 949 | :remu ar, as, at, is op2 = 0b1110 & op1 = 0b0010 & ar & as & at & op0 = 0 { 950 | ar = as % at; 951 | } 952 | 953 | # RER - Read External Register, pg. 477. 954 | :rer as, at is op2 = 0b0100 & op1 = 0 & ar = 0b0110 & as & at & op0 = 0 { 955 | as = rer(at); 956 | } 957 | 958 | # RET.N - Narrow Non-Windowed Return, pg. 479. 959 | :ret.n is n_ar = 0b1111 & n_as = 0 & n_at = 0 & n_op0 = 0b1101 { 960 | return [a0]; 961 | } 962 | 963 | # RFDD - Return from Debug and Dispatch, pg. 484. 964 | :rfdd is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1110 & (as = 0b0000 | as = 0b0001) & at = 0b0001 & op0 = 0 { 965 | rfdd(); 966 | } 967 | 968 | # RFDE _ Return From Double Exception, pg. 485. 969 | :rfde is op2 = 0 & op1 = 0 & ar = 0b0011 & as =0b0010 & at = 0 & op0 = 0 { 970 | rfde(); 971 | } 972 | 973 | # RFDO - Return from Debug Operation, pg. 486. 974 | :rfdo is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1110 & as = 0 & at = 0 & op0 = 0 { 975 | rfdo(); 976 | } 977 | 978 | # RFE - Return From Exception, pg. 487. 979 | :rfe is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0 & at = 0 & op0 = 0 { 980 | rfe(); 981 | } 982 | 983 | # RFI - Return from High-Priority Interrupt, pg. 488. 984 | :rfi u4_8.11 is op2 = 0 & op1 = 0 & ar = 0b0011 & u4_8.11 & at = 0b0001 & op0 = 0 { 985 | rfi(u4_8.11:1); 986 | } 987 | 988 | # RFME - Return from Memory Error, pg. 489. 989 | :rfme is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0 & at = 0b0010 & op0 = 0 { 990 | rfme(); 991 | } 992 | 993 | # RFR - Move FR to AR, pg. 490. 994 | :rfr ar, fs is op2 = 0b1111 & op1 = 0b1010 & ar & fs & at = 0b0100 & op0 = 0 { 995 | ar = fs; 996 | } 997 | 998 | # RFUE - Return from User-Mode Exception, pg. 491. 999 | :rfue is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0001 & at = 0 & op0 = 0 { 1000 | rfue(); 1001 | } 1002 | 1003 | # RFWO - Return from Window Overflow, pg. 492. 1004 | :rfwo is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0100 & at = 0 & op0 = 0 { 1005 | rfwo(); 1006 | } 1007 | 1008 | # RFWU - Return from Window Underflow, pg. 493. 1009 | :rfwu is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0101 & at = 0 & op0 = 0 { 1010 | rfwu(); 1011 | } 1012 | 1013 | # RITLB0 - Read Instruction TLB Virtual Entry, pg. 494. 1014 | :ritlb0 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0011 & as & at & op0 = 0 { 1015 | at = ritlb0(as); 1016 | } 1017 | 1018 | # RITLB1 - Read Instruction TLB Entry Translation, pg. 495. 1019 | :ritlb1 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0111 & as & at & op0 = 0 { 1020 | at = ritlb1(as); 1021 | } 1022 | 1023 | # ROUND.S - Round Single to Fixed, pg. 497. 1024 | :round.s ar, fs, u4_4.7 is op2 = 0b1000 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 { 1025 | local scale:4 = int2float(1:2 << u4_4.7:2); 1026 | ar = round(fs f* scale); 1027 | } 1028 | 1029 | # RSIL - Read and Set Interrupt Level, pg. 498. 1030 | :rsil at, u4_8.11 is op2 = 0 & op1 = 0 & ar = 0b0110 & u4_8.11 & at & op0 = 0 { 1031 | at = rsil(u4_8.11:1); 1032 | } 1033 | 1034 | # RSR - Read Special Register, pg. 500. 1035 | :rsr at, sr is op0 = 0 & op1 = 0b0011 & sr & at & op0 = 0 { 1036 | local src:4 = zext(sr); 1037 | at = *[register]:4 src; 1038 | } 1039 | 1040 | # RSYNC - Register Read Synchronize, pg. 502. 1041 | :rsync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0001 & op0 = 0 { 1042 | rsync(); 1043 | } 1044 | 1045 | # RUR - Read User Register, pg. 503. 1046 | :rur ar, u8_4.11 is op2 = 0b1110 & op1 = 0b0011 & ar & u8_4.11 & op0 = 0 { 1047 | ar = rur(u8_4.11:1); 1048 | } 1049 | 1050 | # S8I - Store 8-bit, pg. 504. 1051 | :s8i at, as, u8_16.23 is u8_16.23 & ar = 0b0100 & as & at & op0 = 0b0010 { 1052 | local addr:4 = as + zext(u8_16.23:1); 1053 | *:1 addr = at:1; 1054 | } 1055 | 1056 | # S16I - Store 16-bit, pg. 505. 1057 | :s16i at, as, u9_16.23_sb1 is u9_16.23_sb1 & ar = 0b0101 & as & at & op0 = 0b0010 { 1058 | local addr:4 = as + zext(u9_16.23_sb1); 1059 | *:2 addr = at:2; 1060 | } 1061 | 1062 | # S32C1I - Store 32-bit Compare Conditional, pg. 506 1063 | :s32c1i at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1110 & as & at & op0 = 0b0010 { 1064 | local addr:4 = as + zext(u10_16.23_sb2); 1065 | at = s32c1i(addr); 1066 | } 1067 | 1068 | # S32I - Store 32-bit, pg. 510. 1069 | :s32i at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0110 & as & at & op0 = 0b0010 { 1070 | local addr:4 = as + zext(u10_16.23_sb2); 1071 | *:4 addr = at; 1072 | } 1073 | 1074 | # S32I.N - Narrow Store 32-bit, pg. 512. 1075 | :s32i.n n_at, n_as, n_u6_12.15_sb2 is n_u6_12.15_sb2 & n_as & n_at & n_op0 = 0b1001 { 1076 | local addr:4 = n_as + zext(n_u6_12.15_sb2); 1077 | *:4 addr = n_at; 1078 | } 1079 | 1080 | # S32RI - Store 32-bit Release, pg. 514. 1081 | :s32ri at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1111 & as & at & op0 = 0b0010 { 1082 | local addr:4 = as + zext(u10_16.23_sb2); 1083 | *:4 addr = at; 1084 | release(addr); 1085 | } 1086 | 1087 | # SDCT - Store Data Cache Tag, pg. 516. 1088 | :sdct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1001 & as & at & op0 = 0 { 1089 | sdct(as, at); 1090 | } 1091 | 1092 | # SEXT - Sign Extend, pg. 518. 1093 | :sext ar, as, u5_4.7_plus7 is op2 = 0b0010 & op1 = 0b0011 & ar & as & u5_4.7_plus7 & op0 = 0 { 1094 | local shift:1 = 31:1 - u5_4.7_plus7; 1095 | local tmp:4 = as << shift; 1096 | ar = tmp s>> shift; 1097 | } 1098 | 1099 | # SICT - Store Instruction Cache Tag, pg. 519. 1100 | :sict at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b0001 & as & at & op0 = 0 { 1101 | sict(as, at); 1102 | } 1103 | 1104 | # SICW - Store Instruction Cache word, pg. 521. 1105 | :sicw at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b0011 & as & at & op0 = 0 { 1106 | sicw(as, at); 1107 | } 1108 | 1109 | # SIMCALL - Simulator Call, pg. 523. 1110 | :simcall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0b0001 & at = 0 & op0 = 0 { 1111 | simcall(); 1112 | } 1113 | 1114 | # SLL - Shift Left Logical, pg. 524. 1115 | :sll ar, as is op2 = 0b1010 & op1 = 0b0001 & ar & as & at = 0 & op0 = 0 { 1116 | local sa = 32 - SAR; 1117 | ar = as << sa; 1118 | } 1119 | 1120 | # SLLI - Shift Left Logical Immediate, pg. 525. 1121 | :slli ar, as, u5_4.7_20_slli is u3_21.23 = 0 & u5_4.7_20_slli & op1 = 0b0001 & ar & as & op0 = 0 { 1122 | ar = as << u5_4.7_20_slli; 1123 | } 1124 | 1125 | # SRA - Shift Right Arithmetic, pg. 526. 1126 | :sra ar, at is op2 = 0b1011 & op1 = 0b0001 & ar & as = 0 & at & op0 = 0 { 1127 | ar = at s>> SAR; 1128 | } 1129 | 1130 | # SRAI - Shift Right Arithmetic Immediate, pg. 527. 1131 | :srai ar, at, u5_8.11_20 is u3_21.23 = 0b001 & u5_8.11_20 & op1 = 0b0001 & ar & at & op0 = 0 { 1132 | ar = at s>> u5_8.11_20; 1133 | } 1134 | 1135 | # SRC - Shift Right Combined, pg. 528. 1136 | :src ar, as, at is op2 = 0b1000 & op1 = 0b0001 & ar & as & at & op0 = 0 { 1137 | local s64:8 = zext(as); 1138 | local t64:8 = zext(at); 1139 | local combined:8 = (s64 << 32) | t64; 1140 | local shifted:8 = combined >> SAR; 1141 | ar = shifted:4; 1142 | } 1143 | 1144 | # SRL - Shift Right Logical, pg. 529. 1145 | :srl ar, at is op2 = 0b1001 & op1 = 0b0001 & ar & as = 0 & at & op0 = 0 { 1146 | ar = at >> SAR; 1147 | } 1148 | 1149 | # SRLI - Shift Right Logical Immediate, pg. 530. 1150 | :srli ar, at, u4_8.11 is op2 = 0b0100 & op1 = 0b0001 & ar & u4_8.11 & at & op0 = 0 { 1151 | ar = at >> u4_8.11; 1152 | } 1153 | 1154 | # SSA8B - Set Shift Amount for BE Byte Shift, pg. 531. 1155 | :ssa8b as is op2 = 0b0100 & op1 = 0 & ar = 0b0011 & as & at = 0 & op0 = 0 { 1156 | local lsa:4 = (as&3)*8; 1157 | SAR = 32 - lsa; 1158 | } 1159 | 1160 | # SSA8L - Set Shift Amount for LE Byte Shift, pg. 532. 1161 | :ssa8l as is op2 = 0b0100 & op1 = 0 & ar = 0b0010 & as & at = 0 & op0 = 0 { 1162 | SAR = (as&3)*8; 1163 | } 1164 | 1165 | # SSAI - Set Shift Amount Immediate, pg. 533. 1166 | :ssai u5_8.11_4 is op2 = 0b0100 & op1 = 0 & ar = 0b0100 & u5_8.11_4 & u3_5.7 = 0 & op0 = 0 { 1167 | SAR = zext(u5_8.11_4); 1168 | } 1169 | 1170 | # SSI - Store Single Immediate, pg. 534. 1171 | :ssi ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0100 & as & ft & op0 = 0b0011 { 1172 | local addr:4 = as + zext(u10_16.23_sb2); 1173 | *:4 addr = ft; 1174 | } 1175 | 1176 | # SSIU - Store Single Immediate with Update, pg. 536. 1177 | :ssiu ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1100 & as & ft & op0 = 0b0011 { 1178 | local addr:4 = as + zext(u10_16.23_sb2); 1179 | *:4 addr = ft; 1180 | as = addr; 1181 | } 1182 | 1183 | # SSL - Set Shift Amount for Left Shift, pg. 538. 1184 | :ssl as is op2 = 0b0100 & op1 = 0 & ar = 0b0001 & as & at = 0 & op0 = 0 { 1185 | SAR = 32 - (as & 0x1f); 1186 | } 1187 | 1188 | # SSR - Set Shift Amount for Right Shift, pg. 539. 1189 | :ssr as is op2 = 0b0100 & op1 = 0 & ar = 0 & as & at = 0 & op0 = 0 { 1190 | SAR = (as & 0x1f); 1191 | } 1192 | 1193 | # SSX - Store Singe Indexed, pg. 540. 1194 | :ssx fr, as, at is op2 = 0b0100 & op1 = 0b1000 & fr & as & at & op0 = 0 { 1195 | local addr:4 = as+at; 1196 | *:4 addr = fr; 1197 | } 1198 | 1199 | # SSXU - Store Singe Indexed with Update, pg. 541. 1200 | :ssxu fr, as, at is op2 = 0b0101 & op1 = 0b1000 & fr & as & at & op0 = 0 { 1201 | local addr:4 = as+at; 1202 | *:4 addr = fr; 1203 | as = addr; 1204 | } 1205 | 1206 | # SUB - Subtract, pg. 542. 1207 | :sub ar, as, at is op2 = 0b1100 & op1 = 0 & ar & as & at & op0 = 0 { 1208 | ar = as - at; 1209 | } 1210 | 1211 | # SUB.S - Subtract Single, pg. 543. 1212 | :sub.s fr, fs, ft is op2 = 0b0001 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { 1213 | fr = fs f- ft; 1214 | } 1215 | 1216 | # SUBX2 - Subtract with Shift by 1, pg. 544. 1217 | :subx2 ar, as, at is op2 = 0b1101 & op1 = 0 & ar & as & at & op0 = 0 { 1218 | ar = (as << 1) - at; 1219 | } 1220 | 1221 | # SUBX4 - Subtract with Shift by 2, pg. 545. 1222 | :subx4 ar, as, at is op2 = 0b1110 & op1 = 0 & ar & as & at & op0 = 0 { 1223 | ar = (as << 2) - at; 1224 | } 1225 | 1226 | # SUBX8 - Subtract with Shift by 3, pg. 546. 1227 | :subx8 ar, as, at is op2 = 0b1111 & op1 = 0 & ar & as & at & op0 = 0 { 1228 | ar = (as << 3) - at; 1229 | } 1230 | 1231 | # SYSCALL - System Call, pg. 547. 1232 | :syscall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0 & at = 0 & op0 = 0 { 1233 | syscall(); 1234 | } 1235 | 1236 | # TRUNC.S - Truncate Single to Fixed, pg. 548 1237 | :trunc.s ar, fs, u4_4.7 is op2 = 0b1001 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 { 1238 | local scale:4 = int2float(1:2 << u4_4.7:2); 1239 | ar = trunc(fs f* scale); 1240 | } 1241 | 1242 | # UEQ.S - Compare Single Unordered or Equal, pg. 549. 1243 | :ueq.s br, fs, ft is op2 = 0b0011 & op1 = 0b1011 & br & fs & ft & op0 = 0 { 1244 | br = nan(fs) || nan(ft) || fs f== ft; 1245 | } 1246 | 1247 | # UFLOAT.S - Convert Unsigned Fixed to Single, pg. 550. 1248 | :ufloat.s fr, as, u4_4.7 is op2 = 0b1101 & op1 = 0b1010 & fr & as & u4_4.7 & op0 = 0 { 1249 | local tmp:8 = zext(as); 1250 | local f = int2float(tmp); 1251 | local d = int2float(1:2 << u4_4.7:2); 1252 | fr = d f/ f; 1253 | } 1254 | 1255 | # ULE.S - Compare Single Unordered or Less Than or Equal, pg. 551. 1256 | :ule.s br, fs, ft is op2 = 0b0111 & op1 = 0b1011 & br & fs & ft & op0 = 0 { 1257 | br = nan(fs) || nan(ft) || fs f<= ft; 1258 | } 1259 | 1260 | # ULT.S - Compare Single Unordered or Less Than, pg. 552. 1261 | :ult.s br, fs, ft is op2 = 0b0101 & op1 = 0b1011 & br & fs & ft & op0 = 0 { 1262 | br = nan(fs) || nan(ft) || fs f< ft; 1263 | } 1264 | 1265 | # FIXME: UMUL.AA* 1266 | 1267 | # UN.S - Compare Single Unordered, pg. 554. 1268 | :un.s br, fs, ft is op2 = 0b0001 & op1 = 0b1011 & br & fs & ft & op0 = 0 { 1269 | br = nan(fs) || nan(ft); 1270 | } 1271 | 1272 | # UTRUNC.S - Truncate Single to Fixed Unsigned, pg. 555. 1273 | :utrunc.s ar, fs, u4_4.7 is op2 = 0b1110 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 { 1274 | local scale:4 = int2float(1:2 << u4_4.7:2); 1275 | local tmp:8 = trunc(fs f* scale); 1276 | local posof = nan(fs) || (tmp >> 16) != 0; 1277 | local negof = tmp s< 0; 1278 | local noof = !posof && !negof; 1279 | ar = zext(posof)*0xffffffff + zext(negof)*0x80000000 + zext(noof)*tmp:4; 1280 | } 1281 | 1282 | # WAITI - Wait Interrupt, pg. 556. 1283 | :waiti u4_8.11 is op2 = 0 & op1 = 0 & ar = 0b0111 & u4_8.11 & at = 0 & op0 = 0 { 1284 | waiti(u4_8.11:4); 1285 | } 1286 | 1287 | # WDTLB - Write Data TLB Entry, pg. 557. 1288 | :wdtlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1110 & as & at & op0 = 0 { 1289 | wdtlb(as, at); 1290 | } 1291 | 1292 | # WER - Write External Register, pg. 558. 1293 | :wer as, at is op2 = 0b0100 & op1 = 0 & ar = 0b0111 & as & at & op0 = 0 { 1294 | wer(as, at); 1295 | } 1296 | 1297 | # WFR - Move AR to FR, pg. 559. 1298 | :wfr fr, as is op2 = 0b1111 & op1 = 0b1010 & fr & as & at = 0b0101 & op0 = 0 { 1299 | fr = as; 1300 | } 1301 | 1302 | # WITLB - Write Instruction TLB Entry, pg. 560. 1303 | :witlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0110 & as & at & op0 = 0 { 1304 | witlb(as, at); 1305 | } 1306 | 1307 | # WSR - Write Special Register, pg. 561. 1308 | :wsr at, sr is op2 = 0b0001 & op1 = 0b0011 & sr & at & op0 = 0 { 1309 | local dst:4 = zext(sr); 1310 | *[register]:4 dst = at; 1311 | } 1312 | 1313 | # WUR - Write User Register, pg. 563. 1314 | :wur at, u8_8.15 is op2 = 0b1111 & op1 = 0b0011 & u8_8.15 & at & op0 = 0 { 1315 | wur(u8_8.15:1, at); 1316 | } 1317 | 1318 | # XOR - Bitwise Exclusive Or, pg. 564. 1319 | :xor ar, as, at is op2 = 0b0011 & op1 = 0 & ar & as & at & op0 = 0 { 1320 | ar = as ^ at; 1321 | } 1322 | 1323 | # XORB - Boolean Exclusive Or, pg. 565. 1324 | :xorb br, bs, bt is op2 = 0b0100 & op1 = 0b0010 & br & bs & bt & op0 = 0 { 1325 | br = bs ^^ bt; 1326 | } 1327 | 1328 | # XSR - Exchange Special Register, pg. 566. 1329 | :xsr at, u8_8.15 is op2 = 0b0110 & op1 = 0b0001 & u8_8.15 & at & op0 = 0 { 1330 | at = xsr(u8_8.15:1, at); 1331 | } 1332 | --------------------------------------------------------------------------------