diff options
-rw-r--r-- | notes/encoding_table | 6 | ||||
-rw-r--r-- | notes/grouped_encodings | 6 | ||||
-rw-r--r-- | notes/reordered_encodings | 6 | ||||
-rw-r--r-- | notes/todo | 54 | ||||
-rw-r--r-- | src/display.rs | 39 | ||||
-rw-r--r-- | src/lib.rs | 265 | ||||
-rw-r--r-- | tests/from_brain.rs | 34 |
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 @@ -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") }, } } } @@ -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] |