diff options
-rw-r--r-- | src/lib.rs | 14 | ||||
-rw-r--r-- | tests/from_brain.rs | 128 |
2 files changed, 136 insertions, 6 deletions
@@ -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); |