summaryrefslogtreecommitdiff
path: root/src/arm32/instruction_codec/encode_arm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/arm32/instruction_codec/encode_arm.rs')
-rw-r--r--src/arm32/instruction_codec/encode_arm.rs155
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)
}