├── 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 | 
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 |
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 |
--------------------------------------------------------------------------------