summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs35
-rw-r--r--tests/from_brain.rs128
2 files changed, 118 insertions, 45 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 4d1a65c..28f7865 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1137,7 +1137,7 @@ pub enum Operand {
RegShiftedReg { base: u8, index: u8, shift: u8 },
- RegShiftOffset { base: u8, shift: u8, offset: i16 },
+ RegShiftOffset { base: u8, shift: u8, offset: u32 },
ImmU8 { imm: u8 },
@@ -4253,9 +4253,14 @@ fn decode_instruction<
let u2 = (inst >> 5) & 0b11;
let u4 = (inst >> 8) & 0b1111;
- let uuuuuu = (u2 | (u4 << 2)) as i16;
+ let uuuuuu = u2 | (u4 << 2);
- handler.on_source_decoded(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset: uuuuuu })?;
+ handler.on_source_decoded(
+ Operand::with_extension(uuuuuu, extender,
+ |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
+ |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
+ )?
+ )?;
}
}
0b101 => {
@@ -4283,9 +4288,14 @@ fn decode_instruction<
let u2 = (inst >> 5) & 0b11;
let u4 = (inst >> 8) & 0b1111;
- let uuuuuu = (u2 | (u4 << 2)) as i16;
+ let uuuuuu = u2 | (u4 << 2);
- handler.on_source_decoded(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset: uuuuuu })?;
+ handler.on_source_decoded(
+ Operand::with_extension(uuuuuu, extender,
+ |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
+ |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: ii, offset }),
+ )?
+ )?;
}
}
0b110 => {
@@ -4329,7 +4339,11 @@ fn decode_instruction<
let dotnew = (inst >> 12) & 0b1 != 0;
handler.inst_predicated(tt as u8, negated, dotnew)?;
- handler.on_source_decoded(Operand::imm_u32(iiiiii as u32))?;
+ handler.on_source_decoded(
+ Operand::immext(iiiiii as u32, extender, |i6| {
+ Ok(Operand::imm_u32(iiiiii as u32))
+ })?
+ )?;
if !wide {
handler.on_dest_decoded(Operand::gpr(ddddd))?;
} else {
@@ -4630,7 +4644,7 @@ fn decode_instruction<
let iiii = (inst >> 3) & 0b1111;
let dotnew = (inst >> 7) & 1 == 1;
decode_store_ops(handler, minbits, ttttt, |shamt| {
- Ok(Operand::RegOffset { base: xxxxx, offset: iiii << shamt })
+ Ok(Operand::RegOffsetInc { base: xxxxx, offset: iiii << shamt })
})?;
handler.inst_predicated(vv as u8, negated, dotnew)?;
}
@@ -4650,9 +4664,12 @@ fn decode_instruction<
let i_hi = (inst >> 13) & 1;
let i_lo = (inst >> 6) & 1;
let i = ((i_hi << 1) | i_lo) as u8;
- let uuuuuu = (inst & 0b111111) as i16;
+ let uuuuuu = inst & 0b111111;
decode_store_ops(handler, minbits, ttttt, |_shamt| {
- Ok(Operand::RegShiftOffset { base: xxxxx, shift: i, offset: uuuuuu })
+ Operand::with_extension(uuuuuu, extender,
+ |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: i, offset }),
+ |offset| Ok(Operand::RegShiftOffset { base: xxxxx, shift: i, offset }),
+ )
})?;
}
},
diff --git a/tests/from_brain.rs b/tests/from_brain.rs
index ca3bbe4..334dc82 100644
--- a/tests/from_brain.rs
+++ b/tests/from_brain.rs
@@ -29,7 +29,7 @@ fn extenders() {
* [ ]: if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (Rs + ##U32)
* [x]: Rd = mem{b,ub,h,uh,w,d} (Rs + ##U32)
* [x]: Rd = mem{b,ub,h,uh,w,d} (Re=##U32)
- * [ ]: Rd = mem{b,ub,h,uh,w,d} (Rt<<#u2 + ##U32)
+ * [x]: Rd = mem{b,ub,h,uh,w,d} (Rt<<#u2 + ##U32)
* [ ]: if ([!]Pt[.new]) Rd = mem{b,ub,h,uh,w,d} (##U32)
* // it turns out these are encoded by applying an extender to the `mem{b,ub,...}(gp+#u16)` forms
* [x]: mem{b,h,w,d}(##U32) = Rs[.new]
@@ -37,7 +37,7 @@ fn extenders() {
* [ ]: if ([!]Pt[.new]) mem{b,h,w,d}(Rs + ##U32) = Rt[.new]
* [x]: mem{b,h,w,d}(Rs + ##U32) = Rt[.new]
* [x]: mem{b,h,w,d}(Rd=##U32) = Rt[.new]
- * [ ]: mem{b,h,w,d}(Ru<<#u2 + ##U32) = Rt[.new]
+ * [x]: mem{b,h,w,d}(Ru<<#u2 + ##U32) = Rt[.new]
* [ ]: if ([!]Pt[.new]) mem{b,h,w,d}(##U32) = Rt[.new]
* [ ]: [if [!]Ps] memw(Rs + #u6) = ##U32 // constant store
* [ ]: memw(Rs + Rt<<#u2) = ##U32 // constant store
@@ -286,6 +286,62 @@ fn extenders() {
test_display(&[
0x08, 0x40, 0x00, 0x00,
+ 0xe6, 0xd3, 0x05, 0x9d,
+ ], "{ r6 = memb(r5<<1 + 0x20f) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xe6, 0xd3, 0x25, 0x9d,
+ ], "{ r6 = memub(r5<<1 + 0x20f) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xe6, 0xd3, 0x45, 0x9d,
+ ], "{ r6 = memh(r5<<1 + 0x20f) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xe6, 0xd3, 0x65, 0x9d,
+ ], "{ r6 = memuh(r5<<1 + 0x20f) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xe6, 0xd3, 0x85, 0x9d,
+ ], "{ r6 = memw(r5<<1 + 0x20f) }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xe6, 0xd3, 0xc5, 0x9d,
+ ], "{ r7:6 = memd(r5<<1 + 0x20f) }");
+
+
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xcf, 0xc6, 0x04, 0xad,
+ ], "{ memb(r4<<1 + 0x20f) = r6 }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xcf, 0xc6, 0x44, 0xad,
+ ], "{ memh(r4<<1 + 0x20f) = r6 }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xcf, 0xc6, 0x84, 0xad,
+ ], "{ memw(r4<<1 + 0x20f) = r6 }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xcf, 0xc6, 0xa4, 0xad,
+ ], "{ memb(r4<<1 + 0x20f) = r6.new }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xcf, 0xce, 0xa4, 0xad,
+ ], "{ memh(r4<<1 + 0x20f) = r6.new }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xcf, 0xd6, 0xa4, 0xad,
+ ], "{ memw(r4<<1 + 0x20f) = r6.new }");
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
+ 0xc7, 0xc6, 0xc4, 0xad,
+ ], "{ memd(r4<<1 + 0x207) = r7:6 }");
+
+
+ test_display(&[
+ 0x08, 0x40, 0x00, 0x00,
0x0f, 0xc6, 0x00, 0x48,
], "{ memb(##0x20f) = r6 }");
test_display(&[
@@ -1250,44 +1306,44 @@ fn inst_1010() {
test_display(&0b1010_1011110_00010_11_0_00100_101_01001u32.to_le_bytes(), "{ memd(r2=#0x29) = r5:4 }");
test_invalid(&0b1010_1011111_00010_11_0_00100_101_01001u32.to_le_bytes(), DecodeError::InvalidOpcode);
- test_display(&0b1010_1011000_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memb(r2+#9) = r4 }");
- test_display(&0b1010_1011000_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memb(r2+#9) = r4 }");
- test_display(&0b1010_1011010_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memh(r2+#18) = r4 }");
- test_display(&0b1010_1011010_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memh(r2+#18) = r4 }");
- test_display(&0b1010_1011011_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memh(r2+#18) = r4.h }");
- test_display(&0b1010_1011011_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memh(r2+#18) = r4.h }");
- test_display(&0b1010_1011100_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memw(r2+#36) = r4 }");
- test_display(&0b1010_1011100_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memw(r2+#36) = r4 }");
-
- test_display(&0b1010_1011000_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memb(r2+#9) = r4 }");
- test_display(&0b1010_1011000_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memb(r2+#9) = r4 }");
- test_display(&0b1010_1011010_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memh(r2+#18) = r4 }");
- test_display(&0b1010_1011010_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memh(r2+#18) = r4 }");
- test_display(&0b1010_1011011_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memh(r2+#18) = r4.h }");
- test_display(&0b1010_1011011_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memh(r2+#18) = r4.h }");
- test_display(&0b1010_1011100_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memw(r2+#36) = r4 }");
- test_display(&0b1010_1011100_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memw(r2+#36) = r4 }");
-
- test_display(&0b1010_1011101_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memb(r2+#9) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memb(r2+#9) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memb(r2+#9) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memb(r2+#9) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_01100_010_01011u32.to_le_bytes(), "{ if (p3) memh(r2+#18) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_01100_010_01111u32.to_le_bytes(), "{ if (!p3) memh(r2+#18) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_01100_110_01011u32.to_le_bytes(), "{ if (p3.new) memh(r2+#18) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_01100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memh(r2+#18) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_10100_010_01011u32.to_le_bytes(), "{ if (p3) memw(r2+#36) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_10100_010_01111u32.to_le_bytes(), "{ if (!p3) memw(r2+#36) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_10100_110_01011u32.to_le_bytes(), "{ if (p3.new) memw(r2+#36) = r4.new }");
- test_display(&0b1010_1011101_00010_11_1_10100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memw(r2+#36) = r4.new }");
+ test_display(&0b1010_1011000_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memb(r2++#0x9) = r4 }");
+ test_display(&0b1010_1011000_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memb(r2++#0x9) = r4 }");
+ test_display(&0b1010_1011010_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memh(r2++#0x12) = r4 }");
+ test_display(&0b1010_1011010_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memh(r2++#0x12) = r4 }");
+ test_display(&0b1010_1011011_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memh(r2++#0x12) = r4.h }");
+ test_display(&0b1010_1011011_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memh(r2++#0x12) = r4.h }");
+ test_display(&0b1010_1011100_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memw(r2++#0x24) = r4 }");
+ test_display(&0b1010_1011100_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memw(r2++#0x24) = r4 }");
+
+ test_display(&0b1010_1011000_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memb(r2++#0x9) = r4 }");
+ test_display(&0b1010_1011000_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memb(r2++#0x9) = r4 }");
+ test_display(&0b1010_1011010_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memh(r2++#0x12) = r4 }");
+ test_display(&0b1010_1011010_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memh(r2++#0x12) = r4 }");
+ test_display(&0b1010_1011011_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memh(r2++#0x12) = r4.h }");
+ test_display(&0b1010_1011011_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memh(r2++#0x12) = r4.h }");
+ test_display(&0b1010_1011100_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memw(r2++#0x24) = r4 }");
+ test_display(&0b1010_1011100_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memw(r2++#0x24) = r4 }");
+
+ test_display(&0b1010_1011101_00010_11_1_00100_010_01011u32.to_le_bytes(), "{ if (p3) memb(r2++#0x9) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_00100_010_01111u32.to_le_bytes(), "{ if (!p3) memb(r2++#0x9) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_00100_110_01011u32.to_le_bytes(), "{ if (p3.new) memb(r2++#0x9) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_00100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memb(r2++#0x9) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_01100_010_01011u32.to_le_bytes(), "{ if (p3) memh(r2++#0x12) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_01100_010_01111u32.to_le_bytes(), "{ if (!p3) memh(r2++#0x12) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_01100_110_01011u32.to_le_bytes(), "{ if (p3.new) memh(r2++#0x12) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_01100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memh(r2++#0x12) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_10100_010_01011u32.to_le_bytes(), "{ if (p3) memw(r2++#0x24) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_10100_010_01111u32.to_le_bytes(), "{ if (!p3) memw(r2++#0x24) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_10100_110_01011u32.to_le_bytes(), "{ if (p3.new) memw(r2++#0x24) = r4.new }");
+ test_display(&0b1010_1011101_00010_11_1_10100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memw(r2++#0x24) = r4.new }");
test_invalid(&0b1010_1011101_00010_11_1_11100_010_01011u32.to_le_bytes(), DecodeError::InvalidOpcode);
test_invalid(&0b1010_1011101_00010_11_1_11100_010_01111u32.to_le_bytes(), DecodeError::InvalidOpcode);
test_invalid(&0b1010_1011101_00010_11_1_11100_110_01011u32.to_le_bytes(), DecodeError::InvalidOpcode);
test_invalid(&0b1010_1011101_00010_11_1_11100_110_01111u32.to_le_bytes(), DecodeError::InvalidOpcode);
- test_display(&0b1010_1011110_00010_11_1_10100_010_01011u32.to_le_bytes(), "{ if (p3) memd(r2+#72) = r21:20 }");
- test_display(&0b1010_1011110_00010_11_1_10100_010_01111u32.to_le_bytes(), "{ if (!p3) memd(r2+#72) = r21:20 }");
- test_display(&0b1010_1011110_00010_11_1_10100_110_01011u32.to_le_bytes(), "{ if (p3.new) memd(r2+#72) = r21:20 }");
- test_display(&0b1010_1011110_00010_11_1_10100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memd(r2+#72) = r21:20 }");
+ test_display(&0b1010_1011110_00010_11_1_10100_010_01011u32.to_le_bytes(), "{ if (p3) memd(r2++#0x48) = r21:20 }");
+ test_display(&0b1010_1011110_00010_11_1_10100_010_01111u32.to_le_bytes(), "{ if (!p3) memd(r2++#0x48) = r21:20 }");
+ test_display(&0b1010_1011110_00010_11_1_10100_110_01011u32.to_le_bytes(), "{ if (p3.new) memd(r2++#0x48) = r21:20 }");
+ test_display(&0b1010_1011110_00010_11_1_10100_110_01111u32.to_le_bytes(), "{ if (!p3.new) memd(r2++#0x48) = r21:20 }");
test_display(&0b1010_1101000_00010_11_1_00110_001_01001u32.to_le_bytes(), "{ memb(r2++m1) = r6 }");
test_invalid(&0b1010_1101001_00010_11_1_00110_001_01001u32.to_le_bytes(), DecodeError::InvalidOpcode);