From 7f315862ad9d88fefff0d420c93a34ece0cc9eb2 Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 21 Mar 2025 23:42:52 -0700 Subject: assign-merge is recorded now, 0100.. is decoded --- notes/todo | 166 +++++++++++++++++++++---------------------- src/display.rs | 52 ++++++++++---- src/lib.rs | 197 ++++++++++++++++++++++++++++++++++++++++++++++------ tests/from_brain.rs | 137 ++++++++++++++++++++++++++++++++++++ 4 files changed, 433 insertions(+), 119 deletions(-) diff --git a/notes/todo b/notes/todo index a3cb149..e616890 100644 --- a/notes/todo +++ b/notes/todo @@ -200,89 +200,89 @@ A L I A S A L I A S A L I A S A L I A S A L I A S | Rd=zxtb(Rs) -|0 0 1 1|1 1 0 - - 0 0|s s s s s| P P |l i i i i i i l l|l l l l l| memb(Rs+#u6:0)=#S8 - ST/slot 0,1 -|0 0 1 1|1 1 0 - - 0 1|s s s s s| P P |l i i i i i i l l|l l l l l| memh(Rs+#u6:1)=#S8 - ST/slot 0,1 -|0 0 1 1|1 1 0 - - 1 0|s s s s s| P P |l i i i i i i l l|l l l l l| memw(Rs+#u6:2)=#S8 - ST/slot 0,1 -|0 0 1 1|1 1 1 0 - 0 0|s s s s s| P P |0 i i i i i i 0 0|t t t t t| memb(Rs+#u6:0)+=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 0 0|s s s s s| P P |0 i i i i i i 0 1|t t t t t| memb(Rs+#u6:0)-=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 0 0|s s s s s| P P |0 i i i i i i 1 0|t t t t t| memb(Rs+#u6:0)&=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 0 0|s s s s s| P P |0 i i i i i i 1 1|t t t t t| memb(Rs+#u6:0)|=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 0 1|s s s s s| P P |0 i i i i i i 0 0|t t t t t| memh(Rs+#u6:0)+=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 0 1|s s s s s| P P |0 i i i i i i 0 1|t t t t t| memh(Rs+#u6:0)-=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 0 1|s s s s s| P P |0 i i i i i i 1 0|t t t t t| memh(Rs+#u6:0)&=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 0 1|s s s s s| P P |0 i i i i i i 1 1|t t t t t| memh(Rs+#u6:0)|=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 1 0|s s s s s| P P |0 i i i i i i 0 0|t t t t t| memw(Rs+#u6:0)+=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 1 0|s s s s s| P P |0 i i i i i i 0 1|t t t t t| memw(Rs+#u6:0)-=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 1 0|s s s s s| P P |0 i i i i i i 1 0|t t t t t| memw(Rs+#u6:0)&=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 0 - 1 0|s s s s s| P P |0 i i i i i i 1 1|t t t t t| memw(Rs+#u6:0)|=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 0|s s s s s| P P |0 i i i i i i 0 0|l l l l l| memb(Rs+#u6:0)+=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 0|s s s s s| P P |0 i i i i i i 0 1|l l l l l| memb(Rs+#u6:0)-=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 0|s s s s s| P P |0 i i i i i i 1 0|l l l l l| memb(Rs+#u6:0)=clrbit(#U5) - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 0|s s s s s| P P |0 i i i i i i 1 1|l l l l l| memb(Rs+#u6:0)=setbit(#U5) - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 1|s s s s s| P P |0 i i i i i i 0 0|l l l l l| memh(Rs+#u6:0)+=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 1|s s s s s| P P |0 i i i i i i 0 1|l l l l l| memh(Rs+#u6:0)-=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 1|s s s s s| P P |0 i i i i i i 1 0|l l l l l| memh(Rs+#u6:0)=clrbit(#U5) - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 0 1|s s s s s| P P |0 i i i i i i 1 1|l l l l l| memh(Rs+#u6:0)=setbit(#U5) - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 1 0|s s s s s| P P |0 i i i i i i 0 0|l l l l l| memw(Rs+#u6:0)+=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 1 0|s s s s s| P P |0 i i i i i i 0 1|l l l l l| memw(Rs+#u6:0)-=Rt - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 1 0|s s s s s| P P |0 i i i i i i 1 0|l l l l l| memw(Rs+#u6:0)=clrbit(#U5) - MEMOP/slot 0 -|0 0 1 1|1 1 1 1 - 1 0|s s s s s| P P |0 i i i i i i 1 1|l l l l l| memw(Rs+#u6:0)=setbit(#U5) - MEMOP/slot 0 -test |0 1 0 0|0 0 0 0 0 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv) memb(Rs+#u6:0)=Rt - ST/slot 0,1 -|0 1 0 0|0 0 0 0 0 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv) memh(Rs+#u6:1)=Rt - ST/slot 0,1 -|0 1 0 0|0 0 0 0 0 1 1|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv) memh(Rs+#u6:1)=Rt.H - ST/slot 0,1 -|0 1 0 0|0 0 0 0 1 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv) memw(Rs+#u6:2)=Rt - ST/slot 0,1 -|0 1 0 0|0 0 0 0 1 0 1|s s s s s| P P |i 0 0 t t t i i i|i i 0 v v| if (Pv) memb(Rs+#u6:0)=Nt.new - NV/slot 0 -|0 1 0 0|0 0 0 0 1 0 1|s s s s s| P P |i 0 1 t t t i i i|i i 0 v v| if (Pv) memh(Rs+#u6:1)=Nt.new - NV/slot 0 -|0 1 0 0|0 0 0 0 1 0 1|s s s s s| P P |i 1 0 t t t i i i|i i 0 v v| if (Pv) memw(Rs+#u6:2)=Nt.new - NV/slot 0 -|0 1 0 0|0 0 0 0 1 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv) memd(Rs+#u6:2)=Rtt - ST/slot 0,1 -|0 1 0 0|0 0 1 0 0 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv) memb(Rs+#u6:0)=Rt - ST/slot 0,1 -|0 1 0 0|0 0 1 0 0 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv) memh(Rs+#u6:1)=Rt - ST/slot 0,1 -|0 1 0 0|0 0 1 0 0 1 1|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv) memh(Rs+#u6:1)=Rt.H - ST/slot 0,1 -|0 1 0 0|0 0 1 0 1 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv) memw(Rs+#u6:2)=Rt - ST/slot 0,1 -|0 1 0 0|0 0 1 0 1 0 1|s s s s s| P P |i 0 0 t t t i i i|i i 0 v v| if (!Pv) memb(Rs+#u6:0)=Nt.new - NV/slot 0 -|0 1 0 0|0 0 1 0 1 0 1|s s s s s| P P |i 0 1 t t t i i i|i i 0 v v| if (!Pv) memh(Rs+#u6:1)=Nt.new - NV/slot 0 -|0 1 0 0|0 0 1 0 1 0 1|s s s s s| P P |i 1 0 t t t i i i|i i 0 v v| if (!Pv) memw(Rs+#u6:2)=Nt.new - NV/slot 0 -|0 1 0 0|0 0 1 0 1 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv) memd(Rs+#u6:2)=Rtt - ST/slot 0,1 -|0 1 0 0|0 1 0 0 0 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv.new) memb(Rs+#u6:0)=Rt - ST/slot 0,1 -|0 1 0 0|0 1 0 0 0 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv.new) memh(Rs+#u6:1)=Rt - ST/slot 0,1 -|0 1 0 0|0 1 0 0 0 1 1|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv.new) memh(Rs+#u6:1)=Rt.H - ST/slot 0,1 -|0 1 0 0|0 1 0 0 1 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv.new) memw(Rs+#u6:2)=Rt - ST/slot 0,1 -|0 1 0 0|0 1 0 0 1 0 1|s s s s s| P P |i 0 0 t t t i i i|i i 0 v v| if (Pv.new) memb(Rs+#u6:0)=Nt.new - NV/slot 0 -|0 1 0 0|0 1 0 0 1 0 1|s s s s s| P P |i 0 1 t t t i i i|i i 0 v v| if (Pv.new) memh(Rs+#u6:1)=Nt.new - NV/slot 0 -|0 1 0 0|0 1 0 0 1 0 1|s s s s s| P P |i 1 0 t t t i i i|i i 0 v v| if (Pv.new) memw(Rs+#u6:2)=Nt.new - NV/slot 0 -|0 1 0 0|0 1 0 0 1 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (Pv.new) memd(Rs+#u6:2)=Rtt - ST/slot 0,1 -|0 1 0 0|0 1 1 0 0 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv.new) memb(Rs+#u6:0)=Rt - ST/slot 0,1 -|0 1 0 0|0 1 1 0 0 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv.new) memh(Rs+#u6:1)=Rt - ST/slot 0,1 -|0 1 0 0|0 1 1 0 0 1 1|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv.new) memh(Rs+#u6:1)=Rt.H - ST/slot 0,1 -|0 1 0 0|0 1 1 0 1 0 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv.new) memw(Rs+#u6:2)=Rt - ST/slot 0,1 -|0 1 0 0|0 1 1 0 1 0 1|s s s s s| P P |i 0 0 t t t i i i|i i 0 v v| if (!Pv.new) memb(Rs+#u6:0)=Nt.new - NV/slot 0 -|0 1 0 0|0 1 1 0 1 0 1|s s s s s| P P |i 0 1 t t t i i i|i i 0 v v| if (!Pv.new) memh(Rs+#u6:1)=Nt.new - NV/slot 0 -|0 1 0 0|0 1 1 0 1 0 1|s s s s s| P P |i 1 0 t t t i i i|i i 0 v v| if (!Pv.new) memw(Rs+#u6:2)=Nt.new - NV/slot 0 -|0 1 0 0|0 1 1 0 1 1 0|s s s s s| P P |i t t t t t i i i|i i 0 v v| if (!Pv.new) memd(Rs+#u6:2)=Rtt - ST/slot 0,1 -|0 1 0 0|0 1 1 1 0 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt.new) Rd=memb(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 1 1 0 0 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt.new) Rd=memub(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 1 1 0 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt.new) Rd=memh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 1 1 0 1 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt.new) Rd=memuh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 1 1 1 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt.new) Rd=memw(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 1 1 1 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt.new) Rdd=memd(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 0 1 0 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt) Rd=memb(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 0 1 0 0 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt) Rd=memub(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 0 1 0 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt) Rd=memh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 0 1 0 1 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt) Rd=memuh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 0 1 1 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt) Rd=memw(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 0 1 1 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt) Rdd=memd(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 1 1 0 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt) Rd=memb(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 1 1 0 0 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt) Rd=memub(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 1 1 0 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt) Rd=memh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 1 1 0 1 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt) Rd=memuh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 1 1 1 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt) Rd=memw(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 0 1 1 1 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (Pt) Rdd=memd(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 0 1 0 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt.new) Rd=memb(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 0 1 0 0 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt.new) Rd=memub(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 0 1 0 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt.new) Rd=memh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 0 1 0 1 1|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt.new) Rd=memuh(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 0 1 1 0 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt.new) Rd=memw(Rs+#u6:3) - LD/slot 0,1 -|0 1 0 0|0 1 0 1 1 1 0|s s s s s| P P |0 t t i i i i i i|d d d d d| if (!Pt.new) Rdd=memd(Rs+#u6:3) - LD/slot 0,1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test |0 1 0 0|1 i i 0 0 0 0|i i i i i| P P |i t t t t t i i i|i i i i i| memb(gp+#u16:0)=Rt - ST/slot 0,1 test |0 1 0 0|1 i i 0 0 1 0|i i i i i| P P |i t t t t t i i i|i i i i i| memh(gp+#u16:1)=Rt - ST/slot 0,1 test |0 1 0 0|1 i i 0 0 1 1|i i i i i| P P |i t t t t t i i i|i i i i i| memh(gp+#u16:1)=Rt.H - ST/slot 0,1 diff --git a/src/display.rs b/src/display.rs index 11d5489..5063350 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,7 +1,7 @@ use core::fmt; use crate::{Instruction, InstructionPacket, Opcode, Operand}; -use crate::{BranchHint, DomainHint}; +use crate::{AssignMode, BranchHint, DomainHint}; impl fmt::Display for InstructionPacket { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -77,19 +77,34 @@ impl fmt::Display for Instruction { static STORES: &[Opcode] = &[ Opcode::StoreMemb, Opcode::StoreMemh, Opcode::StoreMemw, Opcode::StoreMemd, Opcode::MemwRl, Opcode::MemdRl ]; + let mut needs_parens = self.sources_count > 0; if STORES.contains(&self.opcode) { - write!(f, "{}({}){} = {}", + let (assign_op, needs_parens) = match self.flags.assign_mode { + None => ("=", false), + Some(AssignMode::AddAssign) => ("+=", false), + Some(AssignMode::SubAssign) => ("-=", false), + Some(AssignMode::AndAssign) => ("&=", false), + Some(AssignMode::OrAssign) => ("|=", false), + Some(AssignMode::XorAssign) => ("^=", false), + Some(AssignMode::ClrBit) => ("= clrbit", true), + Some(AssignMode::SetBit) => ("= setbit", true), + }; + write!(f, "{}({}){} {}{}{}{}", self.opcode, self.dest.expect("TODO: unreachable; store has a destination"), match self.flags.threads { Some(DomainHint::Same) => { ":st" }, Some(DomainHint::All) => { ":at" }, None => { "" } }, - self.sources[0] + assign_op, + if needs_parens { "(" } else { " " }, + self.sources[0], + if needs_parens { ")" } else { "" }, )?; return Ok(()); } + // TODO: do store conditionals have assign_merge? static SC_STORES: &[Opcode] = &[ Opcode::MemwStoreCond, Opcode::MemdStoreCond, ]; @@ -147,8 +162,20 @@ impl fmt::Display for Instruction { self.dest.unwrap())?; return Ok(()); } + if let Some(o) = self.dest.as_ref() { - write!(f, "{} = ", o)?; + let (assign_op, p) = match self.flags.assign_mode { + None => ("=", false), + Some(AssignMode::AddAssign) => ("+=", false), + Some(AssignMode::SubAssign) => ("-=", false), + Some(AssignMode::AndAssign) => ("&=", false), + Some(AssignMode::OrAssign) => ("|=", false), + Some(AssignMode::XorAssign) => ("^=", false), + Some(AssignMode::ClrBit) => ("=clrbit", true), + Some(AssignMode::SetBit) => ("=setbit", true), + }; + needs_parens |= p; + write!(f, "{} {} ", o, assign_op)?; } // TransferRegister and TransferImmediate display the source operand atypically. @@ -161,27 +188,29 @@ impl fmt::Display for Instruction { f.write_str("!")?; } write!(f, "{}", self.opcode)?; + if needs_parens { f.write_str("(")?; } if self.opcode == Opcode::And_nRR || self.opcode == Opcode::Or_nRR { // while operand order does not matter here at all, the hexagon (v73) manual reverses // Rs and Rt for these specific instructions. - write!(f, "({}, ~{})", self.sources[1], self.sources[0])?; + write!(f, "{}, ~{}", self.sources[1], self.sources[0])?; + if needs_parens { f.write_str(")")?; } return Ok(()); } if self.opcode == Opcode::And_RnR || self.opcode == Opcode::Or_RnR { - write!(f, "({}, ~{})", self.sources[0], self.sources[1])?; + write!(f, "{}, ~{}", self.sources[0], self.sources[1])?; + if needs_parens { f.write_str(")")?; } return Ok(()); } if self.sources_count > 0 { - f.write_str("(")?; write!(f, "{}", self.sources[0])?; for i in 1..self.sources_count { write!(f, ", {}", self.sources[i as usize])?; } - f.write_str(")")?; } + if needs_parens { f.write_str(")")?; } if let Some(mode) = self.flags.rounded { write!(f, "{}", mode.as_label())?; @@ -244,13 +273,6 @@ impl fmt::Display for Opcode { Opcode::StoreMemw => { f.write_str("memw") }, Opcode::StoreMemd => { f.write_str("memd") }, - Opcode::MembAdd => { f.write_str("memb") }, - Opcode::MembSub => { f.write_str("memb") }, - Opcode::MembAnd => { f.write_str("memb") }, - Opcode::MembOr => { f.write_str("memb") }, - Opcode::MembClr => { f.write_str("memb") }, - Opcode::MembSet => { f.write_str("memb") }, - Opcode::Membh => { f.write_str("membh") }, Opcode::MemhFifo => { f.write_str("memh_fifo") }, Opcode::Memubh => { f.write_str("memubh") }, diff --git a/src/lib.rs b/src/lib.rs index 6537bfd..a046abd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -292,6 +292,17 @@ impl RoundingMode { } #[derive(Debug, Copy, Clone)] +enum AssignMode { + AddAssign, + SubAssign, + AndAssign, + OrAssign, + XorAssign, + ClrBit, + SetBit, +} + +#[derive(Debug, Copy, Clone)] struct InstFlags { predicate: Option, branch_hint: Option, @@ -300,6 +311,7 @@ struct InstFlags { chop: bool, rounded: Option, threads: Option, + assign_mode: Option, } #[derive(Debug, Copy, Clone)] @@ -318,6 +330,7 @@ impl Default for InstFlags { chop: false, rounded: None, threads: None, + assign_mode: None, } } } @@ -994,6 +1007,7 @@ trait DecodeHandler::Address, ::Wor fn on_opcode_decoded(&mut self, _opcode: Opcode) -> Result<(), ::DecodeError> { Ok(()) } fn on_source_decoded(&mut self, _operand: Operand) -> Result<(), ::DecodeError> { Ok(()) } fn on_dest_decoded(&mut self, _operand: Operand) -> Result<(), ::DecodeError> { Ok(()) } + fn assign_mode(&mut self, _assign_mode: AssignMode) -> Result<(), ::DecodeError> { Ok(()) } fn inst_predicated(&mut self, num: u8, negated: bool, pred_new: bool) -> Result<(), ::DecodeError> { Ok(()) } fn negate_result(&mut self) -> Result<(), ::DecodeError> { Ok(()) } fn saturate(&mut self) -> Result<(), ::DecodeError> { Ok(()) } @@ -1033,6 +1047,11 @@ impl::Address, ::Word } Ok(()) } + fn assign_mode(&mut self, assign_mode: AssignMode) -> Result<(), ::DecodeError> { + let mut inst = &mut self.instructions[self.instruction_count as usize]; + inst.flags.assign_mode = Some(assign_mode); + Ok(()) + } fn inst_predicated(&mut self, num: u8, negated: bool, pred_new: bool) -> Result<(), ::DecodeError> { let mut flags = &mut self.instructions[self.instruction_count as usize].flags; assert!(flags.predicate.is_none()); @@ -1164,6 +1183,52 @@ fn decode_store_ops< Ok(()) } +// very much like `decode_store_ops`, except for some instructions the strategy is for loads +// instead. +fn decode_load_ops< + T: Reader<::Address, ::Word>, + H: DecodeHandler, +>(handler: &mut H, opbits: u8, dstreg: u8, src_op: impl Fn(u8) -> Operand) -> Result<(), DecodeError> { + // for loads, there's none of the carveout for `R.new` or high register halves. + // just mem{b,ub,h,uh,w,d} + match opbits { + 0b000 => { + handler.on_opcode_decoded(Opcode::LoadMemb)?; + handler.on_dest_decoded(Operand::gpr(dstreg))?; + handler.on_source_decoded(src_op(0))?; + } + 0b001 => { + handler.on_opcode_decoded(Opcode::LoadMemub)?; + handler.on_dest_decoded(Operand::gpr(dstreg))?; + handler.on_source_decoded(src_op(0))?; + } + 0b010 => { + handler.on_opcode_decoded(Opcode::LoadMemh)?; + handler.on_dest_decoded(Operand::gpr(dstreg))?; + handler.on_source_decoded(src_op(1))?; + } + 0b011 => { + handler.on_opcode_decoded(Opcode::LoadMemuh)?; + handler.on_dest_decoded(Operand::gpr(dstreg))?; + handler.on_source_decoded(src_op(1))?; + } + 0b100 => { + handler.on_opcode_decoded(Opcode::LoadMemw)?; + handler.on_dest_decoded(Operand::gpr(dstreg))?; + handler.on_source_decoded(src_op(2))?; + } + 0b110 => { + handler.on_opcode_decoded(Opcode::LoadMemd)?; + handler.on_dest_decoded(Operand::gprpair(dstreg)?)?; + handler.on_source_decoded(src_op(3))?; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + Ok(()) +} + fn decode_packet< T: Reader<::Address, ::Word>, H: DecodeHandler, @@ -1640,6 +1705,7 @@ fn decode_instruction< let opc_upper = opc_bits >> 3; let opc_lower = opc_bits & 0b11; let uuuuuu = (inst >> 7) & 0b111111; + let sssss = (inst >> 16) & 0b11111; match opc_upper { 0b00 | @@ -1648,25 +1714,81 @@ fn decode_instruction< let i_hi = ((inst >> 13) & 0b1) << 7; let i = i_hi | i7; - (match opc_upper { + handler.on_opcode_decoded(match opc_lower { 0b00 => { - handler.on_opcode_decoded(Opcode::StoreMemb)?; + Opcode::StoreMemb } 0b01 => { - Ok(Opcode::StoreMemh), + Opcode::StoreMemh } 0b10 => { - Ok(Opcode::StoreMemd), + Opcode::StoreMemw } - _ => Err(DecodeError::InvalidOpcode) - }?)?; + _ => { return Err(DecodeError::InvalidOpcode); } + })?; handler.on_source_decoded(Operand::imm_i8(i as i8))?; + handler.on_dest_decoded(Operand::RegOffset { + base: sssss as u8, + offset: (uuuuuu as u32) << opc_lower, + })?; }, 0b10 => { + opcode_check!(inst & 0b0010_0000_0000_0000 == 0); + let ttttt = inst & 0b11111; + let assign_mode = (inst >> 5) & 0b11; + handler.on_opcode_decoded(match opc_lower { + 0b00 => { + Opcode::StoreMemb + } + 0b01 => { + Opcode::StoreMemh + } + 0b10 => { + Opcode::StoreMemw + } + _ => { return Err(DecodeError::InvalidOpcode); } + })?; + handler.assign_mode(match assign_mode { + 0b00 => AssignMode::AddAssign, + 0b01 => AssignMode::SubAssign, + 0b10 => AssignMode::AndAssign, + _ => AssignMode::OrAssign, + })?; + handler.on_source_decoded(Operand::gpr(ttttt as u8))?; + handler.on_dest_decoded(Operand::RegOffset { + base: sssss as u8, + offset: (uuuuuu as u32) << opc_lower, + })?; }, _ => { - panic!("TODO: other: {}", other); + opcode_check!(inst & 0b0010_0000_0000_0000 == 0); + let ttttt = inst & 0b11111; + let assign_mode = (inst >> 5) & 0b11; + + handler.on_opcode_decoded(match opc_lower { + 0b00 => { + Opcode::StoreMemb + } + 0b01 => { + Opcode::StoreMemh + } + 0b10 => { + Opcode::StoreMemw + } + _ => { return Err(DecodeError::InvalidOpcode); } + })?; + handler.assign_mode(match assign_mode { + 0b00 => AssignMode::AddAssign, + 0b01 => AssignMode::SubAssign, + 0b10 => AssignMode::ClrBit, + _ => AssignMode::SetBit, + })?; + handler.on_source_decoded(Operand::imm_u8(ttttt as u8))?; + handler.on_dest_decoded(Operand::RegOffset { + base: sssss as u8, + offset: (uuuuuu as u32) << opc_lower, + })?; } } } @@ -1676,34 +1798,67 @@ fn decode_instruction< // 0 1 0 0|... // loads and stores with large (6b+) offsets let predicated = (inst >> 27) & 1 == 0; - let load = (inst >> 24) & 1 == 0; + let store = (inst >> 24) & 1 == 0; if predicated { - let dotnew = (inst >> 23) & 0b1 == 1; - let negated = (inst >> 22) & 0b1 == 0; - let pred_reg = (inst >> 11) & 0b11; - handler.inst_predicated(pred_reg as u8, negated, dotnew)?; + let dotnew = (inst >> 26) & 0b1 == 1; + let negated = (inst >> 25) & 0b1 == 1; + + let opbits = (inst >> 21) & 0b111; + let sssss = reg_b16(inst); + + if store { + let pred_reg = inst & 0b11; + handler.inst_predicated(pred_reg as u8, negated, dotnew)?; - if load { + let srcreg = reg_b8(inst); + let i5 = (inst >> 3) & 0b11111; + let i = ((inst >> 13) & 1) << 5; + let iiiiii = i | i5; + + decode_store_ops(handler, opbits as u8, srcreg as u8, |shamt| { + Operand::RegOffset { + base: sssss as u8, + offset: iiiiii << shamt + } + })?; } else { + let pred_reg = (inst >> 11) & 0b11; + handler.inst_predicated(pred_reg as u8, negated, dotnew)?; + + let dstreg = reg_b0(inst); + let iiiiii = (inst >> 5) & 0b111111; + + decode_load_ops(handler, opbits as u8, dstreg as u8, |shamt| { + Operand::RegOffset { + base: sssss as u8, + offset: iiiiii << shamt + } + })?; } } else { let i14 = (inst >> 25) & 0b11; let i9 = (inst >> 16) & 0b11111; let i_8 = (inst >> 13) & 0b1; - if load { - let i_lo = (inst >> 5) & 0b11111111; + let opbits = ((inst >> 21) & 0b111) as u8; + + if store { + let i_lo = inst & 0b1111_1111; let i = (i14 << 14) | (i9 << 9) | (i_8 << 8) | i_lo; - let ddddd = reg_b0(inst); - let opc = (inst >> 21) & 0b111; + let ttttt = reg_b8(inst); + + decode_store_ops(handler, opbits, ttttt, |shamt| { + Operand::GpOffset { + offset: i << shamt + } + })?; } else { - let i_lo = inst & 0b11111111; + let i_lo = (inst >> 5) & 0b1111_1111; let i = (i14 << 14) | (i9 << 9) | (i_8 << 8) | i_lo; - let ttttt = reg_b8(inst); - let opc = ((inst >> 21) & 0b111) as u8; + let ddddd = reg_b0(inst); - decode_store_ops(handler, opc, ttttt, |shamt| { + decode_load_ops(handler, opbits, ddddd, |shamt| { Operand::GpOffset { offset: i << shamt } })?; } diff --git a/tests/from_brain.rs b/tests/from_brain.rs index 8473617..194ff8a 100644 --- a/tests/from_brain.rs +++ b/tests/from_brain.rs @@ -100,6 +100,143 @@ fn inst_0011() { test_display(&0b0011_1011010_00100_11_1_0_0010_100_11110u32.to_le_bytes(), "{ memh(R4 + R2<<3) = R30 }"); test_display(&0b0011_1011011_00100_11_1_0_0010_100_11110u32.to_le_bytes(), "{ memh(R4 + R2<<3) = R30.H }"); test_display(&0b0011_1011101_00100_11_1_0_0010_100_10110u32.to_le_bytes(), "{ memw(R4 + R2<<3) = R6.new }"); + + test_display(&0b0011_1100000_00100_11_1_1_0010_100_10110u32.to_le_bytes(), "{ memb(R4+#37) = #-106 }"); + test_display(&0b0011_1100001_00100_11_1_1_0010_100_10110u32.to_le_bytes(), "{ memh(R4+#74) = #-106 }"); + test_display(&0b0011_1100010_00100_11_1_1_0010_100_10110u32.to_le_bytes(), "{ memw(R4+#148) = #-106 }"); + test_invalid(&0b0011_1100011_00100_11_1_1_0010_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0011_1110000_00100_11_0_1_0010_100_10110u32.to_le_bytes(), "{ memb(R4+#37) += R22 }"); + test_display(&0b0011_1110000_00100_11_0_1_0010_101_10110u32.to_le_bytes(), "{ memb(R4+#37) -= R22 }"); + test_display(&0b0011_1110000_00100_11_0_1_0010_110_10110u32.to_le_bytes(), "{ memb(R4+#37) &= R22 }"); + test_display(&0b0011_1110000_00100_11_0_1_0010_111_10110u32.to_le_bytes(), "{ memb(R4+#37) |= R22 }"); + test_display(&0b0011_1110001_00100_11_0_1_0010_100_10110u32.to_le_bytes(), "{ memh(R4+#74) += R22 }"); + test_display(&0b0011_1110001_00100_11_0_1_0010_101_10110u32.to_le_bytes(), "{ memh(R4+#74) -= R22 }"); + test_display(&0b0011_1110001_00100_11_0_1_0010_110_10110u32.to_le_bytes(), "{ memh(R4+#74) &= R22 }"); + test_display(&0b0011_1110001_00100_11_0_1_0010_111_10110u32.to_le_bytes(), "{ memh(R4+#74) |= R22 }"); + test_display(&0b0011_1110010_00100_11_0_1_0010_100_10110u32.to_le_bytes(), "{ memw(R4+#148) += R22 }"); + test_display(&0b0011_1110010_00100_11_0_1_0010_101_10110u32.to_le_bytes(), "{ memw(R4+#148) -= R22 }"); + test_display(&0b0011_1110010_00100_11_0_1_0010_110_10110u32.to_le_bytes(), "{ memw(R4+#148) &= R22 }"); + test_display(&0b0011_1110010_00100_11_0_1_0010_111_10110u32.to_le_bytes(), "{ memw(R4+#148) |= R22 }"); + test_invalid(&0b0011_1110011_00100_11_0_1_0010_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0011_1111000_00100_11_0_1_0010_100_10110u32.to_le_bytes(), "{ memb(R4+#37) += #0x16 }"); + test_display(&0b0011_1111000_00100_11_0_1_0010_101_10110u32.to_le_bytes(), "{ memb(R4+#37) -= #0x16 }"); + test_display(&0b0011_1111000_00100_11_0_1_0010_110_10110u32.to_le_bytes(), "{ memb(R4+#37) = clrbit(#0x16) }"); + test_display(&0b0011_1111000_00100_11_0_1_0010_111_10110u32.to_le_bytes(), "{ memb(R4+#37) = setbit(#0x16) }"); + test_display(&0b0011_1111001_00100_11_0_1_0010_100_10110u32.to_le_bytes(), "{ memh(R4+#74) += #0x16 }"); + test_display(&0b0011_1111001_00100_11_0_1_0010_101_10110u32.to_le_bytes(), "{ memh(R4+#74) -= #0x16 }"); + test_display(&0b0011_1111001_00100_11_0_1_0010_110_10110u32.to_le_bytes(), "{ memh(R4+#74) = clrbit(#0x16) }"); + test_display(&0b0011_1111001_00100_11_0_1_0010_111_10110u32.to_le_bytes(), "{ memh(R4+#74) = setbit(#0x16) }"); + test_display(&0b0011_1111010_00100_11_0_1_0010_100_10110u32.to_le_bytes(), "{ memw(R4+#148) += #0x16 }"); + test_display(&0b0011_1111010_00100_11_0_1_0010_101_10110u32.to_le_bytes(), "{ memw(R4+#148) -= #0x16 }"); + test_display(&0b0011_1111010_00100_11_0_1_0010_110_10110u32.to_le_bytes(), "{ memw(R4+#148) = clrbit(#0x16) }"); + test_display(&0b0011_1111010_00100_11_0_1_0010_111_10110u32.to_le_bytes(), "{ memw(R4+#148) = setbit(#0x16) }"); + test_invalid(&0b0011_1111011_00100_11_0_1_0010_100_10110u32.to_le_bytes(), DecodeError::InvalidOpcode); +} + +#[test] +fn inst_0100() { + test_display(&0b0100_0000_000_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2) memb(R10+#45) = R7 }"); + test_display(&0b0100_0000_010_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2) memh(R10+#90) = R7 }"); + test_display(&0b0100_0000_011_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2) memh(R10+#90) = R7.H }"); + test_display(&0b0100_0000_100_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2) memw(R10+#180) = R7 }"); + test_display(&0b0100_0000_101_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2) memb(R10+#45) = R7.new }"); + test_display(&0b0100_0000_101_01010_11_1_01111_011_01010u32.to_le_bytes(), "{ if (P2) memh(R10+#90) = R7.new }"); + test_display(&0b0100_0000_101_01010_11_1_10111_011_01010u32.to_le_bytes(), "{ if (P2) memw(R10+#180) = R7.new }"); + test_invalid(&0b0100_0000_101_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0000_110_01010_11_1_00110_011_01010u32.to_le_bytes(), "{ if (P2) memd(R10+#360) = R7:6 }"); + test_invalid(&0b0100_0000_111_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_0010_000_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2) memb(R10+#45) = R7 }"); + test_display(&0b0100_0010_010_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2) memh(R10+#90) = R7 }"); + test_display(&0b0100_0010_011_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2) memh(R10+#90) = R7.H }"); + test_display(&0b0100_0010_100_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2) memw(R10+#180) = R7 }"); + test_display(&0b0100_0010_101_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2) memb(R10+#45) = R7.new }"); + test_display(&0b0100_0010_101_01010_11_1_01111_011_01010u32.to_le_bytes(), "{ if (!P2) memh(R10+#90) = R7.new }"); + test_display(&0b0100_0010_101_01010_11_1_10111_011_01010u32.to_le_bytes(), "{ if (!P2) memw(R10+#180) = R7.new }"); + test_invalid(&0b0100_0010_101_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0010_110_01010_11_1_00110_011_01010u32.to_le_bytes(), "{ if (!P2) memd(R10+#360) = R7:6 }"); + test_invalid(&0b0100_0010_111_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_0100_000_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2.new) memb(R10+#45) = R7 }"); + test_display(&0b0100_0100_010_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2.new) memh(R10+#90) = R7 }"); + test_display(&0b0100_0100_011_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2.new) memh(R10+#90) = R7.H }"); + test_display(&0b0100_0100_100_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2.new) memw(R10+#180) = R7 }"); + test_display(&0b0100_0100_101_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (P2.new) memb(R10+#45) = R7.new }"); + test_display(&0b0100_0100_101_01010_11_1_01111_011_01010u32.to_le_bytes(), "{ if (P2.new) memh(R10+#90) = R7.new }"); + test_display(&0b0100_0100_101_01010_11_1_10111_011_01010u32.to_le_bytes(), "{ if (P2.new) memw(R10+#180) = R7.new }"); + test_invalid(&0b0100_0100_101_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0100_110_01010_11_1_00110_011_01010u32.to_le_bytes(), "{ if (P2.new) memd(R10+#360) = R7:6 }"); + test_invalid(&0b0100_0100_111_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_0110_000_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2.new) memb(R10+#45) = R7 }"); + test_display(&0b0100_0110_010_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2.new) memh(R10+#90) = R7 }"); + test_display(&0b0100_0110_011_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2.new) memh(R10+#90) = R7.H }"); + test_display(&0b0100_0110_100_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2.new) memw(R10+#180) = R7 }"); + test_display(&0b0100_0110_101_01010_11_1_00111_011_01010u32.to_le_bytes(), "{ if (!P2.new) memb(R10+#45) = R7.new }"); + test_display(&0b0100_0110_101_01010_11_1_01111_011_01010u32.to_le_bytes(), "{ if (!P2.new) memh(R10+#90) = R7.new }"); + test_display(&0b0100_0110_101_01010_11_1_10111_011_01010u32.to_le_bytes(), "{ if (!P2.new) memw(R10+#180) = R7.new }"); + test_invalid(&0b0100_0110_101_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0110_110_01010_11_1_00110_011_01010u32.to_le_bytes(), "{ if (!P2.new) memd(R10+#360) = R7:6 }"); + test_invalid(&0b0100_0110_111_01010_11_1_11111_011_01010u32.to_le_bytes(), DecodeError::InvalidOpcode); + + // now for some loads + test_display(&0b0100_0001_000_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2) R8 = memb(R10+#45) }"); + test_display(&0b0100_0001_001_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2) R8 = memub(R10+#45) }"); + test_display(&0b0100_0001_010_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2) R8 = memh(R10+#90) }"); + test_display(&0b0100_0001_011_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2) R8 = memuh(R10+#90) }"); + test_display(&0b0100_0001_100_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2) R8 = memw(R10+#180) }"); + test_invalid(&0b0100_0001_101_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0001_110_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2) R9:8 = memd(R10+#360) }"); + test_invalid(&0b0100_0001_111_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_0011_000_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2) R8 = memb(R10+#45) }"); + test_display(&0b0100_0011_001_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2) R8 = memub(R10+#45) }"); + test_display(&0b0100_0011_010_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2) R8 = memh(R10+#90) }"); + test_display(&0b0100_0011_011_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2) R8 = memuh(R10+#90) }"); + test_display(&0b0100_0011_100_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2) R8 = memw(R10+#180) }"); + test_invalid(&0b0100_0011_101_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0011_110_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2) R9:8 = memd(R10+#360) }"); + test_invalid(&0b0100_0011_111_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_0101_000_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2.new) R8 = memb(R10+#45) }"); + test_display(&0b0100_0101_001_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2.new) R8 = memub(R10+#45) }"); + test_display(&0b0100_0101_010_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2.new) R8 = memh(R10+#90) }"); + test_display(&0b0100_0101_011_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2.new) R8 = memuh(R10+#90) }"); + test_display(&0b0100_0101_100_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2.new) R8 = memw(R10+#180) }"); + test_invalid(&0b0100_0101_101_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0101_110_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (P2.new) R9:8 = memd(R10+#360) }"); + test_invalid(&0b0100_0101_111_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_0111_000_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2.new) R8 = memb(R10+#45) }"); + test_display(&0b0100_0111_001_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2.new) R8 = memub(R10+#45) }"); + test_display(&0b0100_0111_010_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2.new) R8 = memh(R10+#90) }"); + test_display(&0b0100_0111_011_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2.new) R8 = memuh(R10+#90) }"); + test_display(&0b0100_0111_100_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2.new) R8 = memw(R10+#180) }"); + test_invalid(&0b0100_0111_101_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_0111_110_01010_11_1_10101_101_01000u32.to_le_bytes(), "{ if (!P2.new) R9:8 = memd(R10+#360) }"); + test_invalid(&0b0100_0111_111_01010_11_1_11101_101_01000u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_100_0000_01010_11_1_00110_001_10011u32.to_le_bytes(), "{ memb(gp+#0x1533) = R6 }"); + test_display(&0b0100_100_0010_01010_11_1_00110_001_10011u32.to_le_bytes(), "{ memh(gp+#0x2a66) = R6 }"); + test_display(&0b0100_100_0011_01010_11_1_00110_001_10011u32.to_le_bytes(), "{ memh(gp+#0x2a66) = R6.H }"); + test_display(&0b0100_100_0100_01010_11_1_00110_001_10011u32.to_le_bytes(), "{ memw(gp+#0x54cc) = R6 }"); + test_display(&0b0100_100_0101_01010_11_1_00110_001_10011u32.to_le_bytes(), "{ memb(gp+#0x1533) = R6.new }"); + test_display(&0b0100_100_0101_01010_11_1_01110_001_10011u32.to_le_bytes(), "{ memh(gp+#0x2a66) = R6.new }"); + test_display(&0b0100_100_0101_01010_11_1_10110_001_10011u32.to_le_bytes(), "{ memw(gp+#0x54cc) = R6.new }"); + test_invalid(&0b0100_100_0101_01010_11_1_11110_001_10011u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_100_0110_01010_11_1_00110_001_10011u32.to_le_bytes(), "{ memd(gp+#0xa998) = R7:6 }"); + test_invalid(&0b0100_100_0111_01010_11_1_11110_001_10011u32.to_le_bytes(), DecodeError::InvalidOpcode); + + test_display(&0b0100_100_1000_01010_11_1_00110011_00110u32.to_le_bytes(), "{ R6 = memb(gp+#0x1533) }"); + test_display(&0b0100_100_1001_01010_11_1_00110011_00110u32.to_le_bytes(), "{ R6 = memub(gp+#0x1533) }"); + test_display(&0b0100_100_1010_01010_11_1_00110011_00110u32.to_le_bytes(), "{ R6 = memh(gp+#0x2a66) }"); + test_display(&0b0100_100_1011_01010_11_1_00110011_00110u32.to_le_bytes(), "{ R6 = memuh(gp+#0x2a66) }"); + test_display(&0b0100_100_1100_01010_11_1_00110011_00110u32.to_le_bytes(), "{ R6 = memw(gp+#0x54cc) }"); + test_invalid(&0b0100_100_1101_01010_11_1_00110011_00110u32.to_le_bytes(), DecodeError::InvalidOpcode); + test_display(&0b0100_100_1110_01010_11_1_00110011_00110u32.to_le_bytes(), "{ R7:6 = memd(gp+#0xa998) }"); + test_invalid(&0b0100_100_1111_01010_11_1_00110011_00110u32.to_le_bytes(), DecodeError::InvalidOpcode); } #[test] -- cgit v1.1