From ef761196ae6666f2c8067370d28a1d270ed7f666 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 11 Oct 2020 18:27:48 -0700 Subject: fix reversed l/x instruction word order and immediate decode --- src/lib.rs | 46 ++++++++++++++++++++++++++++++---------------- tests/test.rs | 9 +++++++++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 75b75a7..1f46031 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1261,17 +1261,24 @@ impl Default for InstructionBundle { } impl fmt::Display for InstructionBundle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let stops = if let Some((types, stops)) = BUNDLE_TAGS[self.bundle_tag as usize] { + let (stops, types) = if let Some((types, stops)) = BUNDLE_TAGS[self.bundle_tag as usize] { write!(f, "[{}{}{}]", types[0], types[1], types[2])?; - [(stops & 0b100) > 0, (stops & 0b010) > 0, (stops & 0b001) > 0] + ([(stops & 0b100) > 0, (stops & 0b010) > 0, (stops & 0b001) > 0], types) } else { return write!(f, "tag: invalid ({})", self.bundle_tag); }; - write!(f, " {}{}; {}{}; {}{}", - &self.instructions[0], if stops[0] { ";" } else { "" }, - &self.instructions[1], if stops[1] { ";" } else { "" }, - &self.instructions[2], if stops[2] { ";;" } else { "" }, - ) + if types[2] == InstructionType::X { + write!(f, " {}{}; {}{}", + &self.instructions[0], if stops[0] { ";" } else { "" }, + &self.instructions[1], if stops[1] { ";;" } else { "" }, + ) + } else { + write!(f, " {}{}; {}{}; {}{}", + &self.instructions[0], if stops[0] { ";" } else { "" }, + &self.instructions[1], if stops[1] { ";" } else { "" }, + &self.instructions[2], if stops[2] { ";;" } else { "" }, + ) + } } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -1594,7 +1601,7 @@ impl Decoder for InstDecoder { ]; let (instruction_types, stop_mask) = BUNDLE_TAGS[bundle_tag as usize].ok_or(DecodeError::BadBundle)?; - fn decode_l_instruction(word: &BitSlice, word2: &BitSlice) -> Instruction { + fn decode_l_instruction(word2: &BitSlice, word: &BitSlice) -> Instruction { let tag = word[37..41].load::(); let (opcode, operand_encoding) = get_l_opcode_and_encoding(tag, word); @@ -1867,12 +1874,19 @@ fn read_l_operands(encoding: OperandEncodingX, word: &BitSlice, word2: X2 => { let r1 = word[6..13].load::(); let imm7b = word[13..20].load::(); - let ic = word[21]; - let immdc = word[22..36].load::(); - let i = word[36]; + let ic = word[21] as u64; + let immd = word[27..36].load::(); + let immc = word[22..27].load::(); + let i = word[36] as u64; let imm41 = word2[0..41].load::(); - // TODO: this is certainly assembled incorrectly - let imm = (imm41 << 21) + ((i as u64) << 20) + imm7b + immdc + (ic as u64); + // TODO: might be right, i, c, and imm41 may be mixed up. + let imm = + imm7b + + (immd << 7) + + (immc << 16) + + (i << 21) + + (ic << 22) + + (imm41 << 23); two_op( Some(0), Operand::GPRegister(GPRegister(r1)), @@ -2416,8 +2430,8 @@ fn read_i_operands(encoding: OperandEncodingI, word: &BitSlice) -> (Op let r1 = word[6..13].load::(); let r2 = word[13..20].load::(); let r3 = word[20..27].load::(); - let len = word[27..31].load::(); - let cpos = word[31..37].load::(); + let len = word[27..31].load::() + 1; + let cpos = 63 - word[31..37].load::(); // not sure if this is accurate? makes the dep r14=r18 test pass... ( Some(0), [ @@ -2905,8 +2919,8 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice) -> (Op three_op( Some(0), Operand::GPRegister(GPRegister(r1)), - Operand::GPRegister(GPRegister(r3)), Operand::ImmI64(imm as i64), + Operand::GPRegister(GPRegister(r3)), ) }, A4 => { diff --git a/tests/test.rs b/tests/test.rs index 686d94b..24a1937 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -11,6 +11,15 @@ fn test_addl_imm() { assert_eq!(format!("{}", inst), expected); } #[test] +fn test_mlx_bundle() { + let decoder = InstDecoder::default(); + + let expected = "[MLX] alloc r34=ar.pfs,5,5,0; movl r32=0xfffffffffffff5f8;;"; + let data = [0x05, 0x10, 0x15, 0x0a, 0x80, 0xc5, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x84, 0xf7, 0xaf, 0x6f]; + let inst = decoder.decode(data[..].iter().cloned()).unwrap(); + assert_eq!(format!("{}", inst), expected); +} +#[test] fn test_a_bundle() { // from elf64-ia64-vms.c // [MMI] addl r15=0,r1;; -- cgit v1.1