diff options
Diffstat (limited to 'src/arm32/instruction_codec/encode_arm.rs')
-rw-r--r-- | src/arm32/instruction_codec/encode_arm.rs | 155 |
1 files changed, 81 insertions, 74 deletions
diff --git a/src/arm32/instruction_codec/encode_arm.rs b/src/arm32/instruction_codec/encode_arm.rs index 9c63f81..a24d2bd 100644 --- a/src/arm32/instruction_codec/encode_arm.rs +++ b/src/arm32/instruction_codec/encode_arm.rs @@ -27,6 +27,71 @@ use crate::arm32::{ Shifter, }; +use core::num::Wrapping; + +fn add_shifter(mut opcode: u32, shifter: Shifter) -> Result<u32> { + use Shifter::*; + + let get_shift_code = |shifter: Shifter| match shifter { + LogicalShiftLeftImmediate { .. } => 0b00, + LogicalShiftRightImmediate { .. } => 0b01, + ArithmeticShiftRightImmediate { .. } => 0b10, + RotateRightImmediate { .. } => 0b11, + + _ => panic!("cannot get shifter code of `{shifter:?}`"), + }; + + match shifter { + LogicalShiftLeftImmediate { source, shift: 0x0 } + => { + opcode |= source as u32; + } + + | ArithmeticShiftRightImmediate { source, shift } + | LogicalShiftLeftImmediate { source, shift } + | LogicalShiftRightImmediate { source, shift } + | RotateRightImmediate { source, shift } + => { + assert_or_err!(shift != 0x0, Error::IllegalImmediate { reason: "immediate shift cannot be null on arm" }); + + let code = get_shift_code(shifter); + + opcode |= source as u32; + opcode |= code << 0x5; + opcode |= shift << 0x7; + } + + RotateRightExtend { .. } => { + todo!() + } + + | ArithmeticShiftRightRegister { source, .. } + | LogicalShiftLeftRegister { source, .. } + | LogicalShiftRightRegister { source, .. } + | RotateRightRegister { source, .. } + => { + let _code = get_shift_code(shifter); + + opcode |= 0b00000000_00000000_00000000_00010000; + opcode |= source as u32; + } + + Immediate(source) => { + let (source, rotate) = if source <= 0xFF { + (source, 0x00) + } else { + todo!() + }; + + opcode |= 0b00000010_00000000_00000000_00000000; + opcode |= source; + opcode |= rotate << 0x8; + } + } + + Ok(opcode) +} + impl InstructionCodec { /// Encodes the given Arm instruction. /// @@ -45,7 +110,16 @@ impl InstructionCodec { } => { opcode |= 0b00001011_00000000_00000000_00000000; opcode |= (predicate as u32) << 0x1C; - }, + } + + BranchExchange { + predicate, + source, + } => { + opcode |= 0b00000001_00101111_11111111_00010000; + opcode |= source as u32; + opcode |= (predicate as u32) << 0x1C; + } BranchLink { predicate, @@ -53,7 +127,7 @@ impl InstructionCodec { } => { opcode |= 0b00001010_00000000_00000000_00000000; opcode |= (predicate as u32) << 0x1C; - }, + } Breakpoint { immediate, @@ -61,7 +135,7 @@ impl InstructionCodec { opcode |= 0b11100001_00100000_00000000_01110000; opcode |= immediate & 0b00000000_00000000_00000000_00001111; opcode |= (immediate & 0b00000000_00000000_11111111_11110000) << 0x4; - }, + } Move { predicate, @@ -75,7 +149,7 @@ impl InstructionCodec { opcode |= (predicate as u32) << 0x1C; opcode = add_shifter(opcode, source)?; - }, + } SoftwareInterrupt { predicate, @@ -84,80 +158,13 @@ impl InstructionCodec { opcode |= 0b00001111_00000000_00000000_00000000; opcode |= immediate & 0b00000000_11111111_11111111_11111111; opcode |= (predicate as u32) << 0x1C; - }, + } _ => todo!(), } - self.address += ArmOpcode::SIZE; - Ok(opcode.into()) - } -} - -fn add_shifter(mut opcode: u32, shifter: Shifter) -> Result<u32> { - use Shifter::*; - - match shifter { - LogicalShiftLeftImmediate { source, shift: 0x0 } - => { - opcode |= source as u32; - }, - - | ArithmeticShiftRightImmediate { source, shift } - | LogicalShiftLeftImmediate { source, shift } - | LogicalShiftRightImmediate { source, shift } - | RotateRightImmediate { source, shift } - => { - let code = match shifter { - LogicalShiftLeftImmediate { .. } => 0b00, - LogicalShiftRightImmediate { .. } => 0b01, - ArithmeticShiftRightImmediate { .. } => 0b10, - RotateRightImmediate { .. } => 0b11, - - _ => unreachable!(), - }; - - assert_or_err!(shift != 0x0, Error::IllegalImmediate); - - opcode |= source as u32; - opcode |= code << 0x5; - opcode |= shift << 0x7; - }, - - RotateRightExtend { .. } => { - todo!() - }, - - | ArithmeticShiftRightRegister { source, .. } - | LogicalShiftLeftRegister { source, .. } - | LogicalShiftRightRegister { source, .. } - | RotateRightRegister { source, .. } - => { - let _code = match shifter { - LogicalShiftLeftRegister { .. } => 0b00, - LogicalShiftRightRegister { .. } => 0b01, - ArithmeticShiftRightRegister { .. } => 0b10, - RotateRightRegister { .. } => 0b11, - - _ => unreachable!(), - }; + self.skip_words(0x1); - opcode |= 0b00000000_00000000_00000000_00010000; - opcode |= source as u32; - }, - - Immediate { source } => { - let (source, rotate) = if source <= 0xFF { - (source, 0x00) - } else { - todo!() - }; - - opcode |= 0b00000010_00000000_00000000_00000000; - opcode |= source; - opcode |= rotate << 0x8; - }, + Ok(opcode.into()) } - - Ok(opcode) } |