forked from yath/ghidra-xtensa
Initial commit
This commit is contained in:
54
Makefile
Normal file
54
Makefile
Normal file
@ -0,0 +1,54 @@
|
||||
# Assume we are in Ghidra/Processors/subdir
|
||||
GHIDRA_DIR ?= $(shell readlink -f $(CURDIR)/../../..)
|
||||
SLEIGH ?= $(GHIDRA_DIR)/support/sleigh
|
||||
PERL ?= perl
|
||||
|
||||
# -x turns on parser debugging (SleighCompile)
|
||||
# -u print warnings for unnecessary pcode instructions (SleighCompile)
|
||||
# -l report pattern conflicts (SleighCompile)
|
||||
# -n print warnings for all NOP constructors (SleighCompile)
|
||||
# -t print warnings for dead temporaries (SleighCompile)
|
||||
# -e enforce use of 'local' keyword for temporaries (SleighCompile)
|
||||
# -f print warnings for unused token fields (SleighCompile)
|
||||
SLEIGH_ARGS := -x -u -l -n -t -e -f
|
||||
|
||||
LANGDIR := data/languages
|
||||
|
||||
# Must start with slaspec.
|
||||
SLA_SRCS := $(LANGDIR)/xtensa.slaspec $(wildcard $(LANGDIR)/xtensa*.sinc)
|
||||
SLA := $(LANGDIR)/xtensa.sla
|
||||
|
||||
MANDIR := data/manuals
|
||||
IDX := $(MANDIR)/xtensa.idx
|
||||
|
||||
# Targets
|
||||
|
||||
.PHONY: all
|
||||
all: check-ghidra $(SLA) $(IDX)
|
||||
|
||||
.PHONY: check-ghidra
|
||||
check-ghidra:
|
||||
@if [ ! -d $(GHIDRA_DIR)/Ghidra ]; then \
|
||||
echo "Your Ghidra installation directory could not be determined." >&2; \
|
||||
echo "Please re-run make with GHIDRA_DIR set to the root of your Ghidra installation." >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
$(SLA): $(SLA_SRCS)
|
||||
$(SLEIGH) $(SLEIGH_ARGS) $< $@
|
||||
|
||||
$(IDX): $(SLA_SRCS)
|
||||
mkdir -p $(MANDIR)
|
||||
$(PERL) mkindex.pl $^ > $@
|
||||
|
||||
release.zip: clean all
|
||||
mkdir -p release/Xtensa/$(LANGDIR)
|
||||
cp -r $(LANGDIR)/xtensa* release/Xtensa/$(LANGDIR)
|
||||
mkdir -p release/Xtensa/$(MANDIR)
|
||||
cp -r $(MANDIR)/*.idx release/Xtensa/$(MANDIR)
|
||||
cp Module.manifest release/Xtensa
|
||||
cd release && zip -r ../$@ .
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(SLA) $(IDX) release release.zip
|
0
Module.manifest
Normal file
0
Module.manifest
Normal file
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Tensilica Xtensa module for Ghidra
|
||||
|
||||

|
||||
|
||||
# Installation
|
||||
|
||||
```
|
||||
$ cd ghidra_9.0.X/Ghidra/Processors
|
||||
$ git clone https://github.com/yath/ghidra-xtensa Xtensa
|
||||
$ cd Xtensa
|
||||
$ make
|
||||
$
|
||||
```
|
||||
|
||||
Or download a pre-built release and unzip it to `Ghidra/Processors`.
|
||||
|
||||
# Bugs
|
||||
|
||||
* Some calculations are wrong, causing Ghidra to miscalculate a jump target.
|
||||
* Probably a lot of others in instructions I did not yet happen to encouter. Pull requests
|
||||
appreciated.
|
||||
|
||||
# TODO
|
||||
|
||||
* An `.opinion` file for autodetection
|
||||
* Windowed Register Option
|
||||
* MAC16 Option
|
||||
* Loop Option
|
||||
* ESP8266/ESP32 image loaders?
|
76
data/languages/xtensa.cspec
Normal file
76
data/languages/xtensa.cspec
Normal file
@ -0,0 +1,76 @@
|
||||
<?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>
|
||||
</output>
|
||||
<returnaddress>
|
||||
<register name="a0"/>
|
||||
</returnaddress>
|
||||
<unaffected>
|
||||
<register name="a0"/>
|
||||
<register name="a1"/>
|
||||
<register name="a8"/>
|
||||
<register name="a9"/>
|
||||
<register name="a10"/>
|
||||
<register name="a11"/>
|
||||
<register name="a12"/>
|
||||
<register name="a13"/>
|
||||
<register name="a14"/>
|
||||
<register name="a15"/>
|
||||
</unaffected>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
</compiler_spec>
|
16
data/languages/xtensa.ldefs
Normal file
16
data/languages/xtensa.ldefs
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<language_definitions>
|
||||
<language processor="xtensa"
|
||||
endian="little"
|
||||
size="32"
|
||||
variant="default"
|
||||
version="1.0"
|
||||
slafile="xtensa.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"/>
|
||||
</language>
|
||||
</language_definitions>
|
5
data/languages/xtensa.pspec
Normal file
5
data/languages/xtensa.pspec
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<processor_spec>
|
||||
<programcounter register="pc"/>
|
||||
</processor_spec>
|
294
data/languages/xtensa.sinc
Normal file
294
data/languages/xtensa.sinc
Normal file
@ -0,0 +1,294 @@
|
||||
define endian=little;
|
||||
define alignment=1;
|
||||
|
||||
define space ram type=ram_space size=4 default;
|
||||
define space register type=register_space size=4;
|
||||
|
||||
# Address registers (AR).
|
||||
define register offset=0x0000 size=4 [
|
||||
a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15
|
||||
];
|
||||
|
||||
# Floating Point registers (FR + FCR (control) + FSR (status)).
|
||||
# TODO: FCR and FSR seem unused?
|
||||
define register offset=0x0100 size=4 [
|
||||
f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15
|
||||
fcr fsr
|
||||
];
|
||||
|
||||
# Boolean registers (BR).
|
||||
define register offset=0x0200 size=1 [
|
||||
b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15
|
||||
];
|
||||
|
||||
# Program counter.
|
||||
define register offset=0x1000 size=4 [ pc ];
|
||||
|
||||
# Shift amount register. (TODO: other special registers)
|
||||
define register offset=0x2000 size=1 [ sar ];
|
||||
|
||||
# Regular 24-bit instruction.
|
||||
define token insn(24)
|
||||
# Named opcode/register fields.
|
||||
op2 = (20,23)
|
||||
ar = (12,15)
|
||||
fr = (12,15)
|
||||
br = (12,15)
|
||||
as = (8,11)
|
||||
fs = (8,11)
|
||||
bs = (8,11)
|
||||
at = (4,7)
|
||||
ft = (4,7)
|
||||
bt = (4,7)
|
||||
op1 = (16,19)
|
||||
op0 = (0,3)
|
||||
|
||||
# Signed and unsigned immediates. Named [us]N_L.M, where u and s denote signedness, L and M the
|
||||
# least and most significant bit of the immediate in the instruction word, and N the length
|
||||
# (i.e. M-L+1).
|
||||
u3_21.23 = (21,23)
|
||||
u4_20.23 = (20,23)
|
||||
s8_16.23 = (16,23) signed
|
||||
u8_16.23 = (16,23)
|
||||
u12_12.23 = (12,23)
|
||||
s12_12.23 = (12,23) signed
|
||||
u16_8.23 = (8,23)
|
||||
s8_6.23 = (6,23) signed
|
||||
u1_20 = (20,20)
|
||||
u2_18.19 = (18,19)
|
||||
u3_17.19 = (17,19)
|
||||
u2_16.17 = (16,17)
|
||||
u1_16 = (16,16)
|
||||
u2_14.15 = (14,15)
|
||||
u3_13.15 = (13,15)
|
||||
u4_12.15 = (12,15)
|
||||
u8_8.15 = (8,15)
|
||||
u2_12.13 = (12,13)
|
||||
u1_12 = (12,12)
|
||||
u4_8.11 = (8,11)
|
||||
u8_4.11 = (4,11)
|
||||
# s4_8.11 = (8,11) signed
|
||||
u2_6.7 = (6,7)
|
||||
u3_5.7 = (5,7)
|
||||
u4_4.7 = (4,7)
|
||||
s4_4.7 = (4,7)
|
||||
u2_4.5 = (4,5)
|
||||
u1_4 = (4,4)
|
||||
;
|
||||
|
||||
# Narrow 16-bit instructions; fields are always prefixed with n_.
|
||||
define token narrowinsn(16)
|
||||
n_ar = (12,15)
|
||||
n_as = (8,11)
|
||||
n_at = (4,7)
|
||||
n_op0 = (0, 3)
|
||||
|
||||
n_u4_12.15 = (12,15)
|
||||
n_s4_12.15 = (12,15) signed
|
||||
n_u4_8.11 = (8,11)
|
||||
n_u1_7 = (7,7)
|
||||
n_u2_6.7 = (6,7)
|
||||
n_u4_4.7 = (4,7)
|
||||
n_s3_4.6 = (4,6)
|
||||
n_u2_4.5 = (4,5)
|
||||
|
||||
;
|
||||
|
||||
attach variables [ ar as at n_ar n_as n_at ] [
|
||||
a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15
|
||||
];
|
||||
|
||||
attach variables [ fr fs ft ] [
|
||||
f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15
|
||||
];
|
||||
|
||||
attach variables [ br bs bt ] [
|
||||
b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15
|
||||
];
|
||||
|
||||
# Various 32-bit pointers relative to PC. Any operands that are split across non-consecutive
|
||||
# bits are named foo_LL.LM_ML.MM, where LL is the least significant bits of the least
|
||||
# singificant operand half, LM the most significant bits of the least significant operand half, etc.
|
||||
|
||||
urel_16.23: rel is u8_16.23 [ rel = inst_start + u8_16.23 + 4; ] { export *:4 rel; }
|
||||
|
||||
srel_16.23: rel is s8_16.23 [ rel = inst_start + s8_16.23 + 4; ] { export *:4 rel; }
|
||||
|
||||
srel_12.23: rel is s12_12.23 [ rel = inst_start + s12_12.23 + 4; ] { export *:4 rel; }
|
||||
|
||||
srel_6.23: rel is s8_6.23 [ rel = inst_start + s8_6.23 + 4; ] { export *:4 rel; }
|
||||
|
||||
urel_12.15_4.5: rel is n_u2_4.5 & n_u4_12.15 [
|
||||
rel = inst_start + ((n_u2_4.5 << 4) | n_u4_12.15) + 4;
|
||||
] { export *:4 rel; }
|
||||
|
||||
srel_6.23_sb2: rel is s8_6.23 [
|
||||
rel = (inst_start & ~3) + ( s8_6.23 << 2 ) + 4;
|
||||
] { export *:4 rel; }
|
||||
|
||||
srel_8.23_oex_sb2: rel is u16_8.23 [
|
||||
rel = ((inst_start + 3) & ~3) + ((u16_8.23 | 0xffff0000) << 2);
|
||||
] { export *:4 rel; }
|
||||
|
||||
# Immediates split across the instruction.
|
||||
u5_8.11_20: tmp is u1_20 & u4_8.11 [ tmp = (u1_20 << 4) | u4_8.11; ] { export *[const]:1 tmp; }
|
||||
u5_4.7_20: tmp is u1_20 & u4_4.7 [ tmp = (u1_20 << 4) | u4_4.7; ] { export *[const]:1 tmp; }
|
||||
u5_8.11_16: tmp is u1_16 & u4_8.11 [ tmp = (u1_16 << 4) | u4_8.11; ] { export *[const]:1 tmp; }
|
||||
u5_4.7_12: tmp is u1_12 & u4_4.7 [ tmp = (u1_12 << 4) | u4_4.7; ] { export *[const]:1 tmp; }
|
||||
u5_8.11_4: tmp is u1_4 & u4_8.11 [ tmp = (u1_4 << 4) | u4_8.11; ] { export *[const]:1 tmp; }
|
||||
|
||||
# Signed 12-bit (extended to 16) immediate, used by MOVI.
|
||||
s16_16.23_8.11: tmp is u4_8.11 & u8_16.23 [
|
||||
# FIXME: This table, and the fields used, should be signed, but using s4_8.11 and s8_16.23
|
||||
# somehow confuses Ghidra.
|
||||
tmp = (0xf000 * (u4_8.11 >> 3)) | # Sign-extend.
|
||||
(u4_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 >> 2) & 1) & ((n_s3_4.6 >> 3) & 1)) << 7) | # sign
|
||||
(n_s3_4.6 << 4) | n_s4_12.15;
|
||||
] { 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.
|
||||
# FIXME: “foo: tmp is u4_foo [ tmp = u4_foo; ]” doesn’t work when a more special constructor exists.
|
||||
|
||||
# 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 = 1 [ tmp = 1; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 2 [ tmp = 2; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 3 [ tmp = 3; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 4 [ tmp = 4; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 5 [ tmp = 5; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 6 [ tmp = 6; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 7 [ tmp = 7; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 8 [ tmp = 8; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 9 [ tmp = 9; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 10 [ tmp = 10; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 11 [ tmp = 11; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 12 [ tmp = 12; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 13 [ tmp = 13; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 14 [ tmp = 14; ] { export *[const]:4 tmp; }
|
||||
n_s4_4.7_nozero: tmp is n_u4_4.7 = 15 [ tmp = 15; ] { export *[const]:4 tmp; }
|
||||
|
||||
# B4CONST(ar) (Branch Immediate) encodings, pg. 41 f.
|
||||
r_b4const: tmp is ar = 0 [ tmp = 0xffffffff; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 1 [ tmp = 0x1; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 2 [ tmp = 0x2; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 3 [ tmp = 0x3; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 4 [ tmp = 0x4; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 5 [ tmp = 0x5; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 6 [ tmp = 0x6; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 7 [ tmp = 0x7; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 8 [ tmp = 0x8; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 9 [ tmp = 0xa; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 10 [ tmp = 0xc; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 11 [ tmp = 0x10; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 12 [ tmp = 0x20; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 13 [ tmp = 0x40; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 14 [ tmp = 0x80; ] { export *[const]:4 tmp; }
|
||||
r_b4const: tmp is ar = 15 [ tmp = 0x100; ] { export *[const]:4 tmp; }
|
||||
|
||||
# B4CONSTU(ar) (Branch Unsigned Immediate) encodings, pg. 42.
|
||||
r_b4constu: tmp is ar = 0 [ tmp = 0x8000; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 1 [ tmp = 0x1000; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 2 [ tmp = 0x2; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 3 [ tmp = 0x3; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 4 [ tmp = 0x4; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 5 [ tmp = 0x5; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 6 [ tmp = 0x6; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 7 [ tmp = 0x7; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 8 [ tmp = 0x8; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 9 [ tmp = 0xa; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 10 [ tmp = 0xc; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 11 [ tmp = 0x10; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 12 [ tmp = 0x20; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 13 [ tmp = 0x40; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 14 [ tmp = 0x80; ] { export *[const]:4 tmp; }
|
||||
r_b4constu: tmp is ar = 15 [ tmp = 0x100; ] { export *[const]:4 tmp; }
|
||||
|
||||
define pcodeop breakpoint;
|
||||
define pcodeop dhi;
|
||||
define pcodeop dhu;
|
||||
define pcodeop dhwb;
|
||||
define pcodeop dhwbi;
|
||||
define pcodeop dii;
|
||||
define pcodeop diu;
|
||||
define pcodeop diwb;
|
||||
define pcodeop diwbi;
|
||||
define pcodeop dpfl;
|
||||
define pcodeop dpfr;
|
||||
define pcodeop dpfro;
|
||||
define pcodeop dpfw;
|
||||
define pcodeop dpfwo;
|
||||
define pcodeop dsync;
|
||||
define pcodeop esync;
|
||||
define pcodeop excw;
|
||||
define pcodeop extw;
|
||||
define pcodeop idtlb;
|
||||
define pcodeop ihi;
|
||||
define pcodeop ihu;
|
||||
define pcodeop iii;
|
||||
define pcodeop iitlb;
|
||||
define pcodeop iiu;
|
||||
define pcodeop ill;
|
||||
define pcodeop ipf;
|
||||
define pcodeop ipfl;
|
||||
define pcodeop isync;
|
||||
define pcodeop acquire;
|
||||
define pcodeop ldct;
|
||||
define pcodeop lict;
|
||||
define pcodeop licw;
|
||||
define pcodeop memw;
|
||||
define pcodeop nsa;
|
||||
define pcodeop nsau;
|
||||
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;
|
3
data/languages/xtensa.slaspec
Normal file
3
data/languages/xtensa.slaspec
Normal file
@ -0,0 +1,3 @@
|
||||
@include "xtensa.sinc"
|
||||
@include "xtensaInstructions.sinc"
|
||||
@include "xtensaTodo.sinc"
|
1283
data/languages/xtensaInstructions.sinc
Normal file
1283
data/languages/xtensaInstructions.sinc
Normal file
File diff suppressed because it is too large
Load Diff
66
data/languages/xtensaTodo.sinc
Normal file
66
data/languages/xtensaTodo.sinc
Normal file
@ -0,0 +1,66 @@
|
||||
## Windowed Register Option ##
|
||||
|
||||
# CALL4 - Call PC-relative, Rotate Window by 4, pg. 298.
|
||||
:call4 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b01 & op0 = 0b0101 unimpl
|
||||
|
||||
# CALL8 - Call PC-relative, Rotate Window by 8, pg. 300.
|
||||
:call8 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b10 & op0 = 0b0101 unimpl
|
||||
|
||||
# CALL12 - Call PC-relative, Rotate Window by 12, pg. 302.
|
||||
:call12 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b11 & op0 = 0b0101 unimpl
|
||||
|
||||
# CALLX4 - Call Register, Rotate Window by 4, pg. 305.
|
||||
:callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b01 & op0 = 0 unimpl
|
||||
|
||||
# CALLX8 - Call Register, Rotate Window by 8, pg. 307.
|
||||
:callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b10 & op0 = 0 unimpl
|
||||
|
||||
# CALLX12 - Call Register, Rotate Window by 12, pg. 308.
|
||||
:callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b11 & op0 = 0 unimpl
|
||||
|
||||
# ENTRY - Subroutine Entry, pg. 340.
|
||||
:entry as, u15_12.23_sb3 is u15_12.23_sb3 & as & u2_6.7 = 0b00 & u2_4.5 = 0b11 & op0 = 0b0110 unimpl
|
||||
|
||||
# L32E - Load 32-bit for Window Exceptions, pg. 376.
|
||||
:l32e at, as, s5_12.15_oex is op2 = 0 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl
|
||||
|
||||
# MOVSP - Move to Stack Pointer, pg. 427.
|
||||
:movsp at, as is op2 = 0 & op1 = 0 & ar = 0b0001 & as & at & op0 = 0 unimpl
|
||||
|
||||
# RETW - Windowed Return, pg. 480.
|
||||
:retw is op2 = 0 & ar = 0 & as = 0 & at = 0 & u2_18.19 = 0b10 & u2_16.17 = 0b01 & op0 = 0 unimpl
|
||||
|
||||
# RETW.N - Narrow Windowed Return, pg. 482.
|
||||
:retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 unimpl
|
||||
|
||||
# ROTW - Rotate Window, pg. 496.
|
||||
:rotw s4_4.7 is op2 = 0b0100 & op1 = 0 & ar = 0b1000 & as = 0 & s4_4.7 & op0 = 0 unimpl
|
||||
|
||||
# S32E - Store 32-bit for Window Exceptions, pg. 508.
|
||||
:s32e at, as, s5_12.15_oex is op2 = 0b0100 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl
|
||||
|
||||
|
||||
## MAC16 option ##
|
||||
|
||||
# LDDEC - Load with Autodecrement, pg. 386.
|
||||
:lddec "MAC16_REGS[" u2_12.13 "]", as is op2 = 0b1001 & op1 = 0 & u2_14.15 = 0 & u2_12.13 & as & at = 0 & op0 = 0b0100 unimpl
|
||||
|
||||
# LDINC - Load with Autoincrement, pg. 387.
|
||||
:ldinc "MAC16_REGS[" u2_12.13 "]", as is op2 = 0b1000 & op1 = 0 & u2_14.15 = 0 & u2_12.13 & as & at = 0 & op0 = 0b0100 unimpl
|
||||
|
||||
# MULA.AA.* - Signed Multiply, pg. 431.
|
||||
:mula.aa.* as, at is op2 = 0b0001 & u2_18.19 = 0b01 & ar = 0 & as & at & op0 = 0b0100 unimpl
|
||||
|
||||
# FIXME: Add remaining MUL.* opcodes.
|
||||
|
||||
|
||||
## Loop Option ##
|
||||
|
||||
# LOOP - Loop, pg. 392.
|
||||
:loop as, urel_16.23 is urel_16.23 & ar = 0b1000 & as & at = 0b0111 & op0 = 0b0110 unimpl
|
||||
|
||||
# LOOPGTZ - Loop if Greater Than Zero, pg. 394.
|
||||
:loopgtz as, urel_16.23 is urel_16.23 & ar = 0b1010 & as & at = 0b0111 & op0 = 0b0110 unimpl
|
||||
|
||||
# LOOPNEZ - Loop if Not Equal Zero, pg. 396.
|
||||
:loopnez as, urel_16.23 is urel_16.23 & ar = 0b1001 & as & at = 0b0111 & op0 = 0b0110 unimpl
|
20
mkindex.pl
Normal file
20
mkindex.pl
Normal file
@ -0,0 +1,20 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use constant PAGEOFFSET => 24;
|
||||
|
||||
print "\@xtensa.pdf[Xtensa® Instruction Set Architecture (ISA) Reference Manual, April 2010]\n\n";
|
||||
|
||||
my $last;
|
||||
|
||||
while (<>) {
|
||||
if (/^# (\S+) .*?pg\. (\d+)/) {
|
||||
my ($o, $p) = (lc $1, $2+PAGEOFFSET);
|
||||
print "$o, $p\n";
|
||||
$last = $o;
|
||||
}
|
||||
|
||||
if (/^:(\S+)/ && $last && $last ne $1) {
|
||||
warn "Constructor for opcode $1 is preceded by comment for $last";
|
||||
}
|
||||
}
|
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 347 KiB |
Reference in New Issue
Block a user