Merge remote-tracking branch

'origin/GP-1062_ghidorahrex_PR-1407_and_5442_Xtensa' (Closes #1407,
Closes #5442)
This commit is contained in:
Ryan Kurtz 2023-11-20 06:50:14 -05:00
commit 7df3fd39c8
25 changed files with 3897 additions and 0 deletions

View File

@ -689,3 +689,22 @@ PCodeTest({
'has_double': 0,
'has_longlong': 0,
})
PCodeTest({
'name': 'Xtensa_LE',
'build_all': 1,
'build_exe': 1,
'toolchain': 'Xtensa/xtensa-esp32-elf',
'language_id': 'Xtensa:LE:32:default',
'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',
})

View File

View File

@ -0,0 +1,29 @@
/* ###
* 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"
apply from: "$rootProject.projectDir/gradle/processorProject.gradle"
apply plugin: 'eclipse'
eclipse.project.name = 'Processors Xtensa'
dependencies {
api project(':Base')
}
sleighCompileOptions = [
"-l"
]

View File

@ -0,0 +1,18 @@
##VERSION: 2.0
Module.manifest||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/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|

View File

@ -0,0 +1,17 @@
# Per the manual:
# CUST0 and CUST1 opcode encodings shown in Table 7193 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();
}

View File

@ -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 found they should be flagged.
define pcodeop flix;
:FLIX u_4_23 is op0=0xe & u_4_23 {
flix();
}

View File

@ -0,0 +1,260 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<absolute_max_alignment value="0" />
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="4" />
<pointer_size value="4" />
<wchar_size value="4" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="4" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="8" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
</global>
<stackpointer register="a1" space="ram"/>
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<input>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a2"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a3"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a4"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a5"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a6"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a7"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="0" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a2"/>
</pentry>
<!-- TODO: Are joins impacted by endianess ? -->
<pentry minsize="5" maxsize="8" extension="inttype">
<addr space="join" piece1="a3" piece2="a2"/>
</pentry>
<pentry minsize="9" maxsize="12" extension="inttype">
<addr space="join" piece1="a4" piece2="a3" piece3="a2"/>
</pentry>
<pentry minsize="13" maxsize="16" extension="inttype">
<addr space="join" piece1="a5" piece2="a4" piece3="a3" piece4="a2"/>
</pentry>
</output>
<returnaddress>
<register name="a0"/>
</returnaddress>
<unaffected>
<register name="a1"/>
<register name="a0"/>
<!--
These are commented out, because they get preserved by the current
windowing mechanism swapX, callX, restorX
Removing them here makes the default calling convention
generally compatible with the CALL0 convention in most cases
<register name="a2"/>
<register name="a3"/>
<register name="a4"/>
<register name="a5"/>
<register name="a6"/>
<register name="a7"/>
-->
<register name="a8"/>
<register name="a9"/>
<register name="a10"/>
<register name="a11"/>
<register name="t2"/>
<register name="t3"/>
<register name="t4"/>
<register name="t5"/>
<register name="t6"/>
<register name="t7"/>
</unaffected>
</prototype>
</default_proto>
<prototype name="__call0" extrapop="0" stackshift="0">
<input>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a2"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a3"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a4"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a5"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a6"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a7"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="0" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="a2"/>
</pentry>
<!-- TODO: Are joins impacted by endianess ? -->
<pentry minsize="5" maxsize="8" extension="inttype">
<addr space="join" piece1="a3" piece2="a2"/>
</pentry>
<pentry minsize="9" maxsize="12" extension="inttype">
<addr space="join" piece1="a4" piece2="a3" piece3="a2"/>
</pentry>
<pentry minsize="13" maxsize="16" extension="inttype">
<addr space="join" piece1="a5" piece2="a4" piece3="a3" piece4="a2"/>
</pentry>
</output>
<returnaddress>
<register name="a0"/>
</returnaddress>
<unaffected>
<register name="a1"/>
<register name="a0"/>
<register name="a12"/>
<register name="a13"/>
<register name="a14"/>
<register name="a15"/>
</unaffected>
</prototype>
<callotherfixup targetop="swap4">
<pcode incidentalcopy="true">
<body><![CDATA[
t2 = a2;
t3 = a3;
a2 = a6;
a3 = a7;
a4 = a8;
a5 = a9;
a6 = a10;
a7 = a11;
]]></body>
</pcode>
</callotherfixup>
<callotherfixup targetop="restore4">
<pcode incidentalcopy="true">
<body><![CDATA[
a6 = a2;
a7 = a3;
a2 = t2;
a3 = t3;
a4 = t0;
a5 = t0;
a8 = t0;
a9 = t0;
a10 = t0;
a11 = t0;
]]></body>
</pcode>
</callotherfixup>
<callotherfixup targetop="swap8">
<pcode incidentalcopy="true">
<body><![CDATA[
t2 = a2;
t3 = a3;
t4 = a4;
t5 = a5;
t6 = a6;
t7 = a7;
a2 = a10;
a3 = a11;
a4 = a12;
a5 = a13;
a6 = a14;
a7 = a15;
]]></body>
</pcode>
</callotherfixup>
<callotherfixup targetop="restore8">
<pcode incidentalcopy="true">
<body><![CDATA[
a10 = a2;
a11 = a3;
a2 = t2;
a3 = t3;
a4 = t4;
a5 = t5;
a6 = t6;
a7 = t7;
a8 = t0;
a9 = t0;
]]></body>
</pcode>
</callotherfixup>
<callotherfixup targetop="swap12">
<pcode incidentalcopy="true">
<body><![CDATA[
t2 = a2;
t3 = a3;
a2 = a14;
a3 = a15;
]]></body>
</pcode>
</callotherfixup>
<callotherfixup targetop="restore12">
<pcode incidentalcopy="true">
<body><![CDATA[
a14 = a2;
a15 = a3;
a2 = t2;
a3 = t3;
]]></body>
</pcode>
</callotherfixup>
<callotherfixup targetop="rotateRegWindow">
<pcode>
<input name="CALLINC"/>
<body><![CDATA[
t0 = t0;
]]></body>
</pcode>
</callotherfixup>
<callotherfixup targetop="restoreRegWindow">
<pcode>
<body><![CDATA[
t0 = t0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>

View File

@ -0,0 +1,7 @@
<dwarf>
<register_mappings>
<register_mapping dwarf="0" ghidra="a0"/>
<register_mapping dwarf="1" ghidra="a1" stackpointer="true"/>
<register_mapping dwarf="2" ghidra="a2" auto_count="14"/> <!-- a2..a15 -->
</register_mappings>
</dwarf>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<language_definitions>
<language processor="Xtensa"
endian="little"
size="32"
variant="default"
version="4.0"
slafile="xtensa_le.sla"
processorspec="xtensa.pspec"
manualindexfile="../manuals/xtensa.idx"
id="Xtensa:LE:32:default">
<description>Tensilica Xtensa 32-bit little-endian</description>
<compiler name="default" spec="xtensa.cspec" id="default"/>
<external_name tool="gnu" name="xtensa"/>
<external_name tool="DWARF.register.mapping.file" name="xtensa.dwarf"/>
</language>
<language processor="Xtensa"
endian="big"
size="32"
variant="default"
version="4.0"
slafile="xtensa_be.sla"
processorspec="xtensa.pspec"
manualindexfile="../manuals/xtensa.idx"
id="Xtensa:BE:32:default">
<description>Tensilica Xtensa 32-bit big-endian</description>
<compiler name="default" spec="xtensa.cspec" id="default"/>
<external_name tool="gnu" name="xtensa"/>
<external_name tool="DWARF.register.mapping.file" name="xtensa.dwarf"/>
</language>
</language_definitions>

View File

@ -0,0 +1,6 @@
<opinions>
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="default">
<constraint primary="94" processor="Xtensa" size="32"/>
<constraint primary="43975" processor="Xtensa" size="32"/>
</constraint>
</opinions>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<processor_spec>
<programcounter register="pc"/>
<properties>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.XtensaEmulateInstructionStateModifier" />
</properties>
<context_data>
<tracked_set space="ram">
<set name="PS" val="0"/>
</tracked_set>
</context_data>
</processor_spec>

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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 arent 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 cant 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;
}

View File

@ -0,0 +1,12 @@
@define ENDIAN "big"
@include "xtensaArch.sinc"
@include "xtensaMain.sinc"
with : phase=1 {
@include "xtensaInstructions.sinc"
#@include "xtensa_depbits.sinc" #uncomment this to use depbits instruction, collides with floating point
@include "cust.sinc"
@include "flix.sinc"
}

View File

@ -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;
}

View File

@ -0,0 +1,12 @@
@define ENDIAN "little"
@include "xtensaArch.sinc"
@include "xtensaMain.sinc"
with : phase=1 {
@include "xtensaInstructions.sinc"
#@include "xtensa_depbits.sinc" #uncomment this to use depbits instruction, collides with floating point
@include "cust.sinc"
@include "flix.sinc"
}

View File

@ -0,0 +1,354 @@
@isa_summary.pdf[Xtensa® Instruction Set Architecture Summary, For all Xtensa LX Processors April 2022]
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

View File

@ -0,0 +1,7 @@
<patternconstraints>
<language id="Xtensa:*:*:*">
<compiler id="default">
<patternfile>xtensa_patterns.xml</patternfile>
</compiler>
</language>
</patternconstraints>

View File

@ -0,0 +1,98 @@
<patternlist>
<patternpairs totalbits="32" postbits="21">
<!-- Higher confidence patterns, after a return and more defined bits -->
<prepatterns>
<data>0x0d 0xf0</data> <!-- ret //0 filler -->
<data>0x0d 0xf0 0x00 </data> <!-- ret //1 filler -->
<data>0x0d 0xf0 0x00 0x00 </data> <!-- ret //2 filler -->
<data>0x0d 0xf0 0x00 0x00 0x00 </data> <!-- ret //3 filler -->
<data>0x80 0x00 0x00 </data> <!-- ret //0 filler -->
<data>0x80 0x00 0x00 0x00 </data> <!-- ret //1 filler -->
<data>0x80 0x00 0x00 0x00 0x00 </data> <!-- ret //2 filler -->
<data>0x80 0x00 0x00 0x00 0x00 0x00 </data> <!-- ret //3 filler -->
</prepatterns>
<postpatterns>
<data>00010010 11000001 1...0000 </data> <!-- addi a1,a1,-imm // this only includes stack frame size 0x10->0x80 -->
<data>....0010 10100... ........ ....0000 00010001 11000000 </data> <!-- movi at,off ; subi a1,a1,at -->
<!-- this currently applies to the pre-pattern start, so can't use really should be on postpattern start <align mark="0" bits="2"/> -->
<funcstart/>
</postpatterns>
</patternpairs>
<patternpairs totalbits="32" postbits="21">
<prepatterns>
<data>0x1d 0xf0</data> <!-- retw.n -->
<data>0x1d 0xf0 0x00</data> <!-- retw.n -->
<data>0x1d 0xf0 0x00 0x00</data> <!-- retw.n -->
<data>0x1d 0xf0 0x00 0x00 0x00 </data><!-- retw.n -->
</prepatterns>
<postpatterns>
<data>0x36 ...00001 0x00</data> <!-- entry a1, constant // this only includes stack frame size 0x10->0x80 -->
<funcstart/>
</postpatterns>
</patternpairs>
<patternpairs totalbits="48" postbits="21">
<prepatterns>
<data>00010010 11000001 0...0000 00001101 11110000</data> <!-- addi a1,a1,off ; ret.n //0 filler -->
<data>00010010 11000001 0...0000 00001101 11110000 00000000</data> <!-- addi a1,a1,off ; ret.n //1 filler -->
<data>00010010 11000001 0...0000 00001101 11110000 00000000 00000000</data> <!-- addi a1,a1,off ; ret.n //2 filler -->
<data>00010010 11000001 0...0000 00001101 11110000 00000000 00000000 00000000</data> <!-- addi a1,a1,off ; ret.n //3 filler -->
<data>....1010 00010001 00001101 11110000 </data> <!-- add.n a1,a1,at ; ret.n //0 filler -->
<data>....1010 00010001 00001101 11110000 00000000</data> <!-- add.n a1,a1,at ; ret.n //1 filler -->
<data>....1010 00010001 00001101 11110000 00000000 00000000</data> <!-- add.n a1,a1,at ; ret.n //2 filler -->
<data>....1010 00010001 00001101 11110000 00000000 00000000 00000000</data> <!-- add.n a1,a1,at ; ret.n //3 filler -->
</prepatterns>
<postpatterns>
<data>00010010 11000001 1...0000</data> <!-- addi a1,a1,-off -->
<data>....0010 10100... ........ ....0000 00010001 11000000</data> <!-- movi at,off ; subi a1,a1,at -->
<!-- this currently applies to the pre-pattern start, so can't use really should be on postpattern start <align mark="0" bits="2"/> -->
<funcstart/>
</postpatterns>
</patternpairs>
<patternpairs totalbits="28" postbits="21">
<prepatterns>
<data>..000110 ........ 1....... </data> <!-- j -off //0 filler -->
<data>..000110 ........ 1....... 00000000 </data> <!-- j -off //1 filler -->
<data>..000110 ........ 1....... 00000000 00000000 </data> <!-- j -off //2 filler -->
<data>..000110 ........ 1....... 00000000 00000000 00000000</data> <!-- j -off //3 filler -->
</prepatterns>
<postpatterns>
<data>....0010 10100... ........ ....0000 00010001 11000000</data> <!-- movi at,off ; subi a1,a1,at -->
<data>00010010 11000001 1...0000</data> <!-- addi a1, a1, -offset -->
<!-- this currently applies to the pre-pattern start, so can't use really should be on postpattern start <align mark="0" bits="2"/> -->
<possiblefuncstart/>
</postpatterns>
</patternpairs>
<pattern>
<data>....0010 10100... ........ ....0000 00010001 11000000</data> <!-- movi at,off ; subi a1,a1,at -->
<align mark="0" bits="2"/>
<possiblefuncstart after="defined" />
</pattern>
<pattern>
<data>00010010 11000001 1...0000</data> <!-- addi a1, a1, -offset -->
<align mark="0" bits="2"/>
<possiblefuncstart after="defined" />
</pattern>
<pattern>
<data>0x12 0xc1 0xf0 0x09 0x01 ..000101 ........ ........ 0x08 0x01 0x12 0xc1 0x10 0x0d 0xf0</data>
<!--
addi a1,a1,-0x10
s32i.n a0,a1,0x0
call0 FUN
l32i.n a0,a1,0x0
addi a1,a1,0x10
ret.n
-->
<align mark="0" bits="2" />
<funcstart validcode="function" thunk="true" />
</pattern>
</patternlist>

View File

@ -0,0 +1,73 @@
/* ###
* 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 {
/* Xtensa processor ELF architecture-magic number */
// EM_XTENSA is already definded
public static final int EM_XTENSA_OLD = 0xABC7;
/* Xtensa relocations defined by the ABIs */
public static final int R_XTENSA_NONE = 0;
public static final int R_XTENSA_32 = 1;
public static final int R_XTENSA_RTLD = 2;
public static final int R_XTENSA_GLOB_DAT = 3;
public static final int R_XTENSA_JMP_SLOT = 4;
public static final int R_XTENSA_RELATIVE = 5;
public static final int R_XTENSA_PLT = 6;
public static final int R_XTENSA_OP0 = 8;
public static final int R_XTENSA_OP1 = 9;
public static final int R_XTENSA_OP2 = 10;
public static final int R_XTENSA_ASM_EXPAND = 11;
public static final int R_XTENSA_ASM_SIMPLIFY = 12;
public static final int R_XTENSA_GNU_VTINHERIT = 15;
public static final int R_XTENSA_GNU_VTENTRY = 16;
public static final int R_XTENSA_DIFF8 = 17;
public static final int R_XTENSA_DIFF16 = 18;
public static final int R_XTENSA_DIFF32 = 19;
public static final int R_XTENSA_SLOT0_OP = 20;
public static final int R_XTENSA_SLOT1_OP = 21;
public static final int R_XTENSA_SLOT2_OP = 22;
public static final int R_XTENSA_SLOT3_OP = 23;
public static final int R_XTENSA_SLOT4_OP = 24;
public static final int R_XTENSA_SLOT5_OP = 25;
public static final int R_XTENSA_SLOT6_OP = 26;
public static final int R_XTENSA_SLOT7_OP = 27;
public static final int R_XTENSA_SLOT8_OP = 28;
public static final int R_XTENSA_SLOT9_OP = 29;
public static final int R_XTENSA_SLOT10_OP = 30;
public static final int R_XTENSA_SLOT11_OP = 31;
public static final int R_XTENSA_SLOT12_OP = 32;
public static final int R_XTENSA_SLOT13_OP = 33;
public static final int R_XTENSA_SLOT14_OP = 34;
public static final int R_XTENSA_SLOT0_ALT = 35;
public static final int R_XTENSA_SLOT1_ALT = 36;
public static final int R_XTENSA_SLOT2_ALT = 37;
public static final int R_XTENSA_SLOT3_ALT = 38;
public static final int R_XTENSA_SLOT4_ALT = 39;
public static final int R_XTENSA_SLOT5_ALT = 40;
public static final int R_XTENSA_SLOT6_ALT = 41;
public static final int R_XTENSA_SLOT7_ALT = 42;
public static final int R_XTENSA_SLOT8_ALT = 43;
public static final int R_XTENSA_SLOT9_ALT = 44;
public static final int R_XTENSA_SLOT10_ALT = 45;
public static final int R_XTENSA_SLOT11_ALT = 46;
public static final int R_XTENSA_SLOT12_ALT = 47;
public static final int R_XTENSA_SLOT13_ALT = 48;
public static final int R_XTENSA_SLOT14_ALT = 49;
}

