From f55d6b0f3b765411967c438b0bc34ecbe0986c02 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Tue, 22 Jun 2021 10:02:24 -0400 Subject: [PATCH] GP-1062 revisions made to combined PR 1407 and 5442 (includes merge changes by ghidra1) --- .../SleighDevTools/pcodetest/defaults.py | 2 +- .../SleighDevTools/pcodetest/pcode_defs.py | 16 +- Ghidra/Processors/Xtensa/build.gradle | 19 + .../Processors/Xtensa/certification.manifest | 16 +- .../Xtensa/data/languages/cust.sinc | 17 + .../Xtensa/data/languages/flix.sinc | 9 + .../Xtensa/data/languages/xtensa.cspec | 227 ++- .../Xtensa/data/languages/xtensa.ldefs | 19 +- .../Xtensa/data/languages/xtensa.opinion | 4 +- .../Xtensa/data/languages/xtensa.pspec | 10 + .../Xtensa/data/languages/xtensa.sinc | 469 ------ .../Xtensa/data/languages/xtensa.slaspec | 25 - .../Xtensa/data/languages/xtensaArch.sinc | 433 +++++ .../data/languages/xtensaInstructions.sinc | 1410 +++++++++++------ .../Xtensa/data/languages/xtensaMain.sinc | 116 ++ .../Xtensa/data/languages/xtensaTodo.sinc | 66 - .../Xtensa/data/languages/xtensa_be.slaspec | 12 + .../Xtensa/data/languages/xtensa_depbits.sinc | 11 + .../Xtensa/data/languages/xtensa_le.slaspec | 12 + .../Processors/Xtensa/data/manuals/xtensa.idx | 594 ++++--- .../Xtensa/src/main/help/help/TOC_Source.xml | 57 - .../main/help/help/topics/xtensa/help.html | 23 - .../Xtensa_ElfRelocationConstants.java | 15 + .../Xtensa_ElfRelocationHandler.java | 408 ++--- ...XtensaEmulateInstructionStateModifier.java | 159 ++ .../processors/Xtensa_O0_EmulatorTest.java | 15 + .../processors/Xtensa_O3_EmulatorTest.java | 15 + 27 files changed, 2482 insertions(+), 1697 deletions(-) create mode 100644 Ghidra/Processors/Xtensa/data/languages/cust.sinc create mode 100644 Ghidra/Processors/Xtensa/data/languages/flix.sinc delete mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensa.sinc delete mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensa.slaspec create mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc create mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc delete mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensaTodo.sinc create mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensa_be.slaspec create mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc create mode 100644 Ghidra/Processors/Xtensa/data/languages/xtensa_le.slaspec delete mode 100644 Ghidra/Processors/Xtensa/src/main/help/help/TOC_Source.xml delete mode 100644 Ghidra/Processors/Xtensa/src/main/help/help/topics/xtensa/help.html create mode 100644 Ghidra/Processors/Xtensa/src/main/java/ghidra/program/emulation/XtensaEmulateInstructionStateModifier.java diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py index 8bc78ab34e..7c98b33bed 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py @@ -20,7 +20,7 @@ PCodeTest.defaults.toolchain_root = '/local/ToolChains' PCodeTest.defaults.build_root = '/local/build-pcodetest' -PCodeTest.defaults.gcc_version = '7.3.0' +PCodeTest.defaults.gcc_version = '9.2.0' PCodeTest.defaults.skip_files = [] PCodeTest.defaults.export_root = os.getcwd() + '/../../../../../ghidra.bin/Ghidra/Test/TestResources/data/pcodetests/' PCodeTest.defaults.pcodetest_src = os.getcwd() + '/c_src' diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py index be7f938095..a3972d852f 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py @@ -665,10 +665,20 @@ PCodeTest({ }) PCodeTest({ - 'name': 'Xtensa', + 'name': 'Xtensa_LE', 'build_all': 1, 'build_exe': 1, - 'toolchain': 'Xtensa/xtensa-lx106-elf', + 'toolchain': 'Xtensa/xtensa-esp32-elf', 'language_id': 'Xtensa:LE:32:default', - 'ccflags': '-L %(toolchain_dir)s/lib/gcc/xtensa-lx106-elf/%(gcc_version)s -lgcc', + 'gcc_version' : '8.4.0', + 'ccflags': '-L %(toolchain_dir)s/lib/gcc/xtensa-esp32-elf/%(gcc_version)s', +}) + +PCodeTest({ + 'name': 'Xtensa_BE', + 'build_all': 1, + 'build_exe': 1, + 'toolchain': 'Xtensa/xtensa-elf', + 'language_id': 'Xtensa:BE:32:default', + 'ccflags': '-L %(toolchain_dir)s/lib/gcc/xtensa-elf/%(gcc_version)s', }) diff --git a/Ghidra/Processors/Xtensa/build.gradle b/Ghidra/Processors/Xtensa/build.gradle index 9dadac96d0..b52d6e1866 100644 --- a/Ghidra/Processors/Xtensa/build.gradle +++ b/Ghidra/Processors/Xtensa/build.gradle @@ -1,3 +1,18 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" @@ -8,3 +23,7 @@ eclipse.project.name = 'Processors Xtensa' dependencies { api project(':Base') } + +sleighCompileOptions = [ + "-l" +] diff --git a/Ghidra/Processors/Xtensa/certification.manifest b/Ghidra/Processors/Xtensa/certification.manifest index 8d447e56a9..11a527af56 100644 --- a/Ghidra/Processors/Xtensa/certification.manifest +++ b/Ghidra/Processors/Xtensa/certification.manifest @@ -1,20 +1,18 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| -build.gradle||GHIDRA||||END| +data/languages/cust.sinc||GHIDRA||||END| +data/languages/flix.sinc||GHIDRA||||END| data/languages/xtensa.cspec||GHIDRA||||END| data/languages/xtensa.dwarf||GHIDRA||||END| data/languages/xtensa.ldefs||GHIDRA||||END| data/languages/xtensa.opinion||GHIDRA||||END| data/languages/xtensa.pspec||GHIDRA||||END| -data/languages/xtensa.sinc||GHIDRA||||END| -data/languages/xtensa.slaspec||GHIDRA||||END| +data/languages/xtensaArch.sinc||GHIDRA||||END| data/languages/xtensaInstructions.sinc||GHIDRA||||END| +data/languages/xtensaMain.sinc||GHIDRA||||END| +data/languages/xtensa_be.slaspec||GHIDRA||||END| +data/languages/xtensa_depbits.sinc||GHIDRA||||END| +data/languages/xtensa_le.slaspec||GHIDRA||||END| data/manuals/xtensa.idx||GHIDRA||||END| data/patterns/patternconstraints.xml||GHIDRA||||END| data/patterns/xtensa_patterns.xml||GHIDRA||||END| -src/main/help/help/topics/xtensa/help.html||GHIDRA||||END| -src/main/help/help/TOC_Source.xml||GHIDRA||||END| -src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java||GHIDRA||||END| -src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java||GHIDRA||||END| -src/test.processors/java/ghidra/test/processors/Xtensa_O0_EmulatorTest.java||GHIDRA||||END| -src/test.processors/java/ghidra/test/processors/Xtensa_O3_EmulatorTest.java||GHIDRA||||END| diff --git a/Ghidra/Processors/Xtensa/data/languages/cust.sinc b/Ghidra/Processors/Xtensa/data/languages/cust.sinc new file mode 100644 index 0000000000..dc54f28bbe --- /dev/null +++ b/Ghidra/Processors/Xtensa/data/languages/cust.sinc @@ -0,0 +1,17 @@ +# Per the manual: +# CUST0 and CUST1 opcode encodings shown in Table 7–193 are permanently reserved +# for designer-defined opcodes. In the future, customers who use these spaces +# exclusively for their own designer-defined opcodes will be able to add new +# Tensilica-defined options without changing their opcodes or binary executables. + +define pcodeop cust0; + +:cust0 "{op2="^op2^", r="^ar^", s="^as^", t="^at^"}" is op0=0x0 & op1=0x6 & op2 & ar & as & at { + cust0(); +} + +define pcodeop cust1; + +:cust1 "{op2="^op2^", r="^ar^", s="^as^", t="^at^"}" is op0=0x0 & op1=0x7 & op2 & ar & as & at { + cust1(); +} \ No newline at end of file diff --git a/Ghidra/Processors/Xtensa/data/languages/flix.sinc b/Ghidra/Processors/Xtensa/data/languages/flix.sinc new file mode 100644 index 0000000000..5a017ca640 --- /dev/null +++ b/Ghidra/Processors/Xtensa/data/languages/flix.sinc @@ -0,0 +1,9 @@ + +# FLIX (Flexible Length Instruction eXtension) is a Xtensa processor extension +# that allows for variable-length, multi-op instructions with support from 4 +# 16 bytes. Customizable, if if found they should be flagged. + +define pcodeop flix; +:FLIX u_4_23 is op0=0xe & u_4_23 { + flix(); +} \ No newline at end of file diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.cspec b/Ghidra/Processors/Xtensa/data/languages/xtensa.cspec index 81a5b3a373..f502e71cce 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensa.cspec +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.cspec @@ -55,69 +55,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + @@ -125,6 +71,7 @@ + @@ -135,11 +82,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs b/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs index 80c6e25721..295fea8ef0 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs @@ -5,13 +5,28 @@ endian="little" size="32" variant="default" - version="1.0" - slafile="xtensa.sla" + version="4.0" + slafile="xtensa_le.sla" processorspec="xtensa.pspec" manualindexfile="../manuals/xtensa.idx" id="Xtensa:LE:32:default"> Tensilica Xtensa 32-bit little-endian + + + + + Tensilica Xtensa 32-bit big-endian + + diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.opinion b/Ghidra/Processors/Xtensa/data/languages/xtensa.opinion index 3f2eae23ff..1e6ce11602 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensa.opinion +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.opinion @@ -1,6 +1,6 @@ - - + + diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.pspec b/Ghidra/Processors/Xtensa/data/languages/xtensa.pspec index 114b5c47a8..721b2e437a 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensa.pspec +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.pspec @@ -2,4 +2,14 @@ + + + + + + + + + + diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensa.sinc deleted file mode 100644 index 219302428c..0000000000 --- a/Ghidra/Processors/Xtensa/data/languages/xtensa.sinc +++ /dev/null @@ -1,469 +0,0 @@ -define endian=little; -define alignment=1; - -define space ram type=ram_space size=4 default; -define space register type=register_space size=4; - -# Special registers (SR). Not all are actually 32 bit, but for the sake of -# simplicity they are here. -define register offset=0x00 size=4 [ LBEG LEND LCOUNT SAR BR LITBASE ]; -define register offset=0x30 size=4 [ SCOMPARE1 ]; -define register offset=0x40 size=4 [ ACCLO ACCHI ]; -define register offset=0x80 size=4 [ M0 M1 M2 M3 ]; -define register offset=0x120 size=4 [ WindowBase WindowStart ]; -define register offset=0x14c size=4 [ PTEVADDR ]; -define register offset=0x164 size=4 [ MMID RASID ITLBCFG DTLBCFG ]; -define register offset=0x180 size=4 [ IBREAKENABLE ]; -define register offset=0x184 size=4 [ MEMCTL ]; -define register offset=0x188 size=4 [ CACHEATTR ATOMCTL ]; -define register offset=0x1a0 size=4 [ DDR ]; -define register offset=0x1a8 size=4 [ MEPC MEPS MESAVE MESR MECR MEVADDR ]; -define register offset=0x200 size=4 [ IBREAKA0 IBREAKA1 ]; -define register offset=0x240 size=4 [ DBREAKA0 DBREAKA1 ]; -define register offset=0x280 size=4 [ DBREAKC0 DBREAKC1 ]; -define register offset=0x2c4 size=4 [ EPC1 EPC2 EPC3 EPC4 EPC5 EPC6 EPC7 ]; -define register offset=0x300 size=4 [ DEPC ]; -define register offset=0x308 size=4 [ EPS2 EPS3 EPS4 EPS5 EPS6 EPS7 ]; -define register offset=0x344 size=4 [ EXCSAVE1 EXCSAVE2 EXCSAVE3 EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 ]; -define register offset=0x380 size=4 [ CPENABLE ]; -define register offset=0x384 size=4 [ INTERRUPT INTSET INTCLEAR INTENABLE ]; -define register offset=0x398 size=4 [ PS VECBASE EXCCAUSE DEBUGCAUSE CCOUNT PRID ICOUNT ICOUNTLEVEL EXCVADDR ]; -define register offset=0x3c0 size=4 [ CCOMPARE0 CCOMPARE1 CCOMPARE2 ]; -define register offset=0x3d0 size=4 [ MISC0 MISC1 MISC2 MISC3 ]; - -# TODO: Register offsets *might* be firmware specific? - -# Address registers (AR). -define register offset=0x8000 size=4 [ - a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 - i2 i3 i4 i5 i6 i7 - o2 o3 o4 o5 o6 o7 -]; - -# Floating Point registers (FR + FCR (control) + FSR (status)). -define register offset=0x8100 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=0x8200 size=1 [ - b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 -]; - -# Program counter. -# TODO: offset could also be 0x1300 or 0x8300 -define register offset=0x8300 size=4 [ pc ]; - -# Shift amount register. (TODO: other special registers) -# define register offset=0x2000 size=1 [ SAR ]; - -define register offset=0x8400 size=4 contextreg; -define context contextreg - phase=(0,0) - loopEnd=(1,1) noflow -; - -# 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) - sr = (8,15) - 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) -; - -define token opbyte (8) - op0_8 = (0,7) -; - -define token opword (16) - op0_16 = (0,15) -; - -attach variables [ sr ] [ -# 0x...0 0x...4 0x...8 0x...c - LBEG LEND LCOUNT SAR # 0x0_ - BR LITBASE _ _ # 0x1_ - _ _ _ _ # 0x2_ - SCOMPARE1 _ _ _ # 0x3_ - ACCLO ACCHI _ _ # 0x4_ - _ _ _ _ # 0x5_ - _ _ _ _ # 0x6_ - _ _ _ _ # 0x7_ - M0 M1 M2 M3 # 0x8_ - _ _ _ _ # 0x9_ - _ _ _ _ # 0xa_ - _ _ _ _ # 0xb_ - _ _ _ _ # 0xc_ - _ _ _ _ # 0xd_ - _ _ _ _ # 0xe_ - _ _ _ _ # 0xf_ -# 0x...0 0x...4 0x...8 0x...c - _ _ _ _ # 0x10_ - _ _ _ _ # 0x11_ - WindowBase WindowStart _ _ # 0x12_ - _ _ _ _ # 0x13_ - _ _ _ PTEVADDR # 0x14_ - _ _ _ _ # 0x15_ - _ MMID RASID ITLBCFG # 0x16_ - DTLBCFG _ _ _ # 0x17_ - IBREAKENABLE MEMCTL CACHEATTR ATOMCTL # 0x18_ - _ _ _ _ # 0x19_ - DDR _ MEPC MEPS # 0x1a_ - MESAVE MESR MECR MEVADDR # 0x1b_ - _ _ _ _ # 0x1c_ - _ _ _ _ # 0x1d_ - _ _ _ _ # 0x1e_ - _ _ _ _ # 0x1f_ -# 0x...0 0x...4 0x...8 0x...c - IBREAKA0 IBREAKA1 _ _ # 0x20_ - _ _ _ _ # 0x21_ - _ _ _ _ # 0x22_ - _ _ _ _ # 0x23_ - DBREAKA0 DBREAKA1 _ _ # 0x24_ - _ _ _ _ # 0x25_ - _ _ _ _ # 0x26_ - _ _ _ _ # 0x27_ - DBREAKC0 DBREAKC1 _ _ # 0x28_ - _ _ _ _ # 0x29_ - _ _ _ _ # 0x2a_ - _ _ _ _ # 0x2b_ - _ EPC1 EPC2 EPC3 # 0x2c_ - EPC4 EPC5 EPC6 EPC7 # 0x2d_ - _ _ _ _ # 0x2e_ - _ _ _ _ # 0x2f_ -# 0x...0 0x...4 0x...8 0x...c - DEPC _ EPS2 EPS3 # 0x30_ - EPS4 EPS5 EPS6 EPS7 # 0x31_ - _ _ _ _ # 0x32_ - _ _ _ _ # 0x33_ - _ EXCSAVE1 EXCSAVE2 EXCSAVE3 # 0x34_ - EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 # 0x35_ - _ _ _ _ # 0x36_ - _ _ _ _ # 0x37_ - CPENABLE INTERRUPT INTSET INTCLEAR # 0x38_ - INTENABLE _ PS VECBASE # 0x39_ - EXCCAUSE DEBUGCAUSE CCOUNT PRID # 0x3a_ - ICOUNT ICOUNTLEVEL EXCVADDR _ # 0x3b_ - CCOMPARE0 CCOMPARE1 CCOMPARE2 _ # 0x3c_ - MISC0 MISC1 MISC2 MISC3 # 0x3d_ - _ _ _ _ # 0x3e_ - _ _ _ _ # 0x3f_ -# 0x...0 0x...4 0x...8 0x...c -]; - -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 -]; - -attach variables [ u8_8_15 ] [ -# 0x...0 0x...4 0x...8 0x...c - LBEG LEND LCOUNT SAR # 0x0_ - BR LITBASE _ _ # 0x1_ - _ _ _ _ # 0x2_ - SCOMPARE1 _ _ _ # 0x3_ - ACCLO ACCHI _ _ # 0x4_ - _ _ _ _ # 0x5_ - _ _ _ _ # 0x6_ - _ _ _ _ # 0x7_ - M0 M1 M2 M3 # 0x8_ - _ _ _ _ # 0x9_ - _ _ _ _ # 0xa_ - _ _ _ _ # 0xb_ - _ _ _ _ # 0xc_ - _ _ _ _ # 0xd_ - _ _ _ _ # 0xe_ - _ _ _ _ # 0xf_ -# 0x...0 0x...4 0x...8 0x...c - _ _ _ _ # 0x10_ - _ _ _ _ # 0x11_ - WindowBase WindowStart _ _ # 0x12_ - _ _ _ _ # 0x13_ - _ _ _ PTEVADDR # 0x14_ - _ _ _ _ # 0x15_ - _ MMID RASID ITLBCFG # 0x16_ - DTLBCFG _ _ _ # 0x17_ - IBREAKENABLE MEMCTL CACHEATTR ATOMCTL # 0x18_ - _ _ _ _ # 0x19_ - DDR _ MEPC MEPS # 0x1a_ - MESAVE MESR MECR MEVADDR # 0x1b_ - _ _ _ _ # 0x1c_ - _ _ _ _ # 0x1d_ - _ _ _ _ # 0x1e_ - _ _ _ _ # 0x1f_ -# 0x...0 0x...4 0x...8 0x...c - IBREAKA0 IBREAKA1 _ _ # 0x20_ - _ _ _ _ # 0x21_ - _ _ _ _ # 0x22_ - _ _ _ _ # 0x23_ - DBREAKA0 DBREAKA1 _ _ # 0x24_ - _ _ _ _ # 0x25_ - _ _ _ _ # 0x26_ - _ _ _ _ # 0x27_ - DBREAKC0 DBREAKC1 _ _ # 0x28_ - _ _ _ _ # 0x29_ - _ _ _ _ # 0x2a_ - _ _ _ _ # 0x2b_ - _ EPC1 EPC2 EPC3 # 0x2c_ - EPC4 EPC5 EPC6 EPC7 # 0x2d_ - _ _ _ _ # 0x2e_ - _ _ _ _ # 0x2f_ -# 0x...0 0x...4 0x...8 0x...c - DEPC _ EPS2 EPS3 # 0x30_ - EPS4 EPS5 EPS6 EPS7 # 0x31_ - _ _ _ _ # 0x32_ - _ _ _ _ # 0x33_ - _ EXCSAVE1 EXCSAVE2 EXCSAVE3 # 0x34_ - EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 # 0x35_ - _ _ _ _ # 0x36_ - _ _ _ _ # 0x37_ - CPENABLE INTERRUPT INTSET INTCLEAR # 0x38_ - INTENABLE _ PS VECBASE # 0x39_ - EXCCAUSE DEBUGCAUSE CCOUNT PRID # 0x3a_ - ICOUNT ICOUNTLEVEL EXCVADDR _ # 0x3b_ - CCOMPARE0 CCOMPARE1 CCOMPARE2 _ # 0x3c_ - MISC0 MISC1 MISC2 MISC3 # 0x3d_ - _ _ _ _ # 0x3e_ - _ _ _ _ # 0x3f_ -# 0x...0 0x...4 0x...8 0x...c -]; - -# 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 | 0xfffc0000) << 2); - # Below might indicate firmware specific: - # rel = 0x9fa000 + 0x40000 + ((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; } - -# imm stored in sa for slli is 32-shift. -# TODO why can't we use subtable output for this instead of repeating u5_4_7_20 calc? -u5_4_7_20_slli: tmp is u1_20 & u4_4_7 [ tmp = 32 - ((u1_20 << 4) | u4_4_7); ] { export *[const]:1 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 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 deleted file mode 100644 index 523420d04f..0000000000 --- a/Ghidra/Processors/Xtensa/data/languages/xtensa.slaspec +++ /dev/null @@ -1,25 +0,0 @@ -@include "xtensa.sinc" - -# NOTE: This is quite a big hack; a real processor will compare nextPC to LEND on every ifetch. -# As we only inject the branch-back check on addresses marked by loop insns, we may miss -# strange things like loop registers being written directly or loop registers being overwritten -# by a "nested" loop instruction. We also don't check CLOOPENABLE (PS.EXCM). -# For code that hasn't been intentially crafted for anti-analysis this should be fine. -:^instruction is phase=0 & loopEnd=1 & instruction [phase=1;] { - if (LCOUNT == 0) goto ; - LCOUNT = LCOUNT - 1; - goto [LBEG]; - - build instruction; -} - -:^instruction is phase=0 & loopEnd=0 & instruction [phase=1;] { - build instruction; -} - -with : phase=1 { -@include "xtensaInstructions.sinc" -} - -# TODO: Evaluate -# @include "xtensaTodo.sinc" diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc new file mode 100644 index 0000000000..526f5bc590 --- /dev/null +++ b/Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc @@ -0,0 +1,433 @@ +define endian=$(ENDIAN); +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 +]; + +# Temporary Address registers (facilitates simplified CALL register swapping used by decompiler) +define register offset=0x0080 size=4 [ + t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 +]; + +# Floating Point registers +define register offset=0x0100 size=4 [ + f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 +]; + +# 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 +]; + +define register offset=0x0400 size=4 [ +user0 user1 user2 user3 user4 user5 user6 user7 user8 user9 user10 user11 user12 user13 user14 user15 +user16 user17 user18 user19 user20 user21 user22 user23 user24 user25 user26 user27 user28 user29 user30 user31 +user32 user33 user34 user35 user36 user37 user38 user39 user40 user41 user42 user43 user44 user45 user46 user47 +user48 user49 user50 user51 user52 user53 user54 user55 user56 user57 user58 user59 user60 user61 user62 user63 +user64 user65 user66 user67 user68 user69 user70 user71 user72 user73 user74 user75 user76 user77 user78 user79 +user80 user81 user82 user83 user84 user85 user86 user87 user88 user89 user90 user91 user92 user93 user94 user95 +user96 user97 user98 user99 user100 user101 user102 user103 user104 user105 user106 user107 user108 user109 user110 user111 +user112 user113 user114 user115 user116 user117 user118 user119 user120 user121 user122 user123 user124 user125 user126 user127 +user128 user129 user130 user131 user132 user133 user134 user135 user136 user137 user138 user139 user140 user141 user142 user143 +user144 user145 user146 user147 user148 user149 user150 user151 user152 user153 user154 user155 user156 user157 user158 user159 +user160 user161 user162 user163 user164 user165 user166 user167 user168 user169 user170 user171 user172 user173 user174 user175 +user176 user177 user178 user179 user180 user181 user182 user183 user184 user185 user186 user187 user188 user189 user190 user191 +user192 user193 user194 user195 user196 user197 user198 user199 user200 user201 user202 user203 user204 user205 user206 user207 +user208 user209 user210 user211 user212 user213 user214 user215 user216 user217 user218 user219 user220 user221 user222 user223 +user224 user225 user226 user227 user228 user229 user230 THREADPTR FCR FSR user234 user235 user236 user237 user238 user239 +user240 user241 user242 user243 user244 user245 user246 user247 user248 user249 user250 user251 user252 user253 user254 user255 +]; + +# Program counter. +define register offset=0x1000 size=4 [ pc ]; + +define register offset=0x2000 size=4 [ + LBEG LEND LCOUNT SAR BR LITBASE sr6 sr7 sr8 sr9 sr10 sr11 SCOMPARE1 sr13 sr14 sr15 +@if ENDIAN == "big" +ACCHI ACCLO +@else +ACCLO ACCHI +@endif + sr18 sr19 sr20 sr21 sr22 sr23 sr24 sr25 sr26 sr27 sr28 sr29 sr30 sr31 + M0 M1 M2 M3 sr36 sr37 sr38 sr39 sr40 sr41 sr42 sr43 sr44 sr45 sr46 sr47 + sr48 sr49 sr50 sr51 sr52 sr53 sr54 sr55 sr56 sr57 sr58 sr59 sr60 sr61 sr62 sr63 + sr64 sr65 sr66 sr67 sr68 sr69 sr70 sr71 WindowBase WindowStart sr74 sr75 sr76 sr77 sr78 sr79 + sr80 sr81 sr82 PTEVADDR sr84 sr85 sr86 sr87 sr88 MMID RASID ITLBCFG DTLBCFG sr93 sr94 sr95 + IBREAKENABLE MEMCTL CACHEATTR ATOMCTL sr100 sr101 sr102 sr103 DDR sr105 MEPC MEPS MESAVE MESR MECR MEVADDR + sr112 sr113 sr114 sr115 sr116 sr117 sr118 sr119 sr120 sr121 sr122 sr123 sr124 sr125 sr126 sr127 + IBREAKA0 IBREAKA1 sr130 sr131 sr132 sr133 sr134 sr135 sr136 sr137 sr138 sr139 sr140 sr141 sr142 sr143 + DBREAKA0 DBREAKA1 sr146 sr147 sr148 sr149 sr150 sr151 sr152 sr153 sr154 sr155 sr156 sr157 sr158 sr159 + DBREAKC0 DBREAKC1 sr162 sr163 sr164 sr165 sr166 sr167 sr168 sr169 sr170 sr171 sr172 sr173 sr174 sr175 + sr176 EPC1 EPC2 EPC3 EPC4 EPC5 EPC6 EPC7 sr184 sr185 sr186 sr187 sr188 sr189 sr190 sr191 + DEPC sr193 EPS2 EPS3 EPS4 EPS5 EPS6 EPS7 sr200 sr201 sr202 sr203 sr204 sr205 sr206 sr207 + sr208 EXCSAVE1 EXCSAVE2 EXCSAVE3 EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 sr216 sr217 sr218 sr219 sr220 sr221 sr222 sr223 +#TODO: REVIEW NEEDED! - INTSET / INTERRUPT placement/address (also review related attach) + CPENABLE INTERRUPT INTSET INTCLEAR INTENABLE sr229 PS VECBASE EXCCAUSE DEBUGCAUSE CCOUNT PRID ICOUNT ICOUNTLEVEL EXCVADDR sr239 + CCOMPARE0 CCOMPARE1 CCOMPARE2 sr243 MISC0 MISC1 MISC2 MISC3 sr248 sr249 sr250 sr251 sr252 sr253 sr254 sr255 +]; + +define register offset=0x2040 size=8 [ ACC ]; + +@define EPC_BASE "0x22c0" #address of EPCn = $(EPC_BASE) + (n * 4) +@define EPS_BASE "0x2300" #address of EPSn = $(EPS_BASE) + (n * 4) + +@define PS_INTLEVEL "PS[0,4]" +@define PS_EXCM "PS[4,1]" +@define PS_UM "PS[5,1]" +@define PS_RING "PS[6,2]" +@define PS_OWB "PS[8,4]" +@define PS_CALLINC "PS[12,2]" +@define PS_WOE "PS[14,1]" + + +define register offset=0xf000 size=4 contextreg; +define context contextreg + loopMode=(0,0) + loopEnd=(1,1) noflow + + #transient bits + phase=(31,31) +; + +@if ENDIAN == "big" + +# little-endian -> big-endian 24-bit conversion chart +#|00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23| +#|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| + +# Regular 24-bit instruction. +define token insn(24) + # Named opcode/register fields. + op2 = (0,3) + op1 = (4,7) + ar = (8,11) + fr = (8,11) + br = (8,11) + as = (12,15) + fs = (12,15) + bs = (12,15) + sr = (8,15) + at = (16,19) + ft = (16,19) + bt = (16,19) + op0 = (20,23) + + # 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 = (0,2) + u4_20_23 = (0,3) + s8_16_23 = (0,7) signed + u8_16_23 = (0,7) + u12_12_23 = (0,11) + s12_12_23 = (0,11) signed + u16_8_23 = (0,15) + s8_6_23 = (0,17) signed + u1_20 = (3,3) + u2_18_19 = (4,5) + u3_17_19 = (4,6) + u2_16_17 = (6,7) + u1_16 = (7,7) + u1_15_15 = (8,8) + u2_14_15 = (8,9) + u3_13_15 = (8,10) + u4_12_15 = (8,11) + m0m1_14_14 = (9,9) + u2_12_13 = (10,11) + mw_12_13 = (10,11) + u1_12 = (11,11) + u4_8_11 = (12,15) + u8_4_11 = (12,19) + s4_8_11 = (12,15) signed + u1_7_7 = (16,16) + u2_6_7 = (16,17) + u3_5_7 = (16,18) + u4_4_7 = (16,19) + s4_4_7 = (16,19) + m2m3_6_6 = (17,17) + u_4_23 = (0,19) + u2_4_5 = (18,19) + u1_4 = (19,19) +; + +# little-endian -> big-endian 16-bit conversion chart +#|00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| +#|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| + +# Narrow 16-bit instructions; fields are always prefixed with n_. +define token narrowinsn(16) + n_ar = (0,3) + n_as = (4,7) + n_at = (8,11) + n_op0 = (12,15) + + n_u4_12_15 = (0,3) + n_s4_12_15 = (0,3) signed + n_u4_8_11 = (4,7) + n_u1_7 = (8,8) + n_u2_6_7 = (8,9) + n_u4_4_7 = (8,11) + n_s3_4_6 = (9,11) + n_u2_4_5 = (10,11) +; + +@else +# 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) + sr = (8,15) + 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) + u1_15_15 = (15,15) + u2_14_15 = (14,15) + u3_13_15 = (13,15) + u4_12_15 = (12,15) + m0m1_14_14 = (14,14) + u2_12_13 = (12,13) + mw_12_13 = (12,13) + u1_12 = (12,12) + u4_8_11 = (8,11) + u8_4_11 = (4,11) + s4_8_11 = (8,11) signed + u1_7_7 = (7,7) + u2_6_7 = (6,7) + u3_5_7 = (5,7) + u4_4_7 = (4,7) + s4_4_7 = (4,7) + m2m3_6_6 = (6,6) + u_4_23 = (4,23) + 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) +; + +@endif + +attach variables [ sr ] [ +# 0x...0 0x...4 0x...8 0x...c + LBEG LEND LCOUNT SAR # 0x0_ + BR LITBASE _ _ # 0x1_ + _ _ _ _ # 0x2_ + SCOMPARE1 _ _ _ # 0x3_ + ACCLO ACCHI _ _ # 0x4_ + _ _ _ _ # 0x5_ + _ _ _ _ # 0x6_ + _ _ _ _ # 0x7_ + M0 M1 M2 M3 # 0x8_ + _ _ _ _ # 0x9_ + _ _ _ _ # 0xa_ + _ _ _ _ # 0xb_ + _ _ _ _ # 0xc_ + _ _ _ _ # 0xd_ + _ _ _ _ # 0xe_ + _ _ _ _ # 0xf_ +# 0x...0 0x...4 0x...8 0x...c + _ _ _ _ # 0x10_ + _ _ _ _ # 0x11_ + WindowBase WindowStart _ _ # 0x12_ + _ _ _ _ # 0x13_ + _ _ _ PTEVADDR # 0x14_ + _ _ _ _ # 0x15_ + _ MMID RASID ITLBCFG # 0x16_ + DTLBCFG _ _ _ # 0x17_ + IBREAKENABLE MEMCTL CACHEATTR ATOMCTL # 0x18_ + _ _ _ _ # 0x19_ + DDR _ MEPC MEPS # 0x1a_ + MESAVE MESR MECR MEVADDR # 0x1b_ + _ _ _ _ # 0x1c_ + _ _ _ _ # 0x1d_ + _ _ _ _ # 0x1e_ + _ _ _ _ # 0x1f_ +# 0x...0 0x...4 0x...8 0x...c + IBREAKA0 IBREAKA1 _ _ # 0x20_ + _ _ _ _ # 0x21_ + _ _ _ _ # 0x22_ + _ _ _ _ # 0x23_ + DBREAKA0 DBREAKA1 _ _ # 0x24_ + _ _ _ _ # 0x25_ + _ _ _ _ # 0x26_ + _ _ _ _ # 0x27_ + DBREAKC0 DBREAKC1 _ _ # 0x28_ + _ _ _ _ # 0x29_ + _ _ _ _ # 0x2a_ + _ _ _ _ # 0x2b_ + _ EPC1 EPC2 EPC3 # 0x2c_ + EPC4 EPC5 EPC6 EPC7 # 0x2d_ + _ _ _ _ # 0x2e_ + _ _ _ _ # 0x2f_ +# 0x...0 0x...4 0x...8 0x...c + DEPC _ EPS2 EPS3 # 0x30_ + EPS4 EPS5 EPS6 EPS7 # 0x31_ + _ _ _ _ # 0x32_ + _ _ _ _ # 0x33_ + _ EXCSAVE1 EXCSAVE2 EXCSAVE3 # 0x34_ + EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 # 0x35_ + _ _ _ _ # 0x36_ + _ _ _ _ # 0x37_ + CPENABLE INTERRUPT INTSET INTCLEAR # 0x38_ + INTENABLE _ PS VECBASE # 0x39_ + EXCCAUSE DEBUGCAUSE CCOUNT PRID # 0x3a_ + ICOUNT ICOUNTLEVEL EXCVADDR _ # 0x3b_ + CCOMPARE0 CCOMPARE1 CCOMPARE2 _ # 0x3c_ + MISC0 MISC1 MISC2 MISC3 # 0x3d_ + _ _ _ _ # 0x3e_ + _ _ _ _ # 0x3f_ +# 0x...0 0x...4 0x...8 0x...c +]; + +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. + +attach variables [ mw_12_13 ] [ + M0 M1 M2 M3 +]; + +attach variables [ m2m3_6_6 ] [ + M2 M3 +]; + +attach variables [ m0m1_14_14 ] [ + M0 M1 +]; + + +#implemented pcodeops +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 nsau; +define pcodeop pdtlb; +define pcodeop pitlb; +define pcodeop rdtlb0; +define pcodeop rdtlb1; +define pcodeop rer; +define pcodeop restore4; +define pcodeop restore8; +define pcodeop restore12; +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; +define pcodeop rsync; +define pcodeop rur; +define pcodeop s32c1i; +define pcodeop release; +define pcodeop restoreRegWindow; +define pcodeop rotateRegWindow; +define pcodeop sdct; +define pcodeop sict; +define pcodeop sicw; +define pcodeop simcall; +define pcodeop syscall; +define pcodeop swap4; +define pcodeop swap8; +define pcodeop swap12; +define pcodeop waiti; +define pcodeop wdtlb; +define pcodeop wer; +define pcodeop witlb; +define pcodeop wsr; +define pcodeop wur; +define pcodeop xsr; + diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc index 027733a3bc..8ef5613bcf 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc +++ b/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc @@ -1,162 +1,172 @@ + + # 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; + 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); + 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; + 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; + 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; + 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 + s8_16_23; + at = as + s8_16_23; } # 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; + 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); + at = as + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + local test:4 = ~as & at; + if (test == 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; + local test:4 = as & at; + if (test == 0) goto srel_16_23; } -macro extract_bit(val, bit, result) { - result = (val >> bit)&1; +macro extract_bit(bit, result) { +@if ENDIAN == "big" + result = 0x80000000 >> bit; +@else + result = 0x1 << bit; +@endif } # 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; + local bval:4 = 0; + extract_bit(at[0,5], bval); + bval = as & 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; + local bval; + extract_bit(u5_4_7_12, bval); + bval = as & 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; + local bval; + extract_bit(at[0,5], bval); + bval = as & 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; + local bval; + extract_bit(u5_4_7_12, bval); + bval = as & bval; + if (bval != 0) + goto srel_16_23; } # BEQ - Branch if Equal, pg. 272. @@ -287,12 +297,14 @@ macro extract_bit(val, bit, result) { # 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_inst:4 = inst_start; + breakpoint(0x001000:4, break_inst, 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); + break_inst:4 = inst_start; + breakpoint(0x010000:4, break_inst, n_u4_8_11:1, 0:1); } # BT - Branch if True, pg. 296. @@ -303,224 +315,179 @@ macro extract_bit(val, bit, result) { # CALL0 - Non-windowed Call, pg. 297. :call0 srel_6_23_sb2 is srel_6_23_sb2 & u2_4_5 = 0 & op0 = 0b0101 { - #local dst = srel_6_23_sb2; - i2 = a2; - i3 = a3; - i4 = a4; - i5 = a5; - i6 = a6; - i7 = a7; - a0 = inst_start + 3; - call srel_6_23_sb2; + $(PS_CALLINC) = 0; + a0 = inst_next; + call srel_6_23_sb2; } # 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 { - #local dst = srel_6_23_sb2; - i2=a6; - i3=a7; - i4=a8; - i5=a9; - a0 = inst_start + 3; - call srel_6_23_sb2; - a6=o2; +:call4 srel_6_23_sb2 is srel_6_23_sb2 & Ret4 & u2_4_5 = 0b01 & op0 = 0b0101 { + $(PS_CALLINC) = 1; + a4 = Ret4; + swap4(); + call srel_6_23_sb2; + restore4(); } # 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 { - #local dst:4 = - i2=a10; - i3=a11; - i4=a12; - i5=a13; - i6=a14; - i7=a15; - a0 = inst_start + 3; - call srel_6_23_sb2; - a10=o2; +:call8 srel_6_23_sb2 is srel_6_23_sb2 & Ret8 & u2_4_5 = 0b10 & op0 = 0b0101 { + $(PS_CALLINC) = 2; + a8 = Ret8; + swap8(); + call srel_6_23_sb2; + restore8(); } # 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 { - #local dst = srel_6_23_sb2; - i2=a14; - i3=a15; - a0 = inst_start + 3; - call srel_6_23_sb2; - a14=o2; +:call12 srel_6_23_sb2 is srel_6_23_sb2 & Ret12 & u2_4_5 = 0b11 & op0 = 0b0101 { + $(PS_CALLINC) = 3; + a12 = Ret12; + swap12(); + call srel_6_23_sb2; + restore12(); } # 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; - i2 = a2; - i3 = a3; - i4 = a4; - i5 = a5; - i6 = a6; - i7 = a7; - a0 = inst_start + 3; - call [dst]; + $(PS_CALLINC) = 0; + local dst = as; + a0 = inst_next; + call [dst]; } # 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 { - local dst = as; - i2=a6; - i3=a7; - i4=a8; - i5=a9; - i6=a10; - i7=a11; - a0 = inst_start + 3; - call [dst]; - a6=o2; +:callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret4 & u2_6_7 = 0b11 & u2_4_5 = 0b01 & op0 = 0 { + $(PS_CALLINC) = 1; + dest:4 = as; + a4 = Ret4; + swap4(); + call [dest]; + restore4(); } # 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 { - local dst = as; - i2=a10; - i3=a11; - i4=a12; - i5=a13; - i6=a14; - i7=a15; - a0 = inst_start + 3; - call [dst]; - a10=o2; +:callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret8 & u2_6_7 = 0b11 & u2_4_5 = 0b10 & op0 = 0 { + $(PS_CALLINC) = 2; + dest:4 = as; + a8 = Ret8; + swap8(); + call [dest]; + restore8(); } # 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 { - local dst = as; - i2=a14; - i3=a15; - a0 = inst_start + 3; - call [dst]; - a14=o2; +:callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret12 & u2_6_7 = 0b11 & u2_4_5 = 0b11 & op0 = 0 { + $(PS_CALLINC) = 3; + dest:4 = as; + a12 = Ret12; + swap12(); + call [dest]; + restore12(); } # 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); + local scale:4 = 1 << u4_4_7; + ar = ceil(fs f* int2float(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 + # ar min(max(as, -2^{u5_4_7_plus7}), 2^{u5_4_7_plus7}-1) + local x:4 = as; + local clamp:4 = 1 << u5_4_7_plus7; + local mt:1 = (x s> (-clamp)); + local max:4 = (zext(mt) * x) + (zext(!mt) * (-clamp)); + mt = (x s< (clamp-1)); + local y = (zext(mt) * max) + (zext(!mt) * (clamp-1)); } # 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)); + dhi(as + 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)); +:dhu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { + dhu(as + 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)); + dhwb(as + 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)); + dhwbi(as + 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)); + dii(as + 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)); +:diu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { + diu(as + 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)); +:diwb as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0100 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { + diwb(as + 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)); +:diwbi as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0101 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { + diwbi(as + 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)); +:dpfl as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { + dpfl(as + 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)); + dpfr(as + 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)); + dpfro(as + 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)); + dpfw(as + 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)); + dpfwo(as + 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(); + dsync(); } # 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 { - local amn = sext(u15_12_23_sb3); - a2=i2; - a3=i3; - a4=i4; - a5=i5; - a6=i6; - a7=i7; - #as = as + amn; - WindowBase = amn; - a1 = a1 - amn; + local callSP = a1; + callinc:1 = $(PS_CALLINC); + rotateRegWindow(callinc); + as = callSP - zext(u15_12_23_sb3); } # ESYNC - Execute Synchronize, pg. 342. :esync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0010 & op0 = 0 { - esync(); + esync(); } # EXCW - Exception Wait, pg. 343. :excw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1000 & op0 = 0 { - excw(); + excw(); } # EXTUI - Extract Unsigned Immediate, pg. 344. @@ -532,75 +499,76 @@ macro extract_bit(val, bit, result) { # EXTW - External Wait, pg. 345. :extw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1101 & op0 = 0 { - extw(); + 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; + local scale:4 = 1 << u4_4_7; + fr = int2float(as) f/ int2float(scale); } # 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); + local scale:4 = 1 << u4_4_7; + ar = floor(fs f* int2float(scale)); } # IDTLB - Invalidate Data TLB Entry, pg. 348. :idtlb as is op2 = 0b0101 & op1 = 0 & ar = 0b1100 & as & at = 0 & op0 = 0 { - idtlb(); + 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)); + ihi(as + 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)); +:ihu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { + ihu(as + 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)); + iii(as + 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); + 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)); +:iiu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { + iiu(as + u8_20_23_sb4); } # ILL - Illegal Instruction, pg. 358. :ill is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & at = 0 & op0 = 0 { - ill(); + 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(); + 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)); + ipf(as + 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)); +:ipfl as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { + ipfl(as + 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(); + isync(); } # J - Unconditional Jump, pg. 366. @@ -610,31 +578,12 @@ macro extract_bit(val, bit, result) { # J.L is a macro. +# The manual suggests that RET is equivalent to JX A0, yet RET has bit 5 unset, JX doesn’t. # 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]; } -# RETW - Windowed Return, pg. 480. -:retw is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6_7 = 0b10 & u2_4_5 = 0b01 & op0 = 0 { -# Assume call8 - o2=a2; - a1 = a1 + WindowBase; - return [a0]; -} - -# RETW.N - Narrow Windowed Return, pg. 482. -:retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 { - o2=a2; - a1 = a1 + WindowBase; - 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]; @@ -648,32 +597,38 @@ macro extract_bit(val, bit, result) { # 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); + local addr:4 = as + 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); + local addr:4 = as + 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); + local addr:4 = as + u10_16_23_sb2; + at = *:4 addr; + acquire(addr); +} + +# 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 { + ptr:4 = as + sext(s5_12_15_oex); + at = *:4 ptr; } # 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); + local addr:4 = as + 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); + local addr:4 = n_as + n_u6_12_15_sb2; n_at = *:4 addr; } @@ -684,172 +639,129 @@ macro extract_bit(val, bit, result) { # LDCT - Load Data Cache Tag, pg. 384. :ldct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1000 & as & at & op0 = 0 { - at = ldct(as); + 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); + 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); -} - -macro loopSetup(as, end, doit) { - LCOUNT = as - 1; - LBEG = inst_next; - #LEND = end; - if (doit) goto ; - goto end; - -} - -# LOOP - Loop, pg. 392. -:loop as, urel_16_23 is urel_16_23 & ar=0b1000 & as & at=0b0111 & op0=0b0110 -[loopEnd=1; globalset(urel_16_23, loopEnd);] { - loopSetup(as, urel_16_23, 1:1); -} - -# LOOPGTZ - Loop if Greater Than Zero, pg. 394. -:loopgtz as, urel_16_23 is urel_16_23 & ar=0b1010 & as & at=0b0111 & op0=0b0110 -[loopEnd=1; globalset(urel_16_23, loopEnd);] { - loopSetup(as, urel_16_23, as s> 0); -} - -# LOOPNEZ - Loop if Not Equal Zero, pg. 396. -:loopnez as, urel_16_23 is urel_16_23 & ar=0b1001 & as & at=0b0111 & op0=0b0110 -[loopEnd=1; globalset(urel_16_23, loopEnd);] { - loopSetup(as, urel_16_23, as != 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; + local addr:4 = as + 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; + local addr:4 = as + 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; + 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; + 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); + 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; + test:1 = as s< at; + ar = (zext(test) * at) + (zext(!test) * 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; + test:1 = as < at; + ar = (zext(test) * at) + (zext(!test) * as); } # MEMW - Memory Wait, pg. 409. :memw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1100 & op0 = 0 { - memw(); + 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; + test:1 = as s< at; + ar = (zext(test) * as) + (zext(!test) * at); } # 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; + test:1 = as < at; + ar = (zext(test) * as) + (zext(!test) * at); } # 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; + 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; + 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; + if (at != 0) goto ; + 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; + if (at != 0) goto ; + 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; + if (bt) goto ; + 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; + if (bt)goto ; + 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; + if (at s< 0) goto ; + 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; + if (at s< 0) goto ; + fr = fs; + } # MOVI - Move Immediate, pg. 421. @@ -858,7 +770,6 @@ macro loopSetup(as, end, doit) { 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); @@ -867,95 +778,100 @@ macro loopSetup(as, end, doit) { # 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; + if (at s>= 0) goto ; + 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; + if (at s>= 0) goto ; + 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; + if (at == 0) goto ; + 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; + if (at == 0) goto ; + fr = fs; + +} + +# MOVSP - Move to Stack Pointer, pg. 427. +:movsp at, as is op2 = 0 & op1 = 0 & ar = 0b0001 & as & at & op0 = 0 { + at = (zext(WindowStart == 0) * at) + (zext(WindowStart != 0) * as); } # 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; + if (!bt) goto ; + 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; + if (!bt) goto ; + 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); + 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; + 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); + 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); + 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; + 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); + 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); + 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; + 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; + fr = 0 f- fs; } # NOP - No Operation, pg. 459. @@ -976,88 +892,103 @@ macro loopSetup(as, end, doit) { # 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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); + 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); + 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; + 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; + 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); + 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); + 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; + 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; + 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); + 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 { + o2=a2; return [a0]; +} + +# RETW - Windowed Return, pg. 480. +:retw is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6_7 = 0b10 & u2_4_5 = 0b01 & op0 = 0 { +# Assume call8 o2=a2; + a1 = a1 + WindowBase; + return [a0]; +} + +# RETW.N - Narrow Windowed Return, pg. 482. +:retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 { + o2=a2; + a1 = a1 + WindowBase; + return [a0]; } # RFDD - Return from Debug and Dispatch, pg. 484. @@ -1084,21 +1015,25 @@ macro loopSetup(as, end, doit) { return [tmp]; } +rfi_epc: ptr is u4_8_11 [ ptr = $(EPC_BASE) + (4 * u4_8_11); ] { export *[register]:4 ptr; } +rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[register]:4 ptr; } + # 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 { - local tmp:4 = rfi(u4_8_11:1); - return [tmp]; +:rfi u4_8_11 is op2 = 0 & op1 = 0 & ar = 0b0011 & u4_8_11 & at = 0b0001 & op0 = 0 & rfi_epc & rfi_eps { + PS = rfi_eps; + return [rfi_epc]; } # RFME - Return from Memory Error, pg. 489. :rfme is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0 & at = 0b0010 & op0 = 0 { - local tmp:4 = rfme(); - return [tmp]; + PS = MEPS; + MESR[0,1] = 0; + return [MEPC]; } # RFR - Move FR to AR, pg. 490. :rfr ar, fs is op2 = 0b1111 & op1 = 0b1010 & ar & fs & at = 0b0100 & op0 = 0 { - ar = fs; + ar = fs; } # RFUE - Return from User-Mode Exception, pg. 491. @@ -1109,24 +1044,26 @@ macro loopSetup(as, end, doit) { # RFWO - Return from Window Overflow, pg. 492. :rfwo is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0100 & at = 0 & op0 = 0 { - local tmp:4 = rfwo(); - return [tmp]; + $(PS_EXCM) = 0; + rfwo(); + return [EPC1]; } # RFWU - Return from Window Underflow, pg. 493. :rfwu is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0101 & at = 0 & op0 = 0 { - local tmp:4 = rfwu(); - return [tmp]; + $(PS_EXCM) = 0; + rfwu(); + return [EPC1]; } # 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); + 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); + at = ritlb1(as); } # ROTW - Rotate Window, pg. 496. @@ -1136,8 +1073,17 @@ macro loopSetup(as, end, doit) { # 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); + local scale:4 = 1 << u4_4_7; + local result = fs f* int2float(scale); + isNan:1 = nan(result); + if (isNan) goto ; + ar = round(fs f* scale); + goto ; + + ar = 0x80000000; + if (fs f< 0) goto ; + ar = 0x7fffffff; + } # RSIL - Read and Set Interrupt Level, pg. 498. @@ -1147,20 +1093,19 @@ macro loopSetup(as, end, doit) { # RSR - Read Special Register, pg. 500. :rsr at, sr is op0 = 0 & op1 = 0b0011 & sr & at & op0 = 0 { - local src:4 = zext(sr); - at = *[register]:4 src; + at = rsr(sr:1); } # RSYNC - Register Read Synchronize, pg. 502. :rsync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0001 & op0 = 0 { - rsync(); + 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); @@ -1169,77 +1114,81 @@ macro loopSetup(as, end, doit) { # 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); + local addr:4 = as + 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); + local addr:4 = as + u10_16_23_sb2; + old:4 = *:4 addr; + if (old != SCOMPARE1) goto ; + *:4 addr = at; + + at = old; } # 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 { - #local vAddr:4 = as + s5_12_15_oex; - #*:4 vAddr = at; + ptr:4 = as + sext(s5_12_15_oex); + *:4 ptr = at; } # 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); + local addr:4 = as + 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); + local addr:4 = n_as + 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); + local addr:4 = as + u10_16_23_sb2; + release(addr); + *:4 addr = at; } # SDCT - Store Data Cache Tag, pg. 516. :sdct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1001 & as & at & op0 = 0 { - sdct(as, at); + 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; + local shift:4 = 31 - 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); + 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); + sicw(as, at); } # SIMCALL - Simulator Call, pg. 523. :simcall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0b0001 & at = 0 & op0 = 0 { - simcall(); + simcall(); } # SLL - Shift Left Logical, pg. 524. :sll ar, as is op2 = 0b1010 & op1 = 0b0001 & ar & as & at = 0 & op0 = 0 { - local sa = 32 - SAR; - ar = as << sa; + local sa:4 = 32 - SAR; + ar = as << sa; } # SLLI - Shift Left Logical Immediate, pg. 525. -:slli ar, as, u5_4_7_20_slli is u3_21_23 = 0 & u5_4_7_20_slli & op1 = 0b0001 & ar & as & op0 = 0 { - ar = as << u5_4_7_20_slli; +:slli ar, as, u5_4_7_20 is u3_21_23 = 0 & u5_4_7_20 & op1 = 0b0001 & ar & as & op0 = 0 { + ar = as << u5_4_7_20; } # SRA - Shift Right Arithmetic, pg. 526. @@ -1279,25 +1228,26 @@ macro loopSetup(as, end, doit) { # SSA8L - Set Shift Amount for LE Byte Shift, pg. 532. :ssa8l as is op2 = 0b0100 & op1 = 0 & ar = 0b0010 & as & at = 0 & op0 = 0 { - SAR = (as&3)*8; + local rsa:4 = (as & 3)*8; + SAR = rsa; } # 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 = zext(u5_8_11_4); + SAR = u5_8_11_4; } # 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; + local addr:4 = as + 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; + local addr:4 = as + u10_16_23_sb2; + *:4 addr = ft; + as = addr; } # SSL - Set Shift Amount for Left Shift, pg. 538. @@ -1312,81 +1262,87 @@ macro loopSetup(as, end, doit) { # SSX - Store Single 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; + local addr:4 = as+at; + *:4 addr = fr; } # SSXU - Store Single 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; + 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; + 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; + 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; + 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; + 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; + ar = (as << 3) - at; } # SYSCALL - System Call, pg. 547. :syscall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0 & at = 0 & op0 = 0 { - syscall(); + 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); + local scale:4 = 1 << u4_4_7; + local result = fs f* int2float(scale); + isNan:1 = nan(result); + if (isNan) goto ; + ar = trunc(fs f* scale); + goto ; + + ar = 0x80000000; + if (fs f< 0) goto ; + ar = 0x7fffffff; + } # 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; + 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; + local tmp:8 = zext(as); + local scale:4 = 1 << u4_4_7; + fr = int2float(tmp) f/ int2float(scale); } # 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; + 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; + 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); + br = nan(fs) || nan(ft); } # UTRUNC.S - Truncate Single to Fixed Unsigned, pg. 555. @@ -1406,96 +1362,558 @@ macro loopSetup(as, end, doit) { # WDTLB - Write Data TLB Entry, pg. 557. :wdtlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1110 & as & at & op0 = 0 { - wdtlb(as, at); + 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); + 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; + 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); + witlb(as, at); } # WSR - Write Special Register, pg. 561. :wsr at, sr is op2 = 0b0001 & op1 = 0b0011 & sr & at & op0 = 0 { - local dst:4 = zext(sr); - *[register]:4 dst = at; + wsr(sr: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); +:wur at, sr is op2 = 0b1111 & op1 = 0b0011 & sr & at & op0 = 0 { + wur(sr: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; + 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; + 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); -} - -# PAD, dummy -:pad is op0_16=0x0 { -} - -# PAD, dummy -:pad is op0_8=0x0 { +:xsr at, sr is op2 = 0b0110 & op1 = 0b0001 & sr & at & op0 = 0 { + at = xsr(sr:1, at); } ## MAC16 option ## -# This produces correct pcode, tho it would be nicer to display the float in disasm as well -# +0.0 +1.0 +2.0 +0.5 -const.s_imm: tmp is as=0 [ tmp = 0x00000000; ] { export *[const]:4 tmp; } -const.s_imm: tmp is as=1 [ tmp = 0x3F800000; ] { export *[const]:4 tmp; } -const.s_imm: tmp is as=2 [ tmp = 0x40000000; ] { export *[const]:4 tmp; } -const.s_imm: tmp is as=3 [ tmp = 0x3F000000; ] { export *[const]:4 tmp; } - -:const.s fr, const.s_imm is op2=0b1111 & op1=0b1010 & fr & const.s_imm & at=0b0011 & op0=0 { - fr = float2float(const.s_imm); +# LDDEC - Load with Autodecrement, pg. 386. +:lddec "MAC16_REGS[" mw_12_13 "]", as is op2 = 0b1001 & op1 = 0 & u2_14_15 = 0 & mw_12_13 & as & at = 0 & op0 = 0b0100 { + local ptr:4 = as - 4; + mw_12_13 = *:4 ptr; + as = ptr; } -# Stub out some insns which mainly appear in boilerplate library functions... -:div0.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b0111 & op0=0 unimpl -:sqrt0.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1001 & op0=0 unimpl -:nexp01.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1011 & op0=0 unimpl -:mksadj.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1100 & op0=0 unimpl -:mkdadj.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1101 & op0=0 unimpl -:addexp.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1110 & op0=0 unimpl -:addexpm.s fr, fs is op2=0b1111 & op1=0b1010 & fr & fs & at=0b1111 & op0=0 unimpl -:maddn.s fr, fs, ft is op2=0b0110 & op1=0b1010 & fr & fs & ft & op0=0 unimpl -:divn.s fr, fs, ft is op2=0b0111 & op1=0b1010 & fr & fs & ft & op0=0 unimpl - -# UNIMPLEMENTED -# - Windowed Register Option - -# 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 - -# 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 +:ldinc "MAC16_REGS[" mw_12_13 "]", as is op2 = 0b1000 & op1 = 0 & u2_14_15 = 0 & mw_12_13 & as & at = 0 & op0 = 0b0100 { + local ptr:4 = as + 4; + mw_12_13 = *:4 ptr; + as = ptr; +} + +# MUL.AA.* - Signed Multiply, pg. 431. +:mul.aa.ll as, at is op2 = 0x7 & op1 = 0x4 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} +:mul.aa.hl as, at is op2 = 0x7 & op1 = 0x5 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.aa.lh as, at is op2 = 0x7 & op1 = 0x6 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.aa.hh as, at is op2 = 0x7 & op1 = 0x7 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +# MUL.AD.* - Signed Multiply, pg. 432. +:mul.ad.ll as, m2m3_6_6 is op2 = 0x3 & op1 = 0x4 & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.ad.hl as, m2m3_6_6 is op2 = 0x3 & op1 = 0x5 & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} +:mul.ad.lh as, m2m3_6_6 is op2 = 0x3 & op1 = 0x6 & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} +:mul.ad.hh as, m2m3_6_6 is op2 = 0x3 & op1 = 0x7 & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +# MUL.AD.* - Signed Multiply, pg. 433. +:mul.da.ll m0m1_14_14, at is op2 = 0x6 & at & op1 = 0x4 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.da.hl m0m1_14_14, at is op2 = 0x6 & op1 = 0x5 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.da.lh m0m1_14_14, at is op2 = 0x6 & op1 = 0x6 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.da.hh m0m1_14_14, at is op2 = 0x6 & op1 = 0x7 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +# MUL.AD.* - Signed Multiply, pg. 434. +:mul.dd.ll m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x4 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.dd.hl m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x5 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.dd.lh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x6 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} + +:mul.dd.hh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x7 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = sext(M1:2) * sext(M2:2); +} # MULA.AA.* - Signed Multiply, pg. 431. -:mula.aa.* as, at is op2 = 0b0001 & u2_18_19 = 0b01 & ar = 0 & as & at & op0 = 0b0100 unimpl +:mula.aa.ll as, at is op2 = 0x7 & op1 = 0x8 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} +:mula.aa.hl as, at is op2 = 0x7 & op1 = 0x9 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.aa.lh as, at is op2 = 0x7 & op1 = 0xa & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.aa.hh as, at is op2 = 0x7 & op1 = 0xb & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.ad.ll as, m2m3_6_6 is op2 = 0x3 & op1 = 0x8 & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.ad.hl as, m2m3_6_6 is op2 = 0x3 & op1 = 0x9 & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} +:mula.ad.lh as, m2m3_6_6 is op2 = 0x3 & op1 = 0xa & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} +:mula.ad.hh as, m2m3_6_6 is op2 = 0x3 & op1 = 0xb & ar = 0 & as & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.da.ll m0m1_14_14, at is op2 = 0x6 & at & op1 = 0x8 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.da.hl m0m1_14_14, at is op2 = 0x6 & op1 = 0x9 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.da.lh m0m1_14_14, at is op2 = 0x6 & op1 = 0xa & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.da.hh m0m1_14_14, at is op2 = 0x6 & op1 = 0xb & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.dd.ll m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x8 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.dd.hl m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x9 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.dd.lh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0xa & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +:mula.dd.hh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0xb & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); +} + +# Signed Mult/Accum, Ld/Autodec MULA.DA.*.LDDEC, pg. 441. +:mula.da.ll.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & at & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.hl.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.lh.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.hh.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +# Signed Mult/Accum, Ld/Autoinc MULA.DA.*.LDINC, pg. 443. +:mula.da.ll.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & at & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.hl.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.lh.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.hh.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +# Signed Mult/Accum, Ld/Autodec MULA.DD.*.LDDEC, pg. 446. +:mula.dd.ll.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.dd.hl.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.dd.lh.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.dd.hh.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + local vaddr:4 = as - 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +# Signed Mult/Accum, Ld/Autoinc MULA.DD.*.LDINC, pg. 448. +:mula.da.ll.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.hl.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14:2; + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.lh.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +:mula.da.hh.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & u2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { + local vaddr:4 = as + 4; + tm1:2 = m0m1_14_14(2); + tm2:2 = m2m3_6_6(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = ACC + (sext(M1:2) * sext(M2:2)); + as = vaddr; + mw_12_13 = *:4 vaddr; +} + +# UMUL.AA.* - Unsigned Multiply, pg. 553. +:umul.aa.ll as, at is op2 = 0x7 & op1 = 0x0 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = zext(M1:2) * zext(M2:2); +} +:umul.aa.hl as, at is op2 = 0x7 & op1 = 0x1 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = at:2; + M1 = zext(tm1); + M2 = zext(tm2); + ACC = zext(M1:2) * zext(M2:2); +} + +:umul.aa.lh as, at is op2 = 0x7 & op1 = 0x2 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as:2; + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = zext(M1:2) * zext(M2:2); +} + +:umul.aa.hh as, at is op2 = 0x7 & op1 = 0x3 & ar = 0 & as & at & op0 = 0x4 { + tm1:2 = as(2); + tm2:2 = at(2); + M1 = zext(tm1); + M2 = zext(tm2); + ACC = zext(M1:2) * zext(M2:2); +} + +## Loop Option ## + +LoopOffset8: loc is u8_16_23 [ loc = inst_start + u8_16_23 + 4; ] { export *:4 loc; } + +# LOOP - Loop, pg. 392. +:loop as, LoopOffset8 is LoopOffset8 & ar = 8 & as & at = 0b0111 & op0 = 6 + [ loopMode=1; loopEnd = 1; globalset(LoopOffset8, loopEnd); ] { + LCOUNT = as - 1; + LBEG = inst_next; + LEND = &LoopOffset8; +} + +# LOOPGTZ - Loop if Greater Than Zero, pg. 394. +:loopgtz as, LoopOffset8 is LoopOffset8 & ar = 0b1010 & as & at = 0b0111 & op0 = 0b0110 + [ loopMode=1; loopEnd = 1; globalset(LoopOffset8, loopEnd); ] { + LCOUNT = as - 1; + LBEG = inst_next; + LEND = &LoopOffset8; + if (as s<= 0) goto LoopOffset8; +} + +# LOOPNEZ - Loop if Not Equal Zero, pg. 396. +:loopnez as, LoopOffset8 is LoopOffset8 & ar = 0b1001 & as & at = 0b0111 & op0 = 0b0110 + [ loopMode=1; loopEnd = 1; globalset(LoopOffset8, loopEnd); ] { + LCOUNT = as - 1; + LBEG = inst_next; + LEND = &LoopOffset8; + if (as == 0) goto LoopOffset8; +} diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc new file mode 100644 index 0000000000..dd13ae72fb --- /dev/null +++ b/Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc @@ -0,0 +1,116 @@ +# 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. + +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]:4 tmp; } +u5_4_7_20: tmp is u1_20 & u4_4_7 [ tmp = 32 - ((u1_20 << 4) | u4_4_7); ] { export *[const]:4 tmp; } +u5_8_11_16: tmp is u1_16 & u4_8_11 [ tmp = (u1_16 << 4) | u4_8_11; ] { export *[const]:4 tmp; } +u5_4_7_12: tmp is u1_12 & u4_4_7 [ tmp = (u1_12 << 4) | u4_4_7; ] { export *[const]:4 tmp; } +u5_8_11_4: tmp is u1_4 & u4_8_11 [ tmp = (u1_4 << 4) | u4_8_11; ] { export *[const]:4 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]:4 tmp; } +u15_12_23_sb3: tmp is u12_12_23 [ tmp = u12_12_23 << 3; ] { export *[const]:4 tmp; } +u10_16_23_sb2: tmp is u8_16_23 [ tmp = u8_16_23 << 2; ] { export *[const]:4 tmp; } +u9_16_23_sb1: tmp is u8_16_23 [ tmp = u8_16_23 << 1; ] { export *[const]:4 tmp; } +u5_20_23_plus1: tmp is u4_20_23 [ tmp = u4_20_23 + 1; ] { export *[const]:4 tmp; } +u8_20_23_sb4: tmp is u4_20_23 [ tmp = u4_20_23 << 4; ] { export *[const]:4 tmp; } +u5_4_7_plus7: tmp is u4_4_7 [ tmp = u4_4_7 + 7; ] { export *[const]:4 tmp; } + +n_u6_12_15_sb2: tmp is n_u4_12_15 [ tmp = n_u4_12_15 << 2; ] { export *[const]:4 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 = (u4_12_15 << 2) - 64; ] { 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; } + +Ret4: loc is epsilon [loc = ((inst_start + 3) & 0x0fffffff) | 0x40000000; ] { ret:4 = loc; export ret; } +Ret8: loc is epsilon [loc = ((inst_start + 3) & 0x0fffffff) | 0x80000000; ] { ret:4 = loc; export ret; } +Ret12: loc is epsilon [loc = ((inst_start + 3) & 0x0fffffff) | 0xc0000000; ] { ret:4 = loc; export ret; } + +:^instruction is phase=0 & loopMode=1 & instruction [ phase=1; ] { + build instruction; + if (LCOUNT == 0 || $(PS_EXCM)) goto inst_next; + LCOUNT = LCOUNT - 1; + goto [LBEG]; +} +:^instruction is phase=0 & loopMode=1 & loopEnd=1 & instruction + [ loopMode=0; phase=1; ] { + build instruction; +} + +:^instruction is phase=0 & loopMode=0 & instruction + [ phase=1; ] { + build instruction; +} diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaTodo.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaTodo.sinc deleted file mode 100644 index b89eea56e8..0000000000 --- a/Ghidra/Processors/Xtensa/data/languages/xtensaTodo.sinc +++ /dev/null @@ -1,66 +0,0 @@ -## 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/languages/xtensa_be.slaspec b/Ghidra/Processors/Xtensa/data/languages/xtensa_be.slaspec new file mode 100644 index 0000000000..e3d7f63a38 --- /dev/null +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa_be.slaspec @@ -0,0 +1,12 @@ +@define ENDIAN "big" +@include "xtensaArch.sinc" +@include "xtensaMain.sinc" + +with : phase=1 { + +@include "xtensaInstructions.sinc" +#@include "xtensa_depbits.sinc" #comment floating-point and uncomment this to use depbits +@include "cust.sinc" +@include "flix.sinc" + +} \ No newline at end of file diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc new file mode 100644 index 0000000000..ccf799116e --- /dev/null +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc @@ -0,0 +1,11 @@ +# Xtensa Deposit Bits instruction +# This is broken out because it collides with the floating point instructions. It is not included by default + +# DEPBITS - Add (RRR), pg. 394. +shiftimm: simm is u4_20_23 & u1_16 [ simm = u1_16 << 4 + u4_20_23; ] { export *[const]:4 simm; } +:depbits as, at, shiftimm, u4_12_15 is u3_17_19=0x5 & u4_12_15 & as & at & op0 = 0 & shiftimm { + mask:4 = (1 << u4_12_15) - 1; + bits:4 = (as & mask) << shiftimm; + mask = mask << shiftimm; + at = (~mask & at) | bits; +} diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa_le.slaspec b/Ghidra/Processors/Xtensa/data/languages/xtensa_le.slaspec new file mode 100644 index 0000000000..dab1dac032 --- /dev/null +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa_le.slaspec @@ -0,0 +1,12 @@ +@define ENDIAN "little" +@include "xtensaArch.sinc" +@include "xtensaMain.sinc" + +with : phase=1 { + +@include "xtensaInstructions.sinc" +#@include "xtensa_depbits.sinc" #comment floating-point and uncomment this to use depbits +@include "cust.sinc" +@include "flix.sinc" + +} diff --git a/Ghidra/Processors/Xtensa/data/manuals/xtensa.idx b/Ghidra/Processors/Xtensa/data/manuals/xtensa.idx index e98296d090..d8025054d8 100644 --- a/Ghidra/Processors/Xtensa/data/manuals/xtensa.idx +++ b/Ghidra/Processors/Xtensa/data/manuals/xtensa.idx @@ -1,242 +1,354 @@ -@xtensa.pdf[Xtensa® Instruction Set Architecture (ISA) Reference Manual, April 2010] +@isa_summary.pdf[Xtensa® Instruction Set Architecture Summary, For all Xtensa LX Processors April 2022] -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 +ABS, 324 +ABS.D, 324 +ABS.S, 325 +ADD, 326 +ADD.N, 326 +ADD.D, 327 +ADD.S, 328 +ADDEXP.D, 329 +ADDEXP.S, 329 +ADDEXPM.D, 330 +ADDEXPM.S, 331 +ADDI, 332 +ADDI.N, 333 +ADDMI, 334 +ADDX2, 335 +ADDX4, 336 +ADDX8, 336 +ALL4, 337 +ALL8, 338 +AND, 339 +ANDB, 339 +ANDBC, 340 +ANY4, 341 +ANY8, 341 +BALL, 342 +BANY, 343 +BBC, 344 +BBCI, 345 +BBCI.L, 346 +BBS, 347 +BBSI, 348 +BBSI.L, 349 +BEQ, 349 +BEQI, 350 +BEQZ, 351 +BEQZ.N, 352 +BF, 353 +BGE, 354 +BGEI, 355 +ixBGEU, 356 +BGEUI, 357 +BGEZ, 358 +BLT, 359 +BLTI, 360 +BLTU, 361 +BLTUI, 361 +BLTZ, 362 +BNALL, 363 +BNE, 364 +BNEI, 365 +BNEZ, 366 +BNEZ.N, 367 +BNONE, 368 +BREAK, 369 +BREAK.N, 370 +BT, 371 +CALL0, 372 +CALL4 373 +CALL8, 375 +CALL12, 376 +CALLX0, 377 +CALLX4, 378 +CALLX8, 379 +CALLX12, 380 +CEIL.D, 382 +CEIL.S, 383 +CLAMPS, 383 +CLREX, 384 +CONST.D, 385 +CONST.S, 386 +CONST16, 387 +CVTD.S, 388 +CVTS.D, 389 +DCI, 389 +DCWB, 391 +DCWBI, 392 +DEPBITS, 394 +DHI, 395 +DHI.B, 396 +DHU, 397 +DHWB, 398 +DHWB.B, 400 +DHWBI, 400 +DHWBI.B, 402 +xDII, 403 +DIU, 404 +DIV0.D, 406 +DIV0.S, 406 +DIVN.D, 407 +DIVN.S, 408 +DIWB, 409 +DIWBI, 410 +DIWBUI.P, 412 +DPFL, 413 +DPFM.B, 415 +DPFM.BF, 416 +DPFR, 416 +DPFR.B, 418 +DPFR.BF, 419 +DPFRO, 419 +DPFW, 421 +DPFW.B, 422 +DPFW.BF, 423 +DPFWO, 424 +DSYNC, 425 +ENTRY, 426 +ESYNC, 427 +EXCW, 428 +EXTUI, 429 +EXTW, 430 +FLOAT.D, 431 +FLOAT.S, 431 +FLOOR.D, 432 +FLOOR.S, 433 +FSYNC, 434 +GETEX, 434 +IDTLB, 435 +IHI, 436 +IHU, 438 +III, 439 +IITLB, 441 +IIU, 442 +ILL, 443 +ILL.N, 444 +IPF, 444 +IPFL, 446 +ISYNC, 447 +J, 449 +J.L, 449 +JX, 450 +L8UI, 450 +L16SI, 451 +L16UI, 453 +L32AI, 454 +L32E, 455 +L32EX, 457 +L32I, 458 +L32I.N, 459 +L32R, 461 +LDCT, 463 +LDCW, 464 +LDDEC, 465 +LDDR32.P, 467 +LDI, 467 +LDINC, 468 +LDIP, 469 +LDX, 471 +LDXP, 472 +LOOP, 473 +LOOPGTZ, 475 +LOOPNEZ, 476 +LSI, 478 +LSIP, 480 +LSIU, 481 +LSX, 482 +LSXP, 483 +LSXU, 484 +MADD.D, 486 +MADD.S, 486 +MADDN.D, 487 +MADDN.S, 488 +MAX, 489 +MAXU, 489 +MEMW, 490 +MIN, 491 +MINU, 491 +MKDADJ.D, 492 +MKDADJ.S, 493 +MKSADJ.D, 494 +MKSADJ.S, 494 +MOV, 495 +MOV.D, 496 +MOV.N, 497 +MOV.S, 498 +MOVEQZ, 499 +MOVEQZ.D, 499 +MOVEQZ.S, 500 +MOVF, 501 +MOVF.D, 502 +MOVF.S, 503 +MOVGEZ, 504 +MOVGEZ.D, 504 +MOVGEZ.S, 505 +MOVI, 506 +MOVI.N, 507 +MOVLTZ, 508 +MOVLTZ.D, 509 +MOVLTZ.S, 510 +MOVNEZ, 510 +MOVNEZ.D, 511 +MOVNEZ.S, 512 +MOVSP, 513 +MOVT, 514 +MOVT.D, 515 +MOVT.S, 516 +MSUB.D, 517 +MSUB.S, 517 +MUL.AA.*, 518 +MUL.AD.*, 519 +MUL.DA.*, 520 +MUL.DD.*, 521 +MUL.D, 522 +MUL.S, 522 +MUL16S, 523 +MUL16U, 524 +MULA.AA.*, 524 +MULA.AD.*, 525 +MULA.DA.*, 526 +MULA.DA.*.LDDEC, 527 +MULA.DA.*.LDINC, 528 +MULA.DD.*, 530 +MULA.DD.*.LDDEC 531 +MULA.DD.*.LDINC 532 +MULL, 534 +MULS.AA.*, 535 +MULS.AD.*, 535 +MULS.DA.*, 536 +MULS.DD.*, 537 +MULSH, 538 +MULUH, 539 +NEG, 540 +NEG.D, 540 +NEG.S, 541 +NEXP01.D, 541 +NEXP01.S, 542 +NOP, 543 +NOP.N, 544 +NSA, 545 +NSAU, 546 +OEQ.D, 547 +OEQ.S, 547 +OLE.D, 548 +OLE.S, 549 +OLT.D, 550 +OLT.S, 551 +OR, 551 +ORB, 552 +ORBC, 553 +TLB, 553 +PITLB, 554 +PPTLB, 555 +QUOS, 556 +QUOU, 557 +RDTLB0, 558 +RDTLB1, 559 +RECIP0.D, 560 +RECIP0.S, 560 +REMS, 561 +REMU, 562 +RER, 563 +RET, 564 +RET.N, 564 +RETW, 565 +RETW.N, 567 +RFDD, 568 +RFDE, 569 +RFDO, 570 +RFE, 570 +RFI, 571 +RFME, 572 +RFR, 573 +RFRD, 573 +RFUE, 574 +RFWO, 575 +RFWU, 576 +RITLB0, 576 +RITLB1, 577 +ROTW, 578 +ROUND.D, 579 +ROUND.S, 580 +RPTLB0, 580 +RPTLB1, 581 +RSIL, 582 +RSQRT0.D, 583 +RSQRT0.S, 584 +RSR.*, 585 +RSYNC, 586 +RUR.*, 586 +S8I, 587 +S16I, 588 +S32C1I, 589 +S32E, 591 +S32EX, 592 +S32I, 594 +S32I.N, 595 +S32NB, 596 +S32RI, 597 +SALT, 599 +SALTU, 600 +SDDR32.P, 600 +SDI, 601 +SDIP, 602 +SDX, 603 +SDXP, 604 +SEXT, 605 +SICT, 606 +SICW, 607 +SIMCALL, 609 +SLL, 609 +SLLI, 610 +SQRT0.D, 611 +SQRT0.S, 612 +SRA, 613 +SRAI, 613 +SRC, 614 +SRL, 615 +SRLI, 616 +SSA8B, 616 +SSA8L, 617 +SSAI, 618 +SSI, 619 +SSIP, 620 +SSIU, 621 +SSL, 622 +SSR, 623 +SSX, 624 +SSXP, 625 +SSXU, 626 +SUB, 627 +SUB.D, 627 +SUB.S, 628 +SUBX2, 629 +SUBX4, 629 +SUBX8, 630 +SYSCALL, 631 +TRUNC.D, 632 +TRUNC.S, 632 +UEQ.D, 633 +UEQ.S, 634 +UFLOAT.D, 635 +UFLOAT.S, 636 +ULE.D, 636 +ULE.S, 637 +ULT.D, 638 +ULT.S, 639 +UMUL.AA.*, 639 +UN.D, 640 +UN.S, 641 +UTRUNC.D, 642 +UTRUNC.S, 642 +WAITI, 643 +WDTLB, 644 +WER, 645 +WFR, 646 +WFRD, 647 +WITLB, 648 +WPTLB, 649 +WSR.*, 650 +WUR.*, 651 +XOR, 652 +XORB, 652 +XSR.*, 653 diff --git a/Ghidra/Processors/Xtensa/src/main/help/help/TOC_Source.xml b/Ghidra/Processors/Xtensa/src/main/help/help/TOC_Source.xml deleted file mode 100644 index a34f62e8f1..0000000000 --- a/Ghidra/Processors/Xtensa/src/main/help/help/TOC_Source.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - diff --git a/Ghidra/Processors/Xtensa/src/main/help/help/topics/xtensa/help.html b/Ghidra/Processors/Xtensa/src/main/help/help/topics/xtensa/help.html deleted file mode 100644 index 1f9d6a1fc7..0000000000 --- a/Ghidra/Processors/Xtensa/src/main/help/help/topics/xtensa/help.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - Skeleton Help File for a Module - - - - -

