summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2025-03-23 00:01:55 -0700
committeriximeow <me@iximeow.net>2025-03-23 00:01:55 -0700
commit6af27d4defec112ee9f6bbf7840336ccb5861fe4 (patch)
tree7344f56c4cf947ee21f72299abcc03af5388cc5f
parent1032026bfa72b52b82953b7506a25803b43852d3 (diff)
more loop support, transcription errors, etc
-rw-r--r--notes/encoding_table6
-rw-r--r--notes/grouped_encodings6
-rw-r--r--notes/reordered_encodings6
-rw-r--r--notes/todo54
-rw-r--r--src/display.rs39
-rw-r--r--src/lib.rs265
-rw-r--r--tests/from_brain.rs34
7 files changed, 374 insertions, 36 deletions
diff --git a/notes/encoding_table b/notes/encoding_table
index 5a6b4c0..2d4bc63 100644
--- a/notes/encoding_table
+++ b/notes/encoding_table
@@ -144,7 +144,7 @@ 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 1 1 0|1 1 0 0 1 1 1|s s s s s| P P |- - - - - - - - -|d d d d d| Rd=tlboc(Rss) - SYSTEM/slot 3
|0 1 1 0|0 0 0 0 0 0 0|s s s s s| P P |- i i i i i - - -|i i - - -| loop0(#r7:2,Rs) - CR/slot 3
|0 1 1 0|0 0 0 0 0 0 1|s s s s s| P P |- i i i i i - - -|i i - - -| loop1(#r7:2,Rs) - CR/slot 3
-|0 1 1 0|1 0 0 1 0 0 0|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
+|0 1 1 0|1 0 0 1 0 0 0|l l l l l| P P |- i i i i i l l l|i i - l l| loop0(#r7:2,#U10) - CR/slot 3
|0 1 1 0|1 0 0 1 0 0 1|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
|0 1 1 0|1 0 1 0 0 1 0|0 1 0 0 1| P P |- i i i i i i - -|d d d d d| Rd=add(pc,#u6) - CR/slot 3
|0 1 1 0|0 0 0 0 1 0 1|s s s s s| P P |- i i i i i - - -|i i - - -| p3=sp1loop0(#r7:2,Rs) - CR/slot 3
@@ -286,8 +286,8 @@ 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 1 1 0|0 0 0 1 0 0 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs!=#0) jump:t #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs>=#0) jump:nt #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs>=#0) jump:t #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs==#0) jump:nt #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs==#0) jump:t #r13:2 - J/slot 3
+|0 1 1 0|0 0 0 1 1 0 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs==#0) jump:nt #r13:2 - J/slot 3
+|0 1 1 0|0 0 0 1 1 0 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs==#0) jump:t #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs<=#0) jump:nt #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs<=#0) jump:t #r13:2 - J/slot 3
|ICLASS |P MajOp MinOp|s5 |Parse| |d5 |
diff --git a/notes/grouped_encodings b/notes/grouped_encodings
index b029403..429acae 100644
--- a/notes/grouped_encodings
+++ b/notes/grouped_encodings
@@ -138,7 +138,7 @@ 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 1 1 0|1 0 1 1 1 0 1|0 - - s s| P P |0 - - - - - - - -|- - - d d| Pd=all8(Ps) - CR/slot 3
|0 1 1 0|0 0 0 0 0 0 0|s s s s s| P P |- i i i i i - - -|i i - - -| loop0(#r7:2,Rs) - CR/slot 3
|0 1 1 0|0 0 0 0 0 0 1|s s s s s| P P |- i i i i i - - -|i i - - -| loop1(#r7:2,Rs) - CR/slot 3
-|0 1 1 0|1 0 0 1 0 0 0|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
+|0 1 1 0|1 0 0 1 0 0 0|l l l l l| P P |- i i i i i l l l|i i - l l| loop0(#r7:2,#U10) - CR/slot 3
|0 1 1 0|1 0 0 1 0 0 1|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
|0 1 1 0|1 0 1 0 0 1 0|0 1 0 0 1| P P |- i i i i i i - -|d d d d d| Rd=add(pc,#u6) - CR/slot 3
|0 1 1 0|0 0 0 0 1 0 1|s s s s s| P P |- i i i i i - - -|i i - - -| p3=sp1loop0(#r7:2,Rs) - CR/slot 3
@@ -280,8 +280,8 @@ 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 1 1 0|0 0 0 1 0 0 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs!=#0) jump:t #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs>=#0) jump:nt #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs>=#0) jump:t #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs==#0) jump:nt #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs==#0) jump:t #r13:2 - J/slot 3
+|0 1 1 0|0 0 0 1 1 0 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs==#0) jump:nt #r13:2 - J/slot 3
+|0 1 1 0|0 0 0 1 1 0 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs==#0) jump:t #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs<=#0) jump:nt #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs<=#0) jump:t #r13:2 - J/slot 3
|ICLASS |P MajOp MinOp|s5 |Parse| |d5 |
diff --git a/notes/reordered_encodings b/notes/reordered_encodings
index b775217..64a87c4 100644
--- a/notes/reordered_encodings
+++ b/notes/reordered_encodings
@@ -337,10 +337,10 @@ 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 1 1 0|0 0 0 0 1 1 1|s s s s s| P P |- i i i i i - - -|i i - - -| p3=sp3loop0(#r7:2,Rs) - CR/slot 3
|0 1 1 0|0 0 0 1 0 0 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs!=#0) jump:nt #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 0 0 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs!=#0) jump:t #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs==#0) jump:nt #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs>=#0) jump:nt #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs==#0) jump:t #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs>=#0) jump:t #r13:2 - J/slot 3
+|0 1 1 0|0 0 0 1 1 0 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs==#0) jump:nt #r13:2 - J/slot 3
+|0 1 1 0|0 0 0 1 1 0 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs==#0) jump:t #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs<=#0) jump:nt #r13:2 - J/slot 3
|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs<=#0) jump:t #r13:2 - J/slot 3
|0 1 1 0|0 0 1 0 0 0 1|s s s s s| P P |- - - - - - - - -|d d d d d| Cd=Rs - CR/slot 3 - CONTROL REGISTERS ARE NOT NUMBERED NORMALLY
@@ -350,7 +350,7 @@ 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 1 1 0|0 0 1 0 0 1 0|s s s s s| P P |- t t t t t 0 1 1|- - - - -| diag1(Rss,Rtt) - SYSTEM/slot 3
|0 1 1 0|0 0 1 1 0 0 1|s s s s s| P P |- - - - - - - - -|d d d d d| Cdd=Rss - CR/slot 3 - CONTROL REGISTERS ARE NOT NUMBERED NORMALLY
|0 1 1 0|1 0 0 0 0 0 0|s s s s s| P P |- - - - - - - - -|d d d d d| Rss=Cdd - CR/slot 3 - CONTROL REGISTERS ARE NOT NUMBERED NORMALLY
-|0 1 1 0|1 0 0 1 0 0 0|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
+|0 1 1 0|1 0 0 1 0 0 0|l l l l l| P P |- i i i i i l l l|i i - l l| loop0(#r7:2,#U10) - CR/slot 3
|0 1 1 0|1 0 0 1 0 0 1|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
|0 1 1 0|1 0 0 1 1 0 1|l l l l l| P P |- i i i i i l l l|i i - l l| p3=sp1loop0(#r7:2,#U10) - CR/slot 3
|0 1 1 0|1 0 0 1 1 1 0|l l l l l| P P |- i i i i i l l l|i i - l l| p3=sp2loop0(#r7:2,#U10) - CR/slot 3
diff --git a/notes/todo b/notes/todo
index 4ad9a6b..f438457 100644
--- a/notes/todo
+++ b/notes/todo
@@ -330,31 +330,31 @@ 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 1 1 0|0 0 0 0 0 0 0|s s s s s| P P |- i i i i i - - -|i i - - -| loop0(#r7:2,Rs) - CR/slot 3
-|0 1 1 0|0 0 0 0 0 0 1|s s s s s| P P |- i i i i i - - -|i i - - -| loop1(#r7:2,Rs) - CR/slot 3
-|0 1 1 0|0 0 0 0 1 0 1|s s s s s| P P |- i i i i i - - -|i i - - -| p3=sp1loop0(#r7:2,Rs) - CR/slot 3
-|0 1 1 0|0 0 0 0 1 1 0|s s s s s| P P |- i i i i i - - -|i i - - -| p3=sp2loop0(#r7:2,Rs) - CR/slot 3
-|0 1 1 0|0 0 0 0 1 1 1|s s s s s| P P |- i i i i i - - -|i i - - -| p3=sp3loop0(#r7:2,Rs) - CR/slot 3
-|0 1 1 0|0 0 0 1 0 0 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs!=#0) jump:nt #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 0 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs!=#0) jump:t #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs==#0) jump:nt #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs>=#0) jump:nt #r13:2 - J/slot 3 # TODO: probably transcription error
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs==#0) jump:t #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 0 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs>=#0) jump:t #r13:2 - J/slot 3 # TODO: probably transcription error
-|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 0 i i i i i i i|i i i i -| if (Rs<=#0) jump:nt #r13:2 - J/slot 3
-|0 1 1 0|0 0 0 1 1 1 i|s s s s s| P P |i 1 i i i i i i i|i i i i -| if (Rs<=#0) jump:t #r13:2 - J/slot 3
-
-|0 1 1 0|0 0 1 0 0 1 0|s s s s s| P P |- - - - - - 0 0 0|- - - - -| trace(Rs) - SYSTEM/slot 3
-|0 1 1 0|0 0 1 0 0 1 0|s s s s s| P P |- - - - - - 0 0 1|- - - - -| diag(Rs) - SYSTEM/slot 3
-|0 1 1 0|0 0 1 0 0 1 0|s s s s s| P P |- t t t t t 0 1 0|- - - - -| diag0(Rss,Rtt) - SYSTEM/slot 3
-|0 1 1 0|0 0 1 0 0 1 0|s s s s s| P P |- t t t t t 0 1 1|- - - - -| diag1(Rss,Rtt) - SYSTEM/slot 3
-
-
-|0 1 1 0|1 0 0 1 0 0 0|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
-|0 1 1 0|1 0 0 1 0 0 1|l l l l l| P P |- i i i i i l l l|i i - l l| loop1(#r7:2,#U10) - CR/slot 3
-|0 1 1 0|1 0 0 1 1 0 1|l l l l l| P P |- i i i i i l l l|i i - l l| p3=sp1loop0(#r7:2,#U10) - CR/slot 3
-|0 1 1 0|1 0 0 1 1 1 0|l l l l l| P P |- i i i i i l l l|i i - l l| p3=sp2loop0(#r7:2,#U10) - CR/slot 3
-|0 1 1 0|1 0 0 1 1 1 1|l l l l l| P P |- i i i i i l l l|i i - l l| p3=sp3loop0(#r7:2,#U10) - CR/slot 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|0 1 1 0|1 0 1 1 0 0 0|0 - - s s| P P |0 - - - t t - - -|- - - d d| Pd=and(Pt,Ps) - CR/slot 3
@@ -375,8 +375,8 @@ 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 1 1 0|1 0 1 1 1 1 0|1 - - s s| P P |0 - - - t t u u -|- - - d d| Pd=or(Ps,and(Pt,Pu)) - CR/slot 3
|0 1 1 0|1 0 1 1 1 1 1|0 - - s s| P P |0 - - - t t - - -|- - - d d| Pd=or(Pt,!Ps) - CR/slot 3
|0 1 1 0|1 0 1 1 1 1 1|1 - - s s| P P |0 - - - t t u u -|- - - d d| Pd=or(Ps,or(Pt,Pu)) - CR/slot 3
-|0 1 1 0|1 1 0 0 0 0 1|- - - - -| P P |- - - - - - 0 0 0|- - - - -| barrier - SYSTEM/slot 0
-|0 1 1 0|1 1 1 1 1 1 1|t t t t t| P P |0 s s s s s 0 1 0|d d d d d| Rd=movlen(Rs,Rtt) - LD/slot 0,1 - Solo
+
+
diff --git a/src/display.rs b/src/display.rs
index c40be08..34fb6a7 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -25,6 +25,28 @@ impl fmt::Display for InstructionPacket {
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ static REG_COMPARE_JUMPS: &[Opcode] = &[
+ Opcode::JumpRegNz, Opcode::JumpRegGez,
+ Opcode::JumpRegZ, Opcode::JumpRegLez,
+ ];
+ if REG_COMPARE_JUMPS.contains(&self.opcode) {
+ return write!(f, "if ({}{}#0) jump{} {}",
+ self.sources[0],
+ match self.opcode {
+ Opcode::JumpRegZ => "==",
+ Opcode::JumpRegNz => "!=",
+ Opcode::JumpRegGez => ">=",
+ // JumpRegLez, the one other option
+ _ => "<=",
+ },
+ match self.flags.branch_hint {
+ Some(BranchHint::Taken) => { ":t" },
+ Some(BranchHint::NotTaken) => { ":nt" },
+ None => { "" },
+ },
+ self.dest.as_ref().unwrap()
+ );
+ }
// handle cmp+jump first; this includes elements that would be misformatted below (like
// predication)
static COMPARE_JUMPS: &[Opcode] = &[
@@ -316,6 +338,11 @@ impl fmt::Display for Opcode {
Opcode::CmpGtuJump => { f.write_str("p=cmp.gtu+if(p.new)jump") },
Opcode::TestClrJump => { f.write_str("p=tstbit+if(p.new)jump") },
+ Opcode::JumpRegZ => { f.write_str("if(rn==0)jump") },
+ Opcode::JumpRegNz => { f.write_str("if(rn!=0)jump") },
+ Opcode::JumpRegGez => { f.write_str("if(rn>=0)jump") },
+ Opcode::JumpRegLez => { f.write_str("if(rn<=0)jump") },
+
Opcode::Tlbw => { f.write_str("tlbw") },
Opcode::Tlbr => { f.write_str("tlbr") },
Opcode::Tlbp => { f.write_str("tlbp") },
@@ -406,6 +433,18 @@ impl fmt::Display for Opcode {
Opcode::MemdAq => { f.write_str("memd_aq") },
Opcode::Pmemcpy => { f.write_str("pmemcpy") },
Opcode::Linecpy => { f.write_str("linecpy") },
+
+ Opcode::Loop0 => { f.write_str("loop0") },
+ Opcode::Loop1 => { f.write_str("loop1") },
+ Opcode::Sp1Loop0 => { f.write_str("sp1loop0") },
+ Opcode::Sp2Loop0 => { f.write_str("sp2loop0") },
+ Opcode::Sp3Loop0 => { f.write_str("sp3loop0") },
+ Opcode::Trace => { f.write_str("trace") },
+ Opcode::Diag => { f.write_str("diag") },
+ Opcode::Diag0 => { f.write_str("diag0") },
+ Opcode::Diag1 => { f.write_str("diag1") },
+
+ Opcode::Movlen => { f.write_str("movlen") },
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 98b6f17..d3220a7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -450,6 +450,23 @@ pub enum Opcode {
/// predicate register used for branch condition is part of normal predication bits
CmpGtuJump,
+ /// jump conditioned on a register being equal to zero
+ ///
+ /// source 1 is the register used for jump conditioning, source 2 is the relative branch
+ JumpRegZ,
+ /// jump conditioned on a register being nonzero
+ ///
+ /// source 1 is the register used for jump conditioning, source 2 is the relative branch
+ JumpRegNz,
+ /// jump conditioned on a register being greater than or equal to zero
+ ///
+ /// source 1 is the register used for jump conditioning, source 2 is the relative branch
+ JumpRegGez,
+ /// jump conditioned on a register being less than or equal to zero
+ ///
+ /// source 1 is the register used for jump conditioning, source 2 is the relative branch
+ JumpRegLez,
+
Add,
And,
And_nRR,
@@ -546,6 +563,18 @@ pub enum Opcode {
Pmemcpy,
Linecpy,
+
+ Loop0,
+ Loop1,
+ Sp1Loop0,
+ Sp2Loop0,
+ Sp3Loop0,
+ Trace,
+ Diag,
+ Diag0,
+ Diag1,
+
+ Movlen,
}
impl Opcode {
@@ -2032,6 +2061,123 @@ fn decode_instruction<
let opbits = (inst >> 21) & 0b1111111;
match opbits {
+ 0b0000000 => {
+ let sssss = reg_b16(inst);
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ }
+ 0b0000001 => {
+ let sssss = reg_b16(inst);
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Loop1)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ }
+ 0b0000010 | 0b0000011 => {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ 0b0000101 => {
+ let sssss = reg_b16(inst);
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Sp1Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_dest_decoded(Operand::pred(3))?;
+ }
+ 0b0000110 => {
+ let sssss = reg_b16(inst);
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Sp2Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_dest_decoded(Operand::pred(3))?;
+ }
+ 0b0000111 => {
+ let sssss = reg_b16(inst);
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Sp3Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_dest_decoded(Operand::pred(3))?;
+ }
+ 0b0001000 | 0b0001001 => {
+ let sssss = reg_b16(inst);
+ let i11 = (inst >> 1) & 0b111_1111_1111;
+ let i_mid = (inst >> 13) & 1;
+ let i_hi = (inst >> 21) & 1;
+ let i13 = i11 | (i_mid << 11) | (i_hi << 12);
+ let rel = (i13 << 3) as i16 as i32 >> 1;
+
+ let taken = (inst >> 12) & 1 == 1;
+ handler.branch_hint(taken)?;
+ handler.on_opcode_decoded(Opcode::JumpRegNz)?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_dest_decoded(Operand::PCRel32 { rel })?;
+ }
+ 0b0001010 | 0b0001011 => {
+ let sssss = reg_b16(inst);
+ let i11 = (inst >> 1) & 0b111_1111_1111;
+ let i_mid = (inst >> 13) & 1;
+ let i_hi = (inst >> 21) & 1;
+ let i13 = i11 | (i_mid << 11) | (i_hi << 12);
+ let rel = (i13 << 3) as i16 as i32 >> 1;
+
+ let taken = (inst >> 12) & 1 == 1;
+ handler.branch_hint(taken)?;
+ handler.on_opcode_decoded(Opcode::JumpRegGez)?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_dest_decoded(Operand::PCRel32 { rel })?;
+ }
+ 0b0001100 | 0b0001101 => {
+ let sssss = reg_b16(inst);
+ let i11 = (inst >> 1) & 0b111_1111_1111;
+ let i_mid = (inst >> 13) & 1;
+ let i_hi = (inst >> 21) & 1;
+ let i13 = i11 | (i_mid << 11) | (i_hi << 12);
+ let rel = (i13 << 3) as i16 as i32 >> 1;
+
+ let taken = (inst >> 12) & 1 == 1;
+ handler.branch_hint(taken)?;
+ handler.on_opcode_decoded(Opcode::JumpRegZ)?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_dest_decoded(Operand::PCRel32 { rel })?;
+ }
+ 0b0001110 | 0b0001111 => {
+ let sssss = reg_b16(inst);
+ let i11 = (inst >> 1) & 0b111_1111_1111;
+ let i_mid = (inst >> 13) & 1;
+ let i_hi = (inst >> 21) & 1;
+ let i13 = i11 | (i_mid << 11) | (i_hi << 12);
+ let rel = (i13 << 3) as i16 as i32 >> 1;
+
+ let taken = (inst >> 12) & 1 == 1;
+ handler.branch_hint(taken)?;
+ handler.on_opcode_decoded(Opcode::JumpRegLez)?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_dest_decoded(Operand::PCRel32 { rel })?;
+ }
0b0010001 => {
let sssss = reg_b16(inst);
let ddddd = reg_b0(inst);
@@ -2039,6 +2185,32 @@ fn decode_instruction<
handler.on_source_decoded(Operand::gpr(sssss))?;
handler.on_dest_decoded(Operand::cr(ddddd))?;
}
+ 0b0010010 => {
+ let opc = (inst >> 5) & 0b111;
+ let sssss = reg_b16(inst);
+ let ttttt = reg_b8(inst);
+ match opc {
+ 0b000 => {
+ handler.on_opcode_decoded(Opcode::Trace)?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ },
+ 0b001 => {
+ handler.on_opcode_decoded(Opcode::Diag)?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ },
+ 0b010 => {
+ handler.on_opcode_decoded(Opcode::Diag0)?;
+ handler.on_source_decoded(Operand::gprpair(sssss)?)?;
+ handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
+ },
+ 0b011 => {
+ handler.on_opcode_decoded(Opcode::Diag1)?;
+ handler.on_source_decoded(Operand::gprpair(sssss)?)?;
+ handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
+ },
+ _ => { return Err(DecodeError::InvalidOpcode); }
+ };
+ }
0b0111000 => {
// not in V73! store to supervisor register?
let sssss = reg_b16(inst);
@@ -2047,6 +2219,11 @@ fn decode_instruction<
handler.on_dest_decoded(Operand::sr(ddddddd as u8))?;
handler.on_source_decoded(Operand::gpr(sssss))?;
}
+ // TODO: 1001000 loop0 goes here
+ 0b1100001 => {
+ opcode_check!((inst >> 5) & 0b111 == 0);
+ handler.on_opcode_decoded(Opcode::Barrier)?;
+ }
0b1101000 => {
// not in V73! store to supervisor register?
let sssss = reg_b16(inst);
@@ -2087,6 +2264,84 @@ fn decode_instruction<
handler.on_source_decoded(Operand::crpair(sssss)?)?;
handler.on_dest_decoded(Operand::gprpair(ddddd)?)?;
}
+ 0b1001000 => {
+ let lllll = reg_b16(inst) as u32;
+ let l_mid = (inst >> 5) & 0b111;
+ let l_low = inst & 0b11;
+ let l10 = l_low | (l_mid << 2) | (lllll << 5);
+
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
+ }
+ 0b1001001 => {
+ let lllll = reg_b16(inst) as u32;
+ let l_mid = (inst >> 5) & 0b111;
+ let l_low = inst & 0b11;
+ let l10 = l_low | (l_mid << 2) | (lllll << 5);
+
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Loop1)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
+ }
+ 0b1001101 => {
+ let lllll = reg_b16(inst) as u32;
+ let l_mid = (inst >> 5) & 0b111;
+ let l_low = inst & 0b11;
+ let l10 = l_low | (l_mid << 2) | (lllll << 5);
+
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Sp1Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
+ handler.on_dest_decoded(Operand::pred(3))?;
+ }
+ 0b1001110 => {
+ let lllll = reg_b16(inst) as u32;
+ let l_mid = (inst >> 5) & 0b111;
+ let l_low = inst & 0b11;
+ let l10 = l_low | (l_mid << 2) | (lllll << 5);
+
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Sp2Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
+ handler.on_dest_decoded(Operand::pred(3))?;
+ }
+ 0b1001111 => {
+ let lllll = reg_b16(inst) as u32;
+ let l_mid = (inst >> 5) & 0b111;
+ let l_low = inst & 0b11;
+ let l10 = l_low | (l_mid << 2) | (lllll << 5);
+
+ let iiiii = reg_b8(inst);
+ let ii = ((inst >> 3) & 0b11) as u8;
+ let i7 = (iiiii << 2) | ii;
+ let rel = ((i7 << 1) as i8 as i32) << 1;
+
+ handler.on_opcode_decoded(Opcode::Sp3Loop0)?;
+ handler.on_source_decoded(Operand::PCRel32 { rel })?;
+ handler.on_source_decoded(Operand::ImmU16 { imm: l10 as u16 })?;
+ handler.on_dest_decoded(Operand::pred(3))?;
+ }
0b1010000 => {
let sssss = reg_b16(inst);
let ddddd = reg_b0(inst);
@@ -2153,6 +2408,16 @@ fn decode_instruction<
handler.on_source_decoded(Operand::gprpair(sssss)?)?;
handler.on_dest_decoded(Operand::gpr(ddddd))?;
}
+ 0b1111111 => {
+ opcode_check!((inst >> 5) & 0b100000111 == 0b010);
+ let ddddd = reg_b0(inst);
+ let sssss = reg_b8(inst);
+ let ttttt = reg_b16(inst);
+ handler.on_opcode_decoded(Opcode::Movlen)?;
+ handler.on_dest_decoded(Operand::gpr(ddddd))?;
+ handler.on_source_decoded(Operand::gpr(sssss))?;
+ handler.on_source_decoded(Operand::gprpair(ttttt)?)?;
+ }
_ => {
eprintln!("!!! TODO: {:07b} !!!", opbits);
}
diff --git a/tests/from_brain.rs b/tests/from_brain.rs
index d87ac2e..ca403fd 100644
--- a/tests/from_brain.rs
+++ b/tests/from_brain.rs
@@ -280,11 +280,45 @@ fn inst_0101() {
#[test]
fn inst_0110() {
+ test_display(&0b0110_0000000_00110_11_0_00010_000_01000u32.to_le_bytes(), "{ loop0($+#36, R6) }");
+ test_display(&0b0110_0000001_00110_11_0_00010_000_01000u32.to_le_bytes(), "{ loop1($+#36, R6) }");
+ test_invalid(&0b0110_0000010_00110_11_0_00010_000_01000u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_invalid(&0b0110_0000011_00110_11_0_00010_000_01000u32.to_le_bytes(), DecodeError::InvalidOpcode);
+ test_display(&0b0110_0000101_00110_11_0_00010_000_01000u32.to_le_bytes(), "{ P3 = sp1loop0($+#36, R6) }");
+ test_display(&0b0110_0000110_00110_11_0_00010_000_01000u32.to_le_bytes(), "{ P3 = sp2loop0($+#36, R6) }");
+ test_display(&0b0110_0000111_00110_11_0_00010_000_01000u32.to_le_bytes(), "{ P3 = sp3loop0($+#36, R6) }");
+
+ // TODO: test signed (negative) offsets
+ test_display(&0b0110_0001001_00110_11_1_000101_00_10110u32.to_le_bytes(), "{ if (R6!=#0) jump:nt $+#-6868 }");
+ test_display(&0b0110_0001001_00110_11_1_100101_00_10110u32.to_le_bytes(), "{ if (R6!=#0) jump:t $+#-6868 }");
+ test_display(&0b0110_0001011_00110_11_1_000101_00_10110u32.to_le_bytes(), "{ if (R6>=#0) jump:nt $+#-6868 }");
+ test_display(&0b0110_0001011_00110_11_1_100101_00_10110u32.to_le_bytes(), "{ if (R6>=#0) jump:t $+#-6868 }");
+ test_display(&0b0110_0001101_00110_11_1_000101_00_10110u32.to_le_bytes(), "{ if (R6==#0) jump:nt $+#-6868 }");
+ test_display(&0b0110_0001101_00110_11_1_100101_00_10110u32.to_le_bytes(), "{ if (R6==#0) jump:t $+#-6868 }");
+ test_display(&0b0110_0001111_00110_11_1_000101_00_10110u32.to_le_bytes(), "{ if (R6<=#0) jump:nt $+#-6868 }");
+ test_display(&0b0110_0001111_00110_11_1_100101_00_10110u32.to_le_bytes(), "{ if (R6<=#0) jump:t $+#-6868 }");
+
test_display(&0b0110_0010001_00110_11_0_000101_00_10110u32.to_le_bytes(), "{ C22 = R6 }");
+ test_display(&0b0110_0010010_00110_11_0_00000_000_01000u32.to_le_bytes(), "{ trace(R6) }");
+ test_display(&0b0110_0010010_00110_11_0_00000_001_01000u32.to_le_bytes(), "{ diag(R6) }");
+ test_display(&0b0110_0010010_00110_11_0_00100_010_01000u32.to_le_bytes(), "{ diag0(R7:6, R5:4) }");
+ test_display(&0b0110_0010010_00110_11_0_00100_011_01000u32.to_le_bytes(), "{ diag1(R7:6, R5:4) }");
+
test_display(&0b0110_0011001_00110_11_0_000101_00_10110u32.to_le_bytes(), "{ C23:22 = R7:6 }");
test_display(&0b0110_1000000_00110_11_0_000101_00_10110u32.to_le_bytes(), "{ R23:22 = C7:6 }");
+
+ test_display(&0b0110_1001000_00110_11_0_000101_00_01010u32.to_le_bytes(), "{ loop0($+#36, #0xd2) }");
+ test_display(&0b0110_1001001_00110_11_0_000101_00_01010u32.to_le_bytes(), "{ loop1($+#36, #0xd2) }");
+ test_display(&0b0110_1001101_00110_11_0_000101_00_01010u32.to_le_bytes(), "{ P3 = sp1loop0($+#36, #0xd2) }");
+ test_display(&0b0110_1001110_00110_11_0_000101_00_01010u32.to_le_bytes(), "{ P3 = sp2loop0($+#36, #0xd2) }");
+ test_display(&0b0110_1001111_00110_11_0_000101_00_01010u32.to_le_bytes(), "{ P3 = sp3loop0($+#36, #0xd2) }");
+
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_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) }");
}
#[test]