diff options
| author | iximeow <me@iximeow.net> | 2026-07-26 04:36:35 +0000 |
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2026-07-28 02:53:24 +0000 |
| commit | eea7a08447871114c86ad3c42945847336960d2c (patch) | |
| tree | fdaf3d29ba9f46eb690d832a2b3f1d23f3726a79 /src/armv7/thumb.rs | |
| parent | 82df9f3af144814889afb7e289d04dcc1ffa5dbf (diff) | |
some armv7/thumb arms are basically duplicate
Diffstat (limited to 'src/armv7/thumb.rs')
| -rw-r--r-- | src/armv7/thumb.rs | 361 |
1 files changed, 100 insertions, 261 deletions
diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs index 99ab46b..4424d44 100644 --- a/src/armv7/thumb.rs +++ b/src/armv7/thumb.rs @@ -2020,275 +2020,114 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d let size_bits = op1 & 0b011; let has_imm12 = op1 & 0b100 != 0; let op2 = (lower >> 6) & 0b111111; - match size_bits { - 0b00 => { - // `STRB_` - // op2 only selects a form when the imm12 bit is clear; - // otherwise it's just the high bits of imm12. - if !has_imm12 && op2 == 0 { - // `STRB (register)` (`A8-683`) - // encoding T2 - // v6T2 - let rm = (lower & 0b1111) as u8; - let imm2 = (lower >> 4) & 0b11; - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STRB; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - Operand::RegDerefPreindexRegShift( - Reg::from_u8(rn), - RegShift::from_raw( - // do things - 0b00000 | // imm shift - (imm2 << 7) | // imm - rm as u16 | // shiftee - (0b00 << 5) // shift style (lsl) - ), - true, // add - false, // wback - ), - Operand::Nothing, - Operand::Nothing, - ]; - } else if !has_imm12 && (op2 & 0b111100) == 0b111000 { - // `STRBT` (`A8-685`) - // v6T2 - let imm8 = lower & 0b1111_1111; - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STRBT; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - Operand::RegDerefPreindexOffset( - Reg::from_u8(rn), - imm8, - true, // add - false, // wback - ), - Operand::Nothing, - Operand::Nothing, - ]; - } else { - // `STRB (immediate, Thumb)` (`A8-679`) - // encoding T2/T3 - // v6T2 - let (imm, p, u, w) = if has_imm12 { - let imm12 = lower & 0b1111_1111_1111; - let p = true; - let u = true; - let w = false; - (imm12, p, u, w) - } else { - let imm8 = lower & 0b1111_1111; - let puw = (lower >> 8) & 0b111; - let p = puw & 0b100 != 0; - let u = puw & 0b010 != 0; - let w = puw & 0b001 != 0; - (imm8, p, u, w) - }; - // assert!(puw != 0b110) // would be `strbt` - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STRB; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - // do the puw - if p { - Operand::RegDerefPreindexOffset( - Reg::from_u8(rn), - imm, - u, // add - w, // wback - ) - } else { - Operand::RegDerefPostindexOffset( - Reg::from_u8(rn), - imm, - u, // add - w, // wback - ) - }, - Operand::Nothing, - Operand::Nothing, - ]; - } - } - 0b01 => { - // `STRH_` + + let (st_normal, st_unprivileged) = match size_bits { + 0b00 => (Opcode::STRB, Opcode::STRBT), + 0b01 => (Opcode::STRH, Opcode::STRHT), + // practically 0b10, 0b11 is skipped below. + _ => (Opcode::STR, Opcode::STRT), + }; + + if size_bits < 0b11 { + // store (privileged). STRB, STRH, STR. + // + // op2 only selects a form when the imm12 bit is clear; + // otherwise it's just the high bits of imm12. + if !has_imm12 && op2 == 0 { + // `STRB (register)` (`A8-683`) + // `STRH (register)` (`A8-703`) + // `STR (register)` (`A8-677`) + // encoding T2 // v6T2 - if !has_imm12 && op2 == 0 { - // `STRH (register)` (`A8-703`) - let rm = (lower & 0b1111) as u8; - let imm2 = (lower >> 4) & 0b11; - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STRH; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - Operand::RegDerefPreindexRegShift( - Reg::from_u8(rn), - RegShift::from_raw( - // do things - 0b00000 | // imm shift - (imm2 << 7) | // imm - rm as u16 | // shiftee - (0b00 << 5) // shift style (lsl) - ), - true, // add - false, // wback - ), - Operand::Nothing, - Operand::Nothing, - ]; - } else if !has_imm12 && (op2 & 0b111100) == 0b111000 { - // `STRHT` (`A8-705`) - let imm8 = lower & 0b1111_1111; - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STRHT; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - Operand::RegDerefPreindexOffset( - Reg::from_u8(rn), - imm8, - true, // add - false, // wback + let rm = (lower & 0b1111) as u8; + let imm2 = (lower >> 4) & 0b11; + let rt = ((lower >> 12) & 0b1111) as u8; + inst.opcode = st_normal; + inst.operands = [ + Operand::Reg(Reg::from_u8(rt)), + Operand::RegDerefPreindexRegShift( + Reg::from_u8(rn), + RegShift::from_raw( + // do things + 0b00000 | // imm shift + (imm2 << 7) | // imm + rm as u16 | // shiftee + (0b00 << 5) // shift style (lsl) ), - Operand::Nothing, - Operand::Nothing, - ]; + true, // add + false, // wback + ), + Operand::Nothing, + Operand::Nothing, + ]; + } else if !has_imm12 && (op2 & 0b111100) == 0b111000 { + // `STRBT` (`A8-685`) + // `STRHT` (`A8-705`) + // `STRT` (`A8-707`) + // v6T2 + let imm8 = lower & 0b1111_1111; + let rt = ((lower >> 12) & 0b1111) as u8; + inst.opcode = st_unprivileged; + inst.operands = [ + Operand::Reg(Reg::from_u8(rt)), + Operand::RegDerefPreindexOffset( + Reg::from_u8(rn), + imm8, + true, // add + false, // wback + ), + Operand::Nothing, + Operand::Nothing, + ]; + } else { + // `STRB (immediate, Thumb)` (`A8-679`), or + // `STRH (immediate, Thumb)` (`A8-699`) + // encoding T2/T3 + // .. or + // `STR (immediate, Thumb)` (`A8-673`) + // encoding T3/T4 + // v6T2 + let (imm, p, u, w) = if has_imm12 { + let imm12 = lower & 0b1111_1111_1111; + let p = true; + let u = true; + let w = false; + (imm12, p, u, w) } else { - // `STRH (immediate, Thumb)` (`A8-699`) - // encoding T2/T3 - // v6T2 - let (imm, p, u, w) = if has_imm12 { - let imm12 = lower & 0b1111_1111_1111; - let p = true; - let u = true; - let w = false; - (imm12, p, u, w) - } else { - let imm8 = lower & 0b1111_1111; - let puw = (lower >> 8) & 0b111; - let p = puw & 0b100 != 0; - let u = puw & 0b010 != 0; - let w = puw & 0b001 != 0; - (imm8, p, u, w) - }; - // assert!(puw != 0b110) // would be `strbt` - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STRH; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - // do the puw - if p { - Operand::RegDerefPreindexOffset( - Reg::from_u8(rn), - imm, - u, // add - w, // wback - ) - } else { - Operand::RegDerefPostindexOffset( - Reg::from_u8(rn), - imm, - u, // add - w, // wback - ) - }, - Operand::Nothing, - Operand::Nothing, - ]; - } - } - 0b10 => { - // `STR_` - if !has_imm12 && op2 == 0 { - // `STR (register)` (`A8-677`) - // v6T2 - let rm = (lower & 0b1111) as u8; - let imm2 = (lower >> 4) & 0b11; - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STR; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - Operand::RegDerefPreindexRegShift( - Reg::from_u8(rn), - RegShift::from_raw( - // do things - 0b00000 | // imm shift - (imm2 << 7) | // imm - rm as u16 | // shiftee - (0b00 << 5) // shift style (lsl) - ), - true, // add - false, // wback - ), - Operand::Nothing, - Operand::Nothing, - ]; - } else if !has_imm12 && (op2 & 0b111100) == 0b111000 { - // `STRT` (`A8-707`) let imm8 = lower & 0b1111_1111; - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STRT; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), + let puw = (lower >> 8) & 0b111; + let p = puw & 0b100 != 0; + let u = puw & 0b010 != 0; + let w = puw & 0b001 != 0; + (imm8, p, u, w) + }; + // assert!(puw != 0b110) // would be `strbt` + let rt = ((lower >> 12) & 0b1111) as u8; + inst.opcode = st_normal; + inst.operands = [ + Operand::Reg(Reg::from_u8(rt)), + // do the puw + if p { Operand::RegDerefPreindexOffset( Reg::from_u8(rn), - imm8, - true, // add - false, // wback - ), - Operand::Nothing, - Operand::Nothing, - ]; - } else { - // `STR (immediate, Thumb)` (`A8-673`) - // encoding T3/T4 - // v6T2 - let (imm, p, u, w) = if has_imm12 { - let imm12 = lower & 0b1111_1111_1111; - let p = true; - let u = true; - let w = false; - (imm12, p, u, w) + imm, + u, // add + w, // wback + ) } else { - let imm8 = lower & 0b1111_1111; - let puw = (lower >> 8) & 0b111; - let p = puw & 0b100 != 0; - let u = puw & 0b010 != 0; - let w = puw & 0b001 != 0; - (imm8, p, u, w) - }; - // assert!(puw != 0b110) // would be `strbt` - let rt = ((lower >> 12) & 0b1111) as u8; - inst.opcode = Opcode::STR; - inst.operands = [ - Operand::Reg(Reg::from_u8(rt)), - // do the puw - if p { - Operand::RegDerefPreindexOffset( - Reg::from_u8(rn), - imm, - u, // add - w, // wback - ) - } else { - Operand::RegDerefPostindexOffset( - Reg::from_u8(rn), - imm, - u, // add - w, // wback - ) - }, - Operand::Nothing, - Operand::Nothing, - ]; - } - } - 0b11 => { - return Err(DecodeError::Undefined); - } - _ => { - unreachable!("impossible bit pattern"); + Operand::RegDerefPostindexOffset( + Reg::from_u8(rn), + imm, + u, // add + w, // wback + ) + }, + Operand::Nothing, + Operand::Nothing, + ]; } + } else { + return Err(DecodeError::Undefined); } } else { // `Advanced SIMD element or structure load/store instructions` |