Skeleton Help File for a Module

- -

This is a simple skeleton help topic. For a better description of what should and should not - go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your - favorite help topic. In general, language modules do not have their own help topics.

- - 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 index f74eb6d7ff..e5b9598490 100644 --- 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 @@ -1,3 +1,18 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ghidra.app.util.bin.format.elf.relocation; public class Xtensa_ElfRelocationConstants { 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 index f0033e4bed..279ebe4e1c 100644 --- 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 @@ -1,9 +1,21 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ 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.app.util.bin.format.elf.*; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; import ghidra.program.model.mem.MemoryAccessException; @@ -15,24 +27,25 @@ 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; + elf.e_machine() == Xtensa_ElfRelocationConstants.EM_XTENSA_OLD; } @Override - public RelocationResult relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation, Address relocationAddress) + public RelocationResult relocate(ElfRelocationContext elfRelocationContext, + ElfRelocation relocation, Address relocationAddress) throws MemoryAccessException, NotFoundException { ElfHeader elf = elfRelocationContext.getElfHeader(); if (!canRelocate(elf)) { return RelocationResult.FAILURE; } - int type=relocation.getType(); + int type = relocation.getType(); if (Xtensa_ElfRelocationConstants.R_XTENSA_NONE == type) { - return RelocationResult.FAILURE; + return RelocationResult.SKIPPED; } Program program = elfRelocationContext.getProgram(); - + ElfSymbol sym = null; String symbolName = null; @@ -47,243 +60,150 @@ public class Xtensa_ElfRelocationHandler extends ElfRelocationHandler { //int byteLength = 4; // most relocations affect 4-bytes (change if different) - switch(type) { - case Xtensa_ElfRelocationConstants.R_XTENSA_32: - markAsWarning(program, relocationAddress, "R_XTENSA_32", - symbolName, symbolIndex, "TODO, needs support ", + switch (type) { + case Xtensa_ElfRelocationConstants.R_XTENSA_32: + markAsWarning(program, relocationAddress, "R_XTENSA_32", symbolName, symbolIndex, + "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_RTLD: + markAsWarning(program, relocationAddress, "R_XTENSA_RTLD", symbolName, symbolIndex, + "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_GLOB_DAT: + markAsWarning(program, relocationAddress, "R_XTENSA_GLOB_DAT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_JMP_SLOT: + markAsWarning(program, relocationAddress, "R_XTENSA_JMP_SLOT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_RELATIVE: + markAsWarning(program, relocationAddress, "R_XTENSA_RELATIVE", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_PLT: + markAsWarning(program, relocationAddress, "R_XTENSA_PLT", symbolName, symbolIndex, + "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_OP0: + markAsWarning(program, relocationAddress, "R_XTENSA_OP0", symbolName, symbolIndex, + "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_OP1: + markAsWarning(program, relocationAddress, "R_XTENSA_OP1", symbolName, symbolIndex, + "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_OP2: + markAsWarning(program, relocationAddress, "R_XTENSA_OP2", symbolName, symbolIndex, + "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_EXPAND: + markAsWarning(program, relocationAddress, "R_XTENSA_ASM_EXPAND", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_SIMPLIFY: + markAsWarning(program, relocationAddress, "R_XTENSA_ASM_SIMPLIFY", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTINHERIT: + markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTINHERIT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTENTRY: + markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTENTRY", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF8: + markAsWarning(program, relocationAddress, "R_XTENSA_DIFF8", symbolName, symbolIndex, + "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF16: + markAsWarning(program, relocationAddress, "R_XTENSA_DIFF16", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF32: + markAsWarning(program, relocationAddress, "R_XTENSA_DIFF32", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_OP", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_ALT", symbolName, + symbolIndex, "TODO, needs support ", elfRelocationContext.getLog()); + default: + markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName, elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_RTLD: - markAsWarning(program, relocationAddress, "R_XTENSA_RTLD", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_GLOB_DAT: - markAsWarning(program, relocationAddress, "R_XTENSA_GLOB_DAT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_JMP_SLOT: - markAsWarning(program, relocationAddress, "R_XTENSA_JMP_SLOT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_RELATIVE: - markAsWarning(program, relocationAddress, "R_XTENSA_RELATIVE", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_PLT: - markAsWarning(program, relocationAddress, "R_XTENSA_PLT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_OP0: - markAsWarning(program, relocationAddress, "R_XTENSA_OP0", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_OP1: - markAsWarning(program, relocationAddress, "R_XTENSA_OP1", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_OP2: - markAsWarning(program, relocationAddress, "R_XTENSA_OP2", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_EXPAND: - markAsWarning(program, relocationAddress, "R_XTENSA_ASM_EXPAND", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_SIMPLIFY: - markAsWarning(program, relocationAddress, "R_XTENSA_ASM_SIMPLIFY", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTINHERIT: - markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTINHERIT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTENTRY: - markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTENTRY", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF8: - markAsWarning(program, relocationAddress, "R_XTENSA_DIFF8", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF16: - markAsWarning(program, relocationAddress, "R_XTENSA_DIFF16", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF32: - markAsWarning(program, relocationAddress, "R_XTENSA_DIFF32", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_OP: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_OP", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_ALT: - markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_ALT", - symbolName, symbolIndex, "TODO, needs support ", - elfRelocationContext.getLog()); - return RelocationResult.UNSUPPORTED; - default: - markAsUnhandled(program, relocationAddress, type, symbolIndex, - symbolName, elfRelocationContext.getLog()); - return RelocationResult.SKIPPED; } - + return RelocationResult.UNSUPPORTED; } } diff --git a/Ghidra/Processors/Xtensa/src/main/java/ghidra/program/emulation/XtensaEmulateInstructionStateModifier.java b/Ghidra/Processors/Xtensa/src/main/java/ghidra/program/emulation/XtensaEmulateInstructionStateModifier.java new file mode 100644 index 0000000000..ecd6264872 --- /dev/null +++ b/Ghidra/Processors/Xtensa/src/main/java/ghidra/program/emulation/XtensaEmulateInstructionStateModifier.java @@ -0,0 +1,159 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.program.emulation; + +import java.util.Stack; + +import ghidra.pcode.emulate.Emulate; +import ghidra.pcode.emulate.EmulateInstructionStateModifier; +import ghidra.pcode.emulate.callother.OpBehaviorOther; +import ghidra.pcode.emulate.callother.OpBehaviorOtherNOP; +import ghidra.pcode.error.LowlevelError; +import ghidra.pcode.memstate.MemoryState; +import ghidra.program.model.address.Address; +import ghidra.program.model.lang.Register; +import ghidra.program.model.pcode.Varnode; + +public class XtensaEmulateInstructionStateModifier extends EmulateInstructionStateModifier { + + private Stack stashStack = new Stack(); + public XtensaEmulateInstructionStateModifier(Emulate emu) { + super(emu); + + registerPcodeOpBehavior("rotateRegWindow", new RotateRegWindow()); + registerPcodeOpBehavior("restoreRegWindow", new RestoreRegWindow()); + + registerPcodeOpBehavior("swap4", new OpBehaviorOtherNOP()); + registerPcodeOpBehavior("swap8", new OpBehaviorOtherNOP()); + registerPcodeOpBehavior("swap12", new OpBehaviorOtherNOP()); + registerPcodeOpBehavior("restore4", new OpBehaviorOtherNOP()); + registerPcodeOpBehavior("restore8", new OpBehaviorOtherNOP()); + registerPcodeOpBehavior("restore12", new OpBehaviorOtherNOP()); + } + + private class RotateRegWindow implements OpBehaviorOther { + + @Override + public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) { + if (inputs.length != 2) { + throw new LowlevelError("rotateRegWindow: missing required CALLINC input"); + } + + MemoryState memoryState = emu.getMemoryState(); + Varnode in = inputs[1]; + long callinc = memoryState.getValue(in); + if (callinc == 0) { + return; + } + if (callinc < 0 || callinc > 3) { + throw new LowlevelError("rotateRegWindow: invalid value for CALLINC (0x" + + Long.toHexString(callinc) + ")"); + } + + // push window onto stack + stashStack.push(new RegisterStash((int) callinc)); + + //rotate registers + Address baseARegAddr = language.getRegister("a0").getAddress(); + int count = (int) callinc << 2; // windowSize + long windowRegOffset = count * 4; + count = 16 - count; + + for (int i = 0; i < count; i++) { + Varnode fromRegVarnode = + new Varnode(baseARegAddr.add(windowRegOffset + (i * 4)), 4); + Varnode toRegVarnode = new Varnode(baseARegAddr.add(i * 4), 4); + long value = memoryState.getValue(fromRegVarnode); + memoryState.setValue(toRegVarnode, value); + } + } + } + + private class RestoreRegWindow implements OpBehaviorOther { + + @Override + public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) { + if (inputs.length != 1) { + throw new LowlevelError("restoreRegWindow: unexpected input varnodes"); + } + + MemoryState memoryState = emu.getMemoryState(); + + Register a0Reg = language.getRegister("a0"); + long callinc = (memoryState.getValue(a0Reg) >> 30) & 0x3; + if (callinc == 0) { + return; + } + + if (stashStack.isEmpty()) { + throw new LowlevelError("restoreRegWindow: window register stash is empty"); + } + + RegisterStash stash = stashStack.peek(); + if (callinc != stash.callinc) { + throw new LowlevelError("restoreRegWindow: return address CALLINC (" + callinc + + ") does not match last entry CALLINC value (" + stash.callinc + ")"); + } + + //rotate registers + Address baseARegAddr = language.getRegister("a0").getAddress(); + int count = (int) callinc << 2; // windowSize + long windowRegOffset = count * 4; + count = 16 - count; + + for (int i = 0; i < count; i++) { + Varnode fromRegVarnode = new Varnode(baseARegAddr.add(i * 4), 4); + Varnode toRegVarnode = new Varnode(baseARegAddr.add(windowRegOffset + (i * 4)), 4); + long value = memoryState.getValue(fromRegVarnode); + memoryState.setValue(toRegVarnode, value); + } + + // remove from stack and restore + stashStack.pop(); + stash.restore(); + } + } + + private class RegisterStash { + private int callinc; + private int[] values; + + RegisterStash(int callinc) { + this.callinc = callinc; + + MemoryState memoryState = emu.getMemoryState(); + Address baseARegAddr = language.getRegister("a0").getAddress(); + + int count = callinc << 2; + values = new int[count]; + + for (int i = 0; i < count; i++) { + Varnode regVarnode = new Varnode(baseARegAddr.add(4 * i), 4); + values[i] = (int) memoryState.getValue(regVarnode); + } + } + + public void restore() { + MemoryState memoryState = emu.getMemoryState(); + Address baseARegAddr = language.getRegister("a0").getAddress(); + + for (int i = 0; i < values.length; i++) { + Varnode regVarnode = new Varnode(baseARegAddr.add(4 * i), 4); + memoryState.setValue(regVarnode, values[i]); + } + } + } +} 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 index 65f528001f..628919694d 100644 --- 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 @@ -1,3 +1,18 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ghidra.test.processors; import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; 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 index 7e48b55816..b0b7962368 100644 --- 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 @@ -1,3 +1,18 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ghidra.test.processors; import ghidra.test.processors.support.ProcessorEmulatorTestAdapter;