# 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) op13=(13,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) Rd1215hi=(12,15) Rn0002=(0,2) Rn0003=(0,3) Rd0003hi=(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) thcop=(8,10) thopcode1=(4,7) thop1=(4,6) thopcode2=(5,7) thop2=(7,7) thopcode3=(0,5) thop3=(4,5) 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 [ Rd1215hi Rd0003hi ] [ 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 names [ thcop ] [ p0 p1 p2 p3 p4 p5 p6 p7 ]; 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 ARM Architecture reference section "Pseudocode details of addition and subtraction" macro th_add_with_carry_flags(op1,op2){ local CYz = zext(CY); local result = op1 + op2; tmpCY = carry( op1, op2 ) || carry( result, CYz ); tmpOV = scarry( op1, op2) ^^ scarry( result, CYz ); } #Note: used for subtraction op1 - (op2 + !CY) #sets tmpCY if there is NO borrow macro th_sub_with_carry_flags(op1, op2){ local result = op1 - op2; tmpCY = (op1 > op2) || (result < zext(CY)); tmpOV = sborrow(op1,op2) ^^ sborrow(result,zext(!CY)); } 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; } macro readAPSR_nzcvq(r) { # TODO: GE bits have not been included r = zext( (NG<<4) | (ZR<<3) | (CY<<2) | (OV<<1) | (Q) ) << 27; } macro writeAPSR_nzcvq(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; } macro readAPSR_nzcv(r) { r = zext( (NG<<3) | (ZR<<2) | (CY<<1) | (OV) ) << 28; } macro writeAPSR_nzcv(r) { local tmp = r >> 28 & 0xf; OV = ((tmp) & 0x1) != 0; CY = ((tmp >> 1) & 0x1) != 0; ZR = ((tmp >> 2) & 0x1) != 0; NG = ((tmp >> 3) & 0x1) != 0; } ############################################################################### # 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 | thc0404=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<>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 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 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 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 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 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 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 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 & thc0115=0 { * mult_addr = r0; mult_addr = mult_addr + 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 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 is thc1313=1 & 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 is thc1212=1 & 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 is thc1111=1 & 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 is thc1010=1 & 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 is thc0909=1 & 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 is thc0808=1 & 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 is thc0707=1 & 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 is thc0606=1 & 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 is thc0505=1 & 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 is thc0404=1 & 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 is thc0303=1 & 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 is thc0202=1 & r2 & thc0315=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 is thc0101=1 & 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} is thc0000=1 & 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 with Rd occupying bits 0-2 # Rd0810 with Rd occupying bits 8-10 # Rm0305 with Rm occupying bits 3-5 # Rm0608 with Rm occupying bits 6-8 # Rn0002 with Rn occupying bits 0-2 # Rn0305 with Rn occupying bits 3-5 # Rn0810 with Rn occupying bits 8-10 # Hrd0002 with H1 bit in diagram # Hrn0002 with H1 bit in diagram # Hrm0305 with H2 bit in diagram # Rs0305 with Rs occupying bits 3-5 # Immed3 # # Immed5 # # Immed8 # # Pcrel8 PC,#*4 # Sprel8 SP,#*4 # Immed7_4 #*4 # thcc # Addr8 (for B) # Addr11 (for B no condition) # ThAddr22 (for double BL, BLX) # immed8 (no "#" as in BKPT and SWI) # Rn_exclaim ! # ldbrace (load instructions) # strbrace (store instructions) # RnIndirect4 [,#*4] # RnIndirect2 [,#*2] # RnIndirect1 [,#] # RnRmIndirect [,] # Pcrel8Indirect [PC,#*4] # Sprel8Indirect [SP,#*4] # # Ensure that the condition check phase has been completed with : ARMcondCk=1 { :adc^CheckInIT_CZNO^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^CheckInIT_CZNO^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^CheckInIT_CZNO^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^CheckInIT_CZNO^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^CheckInIT_ZN^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^CheckInIT_CZN^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^CheckInIT_CZN^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^CheckInIT_CZN^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 & thBitWidth { build ItCond; vmask:4 = (1 << thBitWidth) - 1; clear:4 = ~(vmask << thLsbImm); bits:4 = (Rn0003 & vmask) << thLsbImm; Rd0811 = (Rd0811 & clear) | bits; } @endif # VERSION_6T2 || VERSION_7 :bic^CheckInIT_ZN^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^thSBIT_ZN^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); call [dest]; } :bl^ItCond lr is TMode=1 & ItCond & op11=0x1f & offset11=0 & lr { build ItCond; local dest = lr; lr = inst_next|1; SetThumbMode(1); call [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]; } :blx^ItCond lr is TMode=1 & ItCond & op11=0x1d & offset11=0 & thc0000=0 & lr { build ItCond; local dest = (lr & (~0x3)); 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 ; SetThumbMode( (Rn0003&0x00000001)!=0 ); local tmp=Rn0003&0xfffffffe; goto [tmp]; } # 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) @ifndef CDE :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); } @endif #CDE 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 = lzcount(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^CheckInIT_ZN^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 } @ifndef CDE :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 # CDE @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; } # overlaps patterns with the other ldr intructions when Rn==1111, therefore it 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,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf8d & sop0003=15; Rt1215 & RtGotoCheck) & PcrelOffset12 { build ItCond; build PcrelOffset12; Rt1215 = PcrelOffset12:4; build RtGotoCheck; } :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,[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,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf81 & sop0003=15; Rt1215) & PcrelOffset12 { build ItCond; build PcrelOffset12; tmp:1 = PcrelOffset12:1; Rt1215 = zext(tmp); } # overlaps patterns with the other ldrb intructions when Rn==1111, therefore it must occur first :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,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,[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); } # overlaps patterns with the other ldrd intructions when Rn==1111, therefore it must occur first :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); } :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); } # pldw must come before ldrh.w because of overlap of Rt != 1111 in ldrh.w :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); } :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); } :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); } # overlaps patterns with the other ldrh intructions when Rn==1111, therefore it must occur first :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.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,[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); } # pli moevd above ldrsb to avoid conflict for ldrsb when Rt == 1111 :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); } # overlaps patterns with the other ldrsb intructions when Rn==1111, therefore it must occur first :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,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,[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); } # overlaps patterns with the other ldr intructions when Rn==1111, therefore it must occur first :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,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,[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^CheckInIT_CZN^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^CheckInIT_CZN^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^CheckInIT_CZN^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^CheckInIT_CZN^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^CheckInIT_CZN^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 @ifndef CDE :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); } @endif # CDE :mov^CheckInIT_ZN^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=4 & Rd0810 & Immed8 & CheckInIT_ZN { build ItCond; Rd0810 = Immed8; resflags(Rd0810); build CheckInIT_ZN; } :mov^CheckInIT_ZN^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); } @ifndef CDE :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); } :mrc^ItCond thcpn,thc0507,"APSR_nzcv",thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=1 & thCRn; Rt1215=15 & thcpn & thopcode2 & thc0404=1 & thCRm { build ItCond; t_cpn:4 = thcpn; t_op1:4 = thc0507; t_op2:4 = thopcode2; local tmp:4 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm); writeAPSR_nzcv(tmp); } :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); } :mrc2^ItCond thcpn,thc0507,"APSR_nzcv",thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thc0507 & thc0404=1 & thCRn; Rt1215=15 & thcpn & thopcode2 & thc0404=1 & thCRm { build ItCond; t_cpn:4 = thcpn; t_op1:4 = thc0507; t_op2:4 = thopcode2; local tmp:4 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm); writeAPSR_nzcv(tmp); } :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); } @endif #CDE @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 ; ipsr:4 = getCurrentExceptionNumber(); Rd0811 = Rd0811 | (ipsr & 0x1f); } mrsipsr: is thc0000=0 { } mrsepsr: "e" is thc0101=1 { } mrsepsr: is thc0101=0 { } mrsapsr: is thc0202=1 { } mrsapsr: "a" is thc0202=0 & Rd0811 { readAPSR_nzcvq(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 @if defined(CORTEX) define pcodeop setMainStackPointerLimit; :msr^ItCond msplim,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=10 & msplim { build ItCond; setMainStackPointerLimit(Rn0003); } define pcodeop setProcStackPointerLimit; :msr^ItCond psplim,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=11 & psplim { build ItCond; setProcStackPointerLimit(Rn0003); } define pcodeop getMainStackPointerLimit; :mrs^ItCond Rd0811,msplim is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=10 & msplim { build ItCond; Rd0811 = getMainStackPointerLimit(); } define pcodeop getProcessStackPointerLimit; :mrs^ItCond Rd0811,psplim is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=11 & psplim { build ItCond; Rd0811 = getProcessStackPointerLimit(); } @endif #CORTEX :mrs^ItCond Rd0811,cpsr is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=0 & cpsr { build ItCond; tmp:4 = 0; readAPSR_nzcvq(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_nzcvq(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_nzcvq(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^CheckInIT_ZN^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^CheckInIT_ZN^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^CheckInIT_ZN^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); } :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); } :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); } # pld.w moved above ldrh to avoid conflicts #pli moved above ldrsb @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^CheckInIT_CZNO^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^CheckInIT_CZN^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^CheckInIT_CZNO^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x106 & Rm0305 & Rd0002 & CheckInIT_CZNO { build ItCond; th_sub_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_sub_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_sub_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 s/ 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) @ifndef CDE :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); } @endif # CDE :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; } :strt^ItCond^".w" Rt1215,[Rn0003,Immed8] is TMode=1 & ItCond & op4=0xf84 & Rn0003; Rt1215 & thc0811=14 & Immed8 { build ItCond; local tmp = Rn0003 + Immed8; *tmp = Rt1215; } @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; local tmpRt = Rt1215; access:1 = hasExclusiveAccess(tmp); Rd0811 = 1; if (!access) goto inst_next; Rd0811 = 0; *tmp = tmpRt; } @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; local tmpRt = Rt1215; access:1 = hasExclusiveAccess(tmp); Rd0003 = 1; if (!access) goto inst_next; Rd0003 = 0; *tmp = tmpRt:1; } :strexh^ItCond Rd0003,Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & thc0811=15 & thc0407=5 & Rd0003 { build ItCond; local tmp = Rn0003; local tmpRt = Rt1215; access:1 = hasExclusiveAccess(tmp); Rd0003 = 1; if (!access) goto inst_next; Rd0003 = 0; *tmp = tmpRt:2; } :strexd^ItCond Rd0003,Rt1215,Rt0811,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & Rt0811 & thc0407=7 & Rd0003 { build ItCond; local tmp = Rn0003; local tmpRt = Rt1215; local tmpRt2 = Rt0811; access:1 = hasExclusiveAccess(tmp); Rd0003 = 1; if (!access) goto inst_next; Rd0003 = 0; *tmp = tmpRt; tmp = tmp + 4; *tmp = tmpRt2; } @endif # VERSION_7 :sub^CheckInIT_CZNO^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^CheckInIT_CZNO^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^CheckInIT_CZNO^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: [pc,Rm0003] is Rm0003 & thc0404=0 & pc { local tmp = Rm0003; tmp = inst_next + tmp; val:1 = *tmp; tmp = zext(val); export tmp; } Pcrel: [pc,Rm0003] is Rm0003 & thc0404=1 & pc { local tmp = Rm0003; tmp = inst_next + (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(); } @endif #VERSION_6T2 || VERSION_7 } # End with : ARMcondCk=1