summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs14
-rw-r--r--tests/from_brain.rs128
2 files changed, 136 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index fcffc1b..90c87e0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5811,8 +5811,6 @@ fn decode_instruction<
handler.on_source_decoded(Operand::gpr(ttttt))?;
- eprintln!("opc: {:05b}", opc);
-
static OPCODES: [Option<Opcode>; 64] = [
Some(Mpy), Some(Cmpyi), Some(Cmpyr), None, None, None, None, None,
None, None, None, None, None, None, None, None,
@@ -6081,7 +6079,6 @@ fn decode_instruction<
handler.saturate()?;
}
- eprintln!("ok op_lo: {:02b}, opc: {:05b}", op_lo, opc);
if (op_lo & 0b11) == 0b00 {
handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
handler.on_source_decoded(Operand::gprpair(sssss)?)?;
@@ -6444,6 +6441,8 @@ fn decode_instruction<
0b101 => {
handler.on_opcode_decoded(Opcode::Mpy)?;
handler.on_source_decoded(Operand::gpr_low(reg_b8(inst)))?;
+ handler.shift_left(1)?;
+ handler.saturate()?;
}
_ => {
opcode_check!(false);
@@ -6471,9 +6470,10 @@ fn decode_instruction<
}
0b110 => {
opcode_check!(op_hi & 0b001 == 0b001);
+ handler.on_opcode_decoded(Opcode::Cmpy)?;
handler.shift_left(op_hi >> 2)?;
if op_hi & 0b010 == 0 {
- handler.on_dest_decoded(Operand::gpr(reg_b8(inst)))?;
+ handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
} else {
handler.on_source_decoded(Operand::gpr_conjugate(reg_b8(inst)))?;
}
@@ -6482,8 +6482,10 @@ fn decode_instruction<
}
0b111 => {
opcode_check!(op_hi & 0b011 == 0b001);
- handler.on_opcode_decoded(Opcode::Vcmpyh)?;
- handler.on_dest_decoded(Operand::gpr(reg_b8(inst)))?;
+ handler.on_opcode_decoded(Opcode::Vmpyh)?;
+ handler.shift_left(op_hi >> 2)?;
+ handler.on_dest_decoded(Operand::gpr(reg_b0(inst)))?;
+ handler.on_source_decoded(Operand::gpr(reg_b8(inst)))?;
handler.rounded(RoundingMode::Round)?;
handler.saturate()?;
}
diff --git a/tests/from_brain.rs b/tests/from_brain.rs
index dae984f..fdf52b4 100644
--- a/tests/from_brain.rs
+++ b/tests/from_brain.rs
@@ -1580,6 +1580,134 @@ fn inst_1110() {
test_display(&0b1110_1000_011_10100_11_000110_111_10110u32.to_le_bytes(), "{ R23:22 = vmpywouh(R21:20, R7:6):rnd:sat }");
*/
+ test_invalid(&0b1110_1011_000_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b1110_1011_000_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = sfsub(R20, R6) }");
+ test_display(&0b1110_1011_000_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 = sfadd(R20, R6) }");
+ test_display(&0b1110_1011_010_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = sfmpy(R20, R6) }");
+ test_display(&0b1110_1011_100_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = sfmax(R20, R6) }");
+ test_display(&0b1110_1011_100_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = sfmin(R20, R6) }");
+ test_display(&0b1110_1011_110_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = sffixupn(R20, R6) }");
+ test_display(&0b1110_1011_110_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = sffixupd(R20, R6) }");
+ test_display(&0b1110_1011_111_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22,P1 = sfrecipa(R20, R6) }");
+
+ test_display(&0b1110_1100_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L) }");
+ test_display(&0b1110_1100_000_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H) }");
+ test_display(&0b1110_1100_000_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L) }");
+ test_display(&0b1110_1100_000_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H) }");
+ test_display(&0b1110_1100_000_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L):sat }");
+ test_display(&0b1110_1100_000_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H):sat }");
+ test_display(&0b1110_1100_000_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L):sat }");
+ test_display(&0b1110_1100_000_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H):sat }");
+ test_display(&0b1110_1100_001_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L):rnd }");
+ test_display(&0b1110_1100_001_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H):rnd }");
+ test_display(&0b1110_1100_001_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L):rnd }");
+ test_display(&0b1110_1100_001_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H):rnd }");
+ test_display(&0b1110_1100_001_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L):rnd:sat }");
+ test_display(&0b1110_1100_001_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H):rnd:sat }");
+ test_display(&0b1110_1100_001_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L):rnd:sat }");
+ test_display(&0b1110_1100_001_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H):rnd:sat }");
+ test_display(&0b1110_1100_100_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L):<<1 }");
+ test_display(&0b1110_1100_100_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H):<<1 }");
+ test_display(&0b1110_1100_100_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L):<<1 }");
+ test_display(&0b1110_1100_100_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H):<<1 }");
+ test_display(&0b1110_1100_100_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L):<<1:sat }");
+ test_display(&0b1110_1100_100_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H):<<1:sat }");
+ test_display(&0b1110_1100_100_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L):<<1:sat }");
+ test_display(&0b1110_1100_100_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H):<<1:sat }");
+ test_display(&0b1110_1100_101_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L):<<1:rnd }");
+ test_display(&0b1110_1100_101_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H):<<1:rnd }");
+ test_display(&0b1110_1100_101_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L):<<1:rnd }");
+ test_display(&0b1110_1100_101_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H):<<1:rnd }");
+ test_display(&0b1110_1100_101_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.L):<<1:rnd:sat }");
+ test_display(&0b1110_1100_101_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 = mpy(R20.L, R6.H):<<1:rnd:sat }");
+ test_display(&0b1110_1100_101_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.L):<<1:rnd:sat }");
+ test_display(&0b1110_1100_101_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = mpy(R20.H, R6.H):<<1:rnd:sat }");
+
+ test_display(&0b1110_1101_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = mpyi(R20, R6) }");
+ test_display(&0b1110_1101_101_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6.H):<<1:sat }");
+ test_display(&0b1110_1101_111_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6):<<1:sat }");
+ test_display(&0b1110_1101_000_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6) }");
+ test_display(&0b1110_1101_001_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6):rnd }");
+ test_display(&0b1110_1101_010_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpyu(R20, R6) }");
+ test_display(&0b1110_1101_011_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpysu(R20, R6) }");
+ test_display(&0b1110_1101_101_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6.L):<<1:sat }");
+ test_display(&0b1110_1101_101_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6):<<1 }");
+ test_display(&0b1110_1101_101_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6.H):<<1:rnd:sat }");
+ test_display(&0b1110_1101_111_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 = mpy(R20, R6.L):<<1:rnd:sat }");
+
+ test_display(&0b1110_1101_001_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = cmpy(R20, R6):rnd:sat }");
+ test_display(&0b1110_1101_011_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = cmpy(R20, R6*):rnd:sat }");
+ test_display(&0b1110_1101_001_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = vmpyh(R20, R6):rnd:sat }");
+ test_display(&0b1110_1101_101_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = cmpy(R20, R6):<<1:rnd:sat }");
+ test_display(&0b1110_1101_111_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 = cmpy(R20, R6*):<<1:rnd:sat }");
+ test_display(&0b1110_1101_101_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 = vmpyh(R20, R6):<<1:rnd:sat }");
+
+ test_display(&0b1110_1110_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.L) }");
+ test_display(&0b1110_1110_000_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.H) }");
+ test_display(&0b1110_1110_000_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.L) }");
+ test_display(&0b1110_1110_000_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.H) }");
+ test_display(&0b1110_1110_000_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.L):sat }");
+ test_display(&0b1110_1110_000_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.H):sat }");
+ test_display(&0b1110_1110_000_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.L):sat }");
+ test_display(&0b1110_1110_000_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.H):sat }");
+ test_display(&0b1110_1110_001_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.L) }");
+ test_display(&0b1110_1110_001_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.H) }");
+ test_display(&0b1110_1110_001_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.L) }");
+ test_display(&0b1110_1110_001_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.H) }");
+ test_display(&0b1110_1110_001_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.L):sat }");
+ test_display(&0b1110_1110_001_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.H):sat }");
+ test_display(&0b1110_1110_001_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.L):sat }");
+ test_display(&0b1110_1110_001_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.H):sat }");
+ test_display(&0b1110_1110_100_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.L):<<1 }");
+ test_display(&0b1110_1110_100_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.H):<<1 }");
+ test_display(&0b1110_1110_100_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.L):<<1 }");
+ test_display(&0b1110_1110_100_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.H):<<1 }");
+ test_display(&0b1110_1110_100_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.L):<<1:sat }");
+ test_display(&0b1110_1110_100_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 += mpy(R20.L, R6.H):<<1:sat }");
+ test_display(&0b1110_1110_100_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.L):<<1:sat }");
+ test_display(&0b1110_1110_100_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 += mpy(R20.H, R6.H):<<1:sat }");
+ test_display(&0b1110_1110_101_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.L):<<1 }");
+ test_display(&0b1110_1110_101_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.H):<<1 }");
+ test_display(&0b1110_1110_101_10100_11_000110_010_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.L):<<1 }");
+ test_display(&0b1110_1110_101_10100_11_000110_011_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.H):<<1 }");
+ test_display(&0b1110_1110_101_10100_11_000110_100_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.L):<<1:sat }");
+ test_display(&0b1110_1110_101_10100_11_000110_101_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.L, R6.H):<<1:sat }");
+ test_display(&0b1110_1110_101_10100_11_000110_110_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.L):<<1:sat }");
+ test_display(&0b1110_1110_101_10100_11_000110_111_10110u32.to_le_bytes(), "{ R22 -= mpy(R20.H, R6.H):<<1:sat }");
+
+ test_invalid(&0b1110_1110_010_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_010_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_010_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_010_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_010_10100_11_000110_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_010_10100_11_000110_101_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_010_10100_11_000110_110_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_010_10100_11_000110_111_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_101_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_110_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_011_10100_11_000110_111_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_101_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_110_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_110_10100_11_000110_111_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_000_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_001_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_011_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_101_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_110_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b1110_1110_111_10100_11_000110_111_10110u32.to_le_bytes(), DecodeError::InvalidOpcode);
+
test_display(&0b1110_1111_000_10100_11_000110_000_10110u32.to_le_bytes(), "{ R22 += mpyi(R20, R6) }");
test_display(&0b1110_1111_000_10100_11_000110_001_10110u32.to_le_bytes(), "{ R22 += add(R20, R6) }");
test_invalid(&0b1110_1111_000_10100_11_000110_010_10110u32.to_le_bytes(), DecodeError::InvalidOperand);