View File

@ -0,0 +1,209 @@
/* ###
* 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.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.RelocationResult;
import ghidra.util.exception.NotFoundException;
public class Xtensa_ElfRelocationHandler extends ElfRelocationHandler {
@Override
public boolean canRelocate(ElfHeader elf) {
return elf.e_machine() == ElfConstants.EM_XTENSA ||
elf.e_machine() == Xtensa_ElfRelocationConstants.EM_XTENSA_OLD;
}
@Override
public 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();
if (Xtensa_ElfRelocationConstants.R_XTENSA_NONE == type) {
return RelocationResult.SKIPPED;
}
Program program = elfRelocationContext.getProgram();
ElfSymbol sym = null;
String symbolName = null;
int symbolIndex = relocation.getSymbolIndex();
if (symbolIndex != 0) {
sym = elfRelocationContext.getSymbol(symbolIndex);
}
if (null != sym) {
symbolName = sym.getNameAsString();
}
//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 ", 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;
}
}

View File

@ -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<RegisterStash> stashStack = new Stack<RegisterStash>();
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]);
}
}
}
}

View File

@ -0,0 +1,40 @@
/* ###
* 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;
import junit.framework.Test;
public class Xtensa_O0_EmulatorTest extends ProcessorEmulatorTestAdapter {
private static final String LANGUAGE_ID = "Xtensa:LE:32:default";
private static final String COMPILER_SPEC_ID = "default";
private static final String[] REG_DUMP_SET = new String[] {};
public Xtensa_O0_EmulatorTest(String name) throws Exception {
super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
}
@Override
protected String getProcessorDesignator() {
return "Xtensa_GCC_O0";
}
public static Test suite() {
return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(Xtensa_O0_EmulatorTest.class);
}
}

View File

@ -0,0 +1,40 @@
/* ###
* 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;
import junit.framework.Test;
public class Xtensa_O3_EmulatorTest extends ProcessorEmulatorTestAdapter {
private static final String LANGUAGE_ID = "Xtensa:LE:32:default";
private static final String COMPILER_SPEC_ID = "default";
private static final String[] REG_DUMP_SET = new String[] {};
public Xtensa_O3_EmulatorTest(String name) throws Exception {
super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
}
@Override
protected String getProcessorDesignator() {
return "Xtensa_GCC_O3";
}
public static Test suite() {
return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(Xtensa_O3_EmulatorTest.class);
}
}