summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/display.rs11
-rw-r--r--src/lib.rs20
-rw-r--r--tests/from_brain.rs105
3 files changed, 124 insertions, 12 deletions
diff --git a/src/display.rs b/src/display.rs
index 3074701..1d1e1ae 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -340,18 +340,23 @@ impl fmt::Display for Instruction {
}
if needs_parens { f.write_str(")")?; }
+ // ... vxaddsubh has the right shift after round, but cmpyiwh and friends have the left
+ // shift before round.
+ if let Some(shift) = self.flags.shift_left {
+ write!(f, ":<<{}", shift)?;
+ }
if let Some(mode) = self.flags.rounded {
write!(f, "{}", mode.as_label())?;
}
if self.flags.chop {
f.write_str(":chop")?;
}
- if let Some(shift) = self.flags.shift_left {
- write!(f, ":<<{}", shift)?;
- }
if let Some(shift) = self.flags.shift_right {
write!(f, ":>>{}", shift)?;
}
+ if self.flags.carry {
+ f.write_str(":carry")?;
+ }
if self.flags.saturate {
f.write_str(":sat")?;
}
diff --git a/src/lib.rs b/src/lib.rs
index 650c7f9..7f95ad6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -822,6 +822,10 @@ pub enum Opcode {
Vrmpyu,
Vrmpysu,
+ // `Rd=addasl(Rt,Rs,#u3)` sure makes this look like it should not have special
+ // display rules. but wth?
+ AddAsl,
+
AndAnd = 0x8000,
AndOr,
OrAnd,
@@ -837,7 +841,6 @@ pub enum Opcode {
AddLsr,
SubLsr,
AddLsl,
- AddAsl,
SubAsl,
AndAsl,
OrAsl,
@@ -4641,12 +4644,12 @@ fn decode_instruction<
let minbits = (inst >> 5) & 0b111;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
- handler.on_source_decoded(Operand::gpr(sssss))?;
if minbits < 0b100 {
opcode_check!(minbits == 0b010);
handler.on_opcode_decoded(Opcode::Vasrw)?;
- handler.on_dest_decoded(Operand::gpr(ttttt))?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_source_decoded(Operand::gpr(ttttt))?;
} else {
handler.shift_left(1)?;
handler.rounded(RoundingMode::Round)?;
@@ -4656,11 +4659,11 @@ fn decode_instruction<
} else {
handler.on_opcode_decoded(Opcode::Cmpyrwh)?;
}
+ handler.on_source_decoded(Operand::gprpair(sssss)?)?;
if minbits & 0b001 == 0 {
handler.on_source_decoded(Operand::gpr(ttttt))?;
} else {
- panic!("star?");
-// handler.on_source_decoded(Operand::gprstar(ttttt))?;
+ handler.on_source_decoded(Operand::gpr_conjugate(ttttt))?;
}
}
}
@@ -4692,7 +4695,7 @@ fn decode_instruction<
handler.on_opcode_decoded(Opcode::Lsl)?;
},
0b1011 => {
- let i_hi = reg_b8(inst);
+ let i_hi = reg_b16(inst);
let i_lo = ((inst >> 5) & 1) as u8;
let i6 = i_lo | (i_hi << 1);
let i6 = i6 as i8;
@@ -4795,6 +4798,7 @@ fn decode_instruction<
}
0b1010 => {
let minbits = (inst >> 21) & 0b111;
+ opcode_check!(inst & 0b0010_0000_0000_0000 == 0);
if minbits & 0b100 == 0 {
handler.on_opcode_decoded(Opcode::Insert)?;
handler.on_dest_decoded(Operand::gprpair(reg_b0(inst))?)?;
@@ -6261,7 +6265,7 @@ fn decode_instruction<
}
if rtt_star {
- panic!("rtt_star");
+ handler.on_source_decoded(Operand::gpr_conjugate(ttttt))?;
} else {
handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
}
@@ -6413,7 +6417,7 @@ fn decode_instruction<
if op_hi & 0b010 == 0 {
handler.on_dest_decoded(Operand::gpr(reg_b8(inst)))?;
} else {
- todo!("reg rt_star");
+ handler.on_source_decoded(Operand::gpr_conjugate(reg_b8(inst)))?;
}
handler.rounded(RoundingMode::Round)?;
handler.saturate()?;
diff --git a/tests/from_brain.rs b/tests/from_brain.rs
index 55c231e..5be4a5c 100644
--- a/tests/from_brain.rs
+++ b/tests/from_brain.rs
@@ -1073,7 +1073,110 @@ fn inst_1100() {
test_display(&0b1100_0001_110_10100_11_000110_100_10110u32.to_le_bytes(), "{ R23:22 = extractu(R21:20, R7:6) }");
test_display(&0b1100_0001_110_10100_11_000110_110_10110u32.to_le_bytes(), "{ R23:22 = decbin(R21:20, R7:6) }");
-// test_display(&0b1100_0011110_10100_11_000110_011_10110u32.to_le_bytes(), "{ R23:22 = vcnegh(R21:20, R6) }");
+ test_display(&0b1100_0010_000_10100_11_000110_001_10110u32.to_le_bytes(), "{ R23:22 = valignb(R7:6, R21:20, P1) }");
+ test_display(&0b1100_0010_001_10100_11_000110_001_10110u32.to_le_bytes(), "{ R23:22 = valignb(R7:6, R21:20, P1) }");
+ test_display(&0b1100_0010_010_10100_11_000110_001_10110u32.to_le_bytes(), "{ R23:22 = valignb(R7:6, R21:20, P1) }");
+ test_display(&0b1100_0010_011_10100_11_000110_001_10110u32.to_le_bytes(), "{ R23:22 = valignb(R7:6, R21:20, P1) }");
+ test_display(&0b1100_0010_100_10100_11_000110_001_10110u32.to_le_bytes(), "{ R23:22 = vspliceb(R21:20, R7:6, P1) }");
+ test_invalid(&0b1100_0010_101_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0010_110_10100_11_000110_001_10110u32.to_le_bytes(), "{ R23:22 = add(R21:20, R7:6, P1):carry }");
+ test_display(&0b1100_0010_111_10100_11_000110_001_10110u32.to_le_bytes(), "{ R23:22 = sub(R21:20, R7:6, P1):carry }");
+
+ test_display(&0b1100_0011_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R23:22 = vasrw(R21:20, R6) }");
+ test_display(&0b1100_0011_000_10100_11_000110_010_10110u32.to_le_bytes(), "{ R23:22 = vlsrw(R21:20, R6) }");
+ test_display(&0b1100_0011_000_10100_11_000110_100_10110u32.to_le_bytes(), "{ R23:22 = vaslw(R21:20, R6) }");
+ test_display(&0b1100_0011_000_10100_11_000110_110_10110u32.to_le_bytes(), "{ R23:22 = vlslw(R21:20, R6) }");
+ test_display(&0b1100_0011_010_10100_11_000110_000_10110u32.to_le_bytes(), "{ R23:22 = vasrh(R21:20, R6) }");
+ test_display(&0b1100_0011_010_10100_11_000110_010_10110u32.to_le_bytes(), "{ R23:22 = vlsrh(R21:20, R6) }");
+ test_display(&0b1100_0011_010_10100_11_000110_100_10110u32.to_le_bytes(), "{ R23:22 = vaslh(R21:20, R6) }");
+ test_display(&0b1100_0011_010_10100_11_000110_110_10110u32.to_le_bytes(), "{ R23:22 = vlslh(R21:20, R6) }");
+ test_display(&0b1100_0011_100_10100_11_000110_000_10110u32.to_le_bytes(), "{ R23:22 = asr(R21:20, R6) }");
+ test_display(&0b1100_0011_100_10100_11_000110_010_10110u32.to_le_bytes(), "{ R23:22 = lsr(R21:20, R6) }");
+ test_display(&0b1100_0011_100_10100_11_000110_100_10110u32.to_le_bytes(), "{ R23:22 = asl(R21:20, R6) }");
+ test_display(&0b1100_0011_100_10100_11_000110_110_10110u32.to_le_bytes(), "{ R23:22 = lsl(R21:20, R6) }");
+
+ test_display(&0b1100_0011_110_10100_11_000110_000_10110u32.to_le_bytes(), "{ R23:22 = vcrotate(R21:20, R6) }");
+ test_display(&0b1100_0011_110_10100_11_000110_010_10110u32.to_le_bytes(), "{ R23:22 = vcnegh(R21:20, R6) }");
+ test_invalid(&0b1100_0011_110_10100_11_000110_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0011_110_10100_11_100110_110_10110u32.to_le_bytes(), "{ R23:22 = vrcrotate(R21:20, R6, #0x2) }");
+
+ test_display(&0b1100_0100_000_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 = addasl(R6, R20, #0x3) }");
+ test_invalid(&0b1100_0100_001_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0100_011_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0100_101_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0100_111_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+
+ test_invalid(&0b1100_0101_000_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0101_000_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0101_000_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = vasrw(R20, R6) }");
+ test_invalid(&0b1100_0101_000_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0101_000_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = cmpyiwh(R21:20, R6):<<1:rnd:sat }");
+ test_display(&0b1100_0101_000_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 = cmpyiwh(R21:20, R6*):<<1:rnd:sat }");
+ test_display(&0b1100_0101_000_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = cmpyrwh(R21:20, R6):<<1:rnd:sat }");
+ test_display(&0b1100_0101_000_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = cmpyrwh(R21:20, R6*):<<1:rnd:sat }");
+
+ test_display(&0b1100_0110_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = asr(R20, R6):sat }");
+ test_invalid(&0b1100_0110_000_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0110_000_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = asl(R20, R6):sat }");
+ test_invalid(&0b1100_0110_000_10100_11_000110_110_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0110_010_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = asr(R20, R6) }");
+ test_display(&0b1100_0110_010_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = lsr(R20, R6) }");
+ test_display(&0b1100_0110_010_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = asl(R20, R6) }");
+ test_display(&0b1100_0110_010_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = lsl(R20, R6) }");
+
+ test_invalid(&0b1100_0110_100_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0110_100_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0110_100_10100_11_000110_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0110_100_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = lsl(#-24, R6) }");
+ test_display(&0b1100_0110_100_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = lsl(#-23, R6) }");
+
+ test_display(&0b1100_0110_110_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = cround(R20, R6) }");
+ test_display(&0b1100_0110_110_10100_11_000110_010_10110u32.to_le_bytes(), "{ R23:22 = cround(R21:20, R6) }");
+ test_display(&0b1100_0110_110_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = round(R20, R6) }");
+ test_display(&0b1100_0110_110_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = round(R20, R6):sat }");
+
+ test_display(&0b1100_0111_000_10100_11_000110_110_10110u32.to_le_bytes(), "{ P2 = tstbit(R20, R6) }");
+ test_display(&0b1100_0111_001_10100_11_000110_110_10110u32.to_le_bytes(), "{ P2 = !tstbit(R20, R6) }");
+ test_display(&0b1100_0111_010_10100_11_000110_110_10110u32.to_le_bytes(), "{ P2 = bitsset(R20, R6) }");
+ test_display(&0b1100_0111_011_10100_11_000110_110_10110u32.to_le_bytes(), "{ P2 = !bitsset(R20, R6) }");
+ test_display(&0b1100_0111_100_10100_11_000110_110_10110u32.to_le_bytes(), "{ P2 = bitsclr(R20, R6) }");
+ test_display(&0b1100_0111_101_10100_11_000110_110_10110u32.to_le_bytes(), "{ P2 = !bitsclr(R20, R6) }");
+ test_invalid(&0b1100_0111_110_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0111_110_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0111_110_10100_11_000110_010_10110u32.to_le_bytes(), "{ P2 = cmpb.gt(R20, R6) }");
+ test_display(&0b1100_0111_110_10100_11_000110_011_10110u32.to_le_bytes(), "{ P2 = cmph.gt(R20, R6) }");
+ test_display(&0b1100_0111_110_10100_11_000110_100_10110u32.to_le_bytes(), "{ P2 = cmph.eq(R20, R6) }");
+ test_display(&0b1100_0111_110_10100_11_000110_101_10110u32.to_le_bytes(), "{ P2 = cmph.gtu(R20, R6) }");
+ test_display(&0b1100_0111_110_10100_11_000110_110_10110u32.to_le_bytes(), "{ P2 = cmpb.eq(R20, R6) }");
+ test_display(&0b1100_0111_110_10100_11_000110_111_10110u32.to_le_bytes(), "{ P2 = cmpb.gtu(R20, R6) }");
+ test_display(&0b1100_0111_111_10100_11_000110_000_10110u32.to_le_bytes(), "{ P2 = sfcmp.ge(R20, R6) }");
+ test_display(&0b1100_0111_111_10100_11_000110_001_10110u32.to_le_bytes(), "{ P2 = sfcmp.uo(R20, R6) }");
+ test_invalid(&0b1100_0111_111_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_0111_111_10100_11_000110_011_10110u32.to_le_bytes(), "{ P2 = sfcmp.eq(R20, R6) }");
+ test_display(&0b1100_0111_111_10100_11_000110_100_10110u32.to_le_bytes(), "{ P2 = sfcmp.gt(R20, R6) }");
+ test_invalid(&0b1100_0111_111_10100_11_000110_101_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0111_111_10100_11_000110_110_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_0111_111_10100_11_000110_111_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+
+ test_display(&0b1100_1000_111_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = insert(R20, R7:6) }");
+
+ test_invalid(&0b1100_1001_000_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_1001_010_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_1001_100_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_1001_111_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = extractu(R20, R7:6) }");
+ test_display(&0b1100_1001_111_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = extract(R20, R7:6) }");
+ test_invalid(&0b1100_1001_111_10100_11_000110_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_1001_111_10100_11_000110_110_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+
+ test_display(&0b1100_1010_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R23:22 = insert(R21:20, R7:6) }");
+ test_invalid(&0b1100_1010_000_10100_11_100110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1100_1010_100_10100_11_000110_000_10110u32.to_le_bytes(), "{ R23:22 ^= xor(R21:20, R7:6) }");
+ test_invalid(&0b1100_1010_100_10100_11_100110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_1010_100_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_1010_100_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_1010_100_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1100_1010_110_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+
test_display(&0b1100_1011_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R23:22 |= asr(R21:20, R6) }");
test_display(&0b1100_1011_000_10100_11_000110_010_10110u32.to_le_bytes(), "{ R23:22 |= lsr(R21:20, R6) }");