Initial commit

This commit is contained in:
Sebastian Schmidt
2019-06-22 15:04:45 +02:00
commit 9e34a2b211
12 changed files with 1846 additions and 0 deletions

54
Makefile Normal file
View 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
View File

29
README.md Normal file
View File

@ -0,0 +1,29 @@
# Tensilica Xtensa module for Ghidra
![Screenshot](/screenshot.png?raw=true)
# 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?

View 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>

View 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>

View 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
View 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 arent 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 cant be (easily) expressed in a single disassembly action.
# FIXME: “foo: tmp is u4_foo [ tmp = u4_foo; ]” doesnt 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;

View File

@ -0,0 +1,3 @@
@include "xtensa.sinc"
@include "xtensaInstructions.sinc"
@include "xtensaTodo.sinc"

File diff suppressed because it is too large Load Diff

View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB