ghidra/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc

5288 lines
170 KiB
Plaintext

# Specification for the THUMB Version 2
# This closely follows
# "Architecture Reference Manual" Second Edition Edited by David Seal
#
# WARNING NOTE: Be very careful taking a subpiece or truncating a register with :# or (#)
# The LEBE hybrid language causes endian issues if you do not assign the register to a temp
# variable and then take a subpiece or truncate.
#
define token instr2 (16)
part2op=(11,15) # this second instruction token is needed for the
part2J1=(13,13)
part2J2=(11,11)
part2cond=(6,9)
part2imm6=(0,5)
part2S=(10,10)
part2imm11=(0,10)
part2imm10=(0,9)
part2off=(0,10) # bl and blx instructions which use 2 16-bit instructions
part2off_10=(1,10) # blx instruction which switches to ARM mode
part2c1415=(14,15)
part2c1212=(12,12)
part2c0615=(6,15)
part2Rt=(12,15)
part2c0011=(0,11)
part2c0909=(9,9)
part2c0808=(8,8)
part2c0707=(7,7)
part2c0505=(5,5)
part2c0404=(4,4)
part2Rd0003=(0,3)
;
define token instrThumb (16)
op4=(4,15)
op6=(6,15)
op7=(7,15)
op8=(8,15)
op9=(9,15)
op11=(11,15)
op12=(12,15)
op0=(0,15)
sop0407=(4,7)
sop0507=(5,7)
sop0508=(5,8)
sop0003=(0,3)
sop0608=(6,8)
sop0610=(6,10)
sopit=(0,7)
Ra1215=(12,15)
Rd0002=(0,2)
Rd0003=(0,3)
Rd0810=(8,10)
Rd0811=(8,11)
Rn0002=(0,2)
Rn0003=(0,3)
Rn0305=(3,5)
Rn0810=(8,10)
Rm0305=(3,5)
Rm0306=(3,6)
Rm0608=(6,8)
Rm0003=(0,3)
Rs0305=(3,5)
Rt1215=(12,15)
Rt0811=(8,11)
thI9=(9,9)
thP8=(8,8)
thH8=(8,8)
thL8=(8,8)
thU7=(7,7)
thB6=(6,6)
thN6=(6,6)
thS6=(6,6)
thW5=(5,5)
thL4=(4,4)
thCRd=(12,15)
thCRn=(0,3)
thCRm=(0,3)
hrn0002=(0,2)
hrm0305=(3,5)
rm0306=(3,6)
hrd0002=(0,2)
immed3=(6,8)
immed5=(6,10)
immed6=(0,5)
immed7=(0,6)
immed8=(0,7)
immed12_i=(10,10)
immed12_imm3=(12,14)
immed12_imm8=(0,7)
soffset8=(0,7) signed
offset10=(0,9)
offset10S=(10,10)
offset11=(0,10)
soffset11=(0,10) signed
offset12=(0,11)
thcond=(8,11)
thcpn=(8,11)
thopcode1=(4,7)
thopcode2=(5,7)
l07=(7,7)
l11=(11,11)
h1=(7,7)
h2=(6,6)
R=(8,8)
sbz=(0,2)
thwbit=(5,5)
th_psrmask=(8,11)
addr_pbit=(10,10)
addr_ubit=(9,9)
addr_wbit=(8,8)
addr_puw =(8,10)
addr_puw1 =(5,8)
thsrsMode=(0,4)
fcond=(4,7)
throt=(4,6)
imm3_12=(12,14)
imm3_shft=(12,14)
imm2_shft=(6,7)
imm5=(3,7)
sysm=(0,7)
sysm37=(3,7)
sysm02=(0,2)
thc0001=(0,1)
thc0002=(0,2)
thc0003=(0,3)
thc0004=(0,4)
thc0005=(0,5)
thc0006=(0,6)
thc0007=(0,7)
thc0011=(0,11)
thc0107=(1,7)
thc0207=(2,7)
thc0307=(3,7)
thc0407=(4,7)
thc0405=(4,5)
thc0409=(4,9)
thc0506=(5,6)
thc0507=(5,7)
thc0607=(6,7)
thc0810=(8,10)
thc0811=(8,11)
thc0910=(9,10)
thc1414=(14,14)
thc1313=(13,13)
thc1212=(12,12)
thc1214=(12,14)
thc1111=(11,11)
thc1010=(10,10)
thc0909=(9,9)
thc0808=(8,8)
thc0707=(7,7)
thc0606=(6,6)
thc0505=(5,5)
thc0404=(4,4)
thc0303=(3,3)
thc0202=(2,2)
thc0101=(1,1)
thc0000=(0,0)
thc0115=(1,15)
thc0215=(2,15)
thc0315=(3,15)
thc0415=(4,15)
thc0515=(5,15)
thc0615=(6,15)
thc0715=(7,15)
thc0815=(8,15)
thc0915=(9,15)
thc1015=(10,15)
thc1112=(11,12)
thc1115=(11,15)
thc1215=(12,15)
thc1315=(13,15)
thc1415=(14,15)
thc1515=(15,15)
;
attach variables [ Rd0002 Rd0810 Rn0002 Rn0305 Rn0810 Rm0305 Rm0608 Rs0305 ]
[ r0 r1 r2 r3 r4 r5 r6 r7 ];
attach variables [ Rm0003 Rm0306 Rd0811 Rn0003 Rt1215 Rt0811 Ra1215 Rd0003 part2Rt part2Rd0003 ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ];
attach variables [ thCRn thCRd thCRm ] [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10 cr11 cr12 cr13 cr14 cr15 ];
attach names [ thcpn ] [ p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 ];
attach variables [ hrn0002 hrm0305 hrd0002 ]
[ r8 r9 r10 r11 r12 sp lr pc ];
macro th_addflags(op1,op2) {
tmpCY = carry(op1,op2);
tmpOV = scarry(op1,op2);
}
#See Section 2-13, "Overflow Detection", of Hacker's Delight (2nd ed)
macro th_add_with_carry_flags(op1,op2){
tmpCY = ((CY == 0) && carry(op1,op2)) || ((CY == 1) && (op1 >= op1 + op2 + 1:4));
local total= op1 + op2 + zext(CY);
local sign_total = (total >> 31) != 0;
local sign_op1 = (op1 >> 31) != 0;
local sign_op2 = (op2 >> 31) != 0;
tmpOV = (sign_op1 == sign_op2) && (sign_total != sign_op1);
}
macro th_test_flags(result){
ZR = (result == 0);
NG = (result s< 0);
CY = shift_carry;
}
# Note (unlike x86) carry flag is SET if there is NO borrow
macro th_subflags(op1,op2) {
tmpCY = op2 <= op1;
tmpOV = sborrow(op1,op2);
}
macro th_subflags0(op2) {
tmpCY = op2 == 0;
tmpOV = sborrow(0,op2);
}
macro resflags(result) {
tmpNG = result s< 0;
tmpZR = result == 0;
}
macro th_logicflags() {
tmpCY = shift_carry;
tmpOV = OV;
}
macro th_affectflags() {
CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV;
}
###############################################################################
# conditionals for the branch instruction
thcc: "eq" is thcond=0 { tmp:1 = (ZR!=0); export tmp; }
thcc: "ne" is thcond=1 { tmp:1 = (ZR==0); export tmp; }
thcc: "cs" is thcond=2 { tmp:1 = (CY!=0); export tmp; }
thcc: "cc" is thcond=3 { tmp:1 = (CY==0); export tmp; }
thcc: "mi" is thcond=4 { tmp:1 = (NG!=0); export tmp; }
thcc: "pl" is thcond=5 { tmp:1 = (NG==0); export tmp; }
thcc: "vs" is thcond=6 { tmp:1 = (OV!=0); export tmp; }
thcc: "vc" is thcond=7 { tmp:1 = (OV==0); export tmp; }
thcc: "hi" is thcond=8 { tmp:1 = CY && !ZR; export tmp; }
thcc: "ls" is thcond=9 { tmp:1 = !CY || ZR; export tmp; }
thcc: "ge" is thcond=10 { tmp:1 = (NG == OV); export tmp; }
thcc: "lt" is thcond=11 { tmp:1 = (NG != OV); export tmp; }
thcc: "gt" is thcond=12 { tmp:1 = !ZR && (NG == OV); export tmp; }
thcc: "le" is thcond=13 { tmp:1 = ZR || (NG != OV); export tmp; }
# thcc: "AL" is thcond=14 { tmp = 1; export tmp; }
# thcc: "NV" is thcond=15 { tmp = 0; export tmp; }
@define THCC "thcc & (thc1515=0 | thc1414=0 | thc1313=0)"
@if defined(VERSION_6T2) || defined(VERSION_7)
part2thcc: "eq" is part2cond=0 { tmp:1 = (ZR!=0); export tmp; }
part2thcc: "ne" is part2cond=1 { tmp:1 = (ZR==0); export tmp; }
part2thcc: "cs" is part2cond=2 { tmp:1 = (CY!=0); export tmp; }
part2thcc: "cc" is part2cond=3 { tmp:1 = (CY==0); export tmp; }
part2thcc: "mi" is part2cond=4 { tmp:1 = (NG!=0); export tmp; }
part2thcc: "pl" is part2cond=5 { tmp:1 = (NG==0); export tmp; }
part2thcc: "vs" is part2cond=6 { tmp:1 = (OV!=0); export tmp; }
part2thcc: "vc" is part2cond=7 { tmp:1 = (OV==0); export tmp; }
part2thcc: "hi" is part2cond=8 { tmp:1 = CY && !ZR; export tmp; }
part2thcc: "ls" is part2cond=9 { tmp:1 = !CY || ZR; export tmp; }
part2thcc: "ge" is part2cond=10 { tmp:1 = (NG == OV); export tmp; }
part2thcc: "lt" is part2cond=11 { tmp:1 = (NG != OV); export tmp; }
part2thcc: "gt" is part2cond=12 { tmp:1 = !ZR && (NG == OV); export tmp; }
part2thcc: "le" is part2cond=13 { tmp:1 = ZR || (NG != OV); export tmp; }
# part2thcc: "AL" is part2cond=14 { tmp = 1; export tmp; }
# part2thcc: "NV" is part2cond=15 { tmp = 0; export tmp; }
@define PART2THCC "part2thcc & (part2c0909=0 | part2c0808=0 | part2c0707=0)"
@endif # defined(VERSION_6T2) || defined(VERSION_7)
@if defined(VERSION_6T2) || defined(VERSION_7)
# conditionals for IT Block
# Marvel at the UGLINESS: the p-code for pairs (eq,ne) (cs,cc) (mi,pl), etc. are the same
# The IT block decoding fills in the complement (if necessary) based on the IT mask bit for the instruction
it_thfcc: "eq" is fcond=0 { tmp:1 = (ZR!=0); export tmp; }
it_thfcc: "ne" is fcond=1 { tmp:1 = (ZR!=0); export tmp; }
it_thfcc: "cs" is fcond=2 { tmp:1 = (CY!=0); export tmp; }
it_thfcc: "cc" is fcond=3 { tmp:1 = (CY!=0); export tmp; }
it_thfcc: "mi" is fcond=4 { tmp:1 = (NG!=0); export tmp; }
it_thfcc: "pl" is fcond=5 { tmp:1 = (NG!=0); export tmp; }
it_thfcc: "vs" is fcond=6 { tmp:1 = (OV!=0); export tmp; }
it_thfcc: "vc" is fcond=7 { tmp:1 = (OV!=0); export tmp; }
it_thfcc: "hi" is fcond=8 { tmp:1 = CY && !ZR; export tmp; }
it_thfcc: "ls" is fcond=9 { tmp:1 = CY && !ZR; export tmp; }
it_thfcc: "ge" is fcond=10 { tmp:1 = (NG == OV); export tmp; }
it_thfcc: "lt" is fcond=11 { tmp:1 = (NG == OV); export tmp; }
it_thfcc: "gt" is fcond=12 { tmp:1 = !ZR && (NG == OV); export tmp; }
it_thfcc: "le" is fcond=13 { tmp:1 = !ZR && (NG == OV); export tmp; }
it_thfcc: "al" is fcond=14 { tmp:1 = 1; export tmp; }
@define IT_THFCC "it_thfcc & (thc0707=0 | thc0606=0 | thc0505=0)"
ByteRotate: "#"^rot is throt [rot = throt << 3; ] { export *[const]:1 rot; }
thSBIT_CZNO: is thc0404=0 { } # Do nothing to the flag bits
thSBIT_CZNO: "s" is thc0404=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; }
thSBIT_CZN: is thc0404=0 { } # Do nothing to the flags bits
thSBIT_CZN: "s" is thc0404=1 {CY = tmpCY; ZR = tmpZR; NG = tmpNG;}
thSBIT_ZN: is thc0404=0 { } # Do nothing to the flag bits
thSBIT_ZN: "s" is thc0404=1 { ZR = tmpZR; NG = tmpNG; }
@endif # defined(VERSION_6T2) || defined(VERSION_7)
# Addressing modes
# The capitalized fields are raw register addressing modes
Hrd0002: Rd0002 is Rd0002 & h1=0 { export Rd0002; }
Hrd0002: hrd0002 is hrd0002 & h1=1 { export hrd0002; }
Hrd0002: pc is pc & hrd0002=7 & h1=1 { tmp:4 = inst_start + 4; export tmp; }
Hrn0002: Rn0002 is Rn0002 & h1=0 { export Rn0002; }
Hrn0002: hrn0002 is hrn0002 & h1=1 { export hrn0002; }
Hrn0002: pc is pc & hrn0002=7 & h1=1 { tmp:4 = inst_start + 4; export tmp; }
Hrm0305: Rm0305 is Rm0305 & h2=0 { export Rm0305; }
Hrm0305: hrm0305 is hrm0305 & h2=1 { export hrm0305; }
Hrm0305: pc is pc & hrm0305=7 & h2=1 { tmp:4 = inst_start + 4; export tmp; }
@if defined(VERSION_6T2) || defined(VERSION_7)
Immed8_4: "#"^immval is immed8 [ immval = immed8 * 4; ] { export *[const]:4 immval; }
Immed4: "#"^thc0003 is thc0003 { export *[const]:4 thc0003; }
@endif
Immed8: "#"^immed8 is immed8 { export *[const]:4 immed8; }
Immed3: "#"^immed3 is immed3 { export *[const]:4 immed3; }
Pcrel8: [reloc] is immed8
[ reloc = ((inst_start+4) $and 0xfffffffc) + 4*immed8; ]
{
# don't export as an address, may be PIC code, and would add spurious symbols.
export *[const]:4 reloc;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
Pcrel8_s8: [reloc] is immed8
[ reloc = ((inst_start+4) $and 0xfffffffc) + 4*immed8; ]
{
export *:8 reloc;
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
Sprel8: sp,"#"^immval is sp & immed8 [ immval = immed8 * 4; ] { local tmp = sp + immval; export tmp; }
Immed7_4: "#"^immval is immed7 [ immval = immed7 * 4; ] { tmp:4 = immval; export tmp; }
Immed5: "#"^immed5 is immed5 { export *[const]:4 immed5; }
@if defined(VERSION_6T2) || defined(VERSION_7)
Immed12: "#"^immed12 is immed12_i; immed12_imm3 & immed12_imm8
[ immed12=(immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8); ]
{
export *[const]:4 immed12;
}
Immed16: "#"^immed16 is immed12_i & sop0003; immed12_imm3 & immed12_imm8
[ immed16 = (sop0003 << 12) | (immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8); ]
{
export *[const]:2 immed16;
}
PcrelImmed12Addr: reloc is immed12_i; immed12_imm3 & immed12_imm8
[ reloc = ((inst_start+4) $and 0xfffffffc) + ((immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8)); ]
{
# don't export as an address, may be PIC code, and would add spurious symbols.
export *[const]:4 reloc;
}
NegPcrelImmed12Addr: reloc is immed12_i; immed12_imm3 & immed12_imm8
[ reloc = ((inst_start+4) $and 0xfffffffc) - ((immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8)); ]
{
# don't export as an address, may be PIC code, and would add spurious symbols.
export *[const]:4 reloc;
}
PcrelOffset12: [reloc] is thc0707=1; offset12
[ reloc = ((inst_start+4) $and 0xfffffffc) + offset12; ]
{
export *:4 reloc;
}
PcrelOffset12: [reloc] is thc0707=0; offset12
[ reloc = ((inst_start+4) $and 0xfffffffc) - offset12; ]
{
export *:4 reloc;
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
# decode thumb immediate12 encoded value
@if defined(VERSION_6T2) || defined(VERSION_7)
ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=0 & immed12_imm8
[ imm32=immed12_imm8 $and 0xff; ]
{
tmp:4 = imm32; shift_carry = CY; export tmp;
}
ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=1 & immed12_imm8
[ imm32=(immed12_imm8<<16) | (immed12_imm8); ]
{
tmp:4 = imm32; shift_carry = CY; export tmp;
}
ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=2 & immed12_imm8
[ imm32=(immed12_imm8<<24) | (immed12_imm8<<8); ]
{
tmp:4 = imm32; shift_carry = CY; export tmp;
}
ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=3 & immed12_imm8
[ imm32=(immed12_imm8<<24) | (immed12_imm8<<16) | (immed12_imm8<<8) | (immed12_imm8); ]
{
tmp:4 = imm32; shift_carry = CY; export tmp;
}
ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; immed12_imm3 & thc0707 & immed7
[ imm32=(((0x80+immed7)<<(32-((immed12_imm3<<1)|thc0707)))|((0x80+immed7)>>(((immed12_imm3<<1)|thc0707)))) $and 0xffffffff; ]
{
tmp:4 = imm32; local tmp1 = (tmp >> 31); shift_carry = tmp1(0); export tmp;
}
ThumbExpandImm12: "#"^imm32 is immed12_i=1 ; immed12_imm3 & thc0707 & immed7
[ imm32=(((0x80+immed7)<<(32-(16+((immed12_imm3<<1)|thc0707))))|((0x80+immed7)>>((16+((immed12_imm3<<1)|thc0707))))) $and 0xffffffff; ]
{
tmp:4 = imm32; local tmp1 = (tmp >> 31); shift_carry = tmp1(0); export tmp;
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
@if defined(VERSION_6T2) || defined(VERSION_7)
thLsbImm: "#"^lsb is imm3_shft & imm2_shft [ lsb= (imm3_shft<<2) | imm2_shft; ] { tmp:4 = lsb; export tmp; }
thMsbImm: "#"^thc0004 is thc0004 { tmp:4 = thc0004; export tmp; }
thWidthMinus1: "#"^width is thc0004 [ width = thc0004 + 1; ] { tmp:4 = thc0004; export tmp; }
thBitWidth: "#"^w is imm3_shft & imm2_shft & thc0004 [ w = thc0004 - ((imm3_shft<<2) | imm2_shft) + 1; ] { tmp:4 = w; export tmp; }
@endif # VERSION_6T2 || VERSION_7
#####################
###### thshift2 ######
#####################
@if defined(VERSION_6T2) || defined(VERSION_7)
thshift2: Rm0003 is imm3_shft=0 & imm2_shft=0 & thc0405=0 & Rm0003
{
shift_carry = CY; export Rm0003;
}
thshift2: Rm0003, "lsl #"^shftval is imm3_shft & imm2_shft & thc0405=0 & Rm0003
[ shftval=(imm3_shft<<2) | (imm2_shft); ]
{
local tmp1=(Rm0003>>(32-shftval))&1; shift_carry=tmp1(0); local tmp2=Rm0003<<shftval; export tmp2;
}
thshift2: Rm0003, "lsr #32" is imm3_shft=0 & imm2_shft=0 & thc0405=1 & Rm0003
{
local tmp1=(Rm0003>>31); shift_carry=tmp1(0); tmp2:4=0; export tmp2;
}
thshift2: Rm0003, "lsr #"^shftval is imm3_shft & imm2_shft & thc0405=1 & Rm0003
[ shftval=(imm3_shft<<2) | (imm2_shft); ]
{
local tmp1=(Rm0003>>(shftval-1))&1; shift_carry=tmp1(0); local tmp2=Rm0003>>shftval; export tmp2;
}
thshift2: Rm0003, "asr #32" is imm3_shft=0 & imm2_shft=0 & thc0405=2 & Rm0003
{
local tmp1=(Rm0003>>31); shift_carry=tmp1(0); local tmp2 = Rm0003 s>> 32; export tmp2;
}
thshift2: Rm0003, "asr #"^shftval is imm3_shft & imm2_shft & thc0405=2 & Rm0003
[ shftval=(imm3_shft<<2) | (imm2_shft); ]
{
local tmp1=(Rm0003>>(shftval-1))&1; shift_carry=tmp1(0); local tmp2=Rm0003 s>> shftval; export tmp2;
}
thshift2: Rm0003, "rrx" is imm3_shft=0 & imm2_shft=0 & thc0405=3 & Rm0003
{
local tmp1=Rm0003&1; shift_carry=tmp1(0); local tmp2 = (zext(CY)<<31)|(Rm0003>>1); export tmp2;
}
thshift2: Rm0003, "ror #"^shftval is imm3_shft & imm2_shft & thc0405=3 & Rm0003
[ shftval=(imm3_shft<<2) | (imm2_shft); ]
{
local tmp1=(Rm0003>>shftval)|(Rm0003<<(32-shftval)); local tmp2=tmp1 >> 31; shift_carry=tmp2(0); export tmp1;
}
@endif # VERSION_6T2 || VERSION_7
Addr5: reloc is imm5 & thc0909
[ reloc = inst_start + 4 + ((thc0909 << 6) | (imm5 << 1)); ]
{
export *:4 reloc;
}
Addr8: reloc is soffset8
[ reloc = (inst_start+4) + 2*soffset8; ]
{
export *:4 reloc;
}
Addr11: reloc is soffset11
[ reloc = (inst_start+4) + 2*soffset11; ]
{
export *:4 reloc;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
ThAddr20: reloc is part2S=1 & part2imm6; part2J1 & part2J2 & part2imm11
[ reloc = inst_start + 4 + ((-1 << 20) $or (part2J2 << 19) $or (part2J1 << 18) $or (part2imm6 << 12) $or (part2imm11 << 1)); ]
{
export *:4 reloc;
}
ThAddr20: reloc is part2S=0 & part2imm6; part2J1 & part2J2 & part2imm11
[ reloc = inst_start + 4 + ((part2J2 << 19) $or (part2J1 << 18) $or (part2imm6 << 12) $or (part2imm11 << 1)); ]
{
export *:4 reloc;
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
ThAddr24: reloc is offset10S=0 & offset10; part2J1 & part2J2 & part2off
[ reloc = inst_start + 4 + (((part2J1 $xor 1) << 23) $or ((part2J2 $xor 1) << 22) $or (offset10 << 12) $or (part2off << 1)); ]
{
export *:4 reloc;
}
ThAddr24: reloc is offset10S=1 & offset10; part2J1 & part2J2 & part2off
[ reloc = inst_start + 4 + ((-1 << 24) $or (part2J1 << 23) $or (part2J2 << 22) $or (offset10 << 12) $or (part2off << 1)); ]
{
export *:4 reloc;
}
@if defined(VERSION_5)
ThArmAddr23: reloc is offset10S=0 & offset10; part2J1 & part2J2 & part2off_10
[ reloc = ((inst_start + 4) $and 0xfffffffc) + (((part2J1 $xor 1) << 23) $or ((part2J2 $xor 1) << 22) $or (offset10 << 12) $or (part2off_10 << 2)); ]
{
export *:4 reloc;
}
ThArmAddr23: reloc is offset10S=1 & offset10; part2J1 & part2J2 & part2off_10
[ reloc = ((inst_start + 4) $and 0xfffffffc) + ((-1 << 24) $or (part2J1 << 23) $or (part2J2 << 22) $or (offset10 << 12) $or (part2off_10 << 2)); ]
{
export *:4 reloc;
}
@endif # VERSION_5
Rn_exclaim: Rn0810 is Rn0810 & thc0810=0 & thc0000=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810 is Rn0810 & thc0810=1 & thc0101=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810 is Rn0810 & thc0810=2 & thc0202=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810 is Rn0810 & thc0810=3 & thc0303=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810 is Rn0810 & thc0810=4 & thc0404=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810 is Rn0810 & thc0810=5 & thc0505=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810 is Rn0810 & thc0810=6 & thc0606=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810 is Rn0810 & thc0810=7 & thc0707=1 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim: Rn0810! is Rn0810 & thc0810 { mult_addr = Rn0810; export Rn0810; }
Rn_exclaim_WB: is Rn0810 & thc0810=0 & thc0000=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810=1 & thc0101=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810=2 & thc0202=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810=3 & thc0303=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810=4 & thc0404=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810=5 & thc0505=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810=6 & thc0606=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810=7 & thc0707=1 { }
Rn_exclaim_WB: is Rn0810 & thc0810 { Rn0810 = mult_addr; }
# ldlist is the list of registers to be loaded or popped
LdRtype0: " "^r0 is thc0000=1 & r0 & thc0107=0 { r0 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype0: " "^r0^"," is thc0000=1 & r0 { r0 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype0: is thc0000=0 { }
LdRtype1: LdRtype0 r1 is LdRtype0 & thc0101=1 & r1 & thc0207=0 { r1 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype1: LdRtype0 r1^"," is LdRtype0 & thc0101=1 & r1 { r1 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype1: LdRtype0 is LdRtype0 & thc0101=0 { }
LdRtype2: LdRtype1 r2 is LdRtype1 & thc0202=1 & r2 & thc0307=0 { r2 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype2: LdRtype1 r2^"," is LdRtype1 & thc0202=1 & r2 { r2 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype2: LdRtype1 is LdRtype1 & thc0202=0 { }
LdRtype3: LdRtype2 r3 is LdRtype2 & thc0303=1 & r3 & thc0407=0 { r3 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype3: LdRtype2 r3^"," is LdRtype2 & thc0303=1 & r3 { r3 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype3: LdRtype2 is LdRtype2 & thc0303=0 { }
LdRtype4: LdRtype3 r4 is LdRtype3 & thc0404=1 & r4 & thc0507=0 { r4 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype4: LdRtype3 r4^"," is LdRtype3 & thc0404=1 & r4 { r4 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype4: LdRtype3 is LdRtype3 & thc0404=0 { }
LdRtype5: LdRtype4 r5 is LdRtype4 & thc0505=1 & r5 & thc0607=0 { r5 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype5: LdRtype4 r5^"," is LdRtype4 & thc0505=1 & r5 { r5 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype5: LdRtype4 is LdRtype4 & thc0505=0 { }
LdRtype6: LdRtype5 r6 is LdRtype5 & thc0606=1 & r6 & thc0707=0 { r6 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype6: LdRtype5 r6^"," is LdRtype5 & thc0606=1 & r6 { r6 = *mult_addr; mult_addr = mult_addr + 4; }
LdRtype6: LdRtype5 is LdRtype5 & thc0606=0 { }
ldlist: LdRtype6 r7 is LdRtype6 & thc0707=1 & r7 { r7 = *mult_addr; mult_addr = mult_addr + 4; }
ldlist: LdRtype6 is LdRtype6 & thc0707=0 { }
#strlist is the list of registers to be stored
StrType0: " "^r0 is thc0000=1 & r0 & thc0107=0 { *mult_addr = r0; mult_addr = mult_addr + 4; }
StrType0: " "^r0^"," is thc0000=1 & r0 { *mult_addr = r0; mult_addr = mult_addr + 4; }
StrType0: is thc0000=0 { }
StrType1: StrType0 r1 is StrType0 & thc0101=1 & r1 & thc0207=0 { *mult_addr = r1; mult_addr = mult_addr + 4; }
StrType1: StrType0 r1^"," is StrType0 & thc0101=1 & r1 { *mult_addr = r1; mult_addr = mult_addr + 4; }
StrType1: StrType0 is StrType0 & thc0101=0 { }
StrType2: StrType1 r2 is StrType1 & thc0202=1 & r2 & thc0307=0 { *mult_addr = r2; mult_addr = mult_addr + 4; }
StrType2: StrType1 r2^"," is StrType1 & thc0202=1 & r2 { *mult_addr = r2; mult_addr = mult_addr + 4; }
StrType2: StrType1 is StrType1 & thc0202=0 { }
StrType3: StrType2 r3 is StrType2 & thc0303=1 & r3 & thc0407=0 { *mult_addr = r3; mult_addr = mult_addr + 4; }
StrType3: StrType2 r3^"," is StrType2 & thc0303=1 & r3 { *mult_addr = r3; mult_addr = mult_addr + 4; }
StrType3: StrType2 is StrType2 & thc0303=0 { }
StrType4: StrType3 r4 is StrType3 & thc0404=1 & r4 & thc0507=0 { *mult_addr = r4; mult_addr = mult_addr + 4; }
StrType4: StrType3 r4^"," is StrType3 & thc0404=1 & r4 { *mult_addr = r4; mult_addr = mult_addr + 4; }
StrType4: StrType3 is StrType3 & thc0404=0 { }
StrType5: StrType4 r5 is StrType4 & thc0505=1 & r5 & thc0607=0 { *mult_addr = r5; mult_addr = mult_addr + 4; }
StrType5: StrType4 r5^"," is StrType4 & thc0505=1 & r5 { *mult_addr = r5; mult_addr = mult_addr + 4; }
StrType5: StrType4 is StrType4 & thc0505=0 { }
StrType6: StrType5 r6 is StrType5 & thc0606=1 & r6 & thc0707=0 { *mult_addr = r6; mult_addr = mult_addr + 4; }
StrType6: StrType5 r6^"," is StrType5 & thc0606=1 & r6 { *mult_addr = r6; mult_addr = mult_addr + 4; }
StrType6: StrType5 is StrType5 & thc0606=0 { }
StrType7: StrType6 r7 is StrType6 & thc0707=1 & r7 { *mult_addr = r7; mult_addr = mult_addr + 4; }
StrType7: StrType6 is StrType6 & thc0707=0 { }
strlist: StrType7 is StrType7 { }
# pshlist is the list registers to be pushed to memory
# SCR 10921, fix the order in which the regs appear in the disassembled insn, to be in line with objdump
# Also add commas between regs
#
PshType7: "" is thc0707=0 { }
PshType7: r7 is thc0707=1 & r7 { mult_addr = mult_addr - 4; *mult_addr = r7; }
PshType6: PshType7 is PshType7 & thc0606=0 { }
PshType6: r6 is PshType7 & thc0606=1 & r6 & thc0707=0 { mult_addr = mult_addr - 4; *mult_addr = r6; }
PshType6: r6^"," PshType7 is PshType7 & thc0606=1 & r6 { mult_addr = mult_addr - 4; *mult_addr = r6; }
PshType5: PshType6 is PshType6 & thc0505=0 { }
PshType5: r5 is PshType6 & thc0505=1 & r5 & thc0607=0 { mult_addr = mult_addr - 4; *mult_addr = r5; }
PshType5: r5^"," PshType6 is PshType6 & thc0505=1 & r5 { mult_addr = mult_addr - 4; *mult_addr = r5; }
PshType4: PshType5 is PshType5 & thc0404=0 { }
PshType4: r4 is PshType5 & thc0404=1 & r4 & thc0507=0 { mult_addr = mult_addr - 4; *mult_addr = r4; }
PshType4: r4^"," PshType5 is PshType5 & thc0404=1 & r4 { mult_addr = mult_addr - 4; *mult_addr = r4; }
PshType3: PshType4 is PshType4 & thc0303=0 { }
PshType3: r3 is PshType4 & thc0303=1 & r3 & thc0407=0 { mult_addr = mult_addr - 4; *mult_addr = r3; }
PshType3: r3^"," PshType4 is PshType4 & thc0303=1 & r3 { mult_addr = mult_addr - 4; *mult_addr = r3; }
PshType2: PshType3 is PshType3 & thc0202=0 { }
PshType2: r2 is PshType3 & thc0202=1 & r2 & thc0307=0 { mult_addr = mult_addr - 4; *mult_addr = r2; }
PshType2: r2^"," PshType3 is PshType3 & thc0202=1 & r2 { mult_addr = mult_addr - 4; *mult_addr = r2; }
PshType1: PshType2 is PshType2 & thc0101=0 { }
PshType1: r1 is PshType2 & thc0101=1 & r1 & thc0207=0 { mult_addr = mult_addr - 4; *mult_addr = r1; }
PshType1: r1^"," PshType2 is PshType2 & thc0101=1 & r1 { mult_addr = mult_addr - 4; *mult_addr = r1; }
pshlist: PshType1 is PshType1 & thc0000=0 { }
pshlist: r0 is PshType1 & thc0000=1 & r0 & thc0107=0 { mult_addr = mult_addr - 4; *mult_addr = r0; }
pshlist: r0^"," PshType1 is PshType1 & thc0000=1 & r0 { mult_addr = mult_addr - 4; *mult_addr = r0; }
# ldlist_inc is the list of registers to be loaded for pop instructions
thrlist15: r0 is thc0000=1 & r0 & thc0115=0 { r0 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist15: r0^"," is thc0000=1 & r0 { r0 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist15: is thc0000=0 { }
thrlist14: thrlist15 r1 is thc0101=1 & thrlist15 & r1 & thc0215=0 { r1 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist14: thrlist15 r1^"," is thc0101=1 & thrlist15 & r1 { r1 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist14: thrlist15 is thc0101=0 & thrlist15 { }
thrlist13: thrlist14 r2 is thc0202=1 & thrlist14 & r2 & thc0315=0 { r2 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist13: thrlist14 r2^"," is thc0202=1 & thrlist14 & r2 { r2 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist13: thrlist14 is thc0202=0 & thrlist14 { }
thrlist12: thrlist13 r3 is thc0303=1 & thrlist13 & r3 & thc0415=0 { r3 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist12: thrlist13 r3^"," is thc0303=1 & thrlist13 & r3 { r3 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist12: thrlist13 is thc0303=0 & thrlist13 { }
thrlist11: thrlist12 r4 is thc0404=1 & thrlist12 & r4 & thc0515=0 { r4 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist11: thrlist12 r4^"," is thc0404=1 & thrlist12 & r4 { r4 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist11: thrlist12 is thc0404=0 & thrlist12 { }
thrlist10: thrlist11 r5 is thc0505=1 & thrlist11 & r5 & thc0615=0 { r5 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist10: thrlist11 r5^"," is thc0505=1 & thrlist11 & r5 { r5 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist10: thrlist11 is thc0505=0 & thrlist11 { }
thrlist9: thrlist10 r6 is thc0606=1 & thrlist10 & r6 & thc0715=0 { r6 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist9: thrlist10 r6^"," is thc0606=1 & thrlist10 & r6 { r6 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist9: thrlist10 is thc0606=0 & thrlist10 { }
thrlist8: thrlist9 r7 is thc0707=1 & thrlist9 & r7 & thc0815=0 { r7 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist8: thrlist9 r7^"," is thc0707=1 & thrlist9 & r7 { r7 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist8: thrlist9 is thc0707=0 & thrlist9 { }
thrlist7: thrlist8 r8 is thc0808=1 & thrlist8 & r8 & thc0915=0 { r8 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist7: thrlist8 r8^"," is thc0808=1 & thrlist8 & r8 { r8 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist7: thrlist8 is thc0808=0 & thrlist8 { }
thrlist6: thrlist7 r9 is thc0909=1 & thrlist7 & r9 & thc1015=0 { r9 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist6: thrlist7 r9^"," is thc0909=1 & thrlist7 & r9 { r9 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist6: thrlist7 is thc0909=0 & thrlist7 { }
thrlist5: thrlist6 r10 is thc1010=1 & thrlist6 & r10 & thc1115=0 { r10 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist5: thrlist6 r10^"," is thc1010=1 & thrlist6 & r10 { r10 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist5: thrlist6 is thc1010=0 & thrlist6 { }
thrlist4: thrlist5 r11 is thc1111=1 & thrlist5 & r11 & thc1215=0 { r11 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist4: thrlist5 r11^"," is thc1111=1 & thrlist5 & r11 { r11 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist4: thrlist5 is thc1111=0 & thrlist5 { }
thrlist3: thrlist4 r12 is thc1212=1 & thrlist4 & r12 & thc1315=0 { r12 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist3: thrlist4 r12^"," is thc1212=1 & thrlist4 & r12 { r12 = * mult_addr; mult_addr = mult_addr + 4; }
thrlist3: thrlist4 is thc1212=0 & thrlist4 { }
thrlist2: thrlist3 sp is thc1313=1 & thrlist3 & sp & thc1415=0 { sp = * mult_addr; mult_addr = mult_addr + 4; }
thrlist2: thrlist3 sp^"," is thc1313=1 & thrlist3 & sp { sp = * mult_addr; mult_addr = mult_addr + 4; }
thrlist2: thrlist3 is thc1313=0 & thrlist3 { }
thrlist1: thrlist2 lr is thc1414=1 & thrlist2 & lr & thc1515=0 { lr = * mult_addr; mult_addr = mult_addr + 4; }
thrlist1: thrlist2 lr^"," is thc1414=1 & thrlist2 & lr { lr = * mult_addr; mult_addr = mult_addr + 4; }
thrlist1: thrlist2 is thc1414=0 & thrlist2 { }
thldrlist_inc: {thrlist1 pc } is thc1515=1 & thrlist1 & pc { pc = * mult_addr; mult_addr = mult_addr + 4; }
thldrlist_inc: {thrlist1 } is thc1515=0 & thrlist1 { }
@if defined(VERSION_6T2) || defined(VERSION_7)
# thstrlist_inc is the list of registers to be stored using IA or IB in Addressing Mode 4
thsinc15: r0 is thc0000=1 & r0 { * mult_addr = r0; mult_addr = mult_addr + 4; }
thsinc15: is thc0000=0 { }
thsinc14: thsinc15 r1 is thc0101=1 & thsinc15 & r1 & thc0215=0 { * mult_addr = r1; mult_addr = mult_addr + 4; }
thsinc14: thsinc15 r1^"," is thc0101=1 & thsinc15 & r1 { * mult_addr = r1; mult_addr = mult_addr + 4; }
thsinc14: thsinc15 is thc0101=0 & thsinc15 { }
thsinc13: thsinc14 r2 is thc0202=1 & thsinc14 & r2 & thc0315=0 { * mult_addr = r2; mult_addr = mult_addr + 4; }
thsinc13: thsinc14 r2^"," is thc0202=1 & thsinc14 & r2 { * mult_addr = r2; mult_addr = mult_addr + 4; }
thsinc13: thsinc14 is thc0202=0 & thsinc14 { }
thsinc12: thsinc13 r3 is thc0303=1 & thsinc13 & r3 & thc0415=0 { * mult_addr = r3; mult_addr = mult_addr + 4; }
thsinc12: thsinc13 r3^"," is thc0303=1 & thsinc13 & r3 { * mult_addr = r3; mult_addr = mult_addr + 4; }
thsinc12: thsinc13 is thc0303=0 & thsinc13 { }
thsinc11: thsinc12 r4 is thc0404=1 & thsinc12 & r4 & thc0515=0 { * mult_addr = r4; mult_addr = mult_addr + 4; }
thsinc11: thsinc12 r4^"," is thc0404=1 & thsinc12 & r4 { * mult_addr = r4; mult_addr = mult_addr + 4; }
thsinc11: thsinc12 is thc0404=0 & thsinc12 { }
thsinc10: thsinc11 r5 is thc0505=1 & thsinc11 & r5 & thc0615=0 { * mult_addr = r5; mult_addr = mult_addr + 4; }
thsinc10: thsinc11 r5^"," is thc0505=1 & thsinc11 & r5 { * mult_addr = r5; mult_addr = mult_addr + 4; }
thsinc10: thsinc11 is thc0505=0 & thsinc11 { }
thsinc9: thsinc10 r6 is thc0606=1 & thsinc10 & r6 & thc0715=0 { * mult_addr = r6; mult_addr = mult_addr + 4; }
thsinc9: thsinc10 r6^"," is thc0606=1 & thsinc10 & r6 { * mult_addr = r6; mult_addr = mult_addr + 4; }
thsinc9: thsinc10 is thc0606=0 & thsinc10 { }
thsinc8: thsinc9 r7 is thc0707=1 & thsinc9 & r7 & thc0815=0 { * mult_addr = r7; mult_addr = mult_addr + 4; }
thsinc8: thsinc9 r7^"," is thc0707=1 & thsinc9 & r7 { * mult_addr = r7; mult_addr = mult_addr + 4; }
thsinc8: thsinc9 is thc0707=0 & thsinc9 { }
thsinc7: thsinc8 r8 is thc0808=1 & thsinc8 & r8 & thc0915=0 { * mult_addr = r8; mult_addr = mult_addr + 4; }
thsinc7: thsinc8 r8^"," is thc0808=1 & thsinc8 & r8 { * mult_addr = r8; mult_addr = mult_addr + 4; }
thsinc7: thsinc8 is thc0808=0 & thsinc8 { }
thsinc6: thsinc7 r9 is thc0909=1 & thsinc7 & r9 & thc1015=0 { * mult_addr = r9; mult_addr = mult_addr + 4; }
thsinc6: thsinc7 r9^"," is thc0909=1 & thsinc7 & r9 { * mult_addr = r9; mult_addr = mult_addr + 4; }
thsinc6: thsinc7 is thc0909=0 & thsinc7 { }
thsinc5: thsinc6 r10 is thc1010=1 & thsinc6 & r10 & thc1115=0 { * mult_addr = r10; mult_addr = mult_addr + 4; }
thsinc5: thsinc6 r10^"," is thc1010=1 & thsinc6 & r10 { * mult_addr = r10; mult_addr = mult_addr + 4; }
thsinc5: thsinc6 is thc1010=0 & thsinc6 { }
thsinc4: thsinc5 r11 is thc1111=1 & thsinc5 & r11 & thc1215=0 { * mult_addr = r11; mult_addr = mult_addr + 4; }
thsinc4: thsinc5 r11^"," is thc1111=1 & thsinc5 & r11 { * mult_addr = r11; mult_addr = mult_addr + 4; }
thsinc4: thsinc5 is thc1111=0 & thsinc5 { }
thsinc3: thsinc4 r12 is thc1212=1 & thsinc4 & r12 & thc1315=0 { * mult_addr = r12; mult_addr = mult_addr + 4; }
thsinc3: thsinc4 r12^"," is thc1212=1 & thsinc4 & r12 { * mult_addr = r12; mult_addr = mult_addr + 4; }
thsinc3: thsinc4 is thc1212=0 & thsinc4 { }
thsinc2: thsinc3 sp is thc1313=1 & thsinc3 & sp & thc1415=0 { * mult_addr = sp; mult_addr = mult_addr + 4; }
thsinc2: thsinc3 sp^"," is thc1313=1 & thsinc3 & sp { * mult_addr = sp; mult_addr = mult_addr + 4; }
thsinc2: thsinc3 is thc1313=0 & thsinc3 { }
thsinc1: thsinc2 lr is thc1414=1 & thsinc2 & lr & thc1515=0 { * mult_addr = lr; mult_addr = mult_addr + 4; }
thsinc1: thsinc2 lr^"," is thc1414=1 & thsinc2 & lr { * mult_addr = lr; mult_addr = mult_addr + 4; }
thsinc1: thsinc2 is thc1414=0 & thsinc2 { }
thstrlist_inc: {thsinc1 pc } is thc1515=1 & thsinc1 & pc { *:4 mult_addr = inst_start+4; mult_addr = mult_addr + 4; }
thstrlist_inc: {thsinc1 } is thc1515=0 & thsinc1 { }
# thldrlist_dec is the list of registers to be loaded using DA or DB in Addressing Mode 4
thrldec15: pc is thc1515=1 & pc { pc = * mult_addr; mult_addr = mult_addr - 4; }
thrldec15: is thc1515=0 { }
thrldec14: lr thrldec15 is thc1414=1 & thrldec15 & lr & thc1515=0 { lr = * mult_addr; mult_addr = mult_addr - 4; }
thrldec14: lr^"," thrldec15 is thc1414=1 & thrldec15 & lr { lr = * mult_addr; mult_addr = mult_addr - 4; }
thrldec14: thrldec15 is thc1414=0 & thrldec15 { }
thrldec13: sp thrldec14 is thc1313=1 & thrldec14 & sp & thc1415=0 { sp = * mult_addr; mult_addr = mult_addr - 4; }
thrldec13: sp^"," thrldec14 is thc1313=1 & thrldec14 & sp { sp = * mult_addr; mult_addr = mult_addr - 4; }
thrldec13: thrldec14 is thc1313=0 & thrldec14 { }
thrldec12: r12 thrldec13 is thc1212=1 & thrldec13 & r12 & thc1315=0 { r12 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec12: r12^"," thrldec13 is thc1212=1 & thrldec13 & r12 { r12 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec12: thrldec13 is thc1212=0 & thrldec13 { }
thrldec11: r11 thrldec12 is thc1111=1 & thrldec12 & r11 & thc1215=0 { r11 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec11: r11^"," thrldec12 is thc1111=1 & thrldec12 & r11 { r11 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec11: thrldec12 is thc1111=0 & thrldec12 { }
thrldec10: r10 thrldec11 is thc1010=1 & thrldec11 & r10 & thc1115=0 { r10 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec10: r10^"," thrldec11 is thc1010=1 & thrldec11 & r10 { r10 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec10: thrldec11 is thc1010=0 & thrldec11 { }
thrldec9: r9 thrldec10 is thc0909=1 & thrldec10 & r9 & thc1015=0 { r9 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec9: r9^"," thrldec10 is thc0909=1 & thrldec10 & r9 { r9 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec9: thrldec10 is thc0909=0 & thrldec10 { }
thrldec8: r8 thrldec9 is thc0808=1 & thrldec9 & r8 & thc0915=0 { r8 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec8: r8^"," thrldec9 is thc0808=1 & thrldec9 & r8 { r8 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec8: thrldec9 is thc0808=0 & thrldec9 { }
thrldec7: r7 thrldec8 is thc0707=1 & thrldec8 & r7 & thc0815=0 { r7 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec7: r7^"," thrldec8 is thc0707=1 & thrldec8 & r7 { r7 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec7: thrldec8 is thc0707=0 & thrldec8 { }
thrldec6: r6 thrldec7 is thc0606=1 & thrldec7 & r6 & thc0715=0 { r6 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec6: r6^"," thrldec7 is thc0606=1 & thrldec7 & r6 { r6 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec6: thrldec7 is thc0606=0 & thrldec7 { }
thrldec5: r5 thrldec6 is thc0505=1 & thrldec6 & r5 & thc0615=0 { r5 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec5: r5^"," thrldec6 is thc0505=1 & thrldec6 & r5 { r5 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec5: thrldec6 is thc0505=0 & thrldec6 { }
thrldec4: r4 thrldec5 is thc0404=1 & thrldec5 & r4 & thc0515=0 { r4 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec4: r4^"," thrldec5 is thc0404=1 & thrldec5 & r4 { r4 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec4: thrldec5 is thc0404=0 & thrldec5 { }
thrldec3: r3 thrldec4 is thc0303=1 & thrldec4 & r3 & thc0415=0 { r3 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec3: r3^"," thrldec4 is thc0303=1 & thrldec4 & r3 { r3 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec3: thrldec4 is thc0303=0 & thrldec4 { }
thrldec2: r2 thrldec3 is thc0202=1 & thrldec3 & r2 & thc0315=0 { r2 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec2: r2^"," thrldec3 is thc0202=1 & thrldec3 & r2 { r2 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec2: thrldec3 is thc0202=0 & thrldec3 { }
thrldec1: r1 thrldec2 is thc0101=1 & thrldec2 & r1 & thc0215=0 { r1 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec1: r1^"," thrldec2 is thc0101=1 & thrldec2 & r1 { r1 = * mult_addr; mult_addr = mult_addr - 4; }
thrldec1: thrldec2 is thc0101=0 & thrldec2 { }
thldrlist_dec: { r0 thrldec1 } is thc0000=1 & thrldec1 & r0 & thc0115=0 { r0 = * mult_addr; mult_addr = mult_addr - 4; }
thldrlist_dec: { r0^"," thrldec1 } is thc0000=1 & thrldec1 & r0 { r0 = * mult_addr; mult_addr = mult_addr - 4; }
thldrlist_dec: { thrldec1 } is thc0000=0 & thrldec1 { }
@endif # defined(VERSION_6T2) || defined(VERSION_7)
# thstrlist_dec is the list of registers to be pushed
thsdec15: pc is thc1515=1 & pc { *:4 mult_addr = inst_start+4; mult_addr = mult_addr - 4; }
thsdec15: is thc1515=0 { }
thsdec14: lr thsdec15 is thc1414=1 & thsdec15 & lr & thc1515=0 { * mult_addr=lr; mult_addr = mult_addr - 4; }
thsdec14: lr^"," thsdec15 is thc1414=1 & thsdec15 & lr { * mult_addr=lr; mult_addr = mult_addr - 4; }
thsdec14: thsdec15 is thc1414=0 & thsdec15 { }
thsdec13: sp thsdec14 is thc1313=1 & thsdec14 & sp & thc1415=0 { * mult_addr=sp; mult_addr = mult_addr - 4; }
thsdec13: sp^"," thsdec14 is thc1313=1 & thsdec14 & sp { * mult_addr=sp; mult_addr = mult_addr - 4; }
thsdec13: thsdec14 is thc1313=0 & thsdec14 { }
thsdec12: r12 thsdec13 is thc1212=1 & thsdec13 & r12 & thc1315=0 { * mult_addr=r12; mult_addr = mult_addr - 4; }
thsdec12: r12^"," thsdec13 is thc1212=1 & thsdec13 & r12 { * mult_addr=r12; mult_addr = mult_addr - 4; }
thsdec12: thsdec13 is thc1212=0 & thsdec13 { }
thsdec11: r11 thsdec12 is thc1111=1 & thsdec12 & r11 & thc1215=0 { * mult_addr=r11; mult_addr = mult_addr - 4; }
thsdec11: r11^"," thsdec12 is thc1111=1 & thsdec12 & r11 { * mult_addr=r11; mult_addr = mult_addr - 4; }
thsdec11: thsdec12 is thc1111=0 & thsdec12 { }
thsdec10: r10 thsdec11 is thc1010=1 & thsdec11 & r10 & thc1115=0 { * mult_addr=r10; mult_addr = mult_addr - 4; }
thsdec10: r10^"," thsdec11 is thc1010=1 & thsdec11 & r10 { * mult_addr=r10; mult_addr = mult_addr - 4; }
thsdec10: thsdec11 is thc1010=0 & thsdec11 { }
thsdec9: r9 thsdec10 is thc0909=1 & thsdec10 & r9 & thc1015=0 { * mult_addr=r9; mult_addr = mult_addr - 4; }
thsdec9: r9^"," thsdec10 is thc0909=1 & thsdec10 & r9 { * mult_addr=r9; mult_addr = mult_addr - 4; }
thsdec9: thsdec10 is thc0909=0 & thsdec10 { }
thsdec8: r8 thsdec9 is thc0808=1 & thsdec9 & r8 & thc0915=0 { * mult_addr=r8; mult_addr = mult_addr - 4; }
thsdec8: r8^"," thsdec9 is thc0808=1 & thsdec9 & r8 { * mult_addr=r8; mult_addr = mult_addr - 4; }
thsdec8: thsdec9 is thc0808=0 & thsdec9 { }
thsdec7: r7 thsdec8 is thc0707=1 & thsdec8 & r7 & thc0815=0 { * mult_addr=r7; mult_addr = mult_addr - 4; }
thsdec7: r7^"," thsdec8 is thc0707=1 & thsdec8 & r7 { * mult_addr=r7; mult_addr = mult_addr - 4; }
thsdec7: thsdec8 is thc0707=0 & thsdec8 { }
thsdec6: r6 thsdec7 is thc0606=1 & thsdec7 & r6 & thc0715=0 { * mult_addr=r6; mult_addr = mult_addr - 4; }
thsdec6: r6^"," thsdec7 is thc0606=1 & thsdec7 & r6 { * mult_addr=r6; mult_addr = mult_addr - 4; }
thsdec6: thsdec7 is thc0606=0 & thsdec7 { }
thsdec5: r5 thsdec6 is thc0505=1 & thsdec6 & r5 & thc0615=0 { * mult_addr=r5; mult_addr = mult_addr - 4; }
thsdec5: r5^"," thsdec6 is thc0505=1 & thsdec6 & r5 { * mult_addr=r5; mult_addr = mult_addr - 4; }
thsdec5: thsdec6 is thc0505=0 & thsdec6 { }
thsdec4: r4 thsdec5 is thc0404=1 & thsdec5 & r4 & thc0515=0 { * mult_addr=r4; mult_addr = mult_addr - 4; }
thsdec4: r4^"," thsdec5 is thc0404=1 & thsdec5 & r4 { * mult_addr=r4; mult_addr = mult_addr - 4; }
thsdec4: thsdec5 is thc0404=0 & thsdec5 { }
thsdec3: r3 thsdec4 is thc0303=1 & thsdec4 & r3 & thc0415=0 { * mult_addr=r3; mult_addr = mult_addr - 4; }
thsdec3: r3^"," thsdec4 is thc0303=1 & thsdec4 & r3 { * mult_addr=r3; mult_addr = mult_addr - 4; }
thsdec3: thsdec4 is thc0303=0 & thsdec4 { }
thsdec2: r2 thsdec3 is thc0202=1 & thsdec3 & r2 & thc0415=0 { * mult_addr=r2; mult_addr = mult_addr - 4; }
thsdec2: r2^"," thsdec3 is thc0202=1 & thsdec3 & r2 { * mult_addr=r2; mult_addr = mult_addr - 4; }
thsdec2: thsdec3 is thc0202=0 & thsdec3 { }
thsdec1: r1 thsdec2 is thc0101=1 & thsdec2 & r1 & thc0215=0 { * mult_addr=r1; mult_addr = mult_addr - 4; }
thsdec1: r1^"," thsdec2 is thc0101=1 & thsdec2 & r1 { * mult_addr=r1; mult_addr = mult_addr - 4; }
thsdec1: thsdec2 is thc0101=0 & thsdec2 { }
thstrlist_dec: { r0 thsdec1 } is thc0000=1 & thsdec1 & r0 & thc0115=0 { * mult_addr=r0; mult_addr = mult_addr - 4; }
thstrlist_dec: { r0^"," thsdec1 } is thc0000=1 & thsdec1 & r0 { * mult_addr=r0; mult_addr = mult_addr - 4; }
thstrlist_dec: { thsdec1 } is thc0000=0 & thsdec1 { }
ldbrace: {ldlist } is ldlist { }
stbrace: {strlist } is strlist { }
psbrace: { pshlist } is pshlist { }
# Some extra subconstructors for the push and pop instructions
pclbrace:{ldlist^"," pc } is ldlist & pc { build ldlist; pc = *mult_addr; mult_addr = mult_addr + 4; }
pclbrace:{ pc } is thc0007=0 & pc { pc = *mult_addr; mult_addr = mult_addr + 4; }
pcpbrace:{ pshlist^"," lr } is pshlist & lr { mult_addr = mult_addr - 4; *mult_addr = lr; build pshlist; }
pcpbrace:{ lr } is thc0007=0 & lr { mult_addr = mult_addr - 4; *mult_addr = lr; }
@if defined(VERSION_6T2) || defined(VERSION_7)
RnIndirect12: [Rn0003,"#"^offset12] is Rn0003; offset12 { local tmp = Rn0003 + offset12; export tmp; }
RnIndirectPUW: [Rn0003],"#"^-immed8 is Rn0003; addr_puw=1 & immed8 { local tmp = Rn0003; Rn0003=Rn0003-immed8; export tmp; }
RnIndirectPUW: [Rn0003],"#"^immed8 is Rn0003; addr_puw=3 & immed8 { local tmp = Rn0003; Rn0003=Rn0003+immed8; export tmp; }
RnIndirectPUW: [Rn0003,"#"^-immed8] is Rn0003; addr_puw=4 & immed8 { local tmp = Rn0003 - immed8; export tmp; }
RnIndirectPUW: [Rn0003,"#"^-immed8]! is Rn0003; addr_puw=5 & immed8 { local tmp = Rn0003 - immed8; Rn0003=tmp; export tmp; }
RnIndirectPUW: [Rn0003,"#"^immed8]! is Rn0003; addr_puw=7 & immed8 { local tmp = Rn0003 + immed8; Rn0003=tmp; export tmp; }
@define RN_INDIRECT_PUW "(op0; (addr_puw=4 | thc0808=1)) & RnIndirectPUW" # constraint for RnIndirectPUW
RnIndirectPUW1: [Rn0003],"#"^-immval is Rn0003 & addr_puw1=0x3; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003; Rn0003=Rn0003-immval; export tmp; }
RnIndirectPUW1: [Rn0003],"#"^immval is Rn0003 & addr_puw1=0x7; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003; Rn0003=Rn0003+immval; export tmp; }
RnIndirectPUW1: [Rn0003,"#"^-immval] is Rn0003 & addr_puw1=0xa; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 - immval; export tmp; }
RnIndirectPUW1: [Rn0003,"#"^-immval]! is Rn0003 & addr_puw1=0xb; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 - immval; Rn0003=tmp; export tmp; }
RnIndirectPUW1: [Rn0003,"#"^immval] is Rn0003 & addr_puw1=0xe; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 + immval; export tmp; }
RnIndirectPUW1: [Rn0003,"#"^immval]! is Rn0003 & addr_puw1=0xf; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 + immval; Rn0003=tmp; export tmp; }
@endif # VERSION_6T2 || VERSION_7
@define RN_INDIRECT_PUW1 "((thc0808=1 | thc0505=1); op0) & RnIndirectPUW1" # constraint for RnIndirectPUW1
RnIndirect4: [Rn0305,"#"^immval] is Rn0305 & immed5 [ immval = immed5 * 4; ] { local tmp = Rn0305 + immval; export tmp; }
RnIndirect2: [Rn0305,"#"^immval] is Rn0305 & immed5 [ immval = immed5 * 2; ] { local tmp = Rn0305 + immval; export tmp; }
RnIndirect1: [Rn0305,"#"^immed5] is Rn0305 & immed5 { local tmp = Rn0305 + immed5; export tmp; }
RnRmIndirect: [Rn0305,Rm0608] is Rn0305 & Rm0608 { local tmp = Rn0305 + Rm0608; export tmp; }
Pcrel8Indirect: [reloc] is immed8
[ reloc = ((inst_start+4) $and 0xfffffffc) + 4*immed8; ]
{
export *:4 reloc;
}
Sprel8Indirect: [sp,"#"^immval] is sp & immed8 [ immval = immed8 * 4; ] { local tmp = sp + immval; export tmp; }
@if defined(VERSION_6T2) || defined(VERSION_7)
taddrmode5: [Rn0003,"#"^off8] is thP8=1 & thU7=1 & thW5=0 & Rn0003; immed8 [ off8=immed8*4; ] { local tmp = Rn0003 + off8; export tmp; }
taddrmode5: [Rn0003,"#"^noff8] is thP8=1 & thU7=0 & thW5=0 & Rn0003; immed8 [ noff8=-(immed8*4); ] { local tmp = Rn0003 + noff8; export tmp; }
taddrmode5: [Rn0003,"#"^off8]! is thP8=1 & thU7=1 & thW5=1 & Rn0003; immed8 [ off8=immed8*4; ] { Rn0003 = Rn0003 + off8; export Rn0003; }
taddrmode5: [Rn0003,"#"^noff8]! is thP8=1 & thU7=0 & thW5=1 & Rn0003; immed8 [ noff8=-(immed8*4); ] { Rn0003 = Rn0003 + noff8; export Rn0003; }
taddrmode5: [Rn0003],"#"^off8 is thP8=0 & thU7=1 & thW5=1 & Rn0003; immed8 [ off8=immed8*4; ] { local tmp = Rn0003; Rn0003 = Rn0003+off8; export tmp; }
taddrmode5: [Rn0003],"#"^noff8 is thP8=0 & thU7=0 & thW5=1 & Rn0003; immed8 [ noff8=-(immed8*4); ] { local tmp = Rn0003; Rn0003 = Rn0003 + noff8; export tmp; }
taddrmode5: [Rn0003],{immed8} is thP8=0 & thU7=1 & thW5=0 & Rn0003; immed8 { export Rn0003; }
@endif # VERSION_6T2 || VERSION_7
#
# Modes for SRS instructions
#
thSRSMode: "usr" is thsrsMode=8 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "fiq" is thsrsMode=9 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "irq" is thsrsMode=10 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "svc" is thsrsMode=11 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "mon" is thsrsMode=14 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "abt" is thsrsMode=15 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "und" is thsrsMode=19 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "sys" is thsrsMode=23 & thc0004 { export *[const]:1 thc0004; }
thSRSMode: "#"^thsrsMode is thsrsMode { export *[const]:1 thsrsMode; }
#
# Detect if the PC is loaded and do a GOTO
#
# TODO: this is how all detections of writes into the PC should be done.
# Instead of enumerating and splitting the case into PC loaded and non loaded, IE (add PC,#0x...)
# Should only have one base constructor and have a sub constructor and build to test if the PC was loaded and do the right thing.
#
@if defined(VERSION_6T2) || defined(VERSION_7)
RtGotoCheck: is Rt1215=15 {
LoadWritePC(pc);
goto [pc];
}
RtGotoCheck: is Rt1215 {}
@endif # VERSION_6T2 || VERSION_7
############################################################
# Base constructors
# We have the following operand types:
# Type Corresponding syntax in ARM/THUMB manual
#
# Rd0002 <Rd> with Rd occupying bits 0-2
# Rd0810 <Rd> with Rd occupying bits 8-10
# Rm0305 <Rm> with Rm occupying bits 3-5
# Rm0608 <Rm> with Rm occupying bits 6-8
# Rn0002 <Rn> with Rn occupying bits 0-2
# Rn0305 <Rn> with Rn occupying bits 3-5
# Rn0810 <Rn> with Rn occupying bits 8-10
# Hrd0002 <Rd> with H1 bit in diagram
# Hrn0002 <Rn> with H1 bit in diagram
# Hrm0305 <Rm> with H2 bit in diagram
# Rs0305 <Rs> with Rs occupying bits 3-5
# Immed3 #<immed_3>
# Immed5 #<immed_5>
# Immed8 #<immed_8>
# Pcrel8 PC,#<immed_8>*4
# Sprel8 SP,#<immed_8>*4
# Immed7_4 #<immed_7>*4
# thcc <thcond>
# Addr8 <target_address> (for B<thcond>)
# Addr11 <target_address> (for B no condition)
# ThAddr22 <target_address> (for double BL, BLX)
# immed8 <immed_8> (no "#" as in BKPT and SWI)
# Rn_exclaim <Rn>!
# ldbrace <registers> (load instructions)
# strbrace <registers> (store instructions)
# RnIndirect4 [<Rn>,#<immed_5>*4]
# RnIndirect2 [<Rn>,#<immed_5>*2]
# RnIndirect1 [<Rn>,#<immed_5>]
# RnRmIndirect [<Rn>,<Rm>]
# Pcrel8Indirect [PC,#<immed_8>*4]
# Sprel8Indirect [SP,#<immed_8>*4]
#
@if defined(VERSION_6T2) || defined(VERSION_7)
# Ensure that the recursive rule for ARMcond is applied for assembly
with : ARMcondCk=1 {
@endif
:adc^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x105 & Rm0305 & Rd0002 & CheckInIT_CZNO
{
build ItCond;
th_add_with_carry_flags(Rd0002,Rm0305);
Rd0002 = Rd0002 + Rm0305 + zext(CY);
resflags(Rd0002);
build CheckInIT_CZNO;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:adc^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=0xa & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
th_add_with_carry_flags(Rn0003,ThumbExpandImm12);
Rd0811 = Rn0003 + ThumbExpandImm12 + zext(CY);
resflags(Rd0811);
build thSBIT_CZNO;
}
:adc^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=0xa & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
th_add_with_carry_flags(Rn0003,thshift2);
local tmp = thshift2+zext(CY);
Rd0811 = Rn0003+tmp;
resflags(Rd0811);
build thSBIT_CZNO;
}
@endif # VERSION_6T2 || VERSION_7
:add^ItCond Rd0002,Rn0305,Immed3 is TMode=1 & ItCond & op9=0x0e & Immed3 & Rn0305 & Rd0002 & CheckInIT_CZNO
{
build ItCond;
th_addflags(Rn0305,Immed3);
Rd0002 = Rn0305 + Immed3;
resflags(Rd0002);
build CheckInIT_CZNO;
}
:add^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=0x06 & Rd0810 & Immed8 & CheckInIT_CZNO
{
build ItCond;
th_addflags(Rd0810,Immed8);
Rd0810 = Rd0810 + Immed8;
resflags(Rd0810);
build CheckInIT_CZNO;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:add^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
th_addflags(Rn0003,ThumbExpandImm12);
Rd0811 = Rn0003+ThumbExpandImm12;
resflags(Rd0811);
build thSBIT_CZNO;
}
:addw^ItCond Rd0811,Rn0003,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & Rn0003; thc1515=0 & Rd0811) & Immed12
{
build ItCond;
th_addflags(Rn0003,Immed12);
Rd0811 = Rn0003+Immed12;
resflags(Rd0811);
}
:add^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=8 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
local tmp = thshift2;
th_addflags(Rn0003,tmp);
Rd0811 = Rn0003+tmp;
resflags(Rd0811);
build thSBIT_CZNO;
}
:add^thSBIT_CZNO^ItCond^".w" Rd0811,sp,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thSBIT_CZNO & sp & sop0003=0xd; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
th_addflags(sp,ThumbExpandImm12);
Rd0811 = sp+ThumbExpandImm12;
resflags(Rd0811);
build thSBIT_CZNO;
}
:addw^ItCond Rd0811,sp,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & sop0003=0xd & sp; thc1515=0 & Rd0811) & Immed12
{
build ItCond;
th_addflags(sp,Immed12);
Rd0811 = sp+Immed12;
resflags(Rd0811);
}
:add^thSBIT_CZNO^ItCond^".w" Rd0811,sp,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=8 & thSBIT_CZNO & sop0003=0xd & sp; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
local tmp = thshift2;
th_addflags(sp,tmp);
Rd0811 = sp+tmp;
resflags(Rd0811);
build thSBIT_CZNO;
}
@endif # VERSION_6T2 || VERSION_7
:add^ItCond Rd0002,Rn0305,Rm0608 is TMode=1 & ItCond & op9=0x0c & Rm0608 & Rn0305 & Rd0002 & CheckInIT_CZNO
{
build ItCond;
th_addflags(Rn0305,Rm0608);
Rd0002 = Rn0305 + Rm0608;
resflags(Rd0002);
build CheckInIT_CZNO;
}
:add^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x44 & Hrd0002 & Hrm0305
{
build ItCond;
Hrd0002 = Hrd0002 + Hrm0305;
}
:add^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x44 & Hrd0002 & Hrm0305 & hrd0002=7 & h1=1
{
build ItCond;
dest:4 = Hrd0002 + Hrm0305;
BranchWritePC(dest);
goto [pc];
}
:add^ItCond Rd0810,Sprel8 is TMode=1 & ItCond & op11=0x15 & Rd0810 & Sprel8
{
build ItCond;
Rd0810 = Sprel8;
}
:add^ItCond sp,Immed7_4 is TMode=1 & ItCond & op7=0x160 & sp & Immed7_4
{
build ItCond;
sp = sp + Immed7_4;
}
:adr^ItCond Rd0810,Pcrel8 is TMode=1 & ItCond & op11=0x14 & Rd0810 & Pcrel8
{
build ItCond;
Rd0810 = &Pcrel8;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:adr^ItCond^".w" Rd0811,NegPcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811) & NegPcrelImmed12Addr
{
build ItCond;
Rd0811 = &NegPcrelImmed12Addr;
}
:adr^ItCond^".w" Rd0811,PcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811) & PcrelImmed12Addr
{
build ItCond;
Rd0811 = &PcrelImmed12Addr;
}
:adr^ItCond^".w" Rd0811,NegPcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811 & thc0811=15) & NegPcrelImmed12Addr
{
build ItCond;
pc = &NegPcrelImmed12Addr;
goto NegPcrelImmed12Addr;
}
:adr^ItCond^".w" Rd0811,PcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811 & thc0811=15) & PcrelImmed12Addr
{
build ItCond;
pc = &PcrelImmed12Addr;
goto PcrelImmed12Addr;
}
@endif # VERSION_6T2 || VERSION_7
:and^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x100 & Rd0002 & Rm0305 & CheckInIT_ZN
{
build ItCond;
Rd0002 = Rd0002 & Rm0305;
resflags(Rd0002);
build CheckInIT_ZN;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:and^thSBIT_ZN^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=0 & thSBIT_ZN & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
Rd0811 = Rn0003 & ThumbExpandImm12;
resflags(Rd0811);
build thSBIT_ZN;
}
:and^thSBIT_ZN^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=0 & thSBIT_ZN & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
Rd0811 = Rn0003 & thshift2;
resflags(Rd0811);
build thSBIT_ZN;
}
@endif # VERSION_6T2 || VERSION_7
macro th_set_carry_for_asr(op1,shift_count) {
local bit = (op1 s>> (shift_count-1)) & 1;
tmpCY = ((shift_count == 0) && CY) || ((shift_count != 0) && (bit != 0));
}
#note that this is a special case where immed5 = 0, which corresponds to a shift amount of 32
:asr^ItCond Rd0002,Rm0305,"#0x20" is TMode=1 & ItCond & op11=0x02 & Immed5 & Rm0305 & Rd0002 & immed5=0 & CheckInIT_CZN
{
build ItCond;
th_set_carry_for_asr(Rm0305,32:1);
Rd0002 = Rm0305 s>> 32;
resflags(Rd0002);
build CheckInIT_CZN;
}
:asr^ItCond Rd0002,Rm0305,Immed5 is TMode=1 & ItCond & op11=0x02 & Immed5 & Rm0305 & Rd0002 & CheckInIT_CZN
{
build ItCond;
th_set_carry_for_asr(Rm0305,Immed5);
Rd0002 = Rm0305 s>> Immed5;
resflags(Rd0002);
build CheckInIT_CZN;
}
:asr^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x104 & Rd0002 & Rs0305 & CheckInIT_CZN
{
build ItCond;
local shift_amount = Rs0305 & 0xff;
th_set_carry_for_asr(Rd0002,shift_amount);
Rd0002 = Rd0002 s>> (shift_amount);
resflags(Rd0002);
build CheckInIT_CZN;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:asr^thSBIT_CZN^ItCond^".w" Rd0811,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & sop0003=0xf; thc1515=0 & Rd0811 & thc0405=2 & thshift2
{
build ItCond;
build thshift2;
Rd0811 = thshift2;
tmpCY = shift_carry;
resflags(Rd0811);
build thSBIT_CZN;
}
:asr^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op11=0x1f & thc0910=1 & sop0508=2 & thSBIT_CZN & Rn0003; op12=0xf & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
local shift_amount = Rm0003 & 0xff;
th_set_carry_for_asr(Rn0003,shift_amount);
Rd0811 = Rn0003 s>> (shift_amount);
resflags(Rd0811);
build thSBIT_CZN;
}
@endif # VERSION_6T2 || VERSION_7
# this constructor is identical to 16-bit udf instruction. it looks
# like it implented an unconditional branch instruction (giving it a
# made up name), but the thumb 16-bit instruction does not support
# unconditional branching.
@ifdef NOT_AN_INSTRUCTION
:bal Addr8 is TMode=1 & op12=0xd & thcond=14 & Addr8
{
goto Addr8;
}
@endif
:b^thcc Addr8 is TMode=1 & ItCond & op12=0b1101 & $(THCC) & Addr8
{
if (thcc) goto Addr8;
}
:b^ItCond Addr11 is TMode=1 & ItCond & op11=0b11100 & Addr11
{
goto Addr11;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:b^part2thcc^".w" ThAddr20 is TMode=1 & (part2op=0x1e & $(PART2THCC); part2c1415=2 & part2c1212=0) & ThAddr20
{
if (part2thcc) goto ThAddr20;
}
:b^ItCond^".w" ThAddr24 is TMode=1 & ItCond & (op11=0x1e; part2c1415=2 & part2c1212=1) & ThAddr24
{
build ItCond;
goto ThAddr24;
}
@endif # VERSION_6T2 || VERSION_7
@if defined(VERSION_6T2) || defined(VERSION_7)
:bfc^ItCond Rd0811,thLsbImm,thBitWidth is TMode=1 & ItCond & op0=0xf36f; thc1515=0 & Rd0811 & thc0505=0 & thLsbImm & thMsbImm & thBitWidth
{
build ItCond;
clearMask:4 = (-1 << (thMsbImm + 1)) | (-1 >> (32 - thLsbImm));
Rd0811 = Rd0811 & clearMask;
}
:bfi^ItCond Rd0811,Rn0003,thLsbImm,thBitWidth is TMode=1 & ItCond & op4=0xf36 & Rn0003; thc1515=0 & Rd0811 & thc0505=0 & thLsbImm & thMsbImm & thBitWidth
{
build ItCond;
clearMask:4 = (-1 << (thMsbImm + 1)) | (-1 >> (32 - thLsbImm));
bits:4 = (Rn0003 << thLsbImm) & ~clearMask;
Rd0811 = (Rd0811 & clearMask) | bits;
}
@endif # VERSION_6T2 || VERSION_7
:bic^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10e & Rd0002 & Rm0305 & CheckInIT_ZN
{
build ItCond;
Rd0002 = Rd0002 & (~Rm0305);
resflags(Rd0002);
build CheckInIT_ZN;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:bic^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=1 & thSBIT_ZN & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
Rd0811 = Rn0003&(~ThumbExpandImm12);
resflags(Rd0811);
build thSBIT_ZN;
}
:bic^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=1 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
Rd0811 = Rn0003&(~thshift2);
th_logicflags();
resflags(Rd0811);
build thSBIT_CZNO;
}
@endif # VERSION_6T2 || VERSION_7
@if defined(VERSION_5)
# Exception Generation and UDF
:hlt immed6 is TMode=1 & op6=0b1011101010 & immed6
{
software_hlt(immed6:4);
}
:bkpt immed8 is TMode=1 & ItCond & op8=0xbe & immed8
{
software_bkpt(immed8:4);
# Not a mistake, breakpoint always unconditional even in IT Block
build ItCond;
}
:hvc "#"^tmp is TMode=1 & op4=0xf7e & thc0003; op12=0x8 & thc0011 [tmp = thc0003 << 12 | thc0011;]
{
software_hvc(tmp:4);
}
# Requires Security Extensions
:smc^ItCond "#"^thc0003 is TMode=1 & ItCond & op4=0xf7f & thc0003; op12=0x8
{
build ItCond;
software_smc(thc0003:1);
}
@ifndef NOT_AN_INSTRUCTION
:udf^ItCond "#"thc0007 is TMode=1 & ItCond & op8 = 0xde & thc0007
{
build ItCond;
local excaddr:4 = inst_start;
local target:4 = software_udf(thc0007:4, excaddr);
goto [target];
}
@endif
:udf^ItCond "#"tmp is TMode=1 & ItCond & op4=0xf7f & thc0003; op12=0xa & thc0011 [tmp = thc0003 << 12 | thc0011;]
{
build ItCond;
local excaddr:4 = inst_start;
local target:4 = software_udf(tmp:4, excaddr);
goto [target];
}
@endif # VERSION_5
:bl^ItCond ThAddr24 is TMode=1 & ItCond & (op11=0x1e; part2c1415=3 & part2c1212=1) & ThAddr24
{
build ItCond;
lr = inst_next|1;
SetThumbMode(1);
call ThAddr24;
}
@ifndef VERSION_6T2
:bl^ItCond "#"^off is TMode=1 & ItCond & op11=0x1e & soffset11 [ off = inst_start + 4 + (soffset11 << 12); ]
{
build ItCond;
lr = off:4;
}
:bl^ItCond "#"^off is TMode=1 & ItCond & op11=0x1f & offset11 [ off = offset11 << 1; ]
{
build ItCond;
local dest = lr + off:4;
lr = inst_next|1;
SetThumbMode(1);
goto [dest];
}
:blx^ItCond "#"^off is TMode=1 & ItCond & op11=0x1d & offset11 & thc0000=0 [ off = offset11 << 1; ]
{
build ItCond;
local dest = (lr & (~0x3)) + off:4;
lr = inst_next|1;
SetThumbMode(0);
call [dest];
}
@endif
:bl^ItCond ThAddr24 is TMode=1 & CALLoverride=1 & ItCond & (op11=0x1e; part2c1415=3 & part2c1212=1) & ThAddr24
{
build ItCond;
lr = inst_next|1;
SetThumbMode(1);
goto ThAddr24;
}
bxns: "" is thc0003 { }
bxns: "ns" is thc0002=0b100 { }
@if defined(VERSION_5)
:blx^ItCond ThArmAddr23 is TMode=1 & ItCond & (op11=0x1e;part2op=0x1d) & ThArmAddr23 [ TMode=0; globalset(ThArmAddr23,TMode); TMode=1; ]
{
build ItCond;
lr = inst_next|1;
SetThumbMode(0);
call ThArmAddr23;
# Don't set this, assume return will set for emulation. Was screwing up decompiler. TB = 1;
}
:blx^ItCond ThArmAddr23 is TMode=1 & ItCond & CALLoverride=1 & (op11=0x1e;part2op=0x1d) & ThArmAddr23 [ TMode=0; globalset(ThArmAddr23,TMode); TMode=1; ]
{
build ItCond;
lr = inst_next|1;
SetThumbMode(0);
goto ThArmAddr23;
}
:blx^ItCond ThArmAddr23 is TMode=1 & ItCond & (op11=0x1e; part2c1415=3 & part2c1212=0) & ThArmAddr23 [ TMode=0; globalset(ThArmAddr23,TMode); TMode=1; ]
{
build ItCond;
lr = inst_next|1;
SetThumbMode(0);
call ThArmAddr23;
}
:blx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & op7=0x08f & Hrm0305 & bxns
{
build ItCond;
BXWritePC(Hrm0305);
lr = inst_next|1;
call [pc];
# Don't set this, assume return will set for emulation. Was screwing up decompiler. TB = 1;
}
@endif # VERSION_5
:bx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & op7=0x08e & Hrm0305 & hrm0305=6 & h2=1 & bxns
{
build ItCond;
BXWritePC(Hrm0305);
return [pc];
}
:bx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & op7=0x08e & Hrm0305 & bxns
{
build ItCond;
BXWritePC(Hrm0305);
goto [pc];
}
:bx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & LRset=1 & op7=0x08e & Hrm0305 & bxns [ LRset=0; TMode=1; globalset(inst_next,LRset); globalset(inst_next,TMode); ]
{
build ItCond;
BXWritePC(Hrm0305);
call [pc];
# Don't set this, assume return will set for emulation. Was screwing up decompiler. TB = 1;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:bxj^ItCond Rn0003 is TMode=1 & ItCond & op4=0xf3c & Rn0003; op0=0x8f00
{
build ItCond;
success:1 = jazelle_branch();
if (success) goto <skipBx>;
SetThumbMode( (Rn0003&0x00000001)!=0 );
local tmp=Rn0003&0xfffffffe;
goto [tmp];
<skipBx>
} # Optional change to THUMB
@endif # VERSION_6T2 || VERSION_7
:cbnz^ItCond Rn0002,Addr5 is TMode=1 & ItCond & op12=0xb & thc1111=1 & thc1010=0 & thc0808=1 & Rn0002 & Addr5
{
build ItCond;
local tmp = Rn0002 != 0;
if (tmp) goto Addr5;
}
:cbz^ItCond Rn0002,Addr5 is TMode=1 & ItCond & op12=0xb & thc1111=0 & thc1010=0 & thc0808=1 & Rn0002 & Addr5
{
build ItCond;
local tmp = Rn0002 == 0;
if (tmp) goto Addr5;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:cdp^ItCond thcpn,thopcode1,thCRd,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thopcode1 & thCRn; thCRd & thcpn & thopcode2 & thc0404=0 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op1:4 = thopcode1;
t_op2:4 = thopcode2;
coprocessor_function(t_cpn,t_op1,t_op2,thCRd,thCRn,thCRm);
}
:cdp2^ItCond thcpn,thopcode1,thCRd,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thopcode1 & thCRn; thCRd & thcpn & thopcode2 & thc0404=0 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op1:4 = thopcode1;
t_op2:4 = thopcode2;
coprocessor_function2(t_cpn,t_op1,t_op2,thCRd,thCRn,thCRm);
}
define pcodeop IndexCheck;
:chka^ItCond Hrn0002,Rm0306 is TMode=1 & ItCond & TEEMode=1 & op8=0xca & Rm0306 & Hrn0002
{
build ItCond;
local tmp = Hrn0002 <= Rm0306;
if (!tmp) goto inst_next;
lr = inst_next|1;
IndexCheck();
}
:clrex^ItCond is TMode=1 & ItCond & op0=0xf3bf; op0=0x8f2f
{
build ItCond;
ClearExclusiveLocal();
}
:clz^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op4=0xfab & Rm0003; op12=15 & Rd0811
{
build ItCond;
Rd0811 = count_leading_zeroes(Rm0003);
}
:cmn^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thc0404=1 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12
{
build ItCond;
th_addflags(Rn0003,ThumbExpandImm12);
local tmp = Rn0003 + ThumbExpandImm12;
resflags(tmp);
th_affectflags();
}
:cmn^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op4=0xeb1 & Rn0003; thc1515=0 & thc0811=15 & thshift2
{
build ItCond;
build thshift2;
th_addflags(Rn0003,thshift2);
local tmp = Rn0003+thshift2;
resflags(tmp);
th_affectflags();
}
@endif # VERSION_6T2 || VERSION_7
:cmn^ItCond Rn0002,Rm0305 is TMode=1 & ItCond & op6=0x10b & Rm0305 & Rn0002
{
build ItCond;
th_addflags(Rn0002,Rm0305);
local tmp = Rn0002 + Rm0305;
resflags(tmp);
th_affectflags();
}
:cmp^ItCond Rn0810,Immed8 is TMode=1 & ItCond & op11=5 & Rn0810 & Immed8
{
build ItCond;
th_subflags(Rn0810,Immed8);
local tmp = Rn0810 - Immed8;
resflags(tmp);
th_affectflags();
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:cmp^ItCond^".w" Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & thc0404=1 & sop0508=13 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12
{
build ItCond;
th_subflags(Rn0003,ThumbExpandImm12);
local tmp = Rn0003 - ThumbExpandImm12;
resflags(tmp);
th_affectflags();
}
:cmp^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op4=0xebb & Rn0003; thc1515=0 & thc0811=15 & thshift2
{
build ItCond;
th_subflags(Rn0003,thshift2);
local tmp = Rn0003 - thshift2;
resflags(tmp);
th_affectflags();
}
@endif # VERSION_6T2 || VERSION_7
:cmp^ItCond Rn0002,Rm0305 is TMode=1 & ItCond & op6=0x10a & Rm0305 & Rn0002
{
build ItCond;
th_subflags(Rn0002,Rm0305);
local tmp = Rn0002 - Rm0305;
resflags(tmp);
th_affectflags();
}
:cmp^ItCond Hrn0002,Hrm0305 is TMode=1 & ItCond & op8=0x45 & Hrm0305 & Hrn0002
{
build ItCond;
th_subflags(Hrn0002,Hrm0305);
local tmp = Hrn0002 - Hrm0305;
resflags(tmp);
th_affectflags();
}
@if defined(VERSION_6)
aflag: "a" is thc0202=1 & thc0404=0 { enableDataAbortInterrupts(); }
aflag: "a" is thc0202=1 { disableDataAbortInterrupts(); }
aflag: is thc0202=0 { }
iflag: "i" is thc0101=1 & thc0404=0 { enableIRQinterrupts(); } # 7M: set primask
iflag: "i" is thc0101=1 { disableIRQinterrupts(); } # 7M: clear primask
iflag: is thc0101=0 { }
fflag: "f" is thc0000=1 & thc0404=0 { enableFIQinterrupts(); } # 7M: set faultmask
fflag: "f" is thc0000=1 { disableFIQinterrupts(); } # 7M: clear faultmask
fflag: is thc0000=0 { }
iflags: aflag^iflag^fflag is aflag & iflag & fflag { }
:cpsie^ItCond iflags is TMode=1 & ItCond & op8=0xb6 & sop0507=3 & thc0303=0 & iflags & thc0404=0
{
build ItCond;
build iflags;
# see iflags for semantics
}
:cpsid^ItCond iflags is TMode=1 & ItCond & op8=0xb6 & sop0507=3 & thc0303=0 & iflags & thc0404=1
{
build ItCond;
build iflags;
# see iflags for semantics
}
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
# For SCR 11074, implement the "Encoding T2" 32-bit Thumb-2 cps change processor state instruction
# Note the manual says there are no conditions on this insn
#
th2_aflag: "a" is thc0707=1 & thc0910=0x2 { enableDataAbortInterrupts(); }
th2_aflag: "a" is thc0707=1 { disableDataAbortInterrupts(); }
th2_aflag: is thc0707=0 { }
th2_iflag: "i" is thc0606=1 & thc0910=0x2 { enableIRQinterrupts(); } # 7M: set primask
th2_iflag: "i" is thc0606=1 { disableIRQinterrupts(); } # 7M: clear primask
th2_iflag: is thc0606=0 { }
th2_fflag: "f" is thc0505=1 & thc0910=0 { enableFIQinterrupts(); } # 7M: set faultmask
th2_fflag: "f" is thc0505=1 { disableFIQinterrupts(); } # 7M: clear faultmask
th2_fflag: is thc0505=0 { }
th2_iflags: th2_aflag^th2_iflag^th2_fflag is th2_aflag & th2_iflag & th2_fflag { }
th2_SetMode: "#"^16 is thc0004=0x10 { setUserMode(); }
th2_SetMode: "#"^17 is thc0004=0x11 { setFIQMode(); }
th2_SetMode: "#"^18 is thc0004=0x12 { setIRQMode(); }
th2_SetMode: "#"^19 is thc0004=0x13 { setSupervisorMode(); }
th2_SetMode: "#"^22 is thc0004=0x16 { setMonitorMode(); }
th2_SetMode: "#"^23 is thc0004=0x17 { setAbortMode(); }
th2_SetMode: "#"^27 is thc0004=0x1b { setUndefinedMode(); }
th2_SetMode: "#"^31 is thc0004=0x1f { setSystemMode(); }
# 11110 0 1110 1 0 1111 10 0 0 0
:cpsie th2_iflags, th2_SetMode is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2imm6=0x2f ;
thc0910=0x2 & th2_SetMode & op11=0x10 & th2_iflags
{
build th2_iflags;
}
:cpsid th2_iflags, th2_SetMode is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2imm6=0x2f ;
thc0910=0x3 & th2_SetMode & op11=0x10 & th2_iflags
{
build th2_iflags;
}
:cps th2_SetMode is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2imm6=0x2f ;
thc0808=0x1 & th2_SetMode & op11=0x10
{
}
@endif # (VERSION_6T2) || defined(VERSION_7)
@if defined(VERSION_6T2) || defined(VERSION_7)
:dbg^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3af; op4=0x80f & thc0004
{
@if defined(VERSION_7)
HintDebug(thc0004:1);
@endif # VERSION_7
}
@if defined(VERSION_7)
:dmb^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3bf; op4=0x8f5 & thc0004
{
DataMemoryBarrier(thc0004:1);
}
:dsb^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3bf; op4=0x8f4 & thc0004
{
DataSynchronizationBarrier(thc0004:1);
}
@endif
:eor^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=4 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
Rd0811 = Rn0003 ^ ThumbExpandImm12;
th_logicflags();
resflags(Rd0811);
build thSBIT_CZNO;
}
:eor^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=4 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
Rd0811 = Rn0003 ^ thshift2;
th_logicflags();
resflags(Rd0811);
build thSBIT_CZNO;
}
:enterx^ItCond is TMode=1 & ItCond & op0=0xf3bf; op0=0x8f1f [ TEEMode=1; globalset(inst_next,TEEMode); ]
{
build ItCond;
}
:leavex^ItCond is TMode=1 & ItCond & op0=0xf3bf; op0=0x8f0f [ TEEMode=0; globalset(inst_next,TEEMode); ]
{
build ItCond;
}
@endif # VERSION_6T2 || VERSION_7
:eor^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x101 & Rm0305 & Rd0002 & CheckInIT_ZN
{
build ItCond;
Rd0002 = Rd0002 ^ Rm0305;
resflags(Rd0002);
build CheckInIT_ZN;
}
@if defined(VERSION_7)
:hb^ItCond "#"^immed8 is TMode=1 & ItCond & TEEMode=1 & op9=0x61 & immed8
{
build ItCond;
}
:isb^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3bf; op4=0x8f6 & thc0004
{
InstructionSynchronizationBarrier(thc0004:1);
}
@endif # VERSION_7
@if defined(VERSION_8)
# F5.1.178 p2969 SEVL T1 variant
:sevl
is TMode=1 & op0=0b1011111101010000
& ItCond
{
build ItCond;
SendEvent();
}
@endif # VERSION_8
@if defined(VERSION_6T2) || defined(VERSION_7)
X: "t" is TMode=1 & ((thc0404=1 & thc0303=1) | (thc0404=0 & thc0303=0)) & (thc0202=1 | thc0101=1 | thc0000=1) { }
X: "e" is TMode=1 & ((thc0404=1 & thc0303=0) | (thc0404=0 & thc0303=1)) & (thc0202=1 | thc0101=1 | thc0000=1) { }
X: "" is TMode=1 & thc0404 & thc0303 & (thc0202=0 & thc0101=0 & thc0000=0) { }
Y: "t" is TMode=1 & ((thc0404=1 & thc0202=1) | (thc0404=0 & thc0202=0)) & (thc0101=1 | thc0000=1) { }
Y: "e" is TMode=1 & ((thc0404=1 & thc0202=0) | (thc0404=0 & thc0202=1)) & (thc0101=1 | thc0000=1) { }
Y: "" is TMode=1 & thc0404 & thc0202 & (thc0101=0 & thc0000=0) { }
Z: "t" is TMode=1 & ((thc0404=1 & thc0101=1) | (thc0404=0 & thc0101=0)) & (thc0000=1) { }
Z: "e" is TMode=1 & ((thc0404=1 & thc0101=0) | (thc0404=0 & thc0101=1)) & (thc0000=1) { }
Z: "" is TMode=1 & thc0404 & thc0101 & (thc0000=0) { }
XYZ: is TMode=1 & sop0003=8 { }
XYZ: X^Y^Z is TMode=1 & X & Y & Z { }
:it^XYZ it_thfcc is TMode=1 & op8=0xbf & XYZ & $(IT_THFCC) & thc0507 & thc0004
[ itmode=0; cond_base = thc0507; cond_shft=thc0004; globalset(inst_next,condit); ]
{
# just sets up the condition and If Then/Else mask
}
:ldc^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=0 & thL4=1; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_load(t_cpn,thCRd,taddrmode5);
}
:ldcl^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=1 & thL4=1; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_loadlong(t_cpn,thCRd,taddrmode5);
}
:ldc2^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=0 & thL4=1; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_load(t_cpn,thCRd,taddrmode5);
}
:ldc2l^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=1 & thL4=1; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_loadlong(t_cpn,thCRd,taddrmode5);
}
@endif # VERSION_6T2 || VERSION_7
:ldmia^ItCond Rn_exclaim,ldbrace is TMode=1 & ItCond & op11=0x19 & Rn_exclaim & ldbrace & Rn_exclaim_WB
{
build ItCond;
build Rn_exclaim;
build ldbrace;
build Rn_exclaim_WB;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:ldm^ItCond^".w" Rn0003,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=0 & thc0404=1 & Rn0003; thc1313=0 & thldrlist_inc
{
build ItCond;
mult_addr = Rn0003;
build thldrlist_inc;
}
:ldm^ItCond^".w" Rn0003!,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=1 & thc0404=1 & Rn0003; thc1313=0 & thldrlist_inc
{
build ItCond;
mult_addr = Rn0003;
build thldrlist_inc;
Rn0003 = mult_addr;
}
:ldm^ItCond Rn0003,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=0 & thc0404=1 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_inc
{
build ItCond;
mult_addr = Rn0003;
build thldrlist_inc;
LoadWritePC(pc);
goto [pc];
}
:ldm^ItCond^".w" Rn0003,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=1 & thc0404=1 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_inc
{
build ItCond;
mult_addr = Rn0003;
build thldrlist_inc;
Rn0003 = mult_addr;
LoadWritePC(pc);
goto [pc];
}
:ldmdb^ItCond Rn0003,thldrlist_dec is TMode=1 & ItCond & op4=0xe91 & Rn0003; thc1313=0 & thldrlist_dec
{
build ItCond;
mult_addr = Rn0003-4;
build thldrlist_dec;
}
:ldmdb^ItCond Rn0003!,thldrlist_dec is TMode=1 & ItCond & op4=0xe93 & Rn0003; thc1313=0 & thldrlist_dec
{
build ItCond;
mult_addr = Rn0003-4;
build thldrlist_dec;
Rn0003 = mult_addr + 4;
}
:ldmdb^ItCond Rn0003,thldrlist_dec is TMode=1 & ItCond & op4=0xe91 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_dec
{
build ItCond;
mult_addr = Rn0003-4;
build thldrlist_dec;
LoadWritePC(pc);
goto [pc];
}
:ldmdb^ItCond Rn0003,thldrlist_dec is TMode=1 & ItCond & op4=0xe93 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_dec
{
build ItCond;
mult_addr = Rn0003-4;
build thldrlist_dec;
Rn0003 = mult_addr + 4;
LoadWritePC(pc);
goto [pc];
}
@endif # VERSION_6T2 || VERSION_7
:ldr^ItCond Rd0002,RnIndirect4 is TMode=1 & ItCond & op11=0xd & RnIndirect4 & Rd0002
{
build ItCond;
build RnIndirect4;
Rd0002 = *RnIndirect4;
}
:ldr^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2c & RnRmIndirect & Rd0002
{
build ItCond;
build RnRmIndirect;
Rd0002 = *RnRmIndirect;
}
:ldr^ItCond Rd0810,Pcrel8Indirect is TMode=1 & ItCond & op11=9 & Pcrel8Indirect & Rd0810
{
build ItCond;
build Pcrel8Indirect;
Rd0810 = Pcrel8Indirect;
}
# Note: NO '*' IS INTENTIONAL
:ldr^ItCond Rd0810,Sprel8Indirect is TMode=1 & ItCond & op11=0x13 & Sprel8Indirect & Rd0810
{
build ItCond;
build Sprel8Indirect;
Rd0810 = *Sprel8Indirect;
}
:ldrb^ItCond Rd0002,RnIndirect1 is TMode=1 & ItCond & op11=0xf & RnIndirect1 & Rd0002
{
build ItCond;
build RnIndirect1;
Rd0002 = zext( *:1 RnIndirect1 );
}
:ldrb^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2e & RnRmIndirect & Rd0002
{
build ItCond;
build RnRmIndirect;
Rd0002 = zext( *:1 RnRmIndirect);
}
:ldrh^ItCond Rd0002,RnIndirect2 is TMode=1 & ItCond & op11=0x11 & RnIndirect2 & Rd0002
{
build ItCond;
build RnIndirect2;
Rd0002 = zext( *:2 RnIndirect2);
}
:ldrh^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2d & RnRmIndirect & Rd0002
{
build ItCond;
build RnRmIndirect;
Rd0002 = zext( *:2 RnRmIndirect);
}
:ldrsb^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2b & RnRmIndirect & Rd0002
{
build ItCond;
build RnRmIndirect;
Rd0002 = sext( *:1 RnRmIndirect);
}
:ldrsh^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2f & RnRmIndirect & Rd0002
{
build ItCond;
build RnRmIndirect;
Rd0002 = sext( *:2 RnRmIndirect);
}
define pcodeop ExclusiveAccess;
@if defined(VERSION_7)
:ldrexb^ItCond Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; Rt1215 & thc0811=15 & thc0407=4 & thc0003=15
{
build ItCond;
local tmp = Rn0003;
ExclusiveAccess(tmp);
val:1 = *tmp;
Rt1215 = zext(val);
}
:ldrexh^ItCond Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; Rt1215 & thc0811=15 & thc0407=5 & thc0003=15
{
build ItCond;
local tmp = Rn0003;
ExclusiveAccess(tmp);
val:2 = *tmp;
Rt1215 = zext(val);
}
:ldrexd^ItCond Rt1215,Rt0811,[Rn0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; Rt1215 & Rt0811 & thc0407=7 & thc0003=15
{
build ItCond;
local tmp = Rn0003;
ExclusiveAccess(tmp);
val1:4 = *tmp;
val2:4 = *(tmp + 4);
Rt1215 = val1;
Rt0811 = val2;
}
@endif # VERSION_7
@if defined(VERSION_6T2) || defined(VERSION_7)
:ldrex^ItCond Rt1215,[Rn0003,Immed8_4] is TMode=1 & ItCond & op4=0xe85 & Rn0003; Rt1215 & thc0811=15 & Immed8_4
{
build ItCond;
local tmp = Rn0003 + Immed8_4;
ExclusiveAccess(tmp);
Rt1215 = *tmp;
}
:ldr^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8d; Rt1215 & RtGotoCheck) & RnIndirect12
{
build ItCond;
build RnIndirect12;
Rt1215 = *RnIndirect12;
build RtGotoCheck;
}
:ldr^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf85; Rt1215 & thc1111=1 & RtGotoCheck) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
Rt1215 = *RnIndirectPUW;
build RtGotoCheck;
}
:ldr^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf8d & sop0003=15; Rt1215 & RtGotoCheck) & PcrelOffset12
{
build ItCond;
build PcrelOffset12;
Rt1215 = PcrelOffset12:4;
build RtGotoCheck;
}
# overlaps pattern with next ldr intruction, must occur first
:ldr^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf85 & sop0003=15; Rt1215 & RtGotoCheck) & PcrelOffset12
{
build ItCond;
build PcrelOffset12;
Rt1215 = PcrelOffset12:4;
build RtGotoCheck;
}
:ldr^ItCond^".w" Rt1215,[Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xf85 & Rn0003; Rt1215 & RtGotoCheck & thc1111=0 & sop0610=0 & thc0405=0 & Rm0003
{
build ItCond;
local tmp = Rn0003 + Rm0003;
Rt1215 = *tmp;
build RtGotoCheck;
}
:ldr^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf85 & Rn0003; Rt1215 & RtGotoCheck & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
Rt1215 = *tmp;
build RtGotoCheck;
}
:ldrb^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf89; Rt1215) & RnIndirect12
{
build ItCond;
build RnIndirect12;
tmp:1 = *RnIndirect12;
Rt1215 = zext(tmp);
}
:ldrb^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf81; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
tmp:1 = *RnIndirectPUW;
Rt1215 = zext(tmp);
}
:ldrb^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf89 & sop0003=15; Rt1215) & PcrelOffset12
{
build ItCond;
build PcrelOffset12;
tmp:1 = PcrelOffset12:1;
Rt1215 = zext(tmp);
}
:ldrb^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf81 & sop0003=15; Rt1215) & PcrelOffset12
{
build ItCond;
build PcrelOffset12;
tmp:1 = PcrelOffset12:1;
Rt1215 = zext(tmp);
}
:ldrb^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf81 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
val:1 = *tmp;
Rt1215 = zext(val);
}
:ldrbt^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf81 & Rn0003; Rt1215 & thc0811=14 & Immed8
{
build ItCond;
local tmp = Rn0003 + Immed8;
val:1 = *tmp;
Rt1215 = zext(val);
}
:ldrd^ItCond Rt1215,Rt0811,RnIndirectPUW1 is TMode=1 & ItCond & (op9=0x74 & thc0606=1 & thc0404=1 & Rn0003; Rt1215 & Rt0811) & $(RN_INDIRECT_PUW1)
{
build ItCond;
build RnIndirectPUW1;
Rt1215 = *RnIndirectPUW1;
Rt0811 = *(RnIndirectPUW1+4);
}
:ldrd^ItCond Rt1215,Rt0811,Pcrel8_s8 is TMode=1 & ItCond & op9=0x74 & thc0606=1 & thc0404=1 & sop0003=15; Rt1215 & Rt0811 & Pcrel8_s8
{
build ItCond;
build Pcrel8_s8;
local val = Pcrel8_s8;
Rt1215 = val(4);
Rt0811 = val(0);
}
:ldrh.w^ItCond Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8B; Rt1215) & RnIndirect12
{
build ItCond;
build RnIndirect12;
tmp:2 = *RnIndirect12;
Rt1215 = zext(tmp);
}
:ldrh^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf83; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
tmp:2 = *RnIndirectPUW;
Rt1215 = zext(tmp);
}
:ldrh^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf83 & sop0003=15; Rt1215) & PcrelOffset12
{
build ItCond;
local tmp = PcrelOffset12:2;
Rt1215 = zext(tmp);
}
:ldrh^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf8b & sop0003=15; Rt1215) & PcrelOffset12
{
build ItCond;
tmp:2 = PcrelOffset12:2;
Rt1215 = zext(tmp);
}
:ldrh^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf83 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
val:2 = *tmp;
Rt1215 = zext(val);
}
:ldrht^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf83 & Rn0003; Rt1215 & thc0811=14 & Immed8
{
build ItCond;
local tmp = Rn0003 + Immed8;
val:2 = *tmp;
Rt1215 = zext(val);
}
:ldrsb^ItCond".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf99; Rt1215) & RnIndirect12
{
build ItCond;
tmp:1 = *RnIndirect12;
Rt1215 = sext(tmp);
}
:ldrsb^ItCond".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf91; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
tmp:1 = *RnIndirectPUW;
Rt1215 = sext(tmp);
}
:ldrsb^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op8=0xf9 & thc0506=0 & thc0404=1 & sop0003=15; Rt1215) & PcrelOffset12
{
build ItCond;
tmp:1 = *PcrelOffset12;
Rt1215 = sext(tmp);
}
:ldrsb^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf91 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
val:1 = *tmp;
Rt1215 = sext(val);
}
:ldrsbt^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf91 & Rn0003; Rt1215 & thc0811=14 & Immed8
{
build ItCond;
local tmp = Rn0003 + Immed8;
val:1 = *tmp;
Rt1215 = sext(val);
}
:ldrsh^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf9B; Rt1215) & RnIndirect12
{
build ItCond;
tmp:2 = *RnIndirect12;
Rt1215 = sext(tmp);
}
:ldrsh^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf93; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
tmp:2 = *RnIndirectPUW;
Rt1215 = sext(tmp);
}
:ldrsh^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op8=0xf9 & thc0506=1 & thc0404=1 & sop0003=15; Rt1215) & PcrelOffset12
{
build ItCond;
build PcrelOffset12;
tmp:2 = *PcrelOffset12;
Rt1215 = sext(tmp);
}
:ldrsh^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf93 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
val:2 = *tmp;
Rt1215 = sext(val);
}
:ldrsht^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf93 & Rn0003; Rt1215 & thc0811=14 & Immed8
{
build ItCond;
local tmp = Rn0003 + Immed8;
val:2 = *tmp;
Rt1215 = sext(val);
}
:ldrt^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf85 & Rn0003; Rt1215 & thc0811=14 & Immed8
{
build ItCond;
local tmp = Rn0003 + Immed8;
Rt1215 = *tmp;
}
@endif # VERSION_6T2 || VERSION_7
macro th_set_carry_for_lsl(op1,shift_count) {
local bit = (op1 << (shift_count-1)) & 0x80000000;
tmpCY = ((shift_count == 0) && CY) || ((shift_count != 0) && (bit != 0));
}
:lsl^ItCond Rd0002,Rm0305,Immed5 is TMode=1 & ItCond & op11=0x0 & Immed5 & Rm0305 & Rd0002 & CheckInIT_CZN
{
build ItCond;
th_set_carry_for_lsl(Rm0305,Immed5);
Rd0002 = Rm0305 << Immed5;
resflags(Rd0002);
build CheckInIT_CZN;
}
:lsl^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x102 & Rs0305 & Rd0002 & CheckInIT_CZN
{
build ItCond;
local shift_count = Rs0305 & 0xff;
th_set_carry_for_lsl(Rd0002,shift_count);
Rd0002 = Rd0002 << shift_count;
resflags(Rd0002);
build CheckInIT_CZN;
}
macro th_set_carry_for_lsr(op1,shift_count) {
local bit = (op1 >> (shift_count-1)) & 1;
tmpCY = ((shift_count == 0) && CY) || ((shift_count != 0) && (bit != 0));
}
#note that this is a special case where immed5 = 0, which corresponds to a shift amount of 32
:lsr^ItCond Rd0002,Rm0305,"#0x20" is TMode=1 & ItCond & op11=1 & Immed5 & Rm0305 & Rd0002 & immed5=0 & CheckInIT_CZN
{
build ItCond;
th_set_carry_for_lsr(Rm0305,32:1);
Rd0002 = Rm0305 >> 32;
resflags(Rd0002);
build CheckInIT_CZN;
}
:lsr^ItCond Rd0002,Rm0305,Immed5 is TMode=1 & ItCond & op11=1 & Immed5 & Rm0305 & Rd0002 & CheckInIT_CZN
{
build ItCond;
local shift_amount = Immed5;
th_set_carry_for_lsr(Rm0305,shift_amount);
Rd0002 = Rm0305 >> Immed5;
resflags(Rd0002);
build CheckInIT_CZN;
}
:lsr^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x103 & Rd0002 & Rs0305 & CheckInIT_CZN
{
build ItCond;
local shift_amount = (Rs0305 & 0xff);
th_set_carry_for_lsr(Rd0002,shift_amount);
Rd0002 = Rd0002 >> (Rs0305 & 0xff);
resflags(Rd0002);
build CheckInIT_CZN;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:lsl^thSBIT_CZN^ItCond^".w" Rd0811,Rm0003,thLsbImm is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & sop0003=15; thc1515=0 & Rd0811 & thc0405=0 & Rm0003 & thLsbImm
{
build ItCond;
th_set_carry_for_lsl(Rm0003,thLsbImm);
Rd0811 = Rm0003 << thLsbImm;
resflags(Rd0811);
build thSBIT_CZN;
}
:lsl^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op11=0x1f & thc0910=1 & sop0508=0 & thSBIT_CZN & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
local shift_amount = (Rm0003 & 0xff);
th_set_carry_for_lsl(Rn0003,shift_amount);
Rd0811 = Rn0003 << (shift_amount);
resflags(Rd0811);
build thSBIT_CZN;
}
:lsr^thSBIT_CZN^ItCond^".w" Rd0811,Rm0003,thLsbImm is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & sop0003=15; thc1515=0 & Rd0811 & thc0405=1 & Rm0003 & thLsbImm
{
build ItCond;
th_set_carry_for_lsr(Rm0003,thLsbImm);
Rd0811 = Rm0003 >> thLsbImm;
resflags(Rd0811);
build thSBIT_CZN;
}
:lsr^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op11=0x1f & thc0910=1 & sop0508=1 & thSBIT_CZN & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
local shift_amount = Rm0003 & 0xff;
th_set_carry_for_lsr(Rn0003,shift_amount);
Rd0811 = Rn0003 >> shift_amount;
resflags(Rd0811);
build thSBIT_CZN;
}
@endif # VERSION_6T2 || VERSION_7
:mcr^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=0 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op1:4 = thc0507;
t_op2:4 = thopcode2;
coprocessor_moveto(t_cpn,t_op1,t_op2,Rt1215,thCRn,thCRm);
}
:mcr2^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thc0507 & thc0404=0 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op1:4 = thc0507;
t_op2:4 = thopcode2;
coprocessor_moveto(t_cpn,t_op1,t_op2,Rt1215,thCRn,thCRm);
}
:mcrr^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xec4 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op:4 = thopcode1;
coprocessor_moveto2(t_cpn,t_op,Rt1215,Rn0003,thCRm);
}
:mcrr^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xfc4 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op:4 = thopcode1;
coprocessor_moveto2(t_cpn,t_op,Rt1215,Rn0003,thCRm);
}
:mov^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=4 & Rd0810 & Immed8 & CheckInIT_ZN
{
build ItCond;
Rd0810 = Immed8;
resflags(Rd0810);
build CheckInIT_ZN;
}
:mov^ItCond Rd0002,Rn0305 is TMode=1 & ItCond & op6=0x000 & Rn0305 & Rd0002 & CheckInIT_ZN
{
build ItCond;
Rd0002 = Rn0305;
resflags(Rd0002);
build CheckInIT_ZN;
}
:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & Hrd0002
{
build ItCond;
Hrd0002 = Hrm0305;
}
:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & Hrd0002 & hrd0002=7 & h1=1
{
build ItCond;
dest:4 = Hrm0305;
BranchWritePC(dest);
goto [pc];
}
:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & rm0306=14 & Hrd0002 & hrd0002=7 & h1=1
{
build ItCond;
dest:4 = Hrm0305;
BranchWritePC(dest);
return [pc];
}
:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & hrm0305=7 & Hrd0002 & hrd0002=6 & h1=1 [ LRset=1; TMode=1; globalset(inst_next,LRset); globalset(inst_next,TMode); ]
{
build ItCond;
Hrd0002 = Hrm0305;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:mov^thSBIT_ZN^ItCond^".w" Rd0811,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=2 & thSBIT_ZN & sop0003=15; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
Rd0811 = ThumbExpandImm12;
resflags(Rd0811);
build thSBIT_ZN;
}
:movw^ItCond Rd0811,Immed16 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=2 & thc0404=0; thc1515=0 & Rd0811) & Immed16
{
build ItCond;
Rd0811 = zext(Immed16);
resflags(Rd0811);
}
:mov^thSBIT_ZN^ItCond^".w" Rd0811,Rm0003 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_ZN & sop0003=15; op12=0 & Rd0811 & thc0407=0 & Rm0003
{
build ItCond;
Rd0811 = Rm0003;
resflags(Rd0811);
build thSBIT_ZN;
}
:movt^ItCond Rd0811,Immed16 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=6 & thc0404=0; thc1515=0 & Rd0811) & Immed16
{
build ItCond;
Rd0811 = (zext(Immed16) << 16) | (Rd0811 & 0xffff);
}
:mrc^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=1 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op1:4 = thc0507;
t_op2:4 = thopcode2;
Rt1215 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm);
}
:mrc2^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thc0507 & thc0404=1 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op1:4 = thc0507;
t_op2:4 = thopcode2;
Rt1215 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm);
}
:mrrc^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xec5 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op:4 = thopcode1;
Rt1215 = coprocessor_movefromRt(t_cpn,t_op,thCRm);
Rn0003 = coprocessor_movefromRt2(t_cpn,t_op,thCRm);
}
:mrrc2^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xfc5 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm
{
build ItCond;
t_cpn:4 = thcpn;
t_op:4 = thopcode1;
Rt1215 = coprocessor_movefromRt(t_cpn,t_op,thCRm);
Rn0003 = coprocessor_movefromRt2(t_cpn,t_op,thCRm);
}
macro readAPSR(r) {
# TODO: GE bits have not been included
r = r | zext( (NG<<4) | (ZR<<3) | (CY<<2) | (OV<<1) | (Q) ) << 27;
}
macro writeAPSR(r) {
# TODO: GE bits have not been included
local tmp = r >> 27 & 0x1f;
Q = ((tmp ) & 0x1) != 0;
OV = ((tmp >> 1) & 0x1) != 0;
CY = ((tmp >> 2) & 0x1) != 0;
ZR = ((tmp >> 3) & 0x1) != 0;
NG = ((tmp >> 4) & 0x1) != 0;
}
@if defined(VERSION_7M)
define pcodeop getMainStackPointer;
define pcodeop getProcessStackPointer;
define pcodeop getBasePriority;
define pcodeop getCurrentExceptionNumber;
mrsipsr: "i" is thc0000=1 & Rd0811 {
b:1 = isCurrentModePrivileged();
if (!b) goto <notPriv>;
ipsr:4 = getCurrentExceptionNumber();
Rd0811 = Rd0811 | (ipsr & 0x1f);
<notPriv>
}
mrsipsr: is thc0000=0 { }
mrsepsr: "e" is thc0101=1 { }
mrsepsr: is thc0101=0 { }
mrsapsr: is thc0202=1 { }
mrsapsr: "a" is thc0202=0 & Rd0811 { readAPSR(Rd0811); }
mrspsr: mrsipsr^mrsepsr^mrsapsr^"psr" is mrsipsr & mrsepsr & mrsapsr & Rd0811 {
Rd0811 = 0;
build mrsapsr;
build mrsipsr;
}
mrspsr: "xpsr" is sysm02=3 & mrsipsr & mrsepsr & mrsapsr & Rd0811 {
Rd0811 = 0;
build mrsapsr;
build mrsipsr;
}
:mrs^ItCond Rd0811,mrspsr is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm37=0 & mrspsr
{
build ItCond;
build mrspsr;
}
msp: "msp" is epsilon {}
:mrs^ItCond Rd0811,msp is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=8 & msp
{
build ItCond;
Rd0811 = getMainStackPointer();
}
psp: "psp" is epsilon {}
:mrs^ItCond Rd0811,psp is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=9 & psp
{
build ItCond;
Rd0811 = getProcessStackPointer();
}
primask: "primask" is epsilon {}
:mrs^ItCond Rd0811,primask is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=16 & primask
{
build ItCond;
Rd0811 = 0;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
Rd0811 = isIRQinterruptsEnabled(); # should reflect primask register/bit
}
basepri: "basepri" is epsilon {}
:mrs^ItCond Rd0811,basepri is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=17 & basepri
{
build ItCond;
Rd0811 = 0;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
Rd0811 = getBasePriority();
}
basepri_max: "basepri_max" is epsilon {}
:mrs^ItCond Rd0811,basepri_max is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=18 & basepri_max
{
build ItCond;
Rd0811 = 0;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
Rd0811 = getBasePriority();
}
faultmask: "faultmask" is epsilon {}
:mrs^ItCond Rd0811,faultmask is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=19 & faultmask
{
build ItCond;
Rd0811 = 0;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
Rd0811 = isFIQinterruptsEnabled(); # should reflect faultmask register/bit
}
define pcodeop isThreadModePrivileged;
define pcodeop isUsingMainStack;
control: "control" is epsilon {}
:mrs^ItCond Rd0811,control is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=20 & control
{
build ItCond;
notPrivileged:1 = isThreadModePrivileged() != 1:1;
altStackMode:1 = isUsingMainStack() != 1:1;
Rd0811 = zext((altStackMode << 1) | notPrivileged);
}
@endif
:mrs^ItCond Rd0811,cpsr is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=0 & cpsr
{
build ItCond;
tmp:4 = 0;
readAPSR(tmp);
Rd0811 = tmp;
}
:mrs^ItCond Rd0811,spsr is TMode=1 & ItCond & op0=0xf3ff; op12=0x8 & Rd0811 & sysm=0 & spsr
{
build ItCond;
Rd0811 = spsr;
}
@if defined(VERSION_7M)
msripsr: "i" is thc0000=1 { }
msripsr: is thc0000=0 { }
msrepsr: "e" is thc0101=1 { }
msrepsr: is thc0101=0 { }
msrapsr: is thc0202=1 { }
msrapsr: "a" is thc0202=0 & Rn0003 {
cpsr = cpsr | (Rn0003 & 0xf8000000);
writeAPSR(cpsr);
}
msrpsr: msripsr^msrepsr^msrapsr^"psr" is msripsr & msrepsr & msrapsr {
build msrapsr;
}
msrpsr: "xpsr" is sysm02=3 & msrapsr {
build msrapsr;
}
:msr^ItCond msrpsr,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm37=0 & msrpsr
{
build ItCond;
build msrpsr;
}
define pcodeop setMainStackPointer;
define pcodeop setProcessStackPointer;
define pcodeop setBasePriority;
:msr^ItCond msp,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=8 & msp
{
build ItCond;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
setMainStackPointer(Rn0003);
}
:msr^ItCond psp,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=9 & psp
{
build ItCond;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
setProcessStackPointer(Rn0003);
}
:msr^ItCond primask,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=16 & primask
{
build ItCond;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
enableIRQinterrupts((Rn0003 & 1) == 1); # should set/clear primask register/bit
}
:msr^ItCond basepri,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=17 & basepri
{
build ItCond;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
setBasePriority(Rn0003);
}
:msr^ItCond basepri_max,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=18 & basepri_max
{
build ItCond;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
if (Rn0003 == 0) goto inst_next;
# TODO: does the following compare need to be signed??
cur:4 = getBasePriority();
if (cur != 0 && Rn0003 >= cur) goto inst_next;
setBasePriority(Rn0003);
}
:msr^ItCond faultmask,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=19 & faultmask
{
build ItCond;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
enableFIQinterrupts((Rn0003 & 1) == 1);
}
define pcodeop setStackMode;
:msr^ItCond control,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=20 & control
{
build ItCond;
b:1 = isCurrentModePrivileged();
if (!b) goto inst_next;
privileged:1 = (Rn0003 & 1) == 0;
setThreadModePrivileged(privileged);
# TODO: not sure about the following semantics
b = isThreadMode();
if (!b) goto inst_next;
stackMode:1 = isUsingMainStack() == 1:1;
setStackMode(stackMode);
# TODO: should we set sp ?
}
@endif
thpsrmask: is th_psrmask=0 { export 0:4; }
thpsrmask: "_c" is th_psrmask=1 { export 0xff:4; }
thpsrmask: "_x" is th_psrmask=2 { export 0xff00:4; }
thpsrmask: "_cx" is th_psrmask=3 { export 0xffff:4; }
thpsrmask: "_s" is th_psrmask=4 { export 0xff0000:4; }
thpsrmask: "_cs" is th_psrmask=5 { export 0xff00ff:4; }
thpsrmask: "_xs" is th_psrmask=6 { export 0xffff00:4; }
thpsrmask: "_cxs" is th_psrmask=7 { export 0xffffff:4; }
thpsrmask: "_f" is th_psrmask=8 { export 0xff000000:4; }
thpsrmask: "_cf" is th_psrmask=9 { export 0xff0000ff:4; }
thpsrmask: "_xf" is th_psrmask=10 { export 0xff00ff00:4; }
thpsrmask: "_cxf" is th_psrmask=11 { export 0xff00ffff:4; }
thpsrmask: "_sf" is th_psrmask=12 { export 0xffff0000:4; }
thpsrmask: "_csf" is th_psrmask=13 { export 0xffff00ff:4; }
thpsrmask: "_xsf" is th_psrmask=14 { export 0xffffff00:4; }
thpsrmask: "_cxsf" is th_psrmask=15 { export 0xffffffff:4; }
thcpsrmask: cpsr^thpsrmask is thpsrmask & cpsr { export thpsrmask; }
:msr^ItCond thcpsrmask,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & thcpsrmask & thc0007=0
{
build ItCond;
build thcpsrmask;
cpsr = (cpsr& ~thcpsrmask) | (Rn0003 & thcpsrmask);
writeAPSR(cpsr);
}
thspsrmask: spsr^thpsrmask is thpsrmask & spsr { export thpsrmask; }
:msr^ItCond thspsrmask,Rn0003 is TMode=1 & ItCond & op4=0xf39 & Rn0003; op12=0x8 & thspsrmask & thc0007=0
{
build ItCond;
build thspsrmask;
spsr = (spsr& ~thspsrmask) | (Rn0003 & thspsrmask);
}
:mvn^thSBIT_ZN^ItCond Rd0811,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=3 & thSBIT_ZN & thc0003=15; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
Rd0811 = ~ThumbExpandImm12;
resflags(Rd0811);
build thSBIT_ZN;
}
:mvn^thSBIT_ZN^ItCond^".w" Rd0811,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=3 & thSBIT_ZN & thc0003=15; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
Rd0811 = ~thshift2;
resflags(Rd0811);
build thSBIT_ZN;
}
@endif # VERSION_6T2 || VERSION_7
:mul^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10d & Rm0305 & Rd0002 & CheckInIT_ZN
{
build ItCond;
Rd0002 = Rm0305 * Rd0002;
resflags(Rd0002);
build CheckInIT_ZN;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:mla^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb0 & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
Rd0811 = Rn0003 * Rm0003 + Ra1215;
}
:mls^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb0 & Rn0003; Ra1215 & Rd0811 & sop0407=1 & Rm0003
{
build ItCond;
Rd0811 = Ra1215- Rn0003 * Rm0003;
}
:mul^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb0 & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
Rd0811 = Rn0003 * Rm0003;
}
@endif # VERSION_6T2 || VERSION_7
:mvn^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10f & Rm0305 & Rd0002 & CheckInIT_ZN
{
build ItCond;
Rd0002 = ~Rm0305;
resflags(Rd0002);
build CheckInIT_ZN;
}
:nop^ItCond is TMode=1 & ItCond & op0=0xbf00
{
}
:nop^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8000
{
}
:nop is op0=0x46c0 # This is just like a mov r0 r0
{
}
:orr^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10c & Rm0305 & Rd0002 & CheckInIT_ZN
{
build ItCond;
Rd0002 = Rd0002 | Rm0305;
resflags(Rd0002);
build CheckInIT_ZN;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:orn^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=3 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
Rd0811 = Rn0003 | ~(ThumbExpandImm12);
th_logicflags();
resflags(Rd0811);
build thSBIT_CZNO;
}
:orn^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=3 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
Rd0811 = Rn0003 | ~(thshift2);
th_logicflags();
resflags(Rd0811);
build thSBIT_CZNO;
}
:orr^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=2 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
Rd0811 = Rn0003 | ThumbExpandImm12;
th_logicflags();
resflags(Rd0811);
build thSBIT_CZNO;
}
:orr^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
Rd0811 = Rn0003 | thshift2;
th_logicflags();
resflags(Rd0811);
build thSBIT_CZNO;
}
:pkhbt^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op4=0xeac & Rn0003; thc1515=0 & Rd0811 & thc0505=0 & thc0404=0 & thshift2
{
build ItCond;
Rd0811 = (Rn0003 & 0x0000ffff) | (thshift2 & 0xffff0000);
th_logicflags();
resflags(Rd0811);
}
:pkhtb^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op4=0xeac & Rn0003; thc1515=0 & Rd0811 & thc0505=1 & thc0404=0 & thshift2
{
build ItCond;
Rd0811 = (Rn0003 & 0xffff0000) | (thshift2 & 0x0000ffff);
th_logicflags();
resflags(Rd0811);
}
:pld^ItCond Rn0003,"#"^offset12 is TMode=1 & ItCond & op6=0x3e2 & thwbit=0 & thc0404=1 & Rn0003; op12=0xf & offset12
{
build ItCond;
addr:4 = Rn0003 + offset12;
HintPreloadData(addr);
}
:pldw^ItCond Rn0003,"#"^offset12 is TMode=1 & ItCond & op6=0x3e2 & thwbit=1 & thc0404=1 & Rn0003; op12=0xf & offset12
{
build ItCond;
addr:4 = Rn0003 + offset12;
HintPreloadDataForWrite(addr);
}
:pld^ItCond Rn0003,"#-"^immed8 is TMode=1 & ItCond & op6=0x3e0 & thwbit=0 & thc0404=1 & Rn0003; op8=0xfc & immed8
{
build ItCond;
addr:4 = Rn0003 - immed8;
HintPreloadData(addr);
}
:pldw^ItCond Rn0003,"#-"^immed8 is TMode=1 & ItCond & op6=0x3e0 & thwbit=1 & thc0404=1 & Rn0003; op8=0xfc & immed8
{
build ItCond;
addr:4 = Rn0003 - immed8;
HintPreloadDataForWrite(addr);
}
:pld^ItCond PcrelOffset12 is TMode=1 & ItCond & (op8=0xf8 & thc0506=0 & thc0004=0x1f; thc1215=0xf) & PcrelOffset12
{
build ItCond;
HintPreloadData(PcrelOffset12);
}
:pld^ItCond Rn0003,Rm0003"lsl #"^thc0405 is TMode=1 & ItCond & op6=0x3e0 & thwbit=0 & thc0404=1 & Rn0003; op8=0xf0 & thc0607=0 & thc0405 & Rm0003
{
build ItCond;
addr:4 = Rn0003 + (Rm0003 << thc0405);
HintPreloadData(addr);
}
:pldw^ItCond Rn0003,Rm0003,"lsl #"^thc0405 is TMode=1 & ItCond & op6=0x3e0 & thwbit=1 & thc0404=1 & Rn0003; op8=0xf0 & thc0607=0 & thc0405 & Rm0003
{
build ItCond;
addr:4 = Rn0003 + (Rm0003 << thc0405);
HintPreloadDataForWrite(addr);
}
:pli^ItCond Rn0003,"#"^offset12 is TMode=1 & ItCond & op4=0xf99 & Rn0003; op12=0xf & offset12
{
build ItCond;
addr:4 = Rn0003 + offset12;
HintPreloadInstruction(addr);
}
:pli^ItCond Rn0003,"#-"^immed8 is TMode=1 & ItCond & op4=0xf91 & Rn0003; op8=0xfc & immed8
{
build ItCond;
addr:4 = Rn0003 - immed8;
HintPreloadInstruction(addr);
}
:pli^ItCond PcrelOffset12 is TMode=1 & ItCond & (op8=0xf9 & thc0506=0 & thc0004=0x1f; thc1215=0xf) & PcrelOffset12
{
build ItCond;
HintPreloadInstruction(PcrelOffset12);
}
:pli^ItCond Rn0003,Rm0003"lsl #"^thc0405 is TMode=1 & ItCond & op4=0xf91 & Rn0003; op6=0x3c0 & thc0405 & Rm0003
{
build ItCond;
addr:4 = Rn0003 + (Rm0003 << thc0405);
HintPreloadInstruction(addr);
}
@endif # VERSION_6T2 || VERSION_7
#
# Removed the masking of the stack pointer on push and pop to ignore the lower 2 bits.
# This isn't really needed for modeling.
# NOTE: It may need to be put back in to model correctly for nasty stack shenanigans.
#
:pop^ItCond ldbrace is TMode=1 & ItCond & op9=0x5e & R=0 & ldbrace
{
build ItCond;
# mult_addr = sp & 0xfffffffc;
mult_addr = sp;
build ldbrace;
sp = mult_addr;
}
:pop^ItCond pclbrace is TMode=1 & ItCond & op9=0x5e & R=1 & pclbrace
{
build ItCond;
# mult_addr = sp & 0xfffffffc;
mult_addr = sp;
build pclbrace;
sp = mult_addr;
LoadWritePC(pc);
return [pc];
}
:pop^ItCond thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thldrlist_inc
{
build ItCond;
# mult_addr = sp & 0xfffffffc;
mult_addr = sp;
build thldrlist_inc;
sp = mult_addr;
}
:pop^ItCond thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thldrlist_inc & thc1515=1
{
build ItCond;
# mult_addr = sp & 0xfffffffc;
mult_addr = sp;
build thldrlist_inc;
sp = mult_addr;
LoadWritePC(pc);
return [pc];
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:pop^ItCond^".w" thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thc1515=0 & thc1313=0 & thldrlist_inc
{
build ItCond;
mult_addr = sp;
build thldrlist_inc;
sp = mult_addr;
}
:pop^ItCond^".w" Rt1215 is TMode=1 & ItCond & op0=0xf85d; Rt1215 & offset12=0xb04
{
build ItCond;
Rt1215 = *sp;
sp=sp+4;
}
:pop^ItCond^".w" thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thc1515=1 & thc1313=0 & thldrlist_inc
{
build ItCond;
mult_addr = sp;
build thldrlist_inc;
sp = mult_addr;
LoadWritePC(pc);
return [pc];
}
:pop^ItCond^".w" Rt1215 is TMode=1 & ItCond & op0=0xf85d; Rt1215 & op12=15 & offset12=0xb04
{
build ItCond;
dest:4 = *sp;
sp=sp+4;
LoadWritePC(dest);
return [pc];
}
:push^ItCond^".w" thstrlist_dec is TMode=1 & ItCond & op0=0xe8ad; thc1515=0 & thc1313=0 & thstrlist_dec
{
build ItCond;
mult_addr = sp-4;
build thstrlist_dec;
sp = mult_addr + 4;
}
:push^ItCond^".w" Rt1215 is TMode=1 & ItCond & op0=0xf84d; Rt1215 & offset12=0xd04
{
build ItCond;
sp=sp-4;
*sp = Rt1215;
}
@endif # VERSION_6T2 || VERSION_7
:push^ItCond psbrace is TMode=1 & ItCond & op9=0x5a & R=0 & psbrace
{
build ItCond;
# mult_addr = sp & 0xfffffffc;
mult_addr = sp;
build psbrace;
sp = mult_addr;
}
:push^ItCond pcpbrace is TMode=1 & ItCond & op9=0x5a & R=1 & pcpbrace
{
build ItCond;
# mult_addr = sp & 0xfffffffc;
mult_addr = sp;
build pcpbrace;
sp = mult_addr;
}
:push^ItCond thstrlist_dec is TMode=1 & ItCond & op0=0xe92d; thstrlist_dec
{
build ItCond;
# mult_addr = sp & 0xfffffffc;
mult_addr = sp-4;
build thstrlist_dec;
sp = mult_addr+4;
}
@if defined(VERSION_5E)
:qadd^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x8 & Rm0003
{
build ItCond;
local sum1 = Rm0003 + Rn0003;
sum1 = SignedSaturate(sum1,32:2);
Q = SignedDoesSaturate(sum1,32:2);
Rd0811 = sum1;
}
@endif # VERSION_5E
@if defined(VERSION_6)
:qadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003
{
build ItCond;
local lRn = Rn0003 & 0xffff;
local lRm = Rm0003 & 0xffff;
local uRn = (Rn0003) & 0xffff;
local uRm = (Rm0003 >> 16) & 0xffff;
sum1:2 = lRn:2 + lRm:2;
sum1 = SignedSaturate(sum1,16:2);
sum2:2 = uRn:2 + uRm:2;
sum2 = SignedSaturate(sum2,16:2);
Rd0811 = (zext(sum2) << 16) | zext(sum1);
}
:qadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003
{
build ItCond;
local rn1 = Rn0003 & 0xff;
local rm1 = Rm0003 & 0xff;
local rn2 = (Rn0003 >> 8) & 0xff;
local rm2 = (Rm0003 >> 8) & 0xff;
local rn3 = (Rn0003 >> 16) & 0xff;
local rm3 = (Rm0003 >> 16) & 0xff;
local rn4 = (Rn0003 >> 24) & 0xff;
local rm4 = (Rm0003 >> 24) & 0xff;
sum1:1 = rn1:1 + rm1:1;
sum1 = SignedSaturate(sum1,8:2);
sum2:1 = rn2:1 + rm2:1;
sum2 = SignedSaturate(sum2,8:2);
sum3:1 = rn3:1 + rm3:1;
sum3 = SignedSaturate(sum3,8:2);
sum4:1 = rn4:1 + rm4:1;
sum4 = SignedSaturate(sum4,8:2);
Rd0811 = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1);
}
# qaddsubx
:qasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003
{
build ItCond;
local lRn = Rn0003 & 0xffff;
local lRm = Rm0003 & 0xffff;
local uRn = (Rn0003 >> 16) & 0xffff;
local uRm = (Rm0003 >> 16) & 0xffff;
sum1:2 = lRn:2 - lRm:2;
sum1 = SignedSaturate(sum1,16:2);
sum2:2 = uRn:2 + uRm:2;
sum2 = SignedSaturate(sum2,16:2);
Rd0811 = (zext(sum2) << 16) | zext(sum1);
}
@endif # VERSION_6
@if defined(VERSION_5E)
:qdadd^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x9 & Rm0003
{
build ItCond;
tmp:4 = Rn0003 * 2;
tmp = SignedSaturate(tmp,32:2);
Q = SignedDoesSaturate(tmp,32:2);
tmp = tmp + Rm0003;
tmp = SignedSaturate(tmp,32:2);
Q = Q | SignedDoesSaturate(tmp,32:2);
Rd0811 = tmp;
}
:qdsub^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0xb & Rm0003
{
build ItCond;
tmp:4 = Rn0003 * 2;
tmp = SignedSaturate(tmp);
Q = SignedDoesSaturate(tmp,32:2);
tmp = Rm0003 - tmp;
tmp = SignedSaturate(tmp,32:2);
Q = Q | SignedDoesSaturate(tmp,32:2);
Rd0811 = tmp;
}
@endif # VERSION_5E
@if defined(VERSION_6)
# qsubaddx
:qsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003
{
build ItCond;
local lRn = Rn0003 & 0xffff;
local lRm = Rm0003 & 0xffff;
local uRn = (Rn0003 >> 16) & 0xffff;
local uRm = (Rm0003 >> 16) & 0xffff;
sum1:2 = lRn:2 + lRm:2;
sum1 = SignedSaturate(sum1,16:2);
sum2:2 = uRn:2 - uRm:2;
sum2 = SignedSaturate(sum2,16:2);
Rd0811 = (zext(sum2) << 16) | zext(sum1);
}
@endif # VERSION_6
@if defined(VERSION_5E)
:qsub^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0xa & Rm0003
{
build ItCond;
tmp:4 = Rm0003 - Rn0003;
tmp = SignedSaturate(tmp,32:2);
Q = SignedDoesSaturate(tmp,32:2);
Rd0811 = tmp;
}
@endif # VERSION_5E
@if defined(VERSION_6)
:qsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003
{
build ItCond;
local lRn = Rn0003 & 0xffff;
local lRm = Rm0003 & 0xffff;
local uRn = (Rn0003 >> 16) & 0xffff;
local uRm = (Rm0003 >> 16) & 0xffff;
sum1:2 = lRn:2 - lRm:2;
sum1 = SignedSaturate(sum1,16:2);
sum2:2 = uRn:2 - uRm:2;
sum2 = SignedSaturate(sum2,16:2);
Rd0811 = (zext(sum2) << 16) | zext(sum1);
}
:qsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003
{
build ItCond;
local rn1 = Rn0003 & 0xff;
local rm1 = Rm0003 & 0xff;
local rn2 = (Rn0003 >> 8) & 0xff;
local rm2 = (Rm0003 >> 8) & 0xff;
local rn3 = (Rn0003 >> 16) & 0xff;
local rm3 = (Rm0003 >> 16) & 0xff;
local rn4 = (Rn0003 >> 24) & 0xff;
local rm4 = (Rm0003 >> 24) & 0xff;
sum1:1 = rn1:1 - rm1:1;
sum1 = SignedSaturate(sum1,8:2);
sum2:1 = rn2:1 - rm2:1;
sum2 = SignedSaturate(sum2,8:2);
sum3:1 = rn3:1 - rm3:1;
sum3 = SignedSaturate(sum3,8:2);
sum4:1 = rn4:1 - rm4:1;
sum4 = SignedSaturate(sum4,8:2);
Rd0811 = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1);
}
@endif # VERSION_6
@if defined(THUMB_2)
# WARNING Rm0003 on the first 2 bytes must be the same value as Rm0003 on the last bytes!
# but there is no easy way to check this now...
:rev^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op4=0xfa9; op6=0x2e8 & Rd0811 & Rm0003
{
build ItCond;
local tmp1 = Rm0003 & 0xff;
local tmp2 = (Rm0003 >> 8) & 0xff;
local tmp3 = (Rm0003 >> 16) & 0xff;
local tmp4 = (Rm0003 >> 24) & 0xff;
Rd0811 = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4;
}
@endif # THUMB_2
:rsb^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x109 & Rm0305 & Rd0002 & CheckInIT_CZNO
{
build ItCond;
th_subflags0(Rm0305);
Rd0002 = 0-Rm0305;
resflags(Rd0002);
build CheckInIT_CZNO;
}
@if defined(VERSION_6)
:rev^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x2e8 & Rd0002 & Rm0305
{
build ItCond;
local tmp1 = Rm0305 & 0xff;
local tmp2 = (Rm0305 >> 8) & 0xff;
local tmp3 = (Rm0305 >> 16) & 0xff;
local tmp4 = (Rm0305 >> 24) & 0xff;
Rd0002 = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4;
}
:rev16^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x2e9 & Rd0002 & Rm0305
{
build ItCond;
local tmp1 = Rm0305 & 0xff;
local tmp2 = (Rm0305 >> 8) & 0xff;
local tmp3 = (Rm0305 >> 16) & 0xff;
local tmp4 = (Rm0305 >> 24) & 0xff;
Rd0002 = (tmp3 << 24) | (tmp4 << 16) | (tmp1 << 8) | tmp2;
}
:revsh^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x2eb & Rd0002 & Rm0305
{
build ItCond;
local tmp1 = Rm0305 & 0xff;
local tmp2 = (Rm0305 >> 8) & 0xff;
local result = (tmp1 << 8) | tmp2;
Rd0002 = sext(result:2);
}
@if defined(VERSION_6T2) || defined(VERSION_7)
macro BitReverse(val) {
tval:1 = val;
result:1 = 0;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
result = (result << 1) | (tval & 1);
tval = tval >> 1;
val = result;
}
:rbit^ItCond Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=0xa & Rn0003
{
build ItCond;
t:4 = Rm0003 & 0xff;
b1:1 = t:1;
t = (Rm0003 >> 8) & 0xff;
b2:1 = t:1;
t = (Rm0003 >> 16) & 0xff;
b3:1 = t:1;
t = (Rm0003 >> 24) & 0xff;
b4:1 = t:1;
BitReverse(b1);
BitReverse(b2);
BitReverse(b3);
BitReverse(b4);
Rd0811 = (zext(b1) << 24) | (zext(b2) << 16) | (zext(b3) << 8) | zext(b4);
}
:rev^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=8 & Rn0003
{
build ItCond;
local tmp1 = Rm0003 & 0xff;
local tmp2 = (Rm0003 >> 8) & 0xff;
local tmp3 = (Rm0003 >> 16) & 0xff;
local tmp4 = (Rm0003 >> 24) & 0xff;
Rd0811 = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4;
}
:rev16^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=9 & Rn0003
{
build ItCond;
local tmp1 = Rm0003 & 0xff;
local tmp2 = (Rm0003 >> 8) & 0xff;
local tmp3 = (Rm0003 >> 16) & 0xff;
local tmp4 = (Rm0003 >> 24) & 0xff;
Rd0811 = (tmp3 << 24) | (tmp4 << 16) | (tmp1 << 8) | tmp2;
}
:revsh^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=0xb & Rn0003
{
build ItCond;
local tmp1 = Rm0003 & 0xff;
local tmp2 = (Rm0003 >> 8) & 0xff;
local result = (tmp1 << 8) | tmp2;
Rd0811 = sext(result:2);
}
# RFE instructions for Thumb-2 "Encoding T1" and "Encoding T2" on page 1574
#
:rfedb part2Rd0003 is TMode=1 & part2c0615=0x3a0 & part2c0505=0x0 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000
{
# register list is always: pc, cpsr
ptr:4 = part2Rd0003 - 4;
cpsr = *ptr;
ptr = ptr - 4;
dest:4 = *ptr;
BranchWritePC(dest);
return [pc];
}
:rfedb part2Rd0003^"!" is TMode=1 & part2c0615=0x3a0 & part2c0505=0x1 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000
{
# register list is always: pc, cpsr
ptr:4 = part2Rd0003 - 4;
cpsr = *ptr;
ptr = ptr - 4;
dest:4 = *ptr;
part2Rd0003 = ptr;
BranchWritePC(dest);
return [pc];
}
:rfeia part2Rd0003 is TMode=1 & part2c0615=0x3a6 & part2c0505=0x0 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000
{
# register list is always: pc, cpsr
ptr:4 = part2Rd0003;
cpsr = *ptr;
ptr = ptr + 4;
dest:4 = *ptr;
BranchWritePC(dest);
return [pc];
}
:rfeia part2Rd0003^"!" is TMode=1 & part2c0615=0x3a6 & part2c0505=0x1 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000
{
# register list is always: pc, cpsr
ptr:4 = part2Rd0003;
cpsr = *ptr;
ptr = ptr + 4;
dest:4 = *ptr;
part2Rd0003 = ptr + 4;
BranchWritePC(dest);
return [pc];
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
:rsb^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=14 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
th_subflags(ThumbExpandImm12,Rn0003);
Rd0811 = ThumbExpandImm12 - Rn0003;
resflags(Rd0811);
build thSBIT_CZNO;
}
:rsb^thSBIT_CZNO^ItCond Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=14 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
th_subflags(thshift2,Rn0003);
Rd0811 = thshift2 - Rn0003;
resflags(Rd0811);
build thSBIT_CZNO;
}
@endif # VERSION_6
macro th_set_carry_for_ror(result, count) {
local bit = result & 0x80000000;
tmpCY = ((count == 0) && CY) || ((count != 0) && (bit != 0));
}
:ror^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x107 & Rs0305 & Rd0002 & CheckInIT_CZN
{
build ItCond;
local shift_amount = Rs0305 & 0x1f;
local tmp = (Rd0002 >> shift_amount)|(Rd0002 << (32-shift_amount));
th_set_carry_for_ror(tmp,Rs0305 & 0xff);
Rd0002 = tmp;
resflags(Rd0002);
build CheckInIT_CZN;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:ror^thSBIT_CZN^ItCond Rd0811,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & thc0003=0xf; thc1515=0 & Rd0811 & thc0405=3 & thshift2
{
build ItCond;
Rd0811 = thshift2;
tmpCY = shift_carry;
resflags(Rd0811);
build thSBIT_CZN;
}
:ror^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op8=0xfa & thc0707=0 & thc0506=3 & thSBIT_CZN & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
local shift_amount = Rm0003 & 0x1f;
local tmp = (Rn0003>>shift_amount)|(Rn0003<<(32-shift_amount));
th_set_carry_for_ror(tmp,Rm0003 & 0xff);
Rd0811 = tmp;
resflags(Rd0811);
build thSBIT_CZN;
}
:rrx^thSBIT_CZN^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & thc0003=0xf; thc1515=0 & thc1214=0 & Rd0811 & thc0607=0 & thc0405=3 & Rm0003
{
build ItCond;
local tmp1=Rm0003&1;
shift_carry=tmp1(0);
local tmp2 = (zext(CY)<<31)|(Rm0003>>1);
Rd0811 = tmp2;
th_logicflags();
resflags(Rd0811);
build thSBIT_CZN;
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
@if defined(VERSION_6T2) || defined(VERSION_7)
:sadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
local tmpRn0003 = Rn0003;
sum1:4 = sext(tmpRn0003[ 0,16]) + sext(tmpRm0003[ 0,16]);
sum2:4 = sext(tmpRn0003[16,16]) + sext(tmpRm0003[16,16]);
Rd0811[ 0,16] = sum1:2;
Rd0811[16,16] = sum2:2;
GE1 = sum1 s>= 0;
GE2 = sum1 s>= 0;
GE3 = sum2 s>= 0;
GE4 = sum2 s>= 0;
}
:sadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
local tmpRn0003 = Rn0003;
sum1:4 = sext(tmpRn0003[ 0,8]) + sext(tmpRm0003[ 0,8]);
sum2:4 = sext(tmpRn0003[ 8,8]) + sext(tmpRm0003[ 8,8]);
sum3:4 = sext(tmpRn0003[16,8]) + sext(tmpRm0003[16,8]);
sum4:4 = sext(tmpRn0003[24,8]) + sext(tmpRm0003[24,8]);
Rd0811[ 0,8] = sum1:1;
Rd0811[ 8,8] = sum2:1;
Rd0811[16,8] = sum3:1;
Rd0811[24,8] = sum4:1;
GE1 = sum1 s>= 0;
GE2 = sum2 s>= 0;
GE3 = sum3 s>= 0;
GE4 = sum4 s>= 0;
}
:sasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
local tmpRn0003 = Rn0003;
diff:4 = sext(tmpRn0003[ 0,16]) - sext(tmpRm0003[16,16]);
sum:4 = sext(tmpRn0003[16,16]) + sext(tmpRm0003[ 0,16]);
Rd0811[ 0,16] = diff[ 0,16];
Rd0811[16,16] = sum[ 0,16];
GE1 = diff s>= 0;
GE2 = diff s>= 0;
GE3 = sum s>= 0;
GE4 = sum s>= 0;
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
:sbc^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x106 & Rm0305 & Rd0002 & CheckInIT_CZNO
{
build ItCond;
th_add_with_carry_flags(Rd0002,~Rm0305);
Rd0002 = Rd0002 - Rm0305 - zext(!CY);
resflags(Rd0002);
build CheckInIT_CZNO;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:sbc^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=11 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
th_add_with_carry_flags(Rn0003,~ThumbExpandImm12);
Rd0811 = Rn0003 - ThumbExpandImm12 - zext(!CY);
resflags(Rd0811);
build thSBIT_CZNO;
}
:sbc^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=11 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
th_add_with_carry_flags(Rn0003,~thshift2);
Rd0811 = Rn0003 - thshift2 - zext(!CY);
resflags(Rd0811);
build thSBIT_CZNO;
}
:sbfx^ItCond Rd0811,Rn0003,thLsbImm,thWidthMinus1 is TMode=1 & ItCond & op4=0xf34 & Rn0003; thc1515=0 & Rd0811 & thLsbImm & thWidthMinus1
{
build ItCond;
build thLsbImm;
build thWidthMinus1;
shift:4 = 31 - (thLsbImm + thWidthMinus1); # thMsbImm represents widthMinus1
Rd0811 = Rn0003 << shift;
shift = 31 - thWidthMinus1; # msbImm represents widthMinus1
Rd0811 = Rd0811 s>> shift;
}
:sdiv^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb9 & Rn0003; op12=0xf & Rd0811 & thc0407=0xf & Rm0003
{
build ItCond;
local result = Rn0003 / Rm0003;
Rd0811 = result;
}
:sel^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x8 & Rm0003
{
build ItCond;
Rd0811[ 0,8] = ((GE1 == 1) * Rn0003[ 0,8]) + ((GE1 == 0) * Rm0003[ 0,8]);
Rd0811[ 8,8] = ((GE2 == 1) * Rn0003[ 8,8]) + ((GE2 == 0) * Rm0003[ 8,8]);
Rd0811[16,8] = ((GE3 == 1) * Rn0003[16,8]) + ((GE3 == 0) * Rm0003[16,8]);
Rd0811[24,8] = ((GE4 == 1) * Rn0003[24,8]) + ((GE4 == 0) * Rm0003[24,8]);
}
:shadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003
{
build ItCond;
sum1:4 = sext(Rn0003[ 0,16]) + sext(Rm0003[ 0,16]);
sum2:4 = sext(Rn0003[16,16]) + sext(Rm0003[16,16]);
Rd0811[ 0,16] = sum1[1,16];
Rd0811[16,16] = sum2[1,16];
}
:shadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003
{
build ItCond;
sum1:4 = sext(Rn0003[ 0,8]) + sext(Rm0003[ 0,8]);
sum2:4 = sext(Rn0003[ 8,8]) + sext(Rm0003[ 8,8]);
sum3:4 = sext(Rn0003[16,8]) + sext(Rm0003[16,8]);
sum4:4 = sext(Rn0003[24,8]) + sext(Rm0003[24,8]);
Rd0811[ 0,8] = sum1[1,8];
Rd0811[ 8,8] = sum2[1,8];
Rd0811[16,8] = sum3[1,8];
Rd0811[24,8] = sum4[1,8];
}
:shasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003
{
build ItCond;
diff:4 = sext(Rn0003[ 0,16]) - sext(Rm0003[16,16]);
sum:4 = sext(Rn0003[16,16]) + sext(Rm0003[ 0,16]);
Rd0811[ 0,16] = diff[1,16];
Rd0811[16,16] = sum[1,16];
}
:shsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003
{
build ItCond;
sum:4 = sext(Rn0003[ 0,16]) + sext(Rm0003[16,16]);
diff:4 = sext(Rn0003[16,16]) - sext(Rm0003[ 0,16]);
Rd0811[ 0,16] = sum[1,16];
Rd0811[16,16] = diff[1,16];
}
:shsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003
{
build ItCond;
diff1:4 = sext(Rn0003[ 0,16]) - sext(Rm0003[ 0,16]);
diff2:4 = sext(Rn0003[16,16]) - sext(Rm0003[16,16]);
Rd0811[ 0,16] = diff1[1,16];
Rd0811[16,16] = diff2[1,16];
}
:shsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003
{
build ItCond;
diff1:4 = sext(Rn0003[ 0,8]) - sext(Rm0003[ 0,8]);
diff2:4 = sext(Rn0003[ 8,8]) - sext(Rm0003[ 8,8]);
diff3:4 = sext(Rn0003[16,8]) - sext(Rm0003[16,8]);
diff4:4 = sext(Rn0003[24,8]) - sext(Rm0003[24,8]);
Rd0811[ 0,8] = diff1[1,8];
Rd0811[ 8,8] = diff2[1,8];
Rd0811[16,8] = diff3[1,8];
Rd0811[24,8] = diff4[1,8];
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
thXBIT: "b" is Rn0003 ; thc0505=0 { local tmpRn0003 = Rn0003; tmp_x:2 = tmpRn0003:2; export tmp_x; }
thXBIT: "t" is Rn0003 ; thc0505=1 { local tmpRn0003 = Rn0003; tmp_x:2 = tmpRn0003(2); export tmp_x; }
thYBIT: "b" is thc0404=0 & Rm0003 { local tmpRm0003 = Rm0003; tmp_y:2 = tmpRm0003:2; export tmp_y; }
thYBIT: "t" is thc0404=1 & Rm0003 { local tmpRm0003 = Rm0003; tmp_y:2 = tmpRm0003(2); export tmp_y; }
:smla^thXBIT^thYBIT^ItCond Rd0811,Rn0003,Rm0003,Rt1215 is TMode=1 & ItCond & (op4=0xfb1 & Rn0003; Rt1215 & Rd0811 & thc0607=0 & thYBIT & Rm0003) & thXBIT
{
build ItCond;
tmp:4 = sext(thXBIT) * sext(thYBIT);
Q = scarry(tmp,Rt1215) || Q; #Q flag is never cleared by this instruction
Rd0811 = tmp + Rt1215;
}
thdXbot: "" is thc0404=0 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003:2; export tmp; }
thdXbot: "X" is thc0404=1 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003(2); export tmp; }
thdXtop: "" is thc0404=0 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003(2); export tmp; }
thdXtop: "X" is thc0404=1 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003:2; export tmp; }
:smlad^thdXbot^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb2 & Rn0003; Ra1215 & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
rnbot:2 = tmpRn0003:2;
rntop:2 = tmpRn0003(2);
tmpbot:4 = sext(rnbot) * sext(thdXbot);
tmptop:4 = sext(rntop) * sext(thdXtop);
tmp:4 = sext(tmpbot) + sext(tmptop);
Q = scarry(tmp,Ra1215) || Q; #Q flag is never cleared by this instruction
Rd0811 = tmp + Ra1215;
}
:smlald^thdXbot^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbc & Rn0003; Rt1215 & Rd0811 & thc0507=6 & thdXbot & thdXtop & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
rnbot:2 = tmpRn0003:2;
rntop:2 = tmpRn0003(2);
tmpbot:4 = sext(rnbot) * sext(thdXbot);
tmptop:4 = sext(rntop) * sext(thdXtop);
accum:8 = (sext(Rd0811) << 32) | zext(Rt1215);
tmp:8 = sext(tmpbot) + sext(tmptop);
accum = tmp + accum;
Rt1215 = accum:4;
Rd0811 = accum(4);
}
:smlal^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbc & Rn0003; Rt1215 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
accum:8 = (sext(Rd0811) << 32) | zext(Rt1215);
val:8 = sext(Rn0003) * sext(Rm0003) + accum;
Rt1215 = val(0);
Rd0811 = val(4);
}
:smlal^thXBIT^thYBIT^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & (op4=0xfbc & Rn0003; Rt1215 & Rd0811 & thc0607=2 & thYBIT & Rm0003) & thXBIT
{
build ItCond;
tmp:4 = sext(thXBIT) * sext(thYBIT);
accum:8 = (zext(Rd0811) << 32) | zext(Rt1215);
val:8 = sext(tmp) + accum;
Rt1215 = val(0);
Rd0811 = val(4);
}
:smlaw^thYBIT^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb3 & Rn0003; Ra1215 & Rd0811 & thc0507=0 & thYBIT & Rm0003
{
build ItCond;
local tmp:6 = (sext(Rn0003) * sext(thYBIT));
local addend:6 = sext(Ra1215) << 16;
Q = scarry(tmp,addend) || Q; #this instruction never clears the Q flag
tmp = tmp + addend;
Rd0811 = tmp(2);
}
:smlsd^thdXbot^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb4 & Rn0003; Ra1215 & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local rnbot:2 = tmpRn0003:2;
local rntop:2 = tmpRn0003(2);
local prod1:4 = sext(rnbot) * sext(thdXbot);
local prod2:4 = sext(rntop) * sext(thdXtop);
local diff = prod1 - prod2;
Q = scarry(diff,Ra1215) || Q; #instruction never clears Q flag
Rd0811 = diff + Ra1215;
}
:smlsld^thdXbot^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbd & Rn0003; Rt1215 & Rd0811 & thc0507=6 & thdXbot & thdXtop & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local rnbot:2 = tmpRn0003:2;
local rntop:2 = tmpRn0003(2);
local tmpbot:4 = sext(rnbot) * sext(thdXbot);
local tmptop:4 = sext(rntop) * sext(thdXtop);
local accum:8 = (sext(Rd0811) << 32) | zext(Rt1215);
local tmp:8 = sext(tmpbot) - sext(tmptop);
accum = tmp + accum;
Rt1215 = accum:4;
Rd0811 = accum(4);
}
:smmla^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; Ra1215 & Rd0811 & thc0407=0 & Rm0003
{
build ItCond;
local val:8 = sext(Rn0003) * sext(Rm0003);
local accum:8 = (zext(Ra1215)) << 32;
val = val + accum;
Rd0811 = val(4);
}
:smmlar^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; Ra1215 & Rd0811 & thc0407=1 & Rm0003
{
build ItCond;
local val:8 = sext(Rn0003) * sext(Rm0003);
local accum:8 = (zext(Ra1215)) << 32;
val = val + accum + 0x80000000;
Rd0811 = val(4);
}
:smmls^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb6 & Rn0003; Ra1215 & Rd0811 & thc0407=0 & Rm0003
{
build ItCond;
local val:8 = sext(Rn0003) * sext(Rm0003);
val = (zext(Ra1215) << 32) - val;
Rd0811 = val(4);
}
:smmlsr^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb6 & Rn0003; Ra1215 & Rd0811 & thc0407=1 & Rm0003
{
build ItCond;
local val:8 = sext(Rn0003) * sext(Rm0003);
val = (zext(Ra1215) << 32) - val;
val = val + 0x80000000;
Rd0811 = val(4);
}
:smmul^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; thc1215=0xf & Rd0811 & thc0407=0 & Rm0003
{
build ItCond;
val:8 = sext(Rn0003) * sext(Rm0003);
Rd0811 = val(4);
}
:smmulr^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; thc1215=0xf & Rd0811 & thc0407=1 & Rm0003
{
build ItCond;
val:8 = sext(Rn0003) * sext(Rm0003);
val = val + 0x80000000;
Rd0811 = val(4);
}
:smuad^thdXbot^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb2 & Rn0003; thc1215=0xf & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local rnbot:2 = tmpRn0003:2;
local rntop:2 = tmpRn0003(2);
local prod1:4 = sext(rnbot) * sext(thdXbot);
local prod2:4 = sext(rntop) * sext(thdXtop);
Q = scarry(prod1,prod2) || Q; #instruction does not clear the Q flag
Rd0811 = prod1 + prod2;
}
:smulbb^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local tmpRm0003 = Rm0003;
op1:2 = tmpRn0003:2;
op2:2 = tmpRm0003:2;
Rd0811 = sext(op1) * sext(op2);
}
:smulbt^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=1 & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local tmpRm0003 = Rm0003;
op1:2 = tmpRn0003:2;
op2:2 = tmpRm0003(2);
Rd0811 = sext(op1) * sext(op2);
}
:smultb^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=2 & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local tmpRm0003 = Rm0003;
op1:2 = tmpRn0003(2);
op2:2 = tmpRm0003:2;
Rd0811 = sext(op1) * sext(op2);
}
:smultt^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=3 & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local tmpRm0003 = Rm0003;
op1:2 = tmpRn0003(2);
op2:2 = tmpRm0003(2);
Rd0811 = sext(op1) * sext(op2);
}
:smull^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb8 & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
val:8 = sext(Rn0003) * sext(Rm0003);
Ra1215 = val(0);
Rd0811 = val(4);
}
:smusd^thdXbot^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb4 & Rn0003; thc1215=0xf & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
rnbot:2 = tmpRn0003:2;
rntop:2 = tmpRn0003(2);
tmpbot:4 = sext(rnbot) * sext(thdXbot);
tmptop:4 = sext(rntop) * sext(thdXtop);
tmp:8 = sext(tmpbot) - sext(tmptop);
Rd0811 = tmp:4;
}
:smulw^thYBIT^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb3 & Rn0003; thc1215=0xf & Rd0811 & thc0507=0 & thYBIT & Rm0003
{
build ItCond;
tmp:8 = (sext(Rn0003) * sext(thYBIT)) s>> 16;
Rd0811 = tmp:4;
}
:srsdb^ItCond sp^"!",thSRSMode is TMode=1 & ItCond & op6=0x3a0 & sp & thc0505=1 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode
{
build ItCond;
# register list is always: r14, spsr
ptr:4 = sp - 4;
*ptr = lr;
ptr = ptr - 4;
*ptr = spsr;
sp = ptr;
}
:srsdb^ItCond sp,thSRSMode is TMode=1 & ItCond & op6=0x3a0 & sp & thc0505=0 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode
{
build ItCond;
# register list is always: r14, spsr
ptr:4 = sp - 4;
*ptr = lr;
ptr = ptr - 4;
*ptr = spsr;
}
:srsib^ItCond sp^"!",thSRSMode is TMode=1 & ItCond & op6=0x3a6 & sp & thc0505=1 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode
{
build ItCond;
# register list is always: r14, spsr
ptr:4 = sp + 4;
*ptr = lr;
ptr = ptr + 4;
*ptr = spsr;
sp = ptr;
}
:srsia^ItCond sp,thSRSMode is TMode=1 & ItCond & op6=0x3a6 & sp & thc0505=0 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode
{
build ItCond;
# register list is always: r14, spsr
ptr:4 = sp + 4;
*ptr = lr;
ptr = ptr + 4;
*ptr = spsr;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
# ssat and ssat16 were defined elsewhere and moved here to preserve sort order
# shift operands for ssat and usat:
th2_shift0: is imm3_shft=0x0 & imm2_shft=0x0 { }
th2_shift0: ",lsl "^thLsbImm is imm3_shft & imm2_shft & thLsbImm { }
th2_shift1: ",asr "^thLsbImm is imm3_shft & imm2_shft & thLsbImm { }
th2_shift1: ",asr #32" is imm3_shft=0x0 & imm2_shft=0x0 { }
:ssat Rt0811, thMsbImm, part2Rd0003^th2_shift0 is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xc & part2c0505=0x0 & part2c0404=0x0 & part2Rd0003 ;
thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift0 & thMsbImm & thLsbImm
{
# Shift bit is 0
tmpRn:4 = part2Rd0003 << thLsbImm;
tmp:4 = SignedSaturate(tmpRn, thMsbImm);
Q = SignedDoesSaturate(tmpRn, thMsbImm);
Rt0811 = tmp;
}
:ssat Rt0811, thMsbImm, part2Rd0003^th2_shift1 is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xc & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003;
thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift1 & thMsbImm & thLsbImm
{
# Shift bit is 1
tmpRn:4 = part2Rd0003 s>> thLsbImm;
tmp:4 = SignedSaturate(tmpRn, thMsbImm);
Q = SignedDoesSaturate(tmpRn, thMsbImm);
Rt0811 = tmp;
}
:ssat16 Rt0811, "#"^Immed4, part2Rd0003 is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xc & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003;
op12=0x0 & Rt0811 & thc0407=0x0 & Immed4
{
tmp:4 = SignedSaturate(part2Rd0003, Immed4);
Q = SignedDoesSaturate(part2Rd0003, Immed4);
Rt0811 = tmp;
}
:ssax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
sum:4 = sext(Rn0003[ 0,16]) + sext(Rm0003[16,16]);
diff:4 = sext(Rn0003[16,16]) - sext(Rm0003[ 0,16]);
Rd0811[ 0,16] = sum[0,16];
Rd0811[16,16] = diff[0,16];
GE1 = sum s>= 0;
GE2 = sum s>= 0;
GE3 = diff s>= 0;
GE4 = diff s>= 0;
}
:ssub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
diff1:4 = sext(Rn0003[ 0,16]) - sext(Rm0003[ 0,16]);
diff2:4 = sext(Rn0003[16,16]) - sext(Rm0003[16,16]);
Rd0811[ 0,16] = diff1[0,16];
Rd0811[16,16] = diff2[0,16];
GE1 = diff1 s>= 0;
GE2 = diff1 s>= 0;
GE3 = diff2 s>= 0;
GE4 = diff2 s>= 0;
}
:ssub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
diff1:4 = sext(Rn0003[ 0,8]) - sext(Rm0003[ 0,8]);
diff2:4 = sext(Rn0003[ 8,8]) - sext(Rm0003[ 8,8]);
diff3:4 = sext(Rn0003[16,8]) - sext(Rm0003[16,8]);
diff4:4 = sext(Rn0003[24,8]) - sext(Rm0003[24,8]);
Rd0811[ 0,8] = diff1[0,8];
Rd0811[ 8,8] = diff2[0,8];
Rd0811[16,8] = diff3[0,8];
Rd0811[24,8] = diff4[0,8];
GE1 = diff1 s>= 0;
GE2 = diff2 s>= 0;
GE3 = diff3 s>= 0;
GE4 = diff4 s>= 0;
}
:umull^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfba & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
val:8 = zext(Rn0003) * zext(Rm0003);
Ra1215 = val(0);
Rd0811 = val(4);
}
:umaal^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbe & Rn0003; Ra1215 & Rd0811 & sop0407=6 & Rm0003
{
build ItCond;
val:8 = zext(Rn0003) * zext(Rm0003) + zext(Ra1215) + zext(Rd0811);
Ra1215 = val(0);
Rd0811 = val(4);
}
:umlal^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbe & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003
{
build ItCond;
accum:8 = (zext(Rd0811) << 32) | zext(Ra1215);
val:8 = zext(Rn0003) * zext(Rm0003) + accum;
Ra1215 = val(0);
Rd0811 = val(4);
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
@if defined(VERSION_6)
thumbEndianNess: "LE" is op0=0xb650 { export 0:1; }
thumbEndianNess: "BE" is op0=0xb658 { export 1:1; }
:setend^ItCond thumbEndianNess is TMode=1 & ItCond & (op0=0xb650 | op0=0xb658) & thumbEndianNess { setEndianState(thumbEndianNess); }
:sev^ItCond is TMode=1 & ItCond & op0=0xbf40
{
build ItCond;
}
:sev^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=8004
{
build ItCond;
}
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
:stc^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=0 & thL4=0; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_store(t_cpn,thCRd,taddrmode5);
}
:stcl^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=1 & thL4=0; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_storelong(t_cpn,thCRd,taddrmode5);
}
:stc2^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=0 & thL4=0; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_store(t_cpn,thCRd,taddrmode5);
}
:stc2l^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=1 & thL4=0; thCRd & thcpn) & taddrmode5
{
build ItCond;
build taddrmode5;
t_cpn:4 = thcpn;
coprocessor_storelong(t_cpn,thCRd,taddrmode5);
}
:stm^ItCond Rn0003,thstrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=0 & thc0404=0 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_inc
{
build ItCond;
mult_addr = Rn0003;
build thstrlist_inc;
}
:stm^ItCond^".w" Rn0003!,thstrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=1 & thc0404=0 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_inc
{
build ItCond;
mult_addr = Rn0003;
build thstrlist_inc;
Rn0003 = mult_addr;
}
:stmdb^ItCond Rn0003!,thstrlist_dec is TMode=1 & ItCond & op4=0xe92 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_dec
{
build ItCond;
mult_addr = Rn0003-4;
build thstrlist_dec;
Rn0003 = mult_addr + 4;
}
:stmdb^ItCond Rn0003,thstrlist_dec is TMode=1 & ItCond & op4=0xe90 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_dec
{
build ItCond;
mult_addr = Rn0003-4;
build thstrlist_dec;
}
@endif # defined(VERSION_6T2) || defined(VERSION_7)
:stmia^ItCond Rn_exclaim,stbrace is TMode=1 & ItCond & op11=0x18 & Rn_exclaim & stbrace & Rn_exclaim_WB
{
build ItCond;
build Rn_exclaim;
build stbrace;
build Rn_exclaim_WB;
}
:str^ItCond Rd0002,RnIndirect4 is TMode=1 & ItCond & op11=0xc & RnIndirect4 & Rd0002
{
build ItCond;
*RnIndirect4 = Rd0002;
}
:str^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x28 & RnRmIndirect & Rd0002
{
build ItCond;
*RnRmIndirect = Rd0002;
}
:str^ItCond Rd0810,Sprel8Indirect is TMode=1 & ItCond & op11=0x12 & Sprel8Indirect & Rd0810
{
build ItCond;
*Sprel8Indirect = Rd0810;
}
:strb^ItCond Rd0002,RnIndirect1 is TMode=1 & ItCond & op11=0xe & RnIndirect1 & Rd0002
{
build ItCond;
local tmpRd0002 = Rd0002;
*RnIndirect1 = tmpRd0002:1;
}
:strb^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2a & RnRmIndirect & Rd0002
{
build ItCond;
local tmpRd0002 = Rd0002;
*RnRmIndirect = tmpRd0002:1;
}
:strh^ItCond Rd0002,RnIndirect2 is TMode=1 & ItCond & op11=0x10 & RnIndirect2 & Rd0002
{
build ItCond;
local tmpRd0002 = Rd0002;
*RnIndirect2 = tmpRd0002:2;
}
:strh^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x29 & RnRmIndirect & Rd0002
{
build ItCond;
local tmpRd0002 = Rd0002;
*RnRmIndirect = tmpRd0002:2;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:str.w^ItCond Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8c; Rt1215) & RnIndirect12
{
build ItCond;
*RnIndirect12 = Rt1215;
}
:str.w^ItCond Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf84; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
*RnIndirectPUW = Rt1215;
}
:str^ItCond^".w" Rt1215,[Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xf84 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405=0 & Rm0003
{
build ItCond;
local tmp = Rn0003 + Rm0003;
*tmp = Rt1215;
}
:str^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf84 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
*tmp = Rt1215;
}
:strb^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf88; Rt1215) & RnIndirect12
{
build ItCond;
build RnIndirect12;
local tmpRt1215 = Rt1215;
*RnIndirect12 = tmpRt1215:1;
}
:strb^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf80; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
local tmpRt1215 = Rt1215;
*RnIndirectPUW = tmpRt1215:1;
}
:strb^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf80 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
local tmpRt1215 = Rt1215;
*tmp = tmpRt1215:1;
}
:strbt^ItCond Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf80 & Rn0003; Rt1215 & thc0811=14 & Immed8
{
build ItCond;
local tmp = Rn0003 + Immed8;
local tmpRt1215 = Rt1215;
*tmp = tmpRt1215:1;
}
:strd^ItCond Rt1215,Rt0811,RnIndirectPUW1 is TMode=1 & ItCond & (op9=0x74 & thc0910=0 & thc0606=1 & thc0404=0 & Rn0003; Rt1215 & Rt0811) & $(RN_INDIRECT_PUW1)
{
build ItCond;
build RnIndirectPUW1;
local tmp = RnIndirectPUW1;
*tmp = Rt1215;
tmp = tmp + 4;
*tmp = Rt0811;
}
:strh^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8A; Rt1215) & RnIndirect12
{
build ItCond;
local tmpRt1215 = Rt1215;
*RnIndirect12 = tmpRt1215:2;
}
:strh^ItCond Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf82; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW)
{
build ItCond;
build RnIndirectPUW;
local tmpRt1215 = Rt1215;
*RnIndirectPUW = tmpRt1215:2;
}
:strh^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf82 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 << thc0405);
local tmpRt1215 = Rt1215;
*tmp = tmpRt1215:2;
}
:strht^ItCond Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf82 & Rn0003; Rt1215 & thc0811=14 & Immed8
{
build ItCond;
local tmp = Rn0003 + Immed8;
local tmpRt1215 = Rt1215;
*tmp = tmpRt1215:2;
}
:strex^ItCond Rd0811,Rt1215,[Rn0003,Immed8_4] is TMode=1 & ItCond & op4=0xe84 & Rn0003; Rt1215 & Rd0811 & Immed8_4
{
build ItCond;
local tmp = Rn0003 + Immed8_4;
access:1 = hasExclusiveAccess(tmp);
Rd0811 = 1;
if (!access) goto inst_next;
Rd0811 = 0;
*tmp = Rt1215;
}
@endif # VERSION_6T2 || VERSION_7
@if defined(VERSION_7)
:strexb^ItCond Rd0003,Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & thc0811=15 & thc0407=4 & Rd0003
{
build ItCond;
local tmp = Rn0003;
access:1 = hasExclusiveAccess(tmp);
Rd0003 = 1;
if (!access) goto inst_next;
Rd0003 = 0;
local tmpRt1215 = Rt1215;
*tmp = tmpRt1215:1;
}
:strexh^ItCond Rd0003,Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & thc0811=15 & thc0407=5 & Rd0003
{
build ItCond;
local tmp = Rn0003;
access:1 = hasExclusiveAccess(tmp);
Rd0003 = 1;
if (!access) goto inst_next;
Rd0003 = 0;
local tmpRt1215 = Rt1215;
*tmp = tmpRt1215:1;
}
:strexd^ItCond Rd0003,Rt1215,Rt0811,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & Rt0811 & thc0407=7 & Rd0003
{
build ItCond;
local tmp = Rn0003;
access:1 = hasExclusiveAccess(tmp);
Rd0003 = 1;
if (!access) goto inst_next;
Rd0003 = 0;
*tmp = Rt1215;
tmp = tmp + 4;
*tmp = Rt0811;
}
@endif # VERSION_7
:sub^ItCond Rd0002,Rn0305,Immed3 is TMode=1 & ItCond & op9=0xf & Immed3 & Rn0305 & Rd0002 & CheckInIT_CZNO
{
build ItCond;
th_subflags(Rn0305,Immed3);
Rd0002 = Rn0305 - Immed3;
resflags(Rd0002);
build CheckInIT_CZNO;
}
:sub^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=7 & Rd0810 & Immed8 & CheckInIT_CZNO
{
build ItCond;
th_subflags(Rd0810,Immed8);
Rd0810 = Rd0810 - Immed8;
resflags(Rd0810);
build CheckInIT_CZNO;
}
:sub^ItCond Rd0002,Rn0305,Rm0608 is TMode=1 & ItCond & op9=0xd & Rm0608 & Rn0305 & Rd0002 & CheckInIT_CZNO
{
build ItCond;
th_subflags(Rn0305,Rm0608);
Rd0002 = Rn0305 - Rm0608;
resflags(Rd0002);
build CheckInIT_CZNO;
}
:sub^ItCond sp,Immed7_4 is TMode=1 & ItCond & op7=0x161 & sp & Immed7_4
{
build ItCond;
sp = sp - Immed7_4;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:sub^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=13 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
th_subflags(Rn0003,ThumbExpandImm12);
Rd0811 = Rn0003-ThumbExpandImm12;
resflags(Rd0811);
build thSBIT_CZNO;
}
:subw^ItCond Rd0811,Rn0003,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & Rn0003; thc1515=0 & Rd0811) & Immed12
{
build ItCond;
th_subflags(Rn0003,Immed12);
Rd0811 = Rn0003-Immed12;
resflags(Rd0811);
}
:sub^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=13 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
local tmp = thshift2;
th_subflags(Rn0003,tmp);
Rd0811 = Rn0003-tmp;
resflags(Rd0811);
build thSBIT_CZNO;
}
:sub^thSBIT_CZNO^ItCond^".w" Rd0811,sp,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=13 & thSBIT_CZNO & sp & sop0003=0xd; thc1515=0 & Rd0811) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
th_subflags(sp,ThumbExpandImm12);
Rd0811 = sp-ThumbExpandImm12;
resflags(Rd0811);
build thSBIT_CZNO;
}
:sub^ItCond pc,lr,Immed8 is TMode=1 & ItCond & op4=0xf3d & pc & sop0003=0xe; op8=0x8f & lr & Immed8
{
build ItCond;
build Immed8;
th_subflags(lr,Immed8);
dest:4 = lr-Immed8;
resflags(dest);
cpsr=spsr;
SetThumbMode( ((cpsr >> 5) & 1) != 0 );
pc = dest;
goto [pc];
}
:subw^ItCond Rd0811,sp,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & sop0003=0xd & sp; thc1515=0 & Rd0811) & Immed12
{
build ItCond;
th_subflags(sp,Immed12);
Rd0811 = sp-Immed12;
resflags(Rd0811);
}
:sub^thSBIT_CZNO^ItCond^".w" Rd0811,sp,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=13 & thSBIT_CZNO & sop0003=0xd & sp; thc1515=0 & Rd0811 & thshift2
{
build ItCond;
build thshift2;
local tmp = thshift2;
th_subflags(sp,tmp);
Rd0811 = sp-tmp;
resflags(Rd0811);
build thSBIT_CZNO;
}
@endif # VERSION_6T2 || VERSION_7
:svc^ItCond immed8 is TMode=1 & ItCond & op8=0xdf & immed8
{
build ItCond;
tmp:4 = immed8;
software_interrupt(tmp);
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:sxtab^ItCond Rd0811, Rn0003, Rm0003, ByteRotate is TMode=1 & ItCond & op4=0xfa4 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = sext(tmp:1) + Rn0003;
}
:sxtab^ItCond Rd0811, Rn0003, Rm0003 is TMode=1 & ItCond & op4=0xfa4 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
Rd0811 = sext(tmpRm0003:1) + Rn0003;
}
:sxtab16^ItCond Rd0811, Rn0003, Rm0003, ByteRotate is TMode=1 & ItCond & op4=0xfa2 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
local tmpRn0003 = Rn0003;
tmpL:2 = sext(tmp:1) + tmpRn0003:2;
tmp = tmp >> 16;
tmpH:2 = sext(tmp:1) + tmpRn0003(2);
Rd0811 = zext(tmpL) + (zext(tmpH) << 16);
}
:sxtab16^ItCond Rd0811, Rn0003, Rm0003 is TMode=1 & ItCond & op4=0xfa2 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRn0003 = Rn0003;
local tmpRm0003 = Rm0003;
tmpL:2 = sext(tmpRm0003:1) + tmpRn0003:2;
local tmp = tmpRm0003 >> 16;
tmpH:2 = sext(tmp:1) + tmpRn0003(2);
Rd0811 = zext(tmpL) + (zext(tmpH) << 16);
}
:sxtah^ItCond Rd0811, Rn0003, Rm0003, ByteRotate is TMode=1 & ItCond & op4=0xfa0 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = sext(tmp:2) + Rn0003;
}
:sxtah^ItCond Rd0811, Rn0003, Rm0003 is TMode=1 & ItCond & op4=0xfa0 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
Rd0811 = sext(tmpRm0003:2) + Rn0003;
}
@endif # VERSION_6T2 || VERSION_7
@if defined(VERSION_6)
:sxtb^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=0 & thc0606=1 & Rm0305 & Rd0002
{
build ItCond;
local tmpRm0305 = Rm0305;
Rd0002 = sext(tmpRm0305:1);
}
:sxtb^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa4f; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = sext(tmp:1);
}
:sxtb^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa4f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
Rd0811 = sext(tmpRm0003:1);
}
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
:sxtb16^ItCond Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa2f; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
tmpL:2 = sext(tmp:1);
tmp = tmp >> 16;
tmpH:2 = sext(tmp:1);
Rd0811 = zext(tmpL) + (zext(tmpH) << 16);
}
:sxtb16^ItCond Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa2f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
tmpL:2 = sext(tmpRm0003:1);
tmp:4 = tmpRm0003 >> 16;
tmpH:2 = sext(tmp:1);
Rd0811 = zext(tmpL) + (zext(tmpH) << 16);
}
@endif # VERSION_6T2 || VERSION_7
@if defined(VERSION_6)
:sxth^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=0 & thc0606=0 & Rm0305 & Rd0002
{
build ItCond;
local tmpRm0305 = Rm0305;
Rd0002 = sext(tmpRm0305:2);
}
:sxth^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa0f; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = sext(tmp:2);
}
:sxth^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa0f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
Rd0811 = sext(tmpRm0003:2);
}
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
:tbb^ItCond [Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; op8=0xf0 & thc0507=0 & thc0404=0 & Rm0003
{
build ItCond;
local tmp = Rn0003 + Rm0003;
offs:1 = *tmp;
SetThumbMode(1);
pc = inst_next + (zext(offs) * 2);
goto [pc];
}
:tbh^ItCond [Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; op8=0xf0 & thc0507=0 & thc0404=1 & Rm0003
{
build ItCond;
local tmp = Rn0003 + (Rm0003 * 2);
offs:2 = *tmp;
SetThumbMode(1);
pc = inst_next + (zext(offs) * 2);
goto [pc];
}
Pcrel: [cloc,Rm0003] is Rm0003 & thc0404=0 [ cloc = inst_next; ]
{
local tmp = Rm0003; tmp = cloc + tmp; val:1 = *tmp; tmp = zext(val); export tmp;
}
Pcrel: [cloc,Rm0003] is Rm0003 & thc0404=1 [ cloc = inst_next; ]
{
local tmp = Rm0003; tmp = cloc + (tmp * 2); val:2 = *tmp; tmp = zext(val); export tmp;
}
:tbb^ItCond Pcrel is TMode=1 & ItCond & op4=0xe8d & thc0003=15; op8=0xf0 & thc0507=0 & thc0404=0 & Pcrel
{
build ItCond;
SetThumbMode(1);
pc = inst_next + (Pcrel * 2);
goto [pc];
}
:tbh^ItCond Pcrel is TMode=1 & ItCond & op4=0xe8d & thc0003=15; op8=0xf0 & thc0507=0 & thc0404=1 & Pcrel
{
build ItCond;
SetThumbMode(1);
pc = inst_next + (Pcrel * 2);
goto [pc];
}
@endif # VERSION_6T2 || VERSION_7
:tst^ItCond Rn0002,Rm0305 is TMode=1 & ItCond & op6=0x108 & Rm0305 & Rn0002
{
build ItCond;
local tmp = Rn0002 & Rm0305;
ZR = (tmp == 0);
NG = (tmp s< 0);
}
@if defined(VERSION_6T2) || defined(VERSION_7)
:teq^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=4 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
local tmp = Rn0003 ^ ThumbExpandImm12;
th_test_flags(tmp);
}
:teq^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=4 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf & thshift2
{
build ItCond;
build thshift2;
local tmp = Rn0003 ^ thshift2;
th_test_flags(tmp);
}
:tst^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=0 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf) & ThumbExpandImm12
{
build ItCond;
build ThumbExpandImm12;
local tmp = Rn0003 & ThumbExpandImm12;
th_test_flags(tmp);
}
:tst^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=0 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf & thshift2
{
build ItCond;
build thshift2;
local tmp = Rn0003 & thshift2;
th_test_flags(tmp);
}
:uadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003
{
build ItCond;
sum1:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[ 0,16]);
sum2:4 = zext(Rn0003[16,16]) + zext(Rm0003[16,16]);
GE1 = carry(Rn0003[0,16],Rm0003[0,16]);
GE2 = GE1;
GE3 = carry(Rn0003[16,16],Rm0003[16,16]);
GE4 = GE3;
Rd0811[ 0,16] = sum1[0,16];
Rd0811[16,16] = sum2[0,16];
}
:uadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003
{
build ItCond;
sum1:4 = zext(Rn0003[ 0,8]) + zext(Rm0003[ 0,8]);
sum2:4 = zext(Rn0003[ 8,8]) + zext(Rm0003[ 8,8]);
sum3:4 = zext(Rn0003[16,8]) + zext(Rm0003[16,8]);
sum4:4 = zext(Rn0003[24,8]) + zext(Rm0003[24,8]);
GE1 = carry(Rn0003[0,8],Rm0003[0,8]);
GE2 = carry(Rn0003[8,8],Rm0003[8,8]);
GE3 = carry(Rn0003[16,8],Rm0003[16,8]);
GE4 = carry(Rn0003[24,8],Rm0003[24,8]);
Rd0811[ 0,8] = sum1[0,8];
Rd0811[ 8,8] = sum2[0,8];
Rd0811[16,8] = sum3[0,8];
Rd0811[24,8] = sum4[0,8];
}
:uasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003
{
build ItCond;
diff:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[16,16]);
sum:4 = zext(Rn0003[16,16]) + zext(Rm0003[ 0,16]);
GE1 = diff s>= 0;
GE2 = GE1;
GE3 = carry(Rn0003[16,16],Rm0003[0,16]);
GE4 = GE3;
Rd0811[ 0,16] = diff[0,16];
Rd0811[16,16] = sum[0,16];
}
:uhadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003
{
build ItCond;
sum1:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[ 0,16]);
sum2:4 = zext(Rn0003[16,16]) + zext(Rm0003[16,16]);
Rd0811[ 0,16] = sum1[1,16];
Rd0811[16,16] = sum2[1,16];
}
:uhadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003
{
build ItCond;
sum1:4 = zext(Rn0003[ 0,8]) + zext(Rm0003[ 0,8]);
sum2:4 = zext(Rn0003[ 8,8]) + zext(Rm0003[ 8,8]);
sum3:4 = zext(Rn0003[16,8]) + zext(Rm0003[16,8]);
sum4:4 = zext(Rn0003[24,8]) + zext(Rm0003[24,8]);
Rd0811[ 0,8] = sum1[1,8];
Rd0811[ 8,8] = sum2[1,8];
Rd0811[16,8] = sum3[1,8];
Rd0811[24,8] = sum4[1,8];
}
:uhasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003
{
build ItCond;
diff:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[16,16]);
sum:4 = zext(Rn0003[16,16]) + zext(Rm0003[ 0,16]);
Rd0811[ 0,16] = diff[1,16];
Rd0811[16,16] = sum[1,16];
}
:uhsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003
{
build ItCond;
sum:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[16,16]);
diff:4 = zext(Rn0003[16,16]) - zext(Rm0003[ 0,16]);
Rd0811[ 0,16] = sum[1,16];
Rd0811[16,16] = diff[1,16];
}
:uhsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[ 0,16]);
diff2:4 = zext(Rn0003[16,16]) - zext(Rm0003[16,16]);
Rd0811[ 0,16] = diff1[1,16];
Rd0811[16,16] = diff2[1,16];
}
:uhsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]);
diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]);
diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]);
diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]);
Rd0811[ 0,8] = diff1[1,8];
Rd0811[ 8,8] = diff2[1,8];
Rd0811[16,8] = diff3[1,8];
Rd0811[24,8] = diff4[1,8];
}
:uqadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003
{
build ItCond;
sum1:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[ 0,16]);
sum2:4 = zext(Rn0003[16,16]) + zext(Rm0003[16,16]);
tmp1:4 = UnsignedSaturate(sum1, 16:2);
tmp2:4 = UnsignedSaturate(sum2, 16:2);
Rd0811[ 0,16] = tmp1[0,16];
Rd0811[16,16] = tmp2[0,16];
}
:uqadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003
{
build ItCond;
sum1:4 = zext(Rn0003[ 0,8]) + zext(Rm0003[ 0,8]);
sum2:4 = zext(Rn0003[ 8,8]) + zext(Rm0003[ 8,8]);
sum3:4 = zext(Rn0003[16,8]) + zext(Rm0003[16,8]);
sum4:4 = zext(Rn0003[24,8]) + zext(Rm0003[24,8]);
tmp1:4 = UnsignedSaturate(sum1, 8:2);
tmp2:4 = UnsignedSaturate(sum2, 8:2);
tmp3:4 = UnsignedSaturate(sum3, 8:2);
tmp4:4 = UnsignedSaturate(sum4, 8:2);
Rd0811[ 0,8] = tmp1[0,8];
Rd0811[ 8,8] = tmp2[0,8];
Rd0811[16,8] = tmp3[0,8];
Rd0811[24,8] = tmp4[0,8];
}
:uqasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003
{
build ItCond;
diff:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[16,16]);
sum:4 = zext(Rn0003[16,16]) + zext(Rm0003[ 0,16]);
tmpdiff:4 = UnsignedSaturate(diff, 16:2);
tmpsum:4 = UnsignedSaturate(sum, 16:2);
Rd0811[ 0,16] = tmpdiff[0,16];
Rd0811[16,16] = tmpsum[0,16];
}
:uqsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003
{
build ItCond;
sum:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[16,16]);
diff:4 = zext(Rn0003[16,16]) - zext(Rm0003[ 0,16]);
tmpsum:4 = UnsignedSaturate(sum, 16:2);
tmpdiff:4 = UnsignedSaturate(diff, 16:2);
Rd0811[ 0,16] = tmpsum[0,16];
Rd0811[16,16] = tmpdiff[0,16];
}
:uqsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[ 0,16]);
diff2:4 = zext(Rn0003[16,16]) - zext(Rm0003[16,16]);
tmp1:4 = UnsignedSaturate(diff1, 16:2);
tmp2:4 = UnsignedSaturate(diff2, 16:2);
Rd0811[ 0,16] = tmp1[0,16];
Rd0811[16,16] = tmp2[0,16];
}
:uqsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]);
diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]);
diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]);
diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]);
tmp1:4 = UnsignedSaturate(diff1, 8:2);
tmp2:4 = UnsignedSaturate(diff2, 8:2);
tmp3:4 = UnsignedSaturate(diff3, 8:2);
tmp4:4 = UnsignedSaturate(diff4, 8:2);
Rd0811[ 0,8] = tmp1[0,8];
Rd0811[ 8,8] = tmp2[0,8];
Rd0811[16,8] = tmp3[0,8];
Rd0811[24,8] = tmp4[0,8];
}
:usad8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb7 & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]);
diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]);
diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]);
diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]);
absdiff1:4 = Absolute(diff1);
absdiff2:4 = Absolute(diff2);
absdiff3:4 = Absolute(diff3);
absdiff4:4 = Absolute(diff4);
Rd0811 = absdiff1 + absdiff2 + absdiff3 + absdiff4;
}
:usada8^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb7 & Rn0003; Ra1215 & Rd0811 & thc0407=0x0 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]);
diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]);
diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]);
diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]);
absdiff1:4 = Absolute(diff1);
absdiff2:4 = Absolute(diff2);
absdiff3:4 = Absolute(diff3);
absdiff4:4 = Absolute(diff4);
# The manual specifies a zero extension of Ra to an unspecified
# intermediate precision, followed by truncation to 4 bytes. In this
# model, zext is retained, but it has no effect because the
# intermediate precision is 4 bytes.
Rd0811 = zext(Ra1215) + absdiff1 + absdiff2 + absdiff3 + absdiff4;
}
# usat and ussat16 were defined elsewhere and moved here to preserve sort order
:usat Rt0811, thMsbImm, part2Rd0003^th2_shift0 is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2c0505=0x0 & part2c0404=0x0 & part2Rd0003 ;
thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift0 & thMsbImm & thLsbImm
{
# Shift bit is 0
tmpRn:4 = part2Rd0003 << thLsbImm;
tmp:4 = UnsignedSaturate(tmpRn, thMsbImm);
Q = UnsignedDoesSaturate(tmpRn, thMsbImm);
Rt0811 = tmp;
}
:usat Rt0811, thMsbImm, part2Rd0003^th2_shift1 is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003 ;
thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift1 & thMsbImm & thLsbImm
{
# Shift bit is 1
tmpRn:4 = part2Rd0003 s>> thLsbImm;
tmp:4 = UnsignedSaturate(tmpRn, thMsbImm);
Q = UnsignedDoesSaturate(tmpRn, thMsbImm);
Rt0811 = tmp;
}
:usat16 Rt0811, "#"^Immed4, part2Rd0003 is
TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003 ;
op12=0x0 & Rt0811 & thc0407=0x0 & Immed4
{
tmp:4 = UnsignedSaturate(part2Rd0003, Immed4);
Q = UnsignedDoesSaturate(part2Rd0003, Immed4);
Rt0811 = tmp;
}
:usax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003
{
build ItCond;
sum:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[16,16]);
diff:4 = zext(Rn0003[16,16]) - zext(Rm0003[ 0,16]);
Rd0811[ 0,16] = sum[0,16];
Rd0811[16,16] = diff[0,16];
# this odd looking condition tests that the 16 bit sum overflowed,
# which would have made it a negative number. That's how it's
# documented, but to be consistent they might have used s< 0.
GE1 = sum s>= 0x10000;
GE2 = sum s>= 0x10000;
GE3 = diff s>= 0;
GE4 = diff s>= 0;
}
:usub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[ 0,16]);
diff2:4 = zext(Rn0003[16,16]) - zext(Rm0003[16,16]);
Rd0811[ 0,16] = diff1[0,16];
Rd0811[16,16] = diff2[0,16];
GE1 = diff1 s>= 0;
GE2 = diff1 s>= 0;
GE3 = diff2 s>= 0;
GE4 = diff2 s>= 0;
}
:usub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003
{
build ItCond;
diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]);
diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]);
diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]);
diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]);
Rd0811[ 0,8] = diff1[0,8];
Rd0811[ 8,8] = diff2[0,8];
Rd0811[16,8] = diff3[0,8];
Rd0811[24,8] = diff4[0,8];
GE1 = diff1 s>= 0;
GE2 = diff2 s>= 0;
GE3 = diff3 s>= 0;
GE4 = diff4 s>= 0;
}
:ubfx^ItCond Rd0811,Rn0003,thLsbImm,thWidthMinus1 is TMode=1 & ItCond & op4=0xf3c & Rn0003; thc1515=0 & Rd0811 & thLsbImm & thc0505=0 & thWidthMinus1
{
build ItCond;
build thLsbImm;
build thWidthMinus1;
shift:4 = 31 - (thLsbImm + thWidthMinus1); # thMsbImm represents widthMinus1
Rd0811 = Rn0003 << shift;
shift = 31 - thWidthMinus1; # msbImm represents widthMinus1
Rd0811 = Rd0811 >> shift;
}
:udiv^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbb & Rn0003; op12=0xf & Rd0811 & thc0407=0xf & Rm0003
{
build ItCond;
result:8 = zext(Rn0003) / zext(Rm0003);
Rd0811 = result(0);
}
:uxtab^ItCond Rd0811,Rn0003,Rm0003,ByteRotate is TMode=1 & ItCond & op4=0xfa5 & Rn0003; op12=15 & Rd0811 & thc0707=1 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = Rn0003 + zext(tmp:1);
}
:uxtab16^ItCond Rd0811,Rn0003,Rm0003,ByteRotate is TMode=1 & ItCond & op4=0xfa3 & Rn0003; op12=15 & Rd0811 & thc0707=1 & ByteRotate & Rm0003
{
build ItCond;
rotated:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
local tmp_b = rotated:1;
local tmpRn0003 = Rn0003;
tmpl:2 = tmpRn0003:2 + zext(tmp_b);
local tmph = (rotated >> 16);
tmp_b = tmph:1;
tmph = (tmpRn0003 >> 16) + zext(tmp_b);
Rd0811 = (tmph << 16) | zext(tmpl);
}
:uxtah^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa1 & Rn0003; op12=15 & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
Rd0811 = Rn0003 + zext(tmpRm0003:2);
}
:uxtah^ItCond Rd0811,Rn0003,Rm0003,ByteRotate is TMode=1 & ItCond & op4=0xfa1 & Rn0003; op12=15 & Rd0811 & thc0707=1 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = Rn0003 + zext(tmp:2);
}
@endif # VERSION_6T2 || VERSION_7
@if defined(VERSION_6)
:uxtb^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=1 & thc0606=1 & Rm0305 & Rd0002
{
build ItCond;
local tmpRm0305 = Rm0305;
Rd0002 = zext(tmpRm0305:1);
}
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
:uxtb^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa5f; op12=0xf & Rd0811 & thc0707=1 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = zext(tmp:1);
}
:uxtb^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa5f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
Rd0811 = zext(tmpRm0003:1);
}
:uxtb16^ItCond Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa3f; op12=0xf & Rd0811 & thc0707=1 & ByteRotate & Rm0003
{
build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = tmp & 0x00ff00ff;
}
:uxtb16^ItCond Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa3f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
Rd0811 = Rm0003 & 0x00ff00ff;
}
@endif # VERSION_6T2 || VERSION_7
@if defined(VERSION_6)
:uxth^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=1 & thc0606=0 & Rm0305 & Rd0002
{
build ItCond;
local tmpRm0305 = Rm0305;
Rd0002 = zext(tmpRm0305:2);
}
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
:uxth^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa1f; op12=0xf & Rd0811 & thc0707=1 & ByteRotate & Rm0003
{ build ItCond;
tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate);
Rd0811 = zext(tmp:2);
}
:uxth^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa1f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003
{
build ItCond;
local tmpRm0003 = Rm0003;
Rd0811 = zext(tmpRm0003:2);
}
@endif # VERSION_6T2 || VERSION_7
# V* see ARMneon.sinc
@if defined(VERSION_6)
:wfe^ItCond is TMode=1 & ItCond & op0=0xbf20
{
WaitForEvent();
}
:wfi^ItCond is TMode=1 & ItCond & op0=0xbf30
{
WaitForInterrupt();
}
:yield^ItCond is TMode=1 & ItCond & op0=0xbf10
{
HintYield();
}
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
:wfe^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8002
{
WaitForEvent();
}
:wfi^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8003
{
WaitForInterrupt();
}
:yield^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8001
{
HintYield();
}
} # End with : ARMcondCk=1
@endif # VERSION_6T2 || VERSION_7