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); + } +}