diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py
index ca300da20c..be7f938095 100644
--- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py
+++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py
@@ -663,3 +663,12 @@ PCodeTest({
'has_double': 0,
'has_longlong': 0,
})
+
+PCodeTest({
+ 'name': 'Xtensa',
+ 'build_all': 1,
+ 'build_exe': 1,
+ 'toolchain': 'Xtensa/xtensa-lx106-elf',
+ 'language_id': 'Xtensa:LE:32:default',
+ 'ccflags': '-L %(toolchain_dir)s/lib/gcc/xtensa-lx106-elf/%(gcc_version)s -lgcc',
+})
diff --git a/Ghidra/Processors/Xtensa/Module.manifest b/Ghidra/Processors/Xtensa/Module.manifest
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Ghidra/Processors/Xtensa/build.gradle b/Ghidra/Processors/Xtensa/build.gradle
new file mode 100644
index 0000000000..701baafa3b
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/build.gradle
@@ -0,0 +1,11 @@
+apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
+apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
+apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
+apply from: "$rootProject.projectDir/gradle/processorProject.gradle"
+apply plugin: 'eclipse'
+eclipse.project.name = 'Processors Xtensa'
+
+dependencies {
+ compile project(':Base')
+}
+
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.cspec b/Ghidra/Processors/Xtensa/data/languages/xtensa.cspec
new file mode 100644
index 0000000000..f7049a22ba
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.cspec
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.dwarf b/Ghidra/Processors/Xtensa/data/languages/xtensa.dwarf
new file mode 100644
index 0000000000..1790648cff
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.dwarf
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs b/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs
new file mode 100644
index 0000000000..80c6e25721
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs
@@ -0,0 +1,17 @@
+
+
+
+
+ Tensilica Xtensa 32-bit little-endian
+
+
+
+
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.opinion b/Ghidra/Processors/Xtensa/data/languages/xtensa.opinion
new file mode 100644
index 0000000000..3f2eae23ff
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.opinion
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.pspec b/Ghidra/Processors/Xtensa/data/languages/xtensa.pspec
new file mode 100644
index 0000000000..114b5c47a8
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.pspec
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensa.sinc
new file mode 100644
index 0000000000..b322f131b8
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.sinc
@@ -0,0 +1,275 @@
+define endian=little;
+define alignment=1;
+
+define space ram type=ram_space size=4 default;
+define space register type=register_space size=4;
+
+# Address registers (AR).
+define register offset=0x0000 size=4 [
+ a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15
+];
+
+# Floating Point registers (FR + FCR (control) + FSR (status)).
+# TODO: FCR and FSR seem unused?
+define register offset=0x0100 size=4 [
+ f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15
+ fcr fsr
+];
+
+# Boolean registers (BR).
+define register offset=0x0200 size=1 [
+ b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15
+];
+
+# Program counter.
+define register offset=0x1000 size=4 [ pc ];
+
+# Shift amount register. (TODO: other special registers)
+define register offset=0x2000 size=1 [ sar ];
+
+# Regular 24-bit instruction.
+define token insn(24)
+ # Named opcode/register fields.
+ op2 = (20,23)
+ ar = (12,15)
+ fr = (12,15)
+ br = (12,15)
+ as = (8,11)
+ fs = (8,11)
+ bs = (8,11)
+ at = (4,7)
+ ft = (4,7)
+ bt = (4,7)
+ op1 = (16,19)
+ op0 = (0,3)
+
+ # Signed and unsigned immediates. Named [us]N_L.M, where u and s denote signedness, L and M the
+ # least and most significant bit of the immediate in the instruction word, and N the length
+ # (i.e. M-L+1).
+ u3_21.23 = (21,23)
+ u4_20.23 = (20,23)
+ s8_16.23 = (16,23) signed
+ u8_16.23 = (16,23)
+ u12_12.23 = (12,23)
+ s12_12.23 = (12,23) signed
+ u16_8.23 = (8,23)
+ s8_6.23 = (6,23) signed
+ u1_20 = (20,20)
+ u2_18.19 = (18,19)
+ u3_17.19 = (17,19)
+ u2_16.17 = (16,17)
+ u1_16 = (16,16)
+ u2_14.15 = (14,15)
+ u3_13.15 = (13,15)
+ u4_12.15 = (12,15)
+ u8_8.15 = (8,15)
+ u2_12.13 = (12,13)
+ u1_12 = (12,12)
+ u4_8.11 = (8,11)
+ u8_4.11 = (4,11)
+ s4_8.11 = (8,11) signed
+ u2_6.7 = (6,7)
+ u3_5.7 = (5,7)
+ u4_4.7 = (4,7)
+ s4_4.7 = (4,7)
+ u2_4.5 = (4,5)
+ u1_4 = (4,4)
+;
+
+# Narrow 16-bit instructions; fields are always prefixed with n_.
+define token narrowinsn(16)
+ n_ar = (12,15)
+ n_as = (8,11)
+ n_at = (4,7)
+ n_op0 = (0, 3)
+
+ n_u4_12.15 = (12,15)
+ n_s4_12.15 = (12,15) signed
+ n_u4_8.11 = (8,11)
+ n_u1_7 = (7,7)
+ n_u2_6.7 = (6,7)
+ n_u4_4.7 = (4,7)
+ n_s3_4.6 = (4,6)
+ n_u2_4.5 = (4,5)
+
+;
+
+attach variables [ ar as at n_ar n_as n_at ] [
+ a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15
+];
+
+attach variables [ fr fs ft ] [
+ f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15
+];
+
+attach variables [ br bs bt ] [
+ b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15
+];
+
+# Various 32-bit pointers relative to PC. Any operands that are split across non-consecutive
+# bits are named foo_LL.LM_ML.MM, where LL is the least significant bits of the least
+# singificant operand half, LM the most significant bits of the least significant operand half, etc.
+
+urel_16.23: rel is u8_16.23 [ rel = inst_start + u8_16.23 + 4; ] { export *:4 rel; }
+
+srel_16.23: rel is s8_16.23 [ rel = inst_start + s8_16.23 + 4; ] { export *:4 rel; }
+
+srel_12.23: rel is s12_12.23 [ rel = inst_start + s12_12.23 + 4; ] { export *:4 rel; }
+
+srel_6.23: rel is s8_6.23 [ rel = inst_start + s8_6.23 + 4; ] { export *:4 rel; }
+
+urel_12.15_4.5: rel is n_u2_4.5 & n_u4_12.15 [
+ rel = inst_start + ((n_u2_4.5 << 4) | n_u4_12.15) + 4;
+] { export *:4 rel; }
+
+srel_6.23_sb2: rel is s8_6.23 [
+ rel = (inst_start & ~3) + ( s8_6.23 << 2 ) + 4;
+] { export *:4 rel; }
+
+srel_8.23_oex_sb2: rel is u16_8.23 [
+ rel = ((inst_start + 3) & ~3) + ((u16_8.23 | 0xffff0000) << 2);
+] { export *:4 rel; }
+
+# Immediates split across the instruction.
+u5_8.11_20: tmp is u1_20 & u4_8.11 [ tmp = (u1_20 << 4) | u4_8.11; ] { export *[const]:1 tmp; }
+u5_4.7_20: tmp is u1_20 & u4_4.7 [ tmp = (u1_20 << 4) | u4_4.7; ] { export *[const]:1 tmp; }
+u5_8.11_16: tmp is u1_16 & u4_8.11 [ tmp = (u1_16 << 4) | u4_8.11; ] { export *[const]:1 tmp; }
+u5_4.7_12: tmp is u1_12 & u4_4.7 [ tmp = (u1_12 << 4) | u4_4.7; ] { export *[const]:1 tmp; }
+u5_8.11_4: tmp is u1_4 & u4_8.11 [ tmp = (u1_4 << 4) | u4_8.11; ] { export *[const]:1 tmp; }
+
+# Signed 12-bit (extended to 16) immediate, used by MOVI.
+s16_16.23_8.11: tmp is s4_8.11 & u8_16.23 [
+ tmp = (s4_8.11 << 8) | u8_16.23;
+] { export *[const]:2 tmp; }
+
+# An “asymmetric” immediate from -32..95, used by MOVI.N.
+n_s8_12.15_4.6_asymm: tmp is n_s3_4.6 & n_s4_12.15 [
+ tmp = ((((n_s3_4.6 & 7) << 4) | (n_s4_12.15 & 15)) |
+ ((((n_s3_4.6 >> 2) & 1) & ((n_s3_4.6 >> 1) & 1)) << 7));
+] { export *[const]:1 tmp; }
+
+# Immediates shifted or with offset.
+s16_16.23_sb8: tmp is s8_16.23 [ tmp = s8_16.23 << 8; ] { export *[const]:2 tmp; }
+u15_12.23_sb3: tmp is u12_12.23 [ tmp = u12_12.23 << 3; ] { export *[const]:2 tmp; }
+u10_16.23_sb2: tmp is u8_16.23 [ tmp = u8_16.23 << 2; ] { export *[const]:2 tmp; }
+u9_16.23_sb1: tmp is u8_16.23 [ tmp = u8_16.23 << 1; ] { export *[const]:2 tmp; }
+u5_20.23_plus1: tmp is u4_20.23 [ tmp = u4_20.23 + 1; ] { export *[const]:1 tmp; }
+u8_20.23_sb4: tmp is u4_20.23 [ tmp = u4_20.23 << 4; ] { export *[const]:1 tmp; }
+u5_4.7_plus7: tmp is u4_4.7 [ tmp = u4_4.7 + 7; ] { export *[const]:1 tmp; }
+
+n_u6_12.15_sb2: tmp is n_u4_12.15 [ tmp = n_u4_12.15 << 2; ] { export *[const]:1 tmp; }
+
+# One-extended. FIXME: Verify this. Only used by [LS]32E (window extension), which aren’t yet
+# implemented.
+s5_12.15_oex: tmp is u4_12.15 [ tmp = (2 << u4_12.15) * -1; ] { export *[const]:2 tmp; }
+
+# Some 4-bit immediates with mappings that can’t be (easily) expressed in a single disassembly action.
+
+# n_u4_4.7 with 0 being -1, used by ADDI.N.
+n_s4_4.7_nozero: tmp is n_u4_4.7 = 0 [ tmp = -1; ] { export *[const]:4 tmp; }
+n_s4_4.7_nozero: tmp is n_u4_4.7 [ tmp = n_u4_4.7+0; ] { export *[const]:4 tmp; }
+
+# B4CONST(ar) (Branch Immediate) encodings, pg. 41 f.
+r_b4const: tmp is ar = 0 [ tmp = 0xffffffff; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 1 [ tmp = 0x1; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 2 [ tmp = 0x2; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 3 [ tmp = 0x3; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 4 [ tmp = 0x4; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 5 [ tmp = 0x5; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 6 [ tmp = 0x6; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 7 [ tmp = 0x7; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 8 [ tmp = 0x8; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 9 [ tmp = 0xa; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 10 [ tmp = 0xc; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 11 [ tmp = 0x10; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 12 [ tmp = 0x20; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 13 [ tmp = 0x40; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 14 [ tmp = 0x80; ] { export *[const]:4 tmp; }
+r_b4const: tmp is ar = 15 [ tmp = 0x100; ] { export *[const]:4 tmp; }
+
+# B4CONSTU(ar) (Branch Unsigned Immediate) encodings, pg. 42.
+r_b4constu: tmp is ar = 0 [ tmp = 0x8000; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 1 [ tmp = 0x1000; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 2 [ tmp = 0x2; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 3 [ tmp = 0x3; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 4 [ tmp = 0x4; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 5 [ tmp = 0x5; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 6 [ tmp = 0x6; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 7 [ tmp = 0x7; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 8 [ tmp = 0x8; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 9 [ tmp = 0xa; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 10 [ tmp = 0xc; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 11 [ tmp = 0x10; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 12 [ tmp = 0x20; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 13 [ tmp = 0x40; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 14 [ tmp = 0x80; ] { export *[const]:4 tmp; }
+r_b4constu: tmp is ar = 15 [ tmp = 0x100; ] { export *[const]:4 tmp; }
+
+define pcodeop breakpoint;
+define pcodeop dhi;
+define pcodeop dhu;
+define pcodeop dhwb;
+define pcodeop dhwbi;
+define pcodeop dii;
+define pcodeop diu;
+define pcodeop diwb;
+define pcodeop diwbi;
+define pcodeop dpfl;
+define pcodeop dpfr;
+define pcodeop dpfro;
+define pcodeop dpfw;
+define pcodeop dpfwo;
+define pcodeop dsync;
+define pcodeop esync;
+define pcodeop excw;
+define pcodeop extw;
+define pcodeop idtlb;
+define pcodeop ihi;
+define pcodeop ihu;
+define pcodeop iii;
+define pcodeop iitlb;
+define pcodeop iiu;
+define pcodeop ill;
+define pcodeop ipf;
+define pcodeop ipfl;
+define pcodeop isync;
+define pcodeop acquire;
+define pcodeop ldct;
+define pcodeop lict;
+define pcodeop licw;
+define pcodeop memw;
+define pcodeop nsa;
+define pcodeop pdtlb;
+define pcodeop pitlb;
+define pcodeop rdtlb0;
+define pcodeop rdtlb1;
+define pcodeop rer;
+define pcodeop rfdd;
+define pcodeop rfde;
+define pcodeop rfdo;
+define pcodeop rfe;
+define pcodeop rfi;
+define pcodeop rfme;
+define pcodeop rfue;
+define pcodeop rfwo;
+define pcodeop rfwu;
+define pcodeop ritlb0;
+define pcodeop ritlb1;
+define pcodeop rsil;
+define pcodeop rsr; # TODO: Map known special registers.
+define pcodeop rsync;
+define pcodeop rur;
+define pcodeop s32c1i;
+define pcodeop release;
+define pcodeop sdct;
+define pcodeop sict;
+define pcodeop sicw;
+define pcodeop simcall;
+define pcodeop syscall;
+define pcodeop waiti;
+define pcodeop wdtlb;
+define pcodeop wer;
+define pcodeop witlb;
+define pcodeop wsr; # TODO: Map known special registers.
+define pcodeop wur;
+define pcodeop xsr;
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.slaspec b/Ghidra/Processors/Xtensa/data/languages/xtensa.slaspec
new file mode 100644
index 0000000000..16a64f3f6e
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.slaspec
@@ -0,0 +1,3 @@
+@include "xtensa.sinc"
+@include "xtensaInstructions.sinc"
+@include "xtensaTodo.sinc"
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc
new file mode 100644
index 0000000000..e3e4766a66
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc
@@ -0,0 +1,1304 @@
+# ABS - Absolute Value (RRR), pg. 246.
+:abs ar, at is op2 = 0b0110 & op1 = 0 & ar & as = 0b0001 & at & op0 = 0 {
+ ar = at;
+ if (ar s> 0)
+ goto inst_next;
+ ar = -ar;
+}
+
+# ABS.S - Absolute Single Value (RRR), pg. 247.
+:abs.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0b0001 & op0 = 0b0000 {
+ fr = abs(fs);
+}
+
+# ADD - Add (RRR), pg. 248.
+:add ar, as, at is op2 = 0b1000 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = as + at;
+}
+
+# ADD.N - Narrow Add (RRRN), pg. 249.
+:add.n n_ar, n_as, n_at is n_ar & n_as & n_at & n_op0 = 0b1010 {
+ n_ar = n_as + n_at;
+}
+
+# ADD.S - Add Single (RRR), pg. 250.
+:add.s fr, fs, ft is op2 = 0 & op1 = 0b1010 & fr & fs & ft & op0 = 0 {
+ fr = fs f+ ft;
+}
+
+# ADDI - Add Immediate (RRI8), pg. 251.
+:addi at, as, s8_16.23 is s8_16.23 & ar = 0b1100 & as & at & op0 = 0b0010 {
+ at = as + sext(s8_16.23:1);
+}
+
+# ADDI.N - Narrow Add Immediate (RRRN), pg. 252.
+:addi.n n_ar, n_as, n_s4_4.7_nozero is n_ar & n_as & n_s4_4.7_nozero & n_op0 = 0b1011 {
+ n_ar = n_as + n_s4_4.7_nozero;
+}
+
+# ADDMI - Add Immediate with Shift by 8, pg. 253.
+:addmi at, as, s16_16.23_sb8 is s16_16.23_sb8 & ar = 0b1101 & as & at & op0 = 0b0010 {
+ at = as + sext(s16_16.23_sb8);
+}
+
+# ADDX2 - Add with Shift by 1, pg. 254.
+:addx2 ar, as, at is op2 = 0b1001 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = (as << 1) + at;
+}
+
+# ADDX4 - Add with Shift by 2, pg. 255.
+:addx4 ar, as, at is op2 = 0b1010 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = (as << 2) + at;
+}
+
+# ADDX8 - Add with Shift by 4, pg. 256.
+:addx8 ar, as, at is op2 = 0b1011 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = (as << 3) + at;
+}
+
+# ALL4 - All 4 Booleans True, pg. 257.
+:all4 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1001 & bs & bt & op0 = 0 {
+ local b = *[register]:1 &:4 bs+1;
+ local c = *[register]:1 &:4 bs+2;
+ local d = *[register]:1 &:4 bs+3;
+ bt = bs && b && c && d;
+}
+
+# ALL8 - All 8 Booleans True, pg. 258.
+:all8 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1011 & bs & bt & op0 = 0 {
+ local b = *[register]:1 &:4 bs+1;
+ local c = *[register]:1 &:4 bs+2;
+ local d = *[register]:1 &:4 bs+3;
+ local e = *[register]:1 &:4 bs+4;
+ local f = *[register]:1 &:4 bs+5;
+ local g = *[register]:1 &:4 bs+6;
+ local h = *[register]:1 &:4 bs+7;
+ bt = bs && b && c && d && e && f && g && h;
+}
+
+# AND - Bitwise Logical And, pg. 259.
+:and ar, as, at is op2 = 0b0001 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = as & at;
+}
+
+# ANDB - Boolean And, pg. 260.
+:andb br, bs, bt is op2 = 0 & op1 = 0b0010 & br & bs & bt & op0 = 0 {
+ br = bs && bt;
+}
+
+# ANDBC - Boolean And with Complement, pg. 261.
+:andbc br, bs, bt is op2 = 0b0001 & op1 = 0b0010 & br & bs & bt & op0 = 0 {
+ br = bs && !bt;
+}
+
+# ANY4 - Any 4 Booleans True, pg. 262.
+:any4 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1000 & bs & bt & op0 = 0 {
+ local b = *[register]:1 &:4 bs+1;
+ local c = *[register]:1 &:4 bs+2;
+ local d = *[register]:1 &:4 bs+3;
+ bt = bs || b || c || d;
+}
+
+# ANY8 - Any 8 Booleans True, pg. 263.
+:any8 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1010 & bs & bt & op0 = 0 {
+ local b = *[register]:1 &:4 bs+1;
+ local c = *[register]:1 &:4 bs+2;
+ local d = *[register]:1 &:4 bs+3;
+ local e = *[register]:1 &:4 bs+4;
+ local f = *[register]:1 &:4 bs+5;
+ local g = *[register]:1 &:4 bs+6;
+ local h = *[register]:1 &:4 bs+7;
+ bt = bs || b || c || d || e || f || g || h;
+}
+
+# BALL - Branch if All Bits Set, pg. 264.
+:ball srel_16.23, as, at is srel_16.23 & ar = 0b0100 & as & at & op0 = 0b0111 {
+ if ((~as & at) == 0)
+ goto srel_16.23;
+}
+
+# BANY - Branch if Any Bit Set, pg. 265.
+:bany srel_16.23, as, at, is srel_16.23 & ar = 0b1000 & as & at & op0 = 0b0111 {
+ if ((as & at) != 0)
+ goto srel_16.23;
+}
+
+macro extract_bit(val, bit, result) {
+ result = (val >> bit)&1;
+}
+
+# BBC - Branch if Bit Clear, pg. 266.
+:bbc as, at, srel_16.23 is srel_16.23 & ar = 0b0101 & as & at & op0 = 0b0111 {
+ local bval;
+ extract_bit(as, at[0,5], bval);
+ if (bval == 0)
+ goto srel_16.23;
+}
+
+# BBCI - Branch if Bit Clear immediate, pg. 267
+:bbci as, u5_4.7_12, srel_16.23 is srel_16.23 & u3_13.15 = 0b011 & as & u5_4.7_12 & op0 = 0b0111 {
+ local bval;
+ extract_bit(as, u5_4.7_12, bval);
+ if (bval == 0)
+ goto srel_16.23;
+}
+
+# BBS - Branch if Bit Set, pg. 269.
+:bbs as, at, srel_16.23 is srel_16.23 & ar = 0b1101 & as & at & op0 = 0b0111 {
+ local bval;
+ extract_bit(as, at[0,5], bval);
+ if (bval != 0)
+ goto srel_16.23;
+}
+
+# BBSI - Branch if Bit Set immediate, pg. 270.
+:bbsi as, u5_4.7_12, srel_16.23 is srel_16.23 & u3_13.15 = 0b111 & as & u5_4.7_12 & op0 = 0b0111 {
+ local bval;
+ extract_bit(as, u5_4.7_12, bval);
+ if (bval == 0)
+ goto srel_16.23;
+}
+
+# BEQ - Branch if Equal, pg. 272.
+:beq as, at, srel_16.23 is srel_16.23 & ar = 0b0001 & as & at & op0 = 0b0111 {
+ if (as == at)
+ goto srel_16.23;
+}
+
+# BEQI - Branch if Equal Immediate, pg. 273.
+:beqi as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0 & u2_4.5 = 0b10 & op0 = 0b0110 {
+ if (as == r_b4const)
+ goto srel_16.23;
+}
+
+# BEQZ - Branch if Equal Zero, pg. 274.
+:beqz as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0 & u2_4.5 = 0b01 & op0 = 0b0110 {
+ if (as == 0)
+ goto srel_12.23;
+}
+
+# BEQZ.N - Narrow Branch if Equal Zero, pg. 275.
+: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 {
+ if (n_as == 0)
+ goto urel_12.15_4.5;
+}
+
+# BF - Branch if False, pg. 276.
+:bf bs, srel_16.23 is srel_16.23 & ar = 0 & bs & at = 0b0111 & op0 = 0b0110 {
+ if (!bs)
+ goto srel_16.23;
+}
+
+# BGE - Branch if Greater Than or Equal, pg. 277.
+:bge as, at, srel_16.23 is srel_16.23 & ar = 0b1010 & as & at & op0 = 0b0111 {
+ if (as s>= at)
+ goto srel_16.23;
+}
+
+# BGEI - Branch if Greater Than or Equal Immediate, pg. 278.
+:bgei as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0b11 & u2_4.5 = 0b10 & op0 = 0b0110 {
+ if (as s>= r_b4const)
+ goto srel_16.23;
+}
+
+# BGEU - Branch if Greater Than or Equal Unsigned, pg. 279.
+:bgeu as, at, srel_16.23 is srel_16.23 & ar = 0b1011 & as & at & op0 = 0b0111 {
+ if (as >= at)
+ goto srel_16.23;
+}
+
+# BGEUI - Branch if Greater Than or Equal Unsigned Immediate, pg. 280.
+:bgeui as, r_b4constu, srel_16.23 is srel_16.23 & r_b4constu & as & u2_6.7 = 0b11 & u2_4.5 = 0b11 & op0 = 0b0110 {
+ if (as >= r_b4constu)
+ goto srel_16.23;
+}
+
+# BGEZ - Branch if Greater Than or Equal Zero, pg. 281.
+:bgez as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0b11 & u2_4.5 = 0b01 & op0 = 0b0110 {
+ if (as s>= 0)
+ goto srel_12.23;
+}
+
+# BLT - Branch if Less Than, pg. 282.
+:blt as, at, srel_16.23 is srel_16.23 & ar = 0b0010 & as & at & op0 = 0b0111 {
+ if (as s< at)
+ goto srel_16.23;
+}
+
+# BLTI - Branch if Less Than Immediate, pg. 283.
+:blti as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0b10 & u2_4.5 = 0b10 & op0 = 0b0110 {
+ if (as s< r_b4const)
+ goto srel_16.23;
+}
+
+# BLTU - Branch if Less Than Unsigned, pg. 284.
+:bltu as, at, srel_16.23 is srel_16.23 & ar = 0b0011 & as & at & op0 = 0b0111 {
+ if (as < at)
+ goto srel_16.23;
+}
+
+# BLTUI - Branch if Less Than Unsigned Immediate, pg. 285.
+:bltui as, r_b4constu, srel_16.23 is srel_16.23 & r_b4constu & as & u2_6.7 = 0b10 & u2_4.5 = 0b11 & op0 = 0b0110 {
+ if (as < r_b4constu)
+ goto srel_16.23;
+}
+
+# BLTZ - Branch if Less Than Zero, pg. 286.
+:bltz as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0b10 & u2_4.5 = 0b01 & op0 = 0b0110 {
+ if (as s< 0)
+ goto srel_12.23;
+}
+
+# BNALL - Branch if Not-All Bits Set, pg. 287.
+:bnall srel_16.23, as, at is srel_16.23 & ar = 0b1100 & as & at & op0 = 0b0111 {
+ if ((~as & at) != 0)
+ goto srel_16.23;
+}
+
+# BNE - Branch if Not Equal, pg. 288.
+:bne as, at, srel_16.23 is srel_16.23 & ar = 0b1001 & as & at & op0 = 0b0111 {
+ if (as != at)
+ goto srel_16.23;
+}
+
+# BNEI - Branch if Not EquaL Immediate, pg. 289.
+:bnei as, r_b4const, srel_16.23 is srel_16.23 & r_b4const & as & u2_6.7 = 0b01 & u2_4.5 = 0b10 & op0 = 0b0110 {
+ if (as != r_b4const)
+ goto srel_16.23;
+}
+
+# BNEZ - Branch if Not Equal Zero, pg. 290.
+:bnez as, srel_12.23 is srel_12.23 & as & u2_6.7 = 0b01 & u2_4.5 = 0b01 & op0 = 0b0110 {
+ if (as != 0)
+ goto srel_12.23;
+}
+
+# BNEZ.N - Narrow Branch if Not Equal Zero, pg. 291.
+: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 {
+ if (n_as != 0)
+ goto urel_12.15_4.5;
+}
+
+# BNONE - Branch if No Bit Set, pg. 292.
+:bnone srel_16.23, as, at, is srel_16.23 & ar = 0 & as & at & op0 = 0b0111 {
+ if ((as & at) == 0)
+ goto srel_16.23;
+}
+
+# BREAK - Breakpoint, pg. 293.
+:break u4_8.11, u4_4.7 is op2 = 0 & op1 = 0 & ar = 0b0100 & u4_8.11 & u4_4.7 & op0 = 0 {
+ breakpoint(0x001000:4, u4_8.11:1, u4_4.7:1);
+}
+
+# BREAK.N - Narrow Breakpoint, pg. 295.
+:break.n n_u4_8.11 is n_ar = 0b1111 & n_u4_8.11 & n_at = 0b0010 & n_op0 = 0b1101 {
+ breakpoint(0x010000:4, n_u4_8.11:1, 0:1);
+}
+
+# BT - Branch if True, pg. 296.
+:bt bs, srel_16.23 is srel_16.23 & ar = 0b0001 & bs & at = 0b0111 & op0 = 0b0110 {
+ if (bs)
+ goto srel_16.23;
+}
+
+# CALL0 - Non-windowed Call, pg. 297.
+:call0 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0 & op0 = 0b0101 {
+ a0 = inst_start + 3;
+ call srel_6.23_sb2;
+}
+
+# CALLX0 - Non-windowed Call Register, pg. 304.
+:callx0 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0 & op0 = 0 {
+ local dst = as;
+ a0 = inst_start + 3;
+ call [dst];
+}
+
+# CEIL.S - Ceiling Single to Fixed, pg. 311.
+:ceil.s ar, fs, u4_4.7 is op2 = 0b1011 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 {
+ local scale:4 = int2float(1:1 << u4_4.7:1);
+ ar = ceil(fs f* scale);
+}
+
+# CLAMPS - Signed Clamp, pg. 312.
+:clamps ar, as, u5_4.7_plus7 is op2 = 0b0011 & op1 = 0b0011 & ar & as & u5_4.7_plus7 & op0 = 0 {
+ # ar ← min(max(as, -2^{u5_4.7_plus7}), 2^{u5_4.7_plus7}-1)
+ local maxval:4 = (1 << u5_4.7_plus7) - 1;
+ local minval:4 = -(1 << u5_4.7_plus7);
+ if (as s< minval)
+ goto ;
+ if (as s> maxval)
+ goto ;
+
+ ar = as;
+ goto inst_next;
+
+
+ ar = minval;
+ goto inst_next;
+
+
+ ar = maxval;
+ # fallthrough inst_next
+}
+
+# DHI - Data Cache Hit Invalidate, pg. 313.
+:dhi as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0110 & op0 = 0b0010 {
+ dhi(as + zext(u10_16.23_sb2));
+}
+
+# DHU - Data Cache Hit Unlock, pg. 315.
+:dhu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 {
+ dhu(as + zext(u8_20.23_sb4));
+}
+
+# DHWB - Data Cache Hit Writeback, pg. 317.
+:dhwb as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0100 & op0 = 0b0010 {
+ dhwb(as + zext(u10_16.23_sb2));
+}
+
+# DHWBI - Data Cache Hit Writeback Invalidate, pg. 319.
+:dhwbi as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0101 & op0 = 0b0010 {
+ dhwbi(as + zext(u10_16.23_sb2));
+}
+
+# DII - Data Cache Index Invalidate, pg. 321.
+:dii as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0111 & op0 = 0b0010 {
+ dii(as + zext(u10_16.23_sb2));
+}
+
+# DIU - Data Cache Index Unlock, pg. 323.
+:diu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 {
+ diu(as + zext(u8_20.23_sb4));
+}
+
+# DIWB - Data Cache Index Write Back, pg. 325.
+:diwb as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0100 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 {
+ diwb(as + zext(u8_20.23_sb4));
+}
+
+# DIWBI - Data Cache Index Write Back Invalidate, pg. 327.
+:diwbi as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0101 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 {
+ diwbi(as + zext(u8_20.23_sb4));
+}
+
+# DPFL - Data Cache Prefetch and Lock, pg. 329.
+:dpfl as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 {
+ dpfl(as + zext(u8_20.23_sb4));
+}
+
+# DPFR - Data Cache Prefetch for Read, pg. 331.
+:dpfr as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0 & op0 = 0b0010 {
+ dpfr(as + zext(u10_16.23_sb2));
+}
+
+# DPFRO - Data Cache Prefetch for Read Once, pg. 333.
+:dpfro as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0010 & op0 = 0b0010 {
+ dpfro(as + zext(u10_16.23_sb2));
+}
+
+# DPFW - Data Cache Prefetch for Write, pg. 335.
+:dpfw as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0001 & op0 = 0b0010 {
+ dpfw(as + zext(u10_16.23_sb2));
+}
+
+# DPFWO - Data Cache Prefetch for Write Once, pg. 337.
+:dpfwo as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b0011 & op0 = 0b0010 {
+ dpfwo(as + zext(u10_16.23_sb2));
+}
+
+# DSYNC - Load/Store Synchronize, pg. 339.
+:dsync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0011 & op0 = 0 {
+ dsync();
+}
+
+# ESYNC - Execute Synchronize, pg. 342.
+:esync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0010 & op0 = 0 {
+ esync();
+}
+
+# EXCW - Exception Wait, pg. 343.
+:excw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1000 & op0 = 0 {
+ excw();
+}
+
+# EXTUI - Extract Unsigned Immediate, pg. 344.
+: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 {
+ local shifted:4 = at >> u5_8.11_16;
+ local mask:4 = (1:4 << (u5_20.23_plus1))-1;
+ ar = shifted & mask;
+}
+
+# EXTW - External Wait, pg. 345.
+:extw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1101 & op0 = 0 {
+ extw();
+}
+
+# FLOAT.S - Convert Fixed to Single, pg. 346.
+:float.s fr, as, u4_4.7 is op2 = 0b1100 & op1 = 0b1010 & fr & as & u4_4.7 & op0 = 0 {
+ local f = int2float(as);
+ local d = int2float(1:2 << u4_4.7:2);
+ fr = d f/ f;
+}
+
+# FLOOR.S - Floor Single to Fixed, pg. 347.
+:floor.s ar, fs, u4_4.7 is op2 = 0b1010 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 {
+ local scale:4 = int2float(1:2 << u4_4.7:2);
+ ar = floor(fs f* scale);
+}
+
+# IDTLB - Invalidate Data TLB Entry, pg. 348.
+:idtlb as is op2 = 0b0101 & op1 = 0 & ar = 0b1100 & as & at = 0 & op0 = 0 {
+ idtlb();
+}
+
+# IHI - Instruction Cache Hit Invalidate, pg. 349.
+:ihi as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b1110 & op0 = 0b0010 {
+ ihi(as + zext(u10_16.23_sb2));
+}
+
+# IHU - Instruction Cache Hit Unlock, pg. 351.
+:ihu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 {
+ ihu(as + zext(u8_20.23_sb4));
+}
+
+# III - Instruction Cache Index Invalidate, pg. 353.
+:iii as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b1111 & op0 = 0b0010 {
+ iii(as + zext(u10_16.23_sb2));
+}
+
+# IITLB - Invalidate Instruction TLB Entry, pg. 355.
+:iitlb as is op2 = 0b0101 & op1 = 0 & ar = 0b0100 & as & at = 0 & op0 = 0 {
+ iitlb(as);
+}
+
+# IIU - Instruction Cache Index Unlock, pg. 356.
+:iiu as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 {
+ iiu(as + zext(u8_20.23_sb4));
+}
+
+# ILL - Illegal Instruction, pg. 358.
+:ill is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & at = 0 & op0 = 0 {
+ ill();
+ goto inst_start;
+}
+
+# ILL.N - Narrow Illegal Instruction, pg. 359.
+:ill.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0110 & n_op0 = 0b1101 {
+ ill();
+ goto inst_start;
+}
+
+# IPF - Instruction Cache Prefetch, pg. 360.
+:ipf as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0111 & as & at = 0b1100 & op0 = 0b0010 {
+ ipf(as + zext(u10_16.23_sb2));
+}
+
+# IPFL - Instruction Cache Prefetch and Lock, pg. 362.
+:ipfl as, u8_20.23_sb4 is u8_20.23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 {
+ ipfl(as + zext(u8_20.23_sb4));
+}
+
+# ISYNC - Instruction Fetch Synchronize, pg. 364.
+:isync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0 & op0 = 0 {
+ isync();
+}
+
+# J - Unconditional Jump, pg. 366.
+:j srel_6.23 is srel_6.23 & u2_4.5 = 0 & op0 = 0b0110 {
+ goto srel_6.23;
+}
+
+# J.L is a macro.
+
+# RET (JX A0) - Non-Windowed Return, pg. 478.
+:ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6.7 = 0b10 & u2_4.5 = 0b10 & op0 = 0 {
+ return [a0];
+}
+
+# The manual suggests that RET is equivalent to JX A0, yet RET has bit 5 unset, JX doesn’t.
+:ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6.7 = 0b10 & u2_4.5 = 0b00 & op0 = 0 {
+ return [a0];
+}
+
+# JX - Uncoditional Jump Register, pg. 368.
+:jx as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b10 & u2_4.5 = 0b10 & op0 = 0 {
+ goto [as];
+}
+
+# L8UI - Load 8-bit Unsigned, pg. 369.
+:l8ui at, as, u8_16.23 is u8_16.23 & ar = 0 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u8_16.23:1);
+ at = zext(*:1 addr);
+}
+
+# L16SI - Load 16-bit Signed, pg. 370.
+:l16si at, as, u9_16.23_sb1 is u9_16.23_sb1 & ar = 0b1001 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u9_16.23_sb1);
+ at = sext(*:2 addr);
+}
+
+# L16UI - Load 16-bit Unsigned, pg. 372.
+:l16ui at, as, u9_16.23_sb1 is u9_16.23_sb1 & ar = 0b001 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u9_16.23_sb1);
+ at = zext(*:2 addr);
+}
+
+# L32AI - Load 32-bit Acquire, pg. 374.
+:l32ai at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1011 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ at = *:4 addr;
+ acquire(addr);
+}
+
+# L32I - Load 32-bit, pg. 378.
+:l32i at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0010 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ at = *:4 addr;
+}
+
+# L32I.N - Narrow Load 32-bit, pg. 380.
+:l32i.n n_at, n_as, n_u6_12.15_sb2 is n_u6_12.15_sb2 & n_as & n_at & n_op0 = 0b1000 {
+ local addr:4 = n_as + zext(n_u6_12.15_sb2);
+ n_at = *:4 addr;
+}
+
+# L32R - Load 32-bit PC-relative, pg. 382.
+:l32r at, srel_8.23_oex_sb2 is srel_8.23_oex_sb2 & at & op0 = 0b0001 {
+ at = srel_8.23_oex_sb2;
+}
+
+# LDCT - Load Data Cache Tag, pg. 384.
+:ldct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1000 & as & at & op0 = 0 {
+ at = ldct(as);
+}
+
+# LICT - Load Instruction Cache Tag, pg. 388.
+:lict at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0 & as & at & op0 = 0 {
+ at = lict(as);
+}
+
+# LICW - Load Instruction Cache Word, pg. 390.
+:licw at, as is op2 = 0b1111 & op1 = 0b0010 & ar = 0 & as & at & op0 = 0 {
+ at = licw(as);
+}
+
+# LSI - Load Single Immediate, pg. 398.
+:lsi ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0 & as & ft & op0 = 0b0011 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ ft = *:4 addr;
+}
+
+# LSIU - Load Single Immediate with Update, pg. 400.
+:lsiu ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1000 & as & ft & op0 = 0b0011 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ ft = *:4 addr;
+ as = addr;
+}
+
+# LSX - Load Single Indexed, pg. 402.
+:lsx fr, as, at is op2 = 0 & op1 = 0b1000 & fr & as & at & op0 = 0 {
+ local addr:4 = as+at;
+ fr = *:4 addr;
+}
+
+# LSXU - Load Single Indexed with Update, pg. 404.
+:lsxu fr, as, at is op2 = 0b0001 & op1 = 0b1000 & fr & as & at & op0 = 0 {
+ local addr:4 = as+at;
+ fr = *:4 addr;
+ as = addr;
+}
+
+# MADD.S - Multiply and Add Single, pg. 406.
+:madd.s fr, fs, ft is op2 = 0b0100 & op1 = 0b1010 & fr & fs & ft & op0 = 0 {
+ fr = fr f+ (fs f* ft);
+}
+
+# MAX - Maximum Value, pg. 407.
+:max ar, as, at is op2 = 0b0101 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (as s> at)
+ goto ;
+ ar = at;
+ goto inst_next;
+
+ ar = as;
+}
+
+# MAXU - Maximum Value Unsigned, pg. 408.
+:maxu ar, as, at is op2 = 0b0111 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (as > at)
+ goto ;
+ ar = at;
+ goto inst_next;
+
+ ar = as;
+}
+
+# MEMW - Memory Wait, pg. 409.
+:memw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1100 & op0 = 0 {
+ memw();
+}
+
+# MIN - Minimum Value, pg. 410.
+:min ar, as, at is op2 = 0b0100 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (as s< at)
+ goto ;
+ ar = at;
+ goto inst_next;
+
+ ar = as;
+}
+
+# MINU - Minimum Value Unsigned, pg. 411.
+:minu ar, as, at is op2 = 0b0110 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (as < at)
+ goto ;
+ ar = at;
+ goto inst_next;
+
+ ar = as;
+}
+
+# MOV.N - Narrow Move, pg. 413.
+:mov.n n_at, n_as is n_ar = 0 & n_as & n_at & n_op0 = 0b1101 {
+ n_at = n_as;
+}
+
+# MOV.S - Move Single, pg. 414.
+:mov.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0 & op0 = 0 {
+ fr = fs;
+}
+
+# MOVEQZ - Move if Equal to Zero, pg. 415.
+:moveqz ar, as, at is op2 = 0b1000 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (at != 0)
+ goto inst_next;
+ ar = as;
+}
+
+# MOVEQZ.S - Move Single if Equal to Zero, pg. 416.
+:moveqz.s fr, fs, at is op2 = 0b1000 & op1 = 0b1011 & fr & fs & at & op0 = 0 {
+ if (at != 0)
+ goto inst_next;
+ fr = fs;
+}
+
+# MOVF - Move if False, pg. 417.
+:movf ar, as, bt is op2 = 0b1100 & op1 = 0b0011 & ar & as & bt & op0 = 0 {
+ if (bt)
+ goto inst_next;
+ ar = as;
+}
+
+# MOVF.S - Move Single if False, pg. 418.
+:movf.s fr, fs, bt is op2 = 0b1100 & op1 = 0b1011 & fr & fs & bt & op0 = 0 {
+ if (bt)
+ goto inst_next;
+ fr = fs;
+}
+
+# MOVGEZ - Move if Greater Than or Equal to Zero, pg. 419.
+:movgez ar, as, at is op2 = 0b1011 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (at s< 0)
+ goto inst_next;
+ ar = as;
+}
+
+# MOVGEZ.S - Move Single if Greater Than or Equal to Zero, pg. 420.
+:movgez.s fr, fs, at is op2 = 0b1011 & op1 = 0b1011 & fr & fs & at & op0 = 0 {
+ if (at s< 0)
+ goto inst_next;
+ fr = fs;
+}
+
+# MOVI - Move Immediate, pg. 421.
+:movi at, s16_16.23_8.11 is s16_16.23_8.11 & ar = 0b1010 & at & op0 = 0b0010 {
+ local val:4 = sext(s16_16.23_8.11);
+ at = val;
+}
+
+
+# MOVI.N - Narrow Move Immediate, pg. 422.
+: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 {
+ local val:4 = sext(n_s8_12.15_4.6_asymm);
+ n_as = val;
+}
+
+# MOVLTZ - Move if Less Than Zero, pg. 423.
+:movltz ar, as, at is op2 = 0b1010 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (at s>= 0)
+ goto inst_next;
+ ar = as;
+}
+
+# MOVLTZ.S - Move Single if Less Than Zero, pg. 424.
+:movltz.s fr, fs, at is op2 = 0b1010 & op1 = 0b1011 & fr & fs & at & op0 = 0 {
+ if (at s>= 0)
+ goto inst_next;
+ fr = fs;
+}
+
+# MOVNEZ - Move if Not Equal to Zero, pg. 425.
+:movnez ar, as, at is op2 = 0b1001 & op1 = 0b0011 & ar & as & at & op0 = 0 {
+ if (at == 0)
+ goto inst_next;
+ ar = as;
+}
+
+# MOVNEZ.S - Move Single if Not Equal to Zero, pg. 426.
+:movnez.s fr, fs, at is op2 = 0b1001 & op1 = 0b1011 & fr & fs & at & op0 = 0 {
+ if (at == 0)
+ goto inst_next;
+ fr = fs;
+}
+
+# MOVT - Move if True, pg. 428.
+:movt ar, as, bt is op2 = 0b1101 & op1 = 0b0011 & ar & as & bt & op0 = 0 {
+ if (!bt)
+ goto inst_next;
+ ar = as;
+}
+
+# MOVT.S - Move Single if True, pg. 429.
+:movt.s fr, fs, bt is op2 = 0b1101 & op1 = 0b1011 & fr & fs & bt & op0 = 0 {
+ if (!bt)
+ goto inst_next;
+ fr = fs;
+}
+
+# MSUB.S - Multiply and Subtract Single, pg. 430.
+:msub.s fr, fs, ft is op2 = 0b0101 & op1 = 0b1010 & fr & fs & ft & op0 = 0 {
+ fr = fr f- (fs f* ft);
+}
+
+# MUL.S - Multiply Single, pg. 435.
+:mul.s fr, fs, ft is op2 = 0b0010 & op1 = 0b1010 & fr & fs & ft & op0 = 0 {
+ fr = fs f* ft;
+}
+
+# MUL16S - Multiply 16-bit Signed, pg. 436.
+:mul16s ar, as, at is op2 = 0b1101 & op1 = 0b0001 & ar & as & at & op0 = 0 {
+ ar = sext(as:2) * sext(at:2);
+}
+
+# MUL16U - Multiply 16-bit Unsigned, pg. 437.
+:mul16u ar, as, at is op2 = 0b1100 & op1 = 0b0001 & ar & as & at & op0 = 0 {
+ ar = zext(as:2) * zext(at:2);
+}
+
+# MULL - Multiply Low, pg. 450.
+:mull ar, as, at is op2 = 0b1000 & op1 = 0b0010 & ar & as & at & op0 = 0 {
+ ar = as * at;
+}
+
+# MULSH - Multiply Signed High, pg. 455.
+:mulsh ar, as, at is op2 = 0b1011 & op1 = 0b0010 & ar & as & at & op0 = 0 {
+ local s64:8 = sext(as);
+ local t64:8 = sext(at);
+ local p:8 = (s64 * t64);
+ ar = p(4);
+}
+
+# MULUH - Multiply Unsigned High, pg. 456.
+:muluh ar, as, at is op2 = 0b1010 & op1 = 0b0010 & ar & as & at & op0 = 0 {
+ local s64:8 = zext(as);
+ local t64:8 = zext(at);
+ local p:8 = (s64 * t64);
+ ar = p(4);
+}
+
+# NEG - Negate, pg. 457.
+:neg ar, at is op2 = 0b0110 & op1 = 0 & ar & as = 0 & at & op0 = 0 {
+ ar = -at;
+}
+
+# NEG.S - Negate Single, pg. 458.
+:neg.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0b0110 & op0 = 0 {
+ fr = f- fs;
+}
+
+# NOP - No Operation, pg. 459.
+:nop is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1111 & op0 = 0 { }
+
+# NOP.N - Narrow No Operation, pg. 460.
+:nop.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0011 & n_op0 = 0b1101 { }
+
+# NSA - Normalization Shift Amount, pg. 461.
+:nsa at, as is op2 = 0b0100 & op1 = 0 & ar = 0b1110 & as & at & op0 = 0 {
+ # https://stackoverflow.com/questions/54772520/normalizing-a-two-complement-number
+ at = nsa(as);
+}
+
+# NSAU - Normalization Shift Amount Unsigned, pg. 462. (Count leading zeros)
+:nsau at, as is op2 = 0b0100 & op1 = 0 & ar = 0b1111 & as & at & op0 = 0 {
+ local z4 = as[16,16] == 0;
+
+ local t3 = zext(z4)*as[0,16] + zext(!z4)*as[16,16];
+ local z3 = t3[8,8] == 0;
+
+ local t2 = (z3)*t3[0,8] + (!z3)*t3[8,8];
+ local z2 = t2[4,4] == 0;
+
+ local t1 = (z2)*t2[0,4] + (!z2)*t2[4,4];
+ local z1 = t1[2,2] == 0;
+
+ local z0 = (z1)*(t1[1,1] == 0) + (!z1)*(t1[3,1] == 0);
+ local all0 = as == 0;
+
+ at = zext((all0)*32 + (!all0)*(z4<<4 | z3<<3 | z2<<2 | z1<<1 | z0));
+}
+
+# OEQ.S - Compare Single Equal, pg. 463.
+:oeq.s br, fs, ft is op2 = 0b0010 & op1 = 0b1011 & br & fs & ft & op0 = 0 {
+ br = !nan(fs) && !nan(ft) && fs f== ft;
+}
+
+# OLE.S - Compare Single Ordered and Less Than or Equal, pg. 464
+:ole.s br, fs, ft is op2 = 0b0110 & op1 = 0b1011 & br & fs & ft & op0 = 0 {
+ br = !nan(fs) && !nan(ft) && fs f<= ft;
+}
+
+# OLT.S - Compare Single Ordered and Less Than, pg. 465.
+:olt.s br, fs, ft is op2 = 0b0100 & op1 = 0b1011 & br & fs & ft & op0 = 0 {
+ br = !nan(fs) && !nan(ft) && fs f< ft;
+}
+
+# MOV - Move, pg. 412. Special case of OR as, at, at.
+:mov ar, as is op2 = 0b0010 & op1 = 0 & ar & as & as = at & op0 = 0 {
+ ar = as;
+}
+
+# OR - Bitwise Logical Or, pg. 466.
+:or ar, as, at is op2 = 0b0010 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = as | at;
+}
+
+# ORB - Boolean Or, pg. 467.
+:orb br, bs, bt is op2 = 0b0010 & op1 = 0b0010 & br & bs & bt & op0 = 0 {
+ br = bs || bt;
+}
+
+# ORBC - Boolean Or with Complement, pg. 468.
+:orbc br, bs, bt is op2 = 0b0011 & op1 = 0b0010 & br & bs & bt & op0 = 0 {
+ br = bs || !bt;
+}
+
+# PDTLB - Probe Data TLB, pg. 469.
+:pdtlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1101 & as & at & op0 = 0 {
+ at = pdtlb(as);
+}
+
+# PITLB - Probe Instruction TLB, pg. 470.
+:pitlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0101 & as & at & op0 = 0 {
+ at = pitlb(as);
+}
+
+# QUOS - Quotient Signed, pg. 471.
+:quos ar, as, at is op2 = 0b1101 & op1 = 0b0010 & ar & as & at & op0 = 0 {
+ ar = as s/ at;
+}
+
+# QUOU - Quotient Unsigned, pg. 472.
+:quou ar, as, at is op2 = 0b1100 & op1 = 0b0010 & ar & as & at & op0 = 0 {
+ ar = as / at;
+}
+
+# RDTLB0 - Read Data TLB Virtual Entry, pg. 473.
+:rdtlb0 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1011 & as & at & op0 = 0 {
+ at = rdtlb0(as);
+}
+
+# RDTLB1 - Read Data TLB Entry Translation, pg. 474.
+:rdtlb1 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1111 & as & at & op0 = 0 {
+ at = rdtlb1(as);
+}
+
+# REMS - Remainder Signed, pg. 475.
+:rems ar, as, at, is op2 = 0b1111 & op1 = 0b0010 & ar & as & at & op0 = 0 {
+ ar = as s% at;
+}
+
+# REMU - Remainder Unsigned, pg. 476.
+:remu ar, as, at, is op2 = 0b1110 & op1 = 0b0010 & ar & as & at & op0 = 0 {
+ ar = as % at;
+}
+
+# RER - Read External Register, pg. 477.
+:rer as, at is op2 = 0b0100 & op1 = 0 & ar = 0b0110 & as & at & op0 = 0 {
+ as = rer(at);
+}
+
+# RET.N - Narrow Non-Windowed Return, pg. 479.
+:ret.n is n_ar = 0b1111 & n_as = 0 & n_at = 0 & n_op0 = 0b1101 {
+ return [a0];
+}
+
+# RFDD - Return from Debug and Dispatch, pg. 484.
+:rfdd is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1110 & (as = 0b0000 | as = 0b0001) & at = 0b0001 & op0 = 0 {
+ rfdd();
+}
+
+# RFDE _ Return From Double Exception, pg. 485.
+:rfde is op2 = 0 & op1 = 0 & ar = 0b0011 & as =0b0010 & at = 0 & op0 = 0 {
+ rfde();
+}
+
+# RFDO - Return from Debug Operation, pg. 486.
+:rfdo is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1110 & as = 0 & at = 0 & op0 = 0 {
+ rfdo();
+}
+
+# RFE - Return From Exception, pg. 487.
+:rfe is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0 & at = 0 & op0 = 0 {
+ rfe();
+}
+
+# RFI - Return from High-Priority Interrupt, pg. 488.
+:rfi u4_8.11 is op2 = 0 & op1 = 0 & ar = 0b0011 & u4_8.11 & at = 0b0001 & op0 = 0 {
+ rfi(u4_8.11:1);
+}
+
+# RFME - Return from Memory Error, pg. 489.
+:rfme is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0 & at = 0b0010 & op0 = 0 {
+ rfme();
+}
+
+# RFR - Move FR to AR, pg. 490.
+:rfr ar, fs is op2 = 0b1111 & op1 = 0b1010 & ar & fs & at = 0b0100 & op0 = 0 {
+ ar = fs;
+}
+
+# RFUE - Return from User-Mode Exception, pg. 491.
+:rfue is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0001 & at = 0 & op0 = 0 {
+ rfue();
+}
+
+# RFWO - Return from Window Overflow, pg. 492.
+:rfwo is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0100 & at = 0 & op0 = 0 {
+ rfwo();
+}
+
+# RFWU - Return from Window Underflow, pg. 493.
+:rfwu is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0101 & at = 0 & op0 = 0 {
+ rfwu();
+}
+
+# RITLB0 - Read Instruction TLB Virtual Entry, pg. 494.
+:ritlb0 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0011 & as & at & op0 = 0 {
+ at = ritlb0(as);
+}
+
+# RITLB1 - Read Instruction TLB Entry Translation, pg. 495.
+:ritlb1 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0111 & as & at & op0 = 0 {
+ at = ritlb1(as);
+}
+
+# ROUND.S - Round Single to Fixed, pg. 497.
+:round.s ar, fs, u4_4.7 is op2 = 0b1000 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 {
+ local scale:4 = int2float(1:2 << u4_4.7:2);
+ ar = round(fs f* scale);
+}
+
+# RSIL - Read and Set Interrupt Level, pg. 498.
+:rsil at, u4_8.11 is op2 = 0 & op1 = 0 & ar = 0b0110 & u4_8.11 & at & op0 = 0 {
+ at = rsil(u4_8.11:1);
+}
+
+# RSR - Read Special Register, pg. 500.
+:rsr at, u8_8.15 is op0 = 0 & op1 = 0b0011 & u8_8.15 & at & op0 = 0 {
+ at = rsr(u8_8.15:1);
+}
+
+# RSYNC - Register Read Synchronize, pg. 502.
+:rsync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0001 & op0 = 0 {
+ rsync();
+}
+
+# RUR - Read User Register, pg. 503.
+:rur ar, u8_4.11 is op2 = 0b1110 & op1 = 0b0011 & ar & u8_4.11 & op0 = 0 {
+ ar = rur(u8_4.11:1);
+}
+
+# S8I - Store 8-bit, pg. 504.
+:s8i at, as, u8_16.23 is u8_16.23 & ar = 0b0100 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u8_16.23:1);
+ *:1 addr = at:1;
+}
+
+# S16I - Store 16-bit, pg. 505.
+:s16i at, as, u9_16.23_sb1 is u9_16.23_sb1 & ar = 0b0101 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u9_16.23_sb1);
+ *:2 addr = at:2;
+}
+
+# S32C1I - Store 32-bit Compare Conditional, pg. 506
+:s32c1i at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1110 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ at = s32c1i(addr);
+}
+
+# S32I - Store 32-bit, pg. 510.
+:s32i at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0110 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ *:4 addr = at;
+}
+
+# S32I.N - Narrow Store 32-bit, pg. 512.
+:s32i.n n_at, n_as, n_u6_12.15_sb2 is n_u6_12.15_sb2 & n_as & n_at & n_op0 = 0b1001 {
+ local addr:4 = n_as + zext(n_u6_12.15_sb2);
+ *:4 addr = n_at;
+}
+
+# S32RI - Store 32-bit Release, pg. 514.
+:s32ri at, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1111 & as & at & op0 = 0b0010 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ *:4 addr = at;
+ release(addr);
+}
+
+# SDCT - Store Data Cache Tag, pg. 516.
+:sdct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1001 & as & at & op0 = 0 {
+ sdct(as, at);
+}
+
+# SEXT - Sign Extend, pg. 518.
+:sext ar, as, u5_4.7_plus7 is op2 = 0b0010 & op1 = 0b0011 & ar & as & u5_4.7_plus7 & op0 = 0 {
+ local shift:1 = 31:1 - u5_4.7_plus7;
+ local tmp:4 = as << shift;
+ ar = tmp s>> shift;
+}
+
+# SICT - Store Instruction Cache Tag, pg. 519.
+:sict at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b0001 & as & at & op0 = 0 {
+ sict(as, at);
+}
+
+# SICW - Store Instruction Cache word, pg. 521.
+:sicw at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b0011 & as & at & op0 = 0 {
+ sicw(as, at);
+}
+
+# SIMCALL - Simulator Call, pg. 523.
+:simcall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0b0001 & at = 0 & op0 = 0 {
+ simcall();
+}
+
+# SLL - Shift Left Logical, pg. 524.
+:sll ar, as is op2 = 0b1010 & op1 = 0b0001 & ar & as & at = 0 & op0 = 0 {
+ local sa:1 = 32 - sar;
+ ar = as << sa;
+}
+
+# SLLI - Shift Left Logical Immediate, pg. 525.
+:slli ar, as, u5_4.7_20 is u3_21.23 = 0 & u5_4.7_20 & op1 = 0b0001 & ar & as & op0 = 0 {
+ local sa:1 = 32 - u5_4.7_20;
+ ar = as << sa;
+}
+
+# SRA - Shift Right Arithmetic, pg. 526.
+:sra ar, at is op2 = 0b1011 & op1 = 0b0001 & ar & as = 0 & at & op0 = 0 {
+ ar = at s>> sar;
+}
+
+# SRAI - Shift Right Arithmetic Immediate, pg. 527.
+:srai ar, at, u5_8.11_20 is u3_21.23 = 0b001 & u5_8.11_20 & op1 = 0b0001 & ar & at & op0 = 0 {
+ ar = at s>> u5_8.11_20;
+}
+
+# SRC - Shift Right Combined, pg. 528.
+:src ar, as, at is op2 = 0b1000 & op1 = 0b0001 & ar & as & at & op0 = 0 {
+ local s64:8 = zext(as);
+ local t64:8 = zext(at);
+ local combined:8 = (s64 << 32) | t64;
+ local shifted:8 = combined >> sar;
+ ar = shifted:4;
+}
+
+# SRL - Shift Right Logical, pg. 529.
+:srl ar, at is op2 = 0b1001 & op1 = 0b0001 & ar & as = 0 & at & op0 = 0 {
+ ar = at >> sar;
+}
+
+# SRLI - Shift Right Logical Immediate, pg. 530.
+:srli ar, at, u4_8.11 is op2 = 0b0100 & op1 = 0b0001 & ar & u4_8.11 & at & op0 = 0 {
+ ar = at >> u4_8.11;
+}
+
+# SSA8B - Set Shift Amount for BE Byte Shift, pg. 531.
+:ssa8b as is op2 = 0b0100 & op1 = 0 & ar = 0b0011 & as & at = 0 & op0 = 0 {
+ local lsa:4 = (as&3)*8;
+ sar = 32 - lsa:1;
+}
+
+# SSA8L - Set Shift Amount for LE Byte Shift, pg. 532.
+:ssa8l as is op2 = 0b0100 & op1 = 0 & ar = 0b0010 & as & at = 0 & op0 = 0 {
+ local rsa:4 = (as&3)*8;
+ sar = rsa:1;
+}
+
+# SSAI - Set Shift Amount Immediate, pg. 533.
+:ssai u5_8.11_4 is op2 = 0b0100 & op1 = 0 & ar = 0b0100 & u5_8.11_4 & u3_5.7 = 0 & op0 = 0 {
+ sar = u5_8.11_4:1;
+}
+
+# SSI - Store Single Immediate, pg. 534.
+:ssi ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b0100 & as & ft & op0 = 0b0011 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ *:4 addr = ft;
+}
+
+# SSIU - Store Single Immediate with Update, pg. 536.
+:ssiu ft, as, u10_16.23_sb2 is u10_16.23_sb2 & ar = 0b1100 & as & ft & op0 = 0b0011 {
+ local addr:4 = as + zext(u10_16.23_sb2);
+ *:4 addr = ft;
+ as = addr;
+}
+
+# SSL - Set Shift Amount for Left Shift, pg. 538.
+:ssl as is op2 = 0b0100 & op1 = 0 & ar = 0b0001 & as & at = 0 & op0 = 0 {
+ sar = 32 - (as:1 & 0x1f);
+}
+
+# SSR - Set Shift Amount for Right Shift, pg. 539.
+:ssr as is op2 = 0b0100 & op1 = 0 & ar = 0 & as & at = 0 & op0 = 0 {
+ sar = (as:1 & 0x1f);
+}
+
+# SSX - Store Singe Indexed, pg. 540.
+:ssx fr, as, at is op2 = 0b0100 & op1 = 0b1000 & fr & as & at & op0 = 0 {
+ local addr:4 = as+at;
+ *:4 addr = fr;
+}
+
+# SSXU - Store Singe Indexed with Update, pg. 541.
+:ssxu fr, as, at is op2 = 0b0101 & op1 = 0b1000 & fr & as & at & op0 = 0 {
+ local addr:4 = as+at;
+ *:4 addr = fr;
+ as = addr;
+}
+
+# SUB - Subtract, pg. 542.
+:sub ar, as, at is op2 = 0b1100 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = as - at;
+}
+
+# SUB.S - Subtract Single, pg. 543.
+:sub.s fr, fs, ft is op2 = 0b0001 & op1 = 0b1010 & fr & fs & ft & op0 = 0 {
+ fr = fs f- ft;
+}
+
+# SUBX2 - Subtract with Shift by 1, pg. 544.
+:subx2 ar, as, at is op2 = 0b1101 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = (as << 1) - at;
+}
+
+# SUBX4 - Subtract with Shift by 2, pg. 545.
+:subx4 ar, as, at is op2 = 0b1110 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = (as << 2) - at;
+}
+
+# SUBX8 - Subtract with Shift by 3, pg. 546.
+:subx8 ar, as, at is op2 = 0b1111 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = (as << 3) - at;
+}
+
+# SYSCALL - System Call, pg. 547.
+:syscall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0 & at = 0 & op0 = 0 {
+ syscall();
+}
+
+# TRUNC.S - Truncate Single to Fixed, pg. 548
+:trunc.s ar, fs, u4_4.7 is op2 = 0b1001 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 {
+ local scale:4 = int2float(1:2 << u4_4.7:2);
+ ar = trunc(fs f* scale);
+}
+
+# UEQ.S - Compare Single Unordered or Equal, pg. 549.
+:ueq.s br, fs, ft is op2 = 0b0011 & op1 = 0b1011 & br & fs & ft & op0 = 0 {
+ br = nan(fs) || nan(ft) || fs f== ft;
+}
+
+# UFLOAT.S - Convert Unsigned Fixed to Single, pg. 550.
+:ufloat.s fr, as, u4_4.7 is op2 = 0b1101 & op1 = 0b1010 & fr & as & u4_4.7 & op0 = 0 {
+ local tmp:8 = zext(as);
+ local f = int2float(tmp);
+ local d = int2float(1:2 << u4_4.7:2);
+ fr = d f/ f;
+}
+
+# ULE.S - Compare Single Unordered or Less Than or Equal, pg. 551.
+:ule.s br, fs, ft is op2 = 0b0111 & op1 = 0b1011 & br & fs & ft & op0 = 0 {
+ br = nan(fs) || nan(ft) || fs f<= ft;
+}
+
+# ULT.S - Compare Single Unordered or Less Than, pg. 552.
+:ult.s br, fs, ft is op2 = 0b0101 & op1 = 0b1011 & br & fs & ft & op0 = 0 {
+ br = nan(fs) || nan(ft) || fs f< ft;
+}
+
+# FIXME: UMUL.AA*
+
+# UN.S - Compare Single Unordered, pg. 554.
+:un.s br, fs, ft is op2 = 0b0001 & op1 = 0b1011 & br & fs & ft & op0 = 0 {
+ br = nan(fs) || nan(ft);
+}
+
+# UTRUNC.S - Truncate Single to Fixed Unsigned, pg. 555.
+:utrunc.s ar, fs, u4_4.7 is op2 = 0b1110 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 {
+ local scale:4 = int2float(1:2 << u4_4.7:2);
+ local tmp:8 = trunc(fs f* scale);
+ local posof = nan(fs) || (tmp >> 16) != 0;
+ local negof = tmp s< 0;
+ local noof = !posof && !negof;
+ ar = zext(posof)*0xffffffff + zext(negof)*0x80000000 + zext(noof)*tmp:4;
+}
+
+# WAITI - Wait Interrupt, pg. 556.
+:waiti u4_8.11 is op2 = 0 & op1 = 0 & ar = 0b0111 & u4_8.11 & at = 0 & op0 = 0 {
+ waiti(u4_8.11:4);
+}
+
+# WDTLB - Write Data TLB Entry, pg. 557.
+:wdtlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1110 & as & at & op0 = 0 {
+ wdtlb(as, at);
+}
+
+# WER - Write External Register, pg. 558.
+:wer as, at is op2 = 0b0100 & op1 = 0 & ar = 0b0111 & as & at & op0 = 0 {
+ wer(as, at);
+}
+
+# WFR - Move AR to FR, pg. 559.
+:wfr fr, as is op2 = 0b1111 & op1 = 0b1010 & fr & as & at = 0b0101 & op0 = 0 {
+ fr = as;
+}
+
+# WITLB - Write Instruction TLB Entry, pg. 560.
+:witlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0110 & as & at & op0 = 0 {
+ witlb(as, at);
+}
+
+# WSR - Write Special Register, pg. 561.
+:wsr at, u8_8.15 is op2 = 0b0001 & op1 = 0b0011 & u8_8.15 & at & op0 = 0 {
+ wsr(u8_8.15:1, at);
+}
+
+# WUR - Write User Register, pg. 563.
+:wur at, u8_8.15 is op2 = 0b1111 & op1 = 0b0011 & u8_8.15 & at & op0 = 0 {
+ wur(u8_8.15:1, at);
+}
+
+# XOR - Bitwise Exclusive Or, pg. 564.
+:xor ar, as, at is op2 = 0b0011 & op1 = 0 & ar & as & at & op0 = 0 {
+ ar = as ^ at;
+}
+
+# XORB - Boolean Exclusive Or, pg. 565.
+:xorb br, bs, bt is op2 = 0b0100 & op1 = 0b0010 & br & bs & bt & op0 = 0 {
+ br = bs ^^ bt;
+}
+
+# XSR - Exchange Special Register, pg. 566.
+:xsr at, u8_8.15 is op2 = 0b0110 & op1 = 0b0001 & u8_8.15 & at & op0 = 0 {
+ at = xsr(u8_8.15:1, at);
+}
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaTodo.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaTodo.sinc
new file mode 100644
index 0000000000..b89eea56e8
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensaTodo.sinc
@@ -0,0 +1,66 @@
+## Windowed Register Option ##
+
+# CALL4 - Call PC-relative, Rotate Window by 4, pg. 298.
+:call4 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b01 & op0 = 0b0101 unimpl
+
+# CALL8 - Call PC-relative, Rotate Window by 8, pg. 300.
+:call8 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b10 & op0 = 0b0101 unimpl
+
+# CALL12 - Call PC-relative, Rotate Window by 12, pg. 302.
+:call12 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b11 & op0 = 0b0101 unimpl
+
+# CALLX4 - Call Register, Rotate Window by 4, pg. 305.
+:callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b01 & op0 = 0 unimpl
+
+# CALLX8 - Call Register, Rotate Window by 8, pg. 307.
+:callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b10 & op0 = 0 unimpl
+
+# CALLX12 - Call Register, Rotate Window by 12, pg. 308.
+:callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b11 & op0 = 0 unimpl
+
+# ENTRY - Subroutine Entry, pg. 340.
+:entry as, u15_12.23_sb3 is u15_12.23_sb3 & as & u2_6.7 = 0b00 & u2_4.5 = 0b11 & op0 = 0b0110 unimpl
+
+# L32E - Load 32-bit for Window Exceptions, pg. 376.
+:l32e at, as, s5_12.15_oex is op2 = 0 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl
+
+# MOVSP - Move to Stack Pointer, pg. 427.
+:movsp at, as is op2 = 0 & op1 = 0 & ar = 0b0001 & as & at & op0 = 0 unimpl
+
+# RETW - Windowed Return, pg. 480.
+:retw is op2 = 0 & ar = 0 & as = 0 & at = 0 & u2_18.19 = 0b10 & u2_16.17 = 0b01 & op0 = 0 unimpl
+
+# RETW.N - Narrow Windowed Return, pg. 482.
+:retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 unimpl
+
+# ROTW - Rotate Window, pg. 496.
+:rotw s4_4.7 is op2 = 0b0100 & op1 = 0 & ar = 0b1000 & as = 0 & s4_4.7 & op0 = 0 unimpl
+
+# S32E - Store 32-bit for Window Exceptions, pg. 508.
+:s32e at, as, s5_12.15_oex is op2 = 0b0100 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl
+
+
+## MAC16 option ##
+
+# LDDEC - Load with Autodecrement, pg. 386.
+: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
+
+# LDINC - Load with Autoincrement, pg. 387.
+: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
+
+# MULA.AA.* - Signed Multiply, pg. 431.
+:mula.aa.* as, at is op2 = 0b0001 & u2_18.19 = 0b01 & ar = 0 & as & at & op0 = 0b0100 unimpl
+
+# FIXME: Add remaining MUL.* opcodes.
+
+
+## Loop Option ##
+
+# LOOP - Loop, pg. 392.
+:loop as, urel_16.23 is urel_16.23 & ar = 0b1000 & as & at = 0b0111 & op0 = 0b0110 unimpl
+
+# LOOPGTZ - Loop if Greater Than Zero, pg. 394.
+:loopgtz as, urel_16.23 is urel_16.23 & ar = 0b1010 & as & at = 0b0111 & op0 = 0b0110 unimpl
+
+# LOOPNEZ - Loop if Not Equal Zero, pg. 396.
+:loopnez as, urel_16.23 is urel_16.23 & ar = 0b1001 & as & at = 0b0111 & op0 = 0b0110 unimpl
diff --git a/Ghidra/Processors/Xtensa/data/manuals/xtensa.idx b/Ghidra/Processors/Xtensa/data/manuals/xtensa.idx
new file mode 100644
index 0000000000..e98296d090
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/data/manuals/xtensa.idx
@@ -0,0 +1,242 @@
+@xtensa.pdf[Xtensa® Instruction Set Architecture (ISA) Reference Manual, April 2010]
+
+b4const(ar), 65
+b4constu(ar), 66
+call4, 322
+call8, 324
+call12, 326
+callx4, 329
+callx8, 331
+callx12, 332
+entry, 364
+l32e, 400
+movsp, 451
+retw, 504
+retw.n, 506
+rotw, 520
+s32e, 532
+lddec, 410
+ldinc, 411
+mula.aa.*, 455
+loop, 416
+loopgtz, 418
+loopnez, 420
+abs, 270
+abs.s, 271
+add, 272
+add.n, 273
+add.s, 274
+addi, 275
+addi.n, 276
+addmi, 277
+addx2, 278
+addx4, 279
+addx8, 280
+all4, 281
+all8, 282
+and, 283
+andb, 284
+andbc, 285
+any4, 286
+any8, 287
+ball, 288
+bany, 289
+bbc, 290
+bbci, 291
+bbs, 293
+bbsi, 294
+beq, 296
+beqi, 297
+beqz, 298
+beqz.n, 299
+bf, 300
+bge, 301
+bgei, 302
+bgeu, 303
+bgeui, 304
+bgez, 305
+blt, 306
+blti, 307
+bltu, 308
+bltui, 309
+bltz, 310
+bnall, 311
+bne, 312
+bnei, 313
+bnez, 314
+bnez.n, 315
+bnone, 316
+break, 317
+break.n, 319
+bt, 320
+call0, 321
+callx0, 328
+ceil.s, 335
+clamps, 336
+dhi, 337
+dhu, 339
+dhwb, 341
+dhwbi, 343
+dii, 345
+diu, 347
+diwb, 349
+diwbi, 351
+dpfl, 353
+dpfr, 355
+dpfro, 357
+dpfw, 359
+dpfwo, 361
+dsync, 363
+esync, 366
+excw, 367
+extui, 368
+extw, 369
+float.s, 370
+floor.s, 371
+idtlb, 372
+ihi, 373
+ihu, 375
+iii, 377
+iitlb, 379
+iiu, 380
+ill, 382
+ill.n, 383
+ipf, 384
+ipfl, 386
+isync, 388
+j, 390
+ret, 502
+jx, 392
+l8ui, 393
+l16si, 394
+l16ui, 396
+l32ai, 398
+l32i, 402
+l32i.n, 404
+l32r, 406
+ldct, 408
+lict, 412
+licw, 414
+lsi, 422
+lsiu, 424
+lsx, 426
+lsxu, 428
+madd.s, 430
+max, 431
+maxu, 432
+memw, 433
+min, 434
+minu, 435
+mov.n, 437
+mov.s, 438
+moveqz, 439
+moveqz.s, 440
+movf, 441
+movf.s, 442
+movgez, 443
+movgez.s, 444
+movi, 445
+movi.n, 446
+movltz, 447
+movltz.s, 448
+movnez, 449
+movnez.s, 450
+movt, 452
+movt.s, 453
+msub.s, 454
+mul.s, 459
+mul16s, 460
+mul16u, 461
+mull, 474
+mulsh, 479
+muluh, 480
+neg, 481
+neg.s, 482
+nop, 483
+nop.n, 484
+nsa, 485
+nsau, 486
+oeq.s, 487
+ole.s, 488
+olt.s, 489
+mov, 436
+or, 490
+orb, 491
+orbc, 492
+pdtlb, 493
+pitlb, 494
+quos, 495
+quou, 496
+rdtlb0, 497
+rdtlb1, 498
+rems, 499
+remu, 500
+rer, 501
+ret.n, 503
+rfdd, 508
+rfde, 509
+rfdo, 510
+rfe, 511
+rfi, 512
+rfme, 513
+rfr, 514
+rfue, 515
+rfwo, 516
+rfwu, 517
+ritlb0, 518
+ritlb1, 519
+round.s, 521
+rsil, 522
+rsr, 524
+rsync, 526
+rur, 527
+s8i, 528
+s16i, 529
+s32c1i, 530
+s32i, 534
+s32i.n, 536
+s32ri, 538
+sdct, 540
+sext, 542
+sict, 543
+sicw, 545
+simcall, 547
+sll, 548
+slli, 549
+sra, 550
+srai, 551
+src, 552
+srl, 553
+srli, 554
+ssa8b, 555
+ssa8l, 556
+ssai, 557
+ssi, 558
+ssiu, 560
+ssl, 562
+ssr, 563
+ssx, 564
+ssxu, 565
+sub, 566
+sub.s, 567
+subx2, 568
+subx4, 569
+subx8, 570
+syscall, 571
+trunc.s, 572
+ueq.s, 573
+ufloat.s, 574
+ule.s, 575
+ult.s, 576
+un.s, 578
+utrunc.s, 579
+waiti, 580
+wdtlb, 581
+wer, 582
+wfr, 583
+witlb, 584
+wsr, 585
+wur, 587
+xor, 588
+xorb, 589
+xsr, 590
diff --git a/Ghidra/Processors/Xtensa/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java b/Ghidra/Processors/Xtensa/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java
new file mode 100644
index 0000000000..f74eb6d7ff
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java
@@ -0,0 +1,58 @@
+package ghidra.app.util.bin.format.elf.relocation;
+
+public class Xtensa_ElfRelocationConstants {
+ /* Xtensa processor ELF architecture-magic number */
+
+ // EM_XTENSA is already definded
+ public static final int EM_XTENSA_OLD = 0xABC7;
+
+ /* Xtensa relocations defined by the ABIs */
+
+ public static final int R_XTENSA_NONE = 0;
+ public static final int R_XTENSA_32 = 1;
+ public static final int R_XTENSA_RTLD = 2;
+ public static final int R_XTENSA_GLOB_DAT = 3;
+ public static final int R_XTENSA_JMP_SLOT = 4;
+ public static final int R_XTENSA_RELATIVE = 5;
+ public static final int R_XTENSA_PLT = 6;
+ public static final int R_XTENSA_OP0 = 8;
+ public static final int R_XTENSA_OP1 = 9;
+ public static final int R_XTENSA_OP2 = 10;
+ public static final int R_XTENSA_ASM_EXPAND = 11;
+ public static final int R_XTENSA_ASM_SIMPLIFY = 12;
+ public static final int R_XTENSA_GNU_VTINHERIT = 15;
+ public static final int R_XTENSA_GNU_VTENTRY = 16;
+ public static final int R_XTENSA_DIFF8 = 17;
+ public static final int R_XTENSA_DIFF16 = 18;
+ public static final int R_XTENSA_DIFF32 = 19;
+ public static final int R_XTENSA_SLOT0_OP = 20;
+ public static final int R_XTENSA_SLOT1_OP = 21;
+ public static final int R_XTENSA_SLOT2_OP = 22;
+ public static final int R_XTENSA_SLOT3_OP = 23;
+ public static final int R_XTENSA_SLOT4_OP = 24;
+ public static final int R_XTENSA_SLOT5_OP = 25;
+ public static final int R_XTENSA_SLOT6_OP = 26;
+ public static final int R_XTENSA_SLOT7_OP = 27;
+ public static final int R_XTENSA_SLOT8_OP = 28;
+ public static final int R_XTENSA_SLOT9_OP = 29;
+ public static final int R_XTENSA_SLOT10_OP = 30;
+ public static final int R_XTENSA_SLOT11_OP = 31;
+ public static final int R_XTENSA_SLOT12_OP = 32;
+ public static final int R_XTENSA_SLOT13_OP = 33;
+ public static final int R_XTENSA_SLOT14_OP = 34;
+ public static final int R_XTENSA_SLOT0_ALT = 35;
+ public static final int R_XTENSA_SLOT1_ALT = 36;
+ public static final int R_XTENSA_SLOT2_ALT = 37;
+ public static final int R_XTENSA_SLOT3_ALT = 38;
+ public static final int R_XTENSA_SLOT4_ALT = 39;
+ public static final int R_XTENSA_SLOT5_ALT = 40;
+ public static final int R_XTENSA_SLOT6_ALT = 41;
+ public static final int R_XTENSA_SLOT7_ALT = 42;
+ public static final int R_XTENSA_SLOT8_ALT = 43;
+ public static final int R_XTENSA_SLOT9_ALT = 44;
+ public static final int R_XTENSA_SLOT10_ALT = 45;
+ public static final int R_XTENSA_SLOT11_ALT = 46;
+ public static final int R_XTENSA_SLOT12_ALT = 47;
+ public static final int R_XTENSA_SLOT13_ALT = 48;
+ public static final int R_XTENSA_SLOT14_ALT = 49;
+}
diff --git a/Ghidra/Processors/Xtensa/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java b/Ghidra/Processors/Xtensa/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java
new file mode 100644
index 0000000000..5882690335
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java
@@ -0,0 +1,292 @@
+package ghidra.app.util.bin.format.elf.relocation;
+
+import ghidra.app.util.bin.format.elf.ElfConstants;
+import ghidra.app.util.bin.format.elf.ElfHeader;
+import ghidra.app.util.bin.format.elf.ElfRelocation;
+import ghidra.app.util.bin.format.elf.ElfSymbol;
+import ghidra.program.model.address.Address;
+import ghidra.program.model.listing.Program;
+import ghidra.program.model.mem.Memory;
+import ghidra.program.model.mem.MemoryAccessException;
+import ghidra.util.exception.NotFoundException;
+
+public class Xtensa_ElfRelocationHandler extends ElfRelocationHandler {
+
+ @Override
+ public boolean canRelocate(ElfHeader elf) {
+ return elf.e_machine() == ElfConstants.EM_XTENSA ||
+ elf.e_machine() == Xtensa_ElfRelocationConstants.EM_XTENSA_OLD;
+ }
+
+ @Override
+ public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation, Address relocationAddress)
+ throws MemoryAccessException, NotFoundException {
+ ElfHeader elf = elfRelocationContext.getElfHeader();
+ if (!canRelocate(elf)) {
+ return;
+ }
+
+ int type=relocation.getType();
+ if (Xtensa_ElfRelocationConstants.R_XTENSA_NONE == type) {
+ return;
+ }
+
+ Program program = elfRelocationContext.getProgram();
+ Memory memory = program.getMemory();
+
+ long addend = relocation.hasAddend() ? relocation.getAddend() : memory.getInt(relocationAddress);
+ long offset = relocationAddress.getOffset();
+ long base = elfRelocationContext.getImageBaseWordAdjustmentOffset();
+ ElfSymbol sym = null;
+ long symbolValue = 0;
+ String symbolName = null;
+
+ int symbolIndex = relocation.getSymbolIndex();
+ if (symbolIndex != 0) {
+ sym = elfRelocationContext.getSymbol(symbolIndex);
+ }
+
+ if (null != sym) {
+ symbolValue = elfRelocationContext.getSymbolValue(sym);
+ symbolName = sym.getNameAsString();
+ }
+
+ switch(type) {
+ case Xtensa_ElfRelocationConstants.R_XTENSA_32:
+ markAsWarning(program, relocationAddress, "R_XTENSA_32",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_RTLD:
+ markAsWarning(program, relocationAddress, "R_XTENSA_RTLD",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_GLOB_DAT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_GLOB_DAT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_JMP_SLOT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_JMP_SLOT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_RELATIVE:
+ markAsWarning(program, relocationAddress, "R_XTENSA_RELATIVE",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_PLT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_PLT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_OP0:
+ markAsWarning(program, relocationAddress, "R_XTENSA_OP0",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_OP1:
+ markAsWarning(program, relocationAddress, "R_XTENSA_OP1",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_OP2:
+ markAsWarning(program, relocationAddress, "R_XTENSA_OP2",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_EXPAND:
+ markAsWarning(program, relocationAddress, "R_XTENSA_ASM_EXPAND",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_SIMPLIFY:
+ markAsWarning(program, relocationAddress, "R_XTENSA_ASM_SIMPLIFY",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTINHERIT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTINHERIT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTENTRY:
+ markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTENTRY",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF8:
+ markAsWarning(program, relocationAddress, "R_XTENSA_DIFF8",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF16:
+ markAsWarning(program, relocationAddress, "R_XTENSA_DIFF16",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF32:
+ markAsWarning(program, relocationAddress, "R_XTENSA_DIFF32",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_OP:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_OP",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_ALT:
+ markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_ALT",
+ symbolName, symbolIndex, "TODO, needs support ",
+ elfRelocationContext.getLog());
+ break;
+ default:
+ markAsUnhandled(program, relocationAddress, type, symbolIndex,
+ symbolName, elfRelocationContext.getLog());
+ break;
+ }
+ }
+
+}
diff --git a/Ghidra/Processors/Xtensa/src/test.processors/java/ghidra/test/processors/Xtensa_O0_EmulatorTest.java b/Ghidra/Processors/Xtensa/src/test.processors/java/ghidra/test/processors/Xtensa_O0_EmulatorTest.java
new file mode 100644
index 0000000000..65f528001f
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/src/test.processors/java/ghidra/test/processors/Xtensa_O0_EmulatorTest.java
@@ -0,0 +1,25 @@
+package ghidra.test.processors;
+
+import ghidra.test.processors.support.ProcessorEmulatorTestAdapter;
+import junit.framework.Test;
+
+public class Xtensa_O0_EmulatorTest extends ProcessorEmulatorTestAdapter {
+
+ private static final String LANGUAGE_ID = "Xtensa:LE:32:default";
+ private static final String COMPILER_SPEC_ID = "default";
+
+ private static final String[] REG_DUMP_SET = new String[] {};
+
+ public Xtensa_O0_EmulatorTest(String name) throws Exception {
+ super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
+ }
+
+ @Override
+ protected String getProcessorDesignator() {
+ return "Xtensa_GCC_O0";
+ }
+
+ public static Test suite() {
+ return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(Xtensa_O0_EmulatorTest.class);
+ }
+}
diff --git a/Ghidra/Processors/Xtensa/src/test.processors/java/ghidra/test/processors/Xtensa_O3_EmulatorTest.java b/Ghidra/Processors/Xtensa/src/test.processors/java/ghidra/test/processors/Xtensa_O3_EmulatorTest.java
new file mode 100644
index 0000000000..7e48b55816
--- /dev/null
+++ b/Ghidra/Processors/Xtensa/src/test.processors/java/ghidra/test/processors/Xtensa_O3_EmulatorTest.java
@@ -0,0 +1,25 @@
+package ghidra.test.processors;
+
+import ghidra.test.processors.support.ProcessorEmulatorTestAdapter;
+import junit.framework.Test;
+
+public class Xtensa_O3_EmulatorTest extends ProcessorEmulatorTestAdapter {
+
+ private static final String LANGUAGE_ID = "Xtensa:LE:32:default";
+ private static final String COMPILER_SPEC_ID = "default";
+
+ private static final String[] REG_DUMP_SET = new String[] {};
+
+ public Xtensa_O3_EmulatorTest(String name) throws Exception {
+ super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
+ }
+
+ @Override
+ protected String getProcessorDesignator() {
+ return "Xtensa_GCC_O3";
+ }
+
+ public static Test suite() {
+ return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(Xtensa_O3_EmulatorTest.class);
+ }
+}