diff options
author | iximeow <me@iximeow.net> | 2025-03-29 02:27:42 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2025-03-29 02:27:42 -0700 |
commit | 8bcec993e3c5b9832ccee91e94eb5de6e80c9b24 (patch) | |
tree | f6bd0dae1803f0178257b69e1a945a463316b94a /src | |
parent | e5849e3fa4830c83825f2d2cf9ef62853012aea2 (diff) |
1101* is all thats left...
Diffstat (limited to 'src')
-rw-r--r-- | src/display.rs | 28 | ||||
-rw-r--r-- | src/lib.rs | 122 |
2 files changed, 148 insertions, 2 deletions
diff --git a/src/display.rs b/src/display.rs index ecd9a26..6e1c376 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,7 +1,7 @@ use core::fmt; use crate::{Instruction, InstructionPacket, Opcode, Operand}; -use crate::{AssignMode, BranchHint, DomainHint}; +use crate::{AssignMode, BranchHint, DomainHint, RawMode}; fn special_display_rules(op: &Opcode) -> bool { *op as u16 & 0x8000 == 0x8000 @@ -80,6 +80,12 @@ impl fmt::Display for Instruction { self.dest.as_ref().unwrap(), self.alt_dest.as_ref().unwrap(), self.opcode, self.sources[0]); } + Opcode::Any8VcmpbEq => { + return write!(f, "{} = {}any8(vcmpb.eq({}, {}))", + self.dest.as_ref().unwrap(), + if self.flags.negated { "!" } else { "" }, + self.sources[0], self.sources[1]); + } _ => { unreachable!("TODO: should be exhaustive for opcodes with special display rules"); } @@ -315,6 +321,12 @@ impl fmt::Display for Instruction { None => {} } + match self.flags.raw_mode { + Some(RawMode::Lo) => { f.write_str(":raw:lo")? }, + Some(RawMode::Hi) => { f.write_str(":raw:hi")? }, + None => {} + } + // DeallocateFrame is shown with `:raw` as a suffix, but after the taken/not-taken hint // same for DeallocReturn if self.opcode == Opcode::AllocFrame || self.opcode == Opcode::DeallocFrame || self.opcode == Opcode::DeallocReturn { @@ -586,6 +598,20 @@ impl fmt::Display for Opcode { Opcode::SfFixupr => { f.write_str("sffixupr") }, Opcode::SfInvsqrta => { f.write_str("sfinvsqrta") }, Opcode::Swiz => { f.write_str("swiz") }, + Opcode::Parity => { f.write_str("parity") }, + Opcode::Tlbmatch => { f.write_str("tlbmatch") }, + Opcode::Boundscheck => { f.write_str("boundscheck") }, + Opcode::Any8VcmpbEq => { f.write_str("any8vcmpbeq") }, + Opcode::Vmux => { f.write_str("vmux") }, + Opcode::VcmpwEq => { f.write_str("vcmpw.eq") }, + Opcode::VcmpwGt => { f.write_str("vcmpw.gt") }, + Opcode::VcmpwGtu => { f.write_str("vcmpw.gtu") }, + Opcode::VcmphEq => { f.write_str("vcmph.eq") }, + Opcode::VcmphGt => { f.write_str("vcmph.gt") }, + Opcode::VcmphGtu => { f.write_str("vcmph.gtu") }, + Opcode::VcmpbEq => { f.write_str("vcmpb.eq") }, + Opcode::VcmpbGt => { f.write_str("vcmpb.gt") }, + Opcode::VcmpbGtu => { f.write_str("vcmpb.gtu") }, } } } @@ -303,6 +303,12 @@ enum AssignMode { } #[derive(Debug, Copy, Clone)] +enum RawMode { + Lo, + Hi, +} + +#[derive(Debug, Copy, Clone)] struct InstFlags { predicate: Option<Predicate>, branch_hint: Option<BranchHint>, @@ -312,6 +318,7 @@ struct InstFlags { rounded: Option<RoundingMode>, threads: Option<DomainHint>, assign_mode: Option<AssignMode>, + raw_mode: Option<RawMode>, } #[derive(Debug, Copy, Clone)] @@ -331,6 +338,7 @@ impl Default for InstFlags { rounded: None, threads: None, assign_mode: None, + raw_mode: None, } } } @@ -651,6 +659,20 @@ pub enum Opcode { SfFixupr, Swiz, + Parity, + Vmux, + VcmpwEq, + VcmpwGt, + VcmpwGtu, + VcmphEq, + VcmphGt, + VcmphGtu, + VcmpbEq, + VcmpbGt, + VcmpbGtu, + Tlbmatch, + Boundscheck, + AndAnd = 0x8000, AndOr, OrAnd, @@ -663,6 +685,7 @@ pub enum Opcode { OrOrNot, AddClb, SfInvsqrta, + Any8VcmpbEq, } impl Opcode { @@ -1140,6 +1163,7 @@ trait DecodeHandler<T: Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Wor fn domain_hint(&mut self, _domain: DomainHint) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) } fn rounded(&mut self, _mode: RoundingMode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) } fn chop(&mut self) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) } + fn raw_mode(&mut self, _mode: RawMode) -> Result<(), <Hexagon as Arch>::DecodeError> { Ok(()) } fn on_word_read(&mut self, _word: <Hexagon as Arch>::Word) {} } @@ -1224,6 +1248,12 @@ impl<T: yaxpeax_arch::Reader<<Hexagon as Arch>::Address, <Hexagon as Arch>::Word flags.chop = true; Ok(()) } + fn raw_mode(&mut self, mode: RawMode) -> Result<(), <Hexagon as Arch>::DecodeError> { + let flags = &mut self.instructions[self.instruction_count as usize].flags; + assert!(flags.raw_mode.is_none()); + flags.raw_mode = Some(mode); + Ok(()) + } #[inline(always)] fn read_inst_word(&mut self, words: &mut T) -> Result<u32, <Hexagon as Arch>::DecodeError> { self.word_count += 1; @@ -4363,7 +4393,97 @@ fn decode_instruction< } } 0b1101 => { - todo!("iclass 1101"); + let opc_hi = (inst >> 24) & 0b1111; + let ddddd = reg_b0(inst); + let ttttt = reg_b8(inst); + let sssss = reg_b16(inst); + + match opc_hi { + 0b0000 => { + handler.on_dest_decoded(Operand::gpr(ddddd))?; + handler.on_source_decoded(Operand::gprpair(sssss)?)?; + handler.on_source_decoded(Operand::gprpair(ttttt)?)?; + handler.on_opcode_decoded(Opcode::Parity)?; + } + 0b0001 => { + let uu = ((inst >> 5) & 0b11) as u8; + handler.on_dest_decoded(Operand::gprpair(ddddd)?)?; + handler.on_source_decoded(Operand::pred(uu))?; + handler.on_source_decoded(Operand::gprpair(sssss)?)?; + handler.on_source_decoded(Operand::gprpair(ttttt)?)?; + handler.on_opcode_decoded(Opcode::Vmux)?; + } + 0b0010 => { + opcode_check!(inst & 0x80_00_00 == 0); + + let ophi = (inst >> 13) & 1; + let oplo = (inst >> 5) & 0b111; + let opc = oplo | (ophi << 3); + let dd = ddddd & 0b11; + + handler.on_dest_decoded(Operand::pred(dd))?; + handler.on_source_decoded(Operand::gprpair(sssss)?)?; + if opc != 0b1011 { + handler.on_source_decoded(Operand::gprpair(ttttt)?)?; + } else { + handler.on_source_decoded(Operand::gpr(ttttt))?; + } + + match opc { + 0b0000 => { + handler.on_opcode_decoded(Opcode::VcmpwEq)?; + } + 0b0001 => { + handler.on_opcode_decoded(Opcode::VcmpwGt)?; + } + 0b0010 => { + handler.on_opcode_decoded(Opcode::VcmpwGtu)?; + } + 0b0011 => { + handler.on_opcode_decoded(Opcode::VcmphEq)?; + } + 0b0100 => { + handler.on_opcode_decoded(Opcode::VcmphGt)?; + } + 0b0101 => { + handler.on_opcode_decoded(Opcode::VcmphGtu)?; + } + 0b0110 => { + handler.on_opcode_decoded(Opcode::VcmpbEq)?; + } + 0b0111 => { + handler.on_opcode_decoded(Opcode::VcmpbGtu)?; + } + 0b1000 => { + handler.on_opcode_decoded(Opcode::Any8VcmpbEq)?; + } + 0b1001 => { + handler.on_opcode_decoded(Opcode::Any8VcmpbEq)?; + handler.negate_result(); + } + 0b1010 => { + handler.on_opcode_decoded(Opcode::VcmpbGt)?; + } + 0b1011 => { + handler.on_opcode_decoded(Opcode::Tlbmatch)?; + } + 0b1100 => { + handler.on_opcode_decoded(Opcode::Boundscheck)?; + handler.raw_mode(RawMode::Lo)?; + } + 0b1101 => { + handler.on_opcode_decoded(Opcode::Boundscheck)?; + handler.raw_mode(RawMode::Hi)?; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + } + _ => { + todo!("other"); + }, + } } 0b1111 => { let ddddd = reg_b0(inst); |