@@ -311,10 +311,12 @@ pub enum Instruction {
311311 rd : u8 ,
312312 rm : u8 ,
313313 } ,
314- /// Wide register-extend (T2): {S,U}XT{B,H}.W Rd, Rm, ROR #rotate.
315- /// `rotate` is 0/8/16/24 (applied to Rm before the extract).
314+ /// Wide register-extend (T2): {S,U}XT{B,H}.W and the extend-and-add
315+ /// {S,U}XTA{B,H}.W. `Rd = (Rn==0xF ? 0 : Rn) + extend(ROR(Rm, rotate))`.
316+ /// `rotate` is 0/8/16/24; `rn`==0xF means the plain extend (no add).
316317 ExtendW {
317318 rd : u8 ,
319+ rn : u8 ,
318320 rm : u8 ,
319321 rotate : u8 ,
320322 /// 0=SXTH, 1=UXTH, 4=SXTB, 5=UXTB (ARM op field h1[6:4]).
@@ -1474,20 +1476,28 @@ pub fn decode_thumb_32(h1: u16, h2: u16) -> Instruction {
14741476 }
14751477 }
14761478
1477- // Register-extend, wide (T2): SXTH.W/UXTH.W/SXTB.W/UXTB.W Rd, Rm{, ROR #r}.
1478- // h1 = 1111 1010 0 op 1111 (Rn=0xF, no add); op: 000=SXTH 001=UXTH
1479- // 100=SXTB 101=UXTB (010/011 = SXTB16/UXTB16, not modeled).
1479+ // Register-extend, wide (T2): the plain {S,U}XT{B,H}.W (Rn=0xF) and the
1480+ // extend-and-add {S,U}XTA{B,H}.W (Rn!=0xF).
1481+ // h1 = 1111 1010 0 op nnnn ; op: 000=SXT(A)H 001=UXT(A)H 100=SXT(A)B
1482+ // 101=UXT(A)B (010/011 = ..B16, not modeled). nnnn = Rn (0xF = no add).
14801483 // h2 = 1111 dddd 10 rr mmmm (rr = rotate/8).
1481- // clang emits e.g. `uxth.w r2, ip` = FA1F F28C when extending via a high
1482- // register; without this the insn decoded to Unknown32 and was skipped,
1483- // leaving the destination register stale.
1484- if ( h1 & 0xFF8F ) == 0xFA0F && ( h2 & 0xF080 ) == 0xF080 {
1484+ // clang emits e.g. `uxth.w r2, ip` = FA1F F28C (extend via high register)
1485+ // and `uxtah r6, r3, r0` = FA13 F680 (4 + path_len). Without this the insn
1486+ // decoded to Unknown32 and was skipped, leaving Rd stale.
1487+ if ( h1 & 0xFF80 ) == 0xFA00 && ( h2 & 0xF080 ) == 0xF080 {
1488+ let rn = ( h1 & 0xF ) as u8 ;
14851489 let rd = ( ( h2 >> 8 ) & 0xF ) as u8 ;
14861490 let rm = ( h2 & 0xF ) as u8 ;
14871491 let rotate = ( ( ( h2 >> 4 ) & 0x3 ) * 8 ) as u8 ;
14881492 let op = ( ( h1 >> 4 ) & 0x7 ) as u8 ;
14891493 if op == 0b000 || op == 0b001 || op == 0b100 || op == 0b101 {
1490- return Instruction :: ExtendW { rd, rm, rotate, op } ;
1494+ return Instruction :: ExtendW {
1495+ rd,
1496+ rn,
1497+ rm,
1498+ rotate,
1499+ op,
1500+ } ;
14911501 }
14921502 }
14931503
0 commit comments