diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/display.rs | 39 | ||||
-rw-r--r-- | src/lib.rs | 265 |
2 files changed, 304 insertions, 0 deletions
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); } |