summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2025-03-23 03:40:06 -0700
committeriximeow <me@iximeow.net>2025-03-23 03:40:06 -0700
commit6aa74072083a618f785b79126cb08938fdd6dc12 (patch)
tree8dadb912ff04c39c4c2160ffddf944843b8ce40e
parent6af27d4defec112ee9f6bbf7840336ccb5861fe4 (diff)
thats 0110... done
-rw-r--r--src/display.rs64
-rw-r--r--src/lib.rs144
-rw-r--r--tests/from_brain.rs19
3 files changed, 227 insertions, 0 deletions
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) }");