From 1e3e699c38ad919946a5352b6c3d0ff7fe977624 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 6 Apr 2025 15:46:15 -0700 Subject: more test coverage, gpr conjugates --- src/display.rs | 11 ++++-- src/lib.rs | 20 ++++++---- tests/from_brain.rs | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++- 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) }"); -- cgit v1.1