From 6aa74072083a618f785b79126cb08938fdd6dc12 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 23 Mar 2025 03:40:06 -0700 Subject: thats 0110... done --- src/display.rs | 64 +++++++++++++++++++++++ src/lib.rs | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/from_brain.rs | 19 +++++++ 3 files changed, 227 insertions(+) diff --git a/src/display.rs b/src/display.rs index 34fb6a7..dbf4e44 100644 --- a/src/display.rs +++ b/src/display.rs @@ -3,6 +3,10 @@ use core::fmt; use crate::{Instruction, InstructionPacket, Opcode, Operand}; use crate::{AssignMode, BranchHint, DomainHint}; +fn special_display_rules(op: &Opcode) -> bool { + *op as u16 & 0x8000 == 0x8000 +} + impl fmt::Display for InstructionPacket { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("{ ")?; @@ -25,6 +29,53 @@ impl fmt::Display for InstructionPacket { impl fmt::Display for Instruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if special_display_rules(&self.opcode) { + match self.opcode { + Opcode::AndAnd => { + return write!(f, "{} = and({}, and({}, {}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + Opcode::AndOr => { + return write!(f, "{} = and({}, or({}, {}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + Opcode::OrAnd => { + return write!(f, "{} = or({}, and({}, {}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + Opcode::AndNot => { + return write!(f, "{} = and({}, !{})", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1]); + } + Opcode::OrOr => { + return write!(f, "{} = or({}, or({}, {}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + Opcode::AndAndNot => { + return write!(f, "{} = and({}, and({}, !{}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + Opcode::AndOrNot => { + return write!(f, "{} = and({}, or({}, !{}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + Opcode::OrAndNot => { + return write!(f, "{} = or({}, and({}, !{}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + Opcode::OrNot => { + return write!(f, "{} = or({}, !{})", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1]); + } + Opcode::OrOrNot => { + return write!(f, "{} = or({}, or({}, !{}))", self.dest.as_ref().unwrap(), + self.sources[0], self.sources[1], self.sources[2]); + } + _ => { + unreachable!("TODO: should be exhaustive for opcodes with special display rules"); + } + } + } static REG_COMPARE_JUMPS: &[Opcode] = &[ Opcode::JumpRegNz, Opcode::JumpRegGez, Opcode::JumpRegZ, Opcode::JumpRegLez, @@ -445,6 +496,19 @@ impl fmt::Display for Opcode { Opcode::Diag1 => { f.write_str("diag1") }, Opcode::Movlen => { f.write_str("movlen") }, + Opcode::Fastcorner9 => { f.write_str("fastcorner9") }, + Opcode::AndAnd => { f.write_str("andand") }, + Opcode::AndOr => { f.write_str("andor") }, + Opcode::OrAnd => { f.write_str("orand") }, + Opcode::AndNot => { f.write_str("andnot") }, + Opcode::OrOr => { f.write_str("oror") }, + Opcode::AndAndNot => { f.write_str("andandnot") }, + Opcode::AndOrNot => { f.write_str("andornot") }, + Opcode::OrAndNot => { f.write_str("orandnot") }, + Opcode::OrNot => { f.write_str("ornot") }, + Opcode::OrOrNot => { f.write_str("orornot") }, + Opcode::Any8 => { f.write_str("any8") }, + Opcode::All8 => { f.write_str("all8") }, } } } diff --git a/src/lib.rs b/src/lib.rs index d3220a7..06e971e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -369,6 +369,7 @@ impl Default for InstFlags { /// ``` #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(u16)] pub enum Opcode { /// TODO: remove. should never be shown. implies an instruction was parially decoded but /// accepted? @@ -575,6 +576,21 @@ pub enum Opcode { Diag1, Movlen, + + Fastcorner9, + Any8, + All8, + + AndAnd = 0x8000, + AndOr, + OrAnd, + AndNot, + OrOr, + AndAndNot, + AndOrNot, + OrAndNot, + OrNot, + OrOrNot, } impl Opcode { @@ -2364,6 +2380,134 @@ fn decode_instruction< handler.on_source_decoded(Operand::imm_u8(iiiiii as u8))?; handler.on_dest_decoded(Operand::gpr(ddddd))?; } + o if o & 0b1111000 == 0b1011000 => { + let opc = (inst >> 20) & 0b1111; + let dd = (inst & 0b11) as u8; + let uu = ((inst >> 6) & 0b11) as u8; + let tt = ((inst >> 8) & 0b11) as u8; + let ss = ((inst >> 16) & 0b11) as u8; + let b13 = (inst >> 13) & 0b1; + + handler.on_dest_decoded(Operand::pred(dd))?; + + match opc { + 0b0000 => { + if b13 == 0 { + handler.on_opcode_decoded(Opcode::And)?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(ss))?; + } else { + opcode_check!(inst & 0b10010000 == 0b10010000); + handler.on_opcode_decoded(Opcode::Fastcorner9)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + } + }, + 0b0001 => { + if b13 == 0 { + handler.on_opcode_decoded(Opcode::AndAnd)?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(uu))?; + } else { + opcode_check!(inst & 0b10010000 == 0b10010000); + handler.on_opcode_decoded(Opcode::Fastcorner9)?; + handler.negate_result()?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + } + }, + 0b0010 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::Or)?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(ss))?; + }, + 0b0011 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::AndOr)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(uu))?; + }, + 0b0100 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::Xor)?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(ss))?; + }, + 0b0101 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::OrAnd)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(uu))?; + }, + 0b0110 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::AndNot)?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(ss))?; + }, + 0b0111 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::OrOr)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(uu))?; + }, + 0b1000 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::Any8)?; + handler.on_source_decoded(Operand::pred(ss))?; + }, + 0b1001 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::AndAndNot)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(uu))?; + }, + 0b1010 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::All8)?; + handler.on_source_decoded(Operand::pred(ss))?; + }, + 0b1011 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::AndOrNot)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(uu))?; + }, + 0b1100 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::Not)?; + handler.on_source_decoded(Operand::pred(ss))?; + }, + 0b1101 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::OrAndNot)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(uu))?; + }, + 0b1110 => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::OrNot)?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(ss))?; + }, + // 0b1111 + _ => { + opcode_check!(b13 == 0); + handler.on_opcode_decoded(Opcode::OrOrNot)?; + handler.on_source_decoded(Operand::pred(ss))?; + handler.on_source_decoded(Operand::pred(tt))?; + handler.on_source_decoded(Operand::pred(uu))?; + }, + } + } 0b1100000 => { opcode_check!(inst & 0x2000 == 0); let sssss = reg_b16(inst); diff --git a/tests/from_brain.rs b/tests/from_brain.rs index ca403fd..8c1f44d 100644 --- a/tests/from_brain.rs +++ b/tests/from_brain.rs @@ -316,6 +316,25 @@ fn inst_0110() { test_display(&0b0110_1010000_00110_11_0_000101_00_10110u32.to_le_bytes(), "{ R22 = C6 }"); test_display(&0b0110_1010010_01001_11_0_000101_00_10110u32.to_le_bytes(), "{ R22 = add(pc, #0x5) }"); + test_display(&0b0110_1011000_00011_11_0_000100_00_00001u32.to_le_bytes(), "{ P1 = and(P2, P3) }"); + test_display(&0b0110_1011000_00011_11_1_000101_00_10001u32.to_le_bytes(), "{ P1 = fastcorner9(P3, P2) }"); + test_display(&0b0110_1011000_10011_11_0_000100_00_00001u32.to_le_bytes(), "{ P1 = and(P2, and(P3, P0)) }"); + test_display(&0b0110_1011000_10011_11_1_000101_00_10001u32.to_le_bytes(), "{ P1 = !fastcorner9(P3, P2) }"); + test_display(&0b0110_1011001_00011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = or(P2, P3) }"); + test_display(&0b0110_1011001_10011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = and(P3, or(P2, P0)) }"); + test_display(&0b0110_1011010_00011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = xor(P2, P3) }"); + test_display(&0b0110_1011010_10011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = or(P3, and(P2, P0)) }"); + test_display(&0b0110_1011011_00011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = and(P2, !P3) }"); + test_display(&0b0110_1011011_10011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = or(P3, or(P2, P0)) }"); + test_display(&0b0110_1011100_00011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = any8(P3) }"); + test_display(&0b0110_1011100_10011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = and(P3, and(P2, !P0)) }"); + test_display(&0b0110_1011101_00011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = all8(P3) }"); + test_display(&0b0110_1011101_10011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = and(P3, or(P2, !P0)) }"); + test_display(&0b0110_1011110_00011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = not(P3) }"); + test_display(&0b0110_1011110_10011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = or(P3, and(P2, !P0)) }"); + test_display(&0b0110_1011111_00011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = or(P2, !P3) }"); + test_display(&0b0110_1011111_10011_11_0_000100_00_10001u32.to_le_bytes(), "{ P1 = or(P3, or(P2, !P0)) }"); + test_display(&0b0110_1100001_01001_11_0_000000_00_00000u32.to_le_bytes(), "{ barrier }"); test_display(&0b0110_1111111_01010_11_0_001100_10_00011u32.to_le_bytes(), "{ R3 = movlen(R6, R11:10) }"); -- cgit v1.1