diff options
-rw-r--r-- | src/armv8/a64.rs | 84 |
1 files changed, 23 insertions, 61 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index d1672c4..a33bc7a 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -7517,70 +7517,32 @@ impl Decoder<ARMv8> for InstDecoder { let immr = (word >> 16) & 0x3f; let N = (word >> 22) & 0x1; - let sf_opc = word >> 29; + let opc = word >> 29 & 0b11; + let sf = word >> 31 & 1; - let size = match sf_opc { - 0b000 => { - if N == 0 { - inst.opcode = Opcode::SBFM; - } else { - inst.opcode = Opcode::Invalid; - } - SizeCode::W - } - 0b001 => { - if N == 0 { - inst.opcode = Opcode::BFM; - } else { - inst.opcode = Opcode::Invalid; - } - SizeCode::W - } - 0b010 => { - if N == 0 { - inst.opcode = Opcode::UBFM; - } else { - inst.opcode = Opcode::Invalid; - } - SizeCode::W - } - 0b011 => { - inst.opcode = Opcode::Invalid; - SizeCode::W - } - 0b100 => { - if N == 1 { - inst.opcode = Opcode::SBFM; - } else { - inst.opcode = Opcode::Invalid; - } - SizeCode::X - } - 0b101 => { - if N == 1 { - inst.opcode = Opcode::BFM; - } else { - inst.opcode = Opcode::Invalid; - } - SizeCode::X - } - 0b110 => { - if N == 1 { - inst.opcode = Opcode::UBFM; - } else { - inst.opcode = Opcode::Invalid; - } - SizeCode::X - } - 0b111 => { - inst.opcode = Opcode::Invalid; - SizeCode::X - } - _ => { - unreachable!("size and opc are three bits"); - } + let opc = &[ + Ok(Opcode::SBFM), + Ok(Opcode::BFM), + Ok(Opcode::UBFM), + Err(DecodeError::InvalidOpcode) + ][opc as usize]?; + + inst.opcode = *opc; + + let size = if sf == 0 { + SizeCode::W + } else { + SizeCode::X }; + if sf != N { + return Err(DecodeError::InvalidOpcode); + } + + if sf == 0 && (immr >= 32 || imms >= 32) { + return Err(DecodeError::InvalidOpcode); + } + inst.operands = [ Operand::Register(size, Rd as u16), Operand::Register(size, Rn as u16), |