summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-10-10 14:27:56 -0700
committeriximeow <me@iximeow.net>2020-10-10 14:27:56 -0700
commitbd7cae741ca961ef6d5959bbf060205d9c514af0 (patch)
tree709bdd04ba392c30386ef5069f2911d07079d693
parent0a67a0cffdb503967885422c2b966a0e70ec6969 (diff)
start getting display impls together, distinguish read/write operands
-rw-r--r--src/lib.rs2072
-rw-r--r--tests/test.rs29
2 files changed, 1967 insertions, 134 deletions
diff --git a/src/lib.rs b/src/lib.rs
index b8dc192..491b3d1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,12 +10,18 @@ pub struct IA64;
impl Arch for IA64 {
type Address = u64;
- type Instruction = Instruction;
+ type Instruction = InstructionBundle;
type DecodeError = DecodeError;
type Decoder = InstDecoder;
type Operand = Operand;
}
+impl Default for Opcode {
+ fn default() -> Self {
+ Opcode::White
+ }
+}
+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[allow(non_camel_case_types)]
pub enum Opcode {
@@ -310,7 +316,8 @@ pub enum Opcode {
Mov_to_pr_rot_imm,
Mov_to_pr,
Mov_from_pr,
- Mov_to_b,
+ Mov_mwh_ih,
+ Mov_ret_mwh_ih,
Dep,
Tbit_z,
Tnat_z,
@@ -493,21 +500,589 @@ pub enum Opcode {
Fselect,
}
+impl fmt::Display for Opcode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ // TODO: what kind of no-op/undefined are these exactly
+ Opcode::Purple => { write!(f, "purple") }
+ Opcode::Cyan => { write!(f, "cyan") }
+ Opcode::Brown => { write!(f, "brown") }
+ Opcode::White => { write!(f, "white") }
+
+ Opcode::Addp4 => { write!(f, "addp4") }
+ Opcode::Adds => { write!(f, "adds") }
+ Opcode::Addl => { write!(f, "addl") }
+ Opcode::Add => { write!(f, "add") }
+ Opcode::AddPlusOne => { write!(f, "addplusone") }
+ Opcode::Sub => { write!(f, "sub") }
+ Opcode::SubMinusOne => { write!(f, "subminusone") }
+ Opcode::SubImm => { write!(f, "subimm") }
+ Opcode::AndImm => { write!(f, "andimm") }
+ Opcode::AndcmImm => { write!(f, "andcmimm") }
+ Opcode::OrImm => { write!(f, "orimm") }
+ Opcode::XorImm => { write!(f, "xorimm") }
+ Opcode::And => { write!(f, "and") }
+ Opcode::Andcm => { write!(f, "andcm") }
+ Opcode::Or => { write!(f, "or") }
+ Opcode::Xor => { write!(f, "xor") }
+
+ Opcode::Ptc_l => { write!(f, "ptc.l") }
+ Opcode::Probe_w_imm => { write!(f, "probe.w.imm") }
+ Opcode::Mov_to_psr_um => { write!(f, "mov.to.psr.um") }
+ Opcode::Probe_w => { write!(f, "probe.w") }
+ Opcode::Ptc_g => { write!(f, "ptc.g") }
+ Opcode::Thash => { write!(f, "thash") }
+ Opcode::Mov_m => { write!(f, "mov.m") }
+ Opcode::Ptc_ga => { write!(f, "ptc.ga") }
+ Opcode::Ttag => { write!(f, "ttag") }
+ Opcode::Ptr_d => { write!(f, "ptr.d") }
+ Opcode::Mov_to_cr => { write!(f, "mov.to.cr") }
+ Opcode::Ptr_i => { write!(f, "ptr.i") }
+ Opcode::Mov_to_psr_l => { write!(f, "mov.to.psr.l") }
+ Opcode::Itr_d => { write!(f, "itr.d") }
+ Opcode::Tpa => { write!(f, "tpa") }
+ Opcode::Itc_d => { write!(f, "itc.d") }
+ Opcode::Itr_i => { write!(f, "itr.i") }
+ Opcode::Tak => { write!(f, "tak") }
+ Opcode::Itc_i => { write!(f, "itc.i") }
+ Opcode::Chk_s_m_int => { write!(f, "chk.s.m.int") }
+ Opcode::Chk_s_fp => { write!(f, "chk.s.fp") }
+ Opcode::Alloc => { write!(f, "alloc") }
+ Opcode::Ld1 => { write!(f, "ld1") }
+ Opcode::Ld2 => { write!(f, "ld2") }
+ Opcode::Ld4 => { write!(f, "ld4") }
+ Opcode::Ld8 => { write!(f, "ld8") }
+ Opcode::Ld1_s => { write!(f, "ld1.s") }
+ Opcode::Ld2_s => { write!(f, "ld2.s") }
+ Opcode::Ld4_s => { write!(f, "ld4.s") }
+ Opcode::Ld8_s => { write!(f, "ld8.s") }
+ Opcode::Ld1_a => { write!(f, "ld1.a") }
+ Opcode::Ld2_a => { write!(f, "ld2.a") }
+ Opcode::Ld4_a => { write!(f, "ld4.a") }
+ Opcode::Ld8_a => { write!(f, "ld8.a") }
+ Opcode::Ld1_sa => { write!(f, "ld1.sa") }
+ Opcode::Ld2_sa => { write!(f, "ld2.sa") }
+ Opcode::Ld4_sa => { write!(f, "ld4.sa") }
+ Opcode::Ld8_sa => { write!(f, "ld8.sa") }
+ Opcode::Ld1_bias => { write!(f, "ld1.bias") }
+ Opcode::Ld2_bias => { write!(f, "ld2.bias") }
+ Opcode::Ld4_bias => { write!(f, "ld4.bias") }
+ Opcode::Ld8_bias => { write!(f, "ld8.bias") }
+ Opcode::Ld1_acq => { write!(f, "ld1.acq") }
+ Opcode::Ld2_acq => { write!(f, "ld2.acq") }
+ Opcode::Ld4_acq => { write!(f, "ld4.acq") }
+ Opcode::Ld8_acq => { write!(f, "ld8.acq") }
+ Opcode::Ld8_fill => { write!(f, "ld8.fill") }
+ Opcode::Ld1_c_clr => { write!(f, "ld1.c.clr") }
+ Opcode::Ld2_c_clr => { write!(f, "ld2.c.clr") }
+ Opcode::Ld4_c_clr => { write!(f, "ld4.c.clr") }
+ Opcode::Ld8_c_clr => { write!(f, "ld8.c.clr") }
+ Opcode::Ld1_c_nc => { write!(f, "ld1.c.nc") }
+ Opcode::Ld2_c_nc => { write!(f, "ld2.c.nc") }
+ Opcode::Ld4_c_nc => { write!(f, "ld4.c.nc") }
+ Opcode::Ld8_c_nc => { write!(f, "ld8.c.nc") }
+ Opcode::Ld1_c_clr_acq => { write!(f, "ld1.c.clr.acq") }
+ Opcode::Ld2_c_clr_acq => { write!(f, "ld2.c.clr.acq") }
+ Opcode::Ld4_c_clr_acq => { write!(f, "ld4.c.clr.acq") }
+ Opcode::Ld8_c_clr_acq => { write!(f, "ld8.c.clr.acq") }
+ Opcode::St1 => { write!(f, "st1") }
+ Opcode::St2 => { write!(f, "st2") }
+ Opcode::St4 => { write!(f, "st4") }
+ Opcode::St8 => { write!(f, "st8") }
+ Opcode::St1_rel => { write!(f, "st1.rel") }
+ Opcode::St2_rel => { write!(f, "st2.rel") }
+ Opcode::St4_rel => { write!(f, "st4.rel") }
+ Opcode::St8_rel => { write!(f, "st8.rel") }
+ Opcode::St8_spill => { write!(f, "st8.spill") }
+ Opcode::Mov_to_pmd => { write!(f, "mov.to.pmd") }
+ Opcode::Mov_from_pmd => { write!(f, "mov.from.pmd") }
+ Opcode::Mov_from_psr => { write!(f, "mov.from.psr") }
+ Opcode::Mov_from_cpuid => { write!(f, "mov.from.cpuid") }
+ Opcode::Probe_r_imm => { write!(f, "probe.r.imm") }
+ Opcode::Probe_r => { write!(f, "probe.r") }
+ Opcode::Cmpxchg1_acq => { write!(f, "cmpxchg1.acq") }
+ Opcode::Cmpxchg2_acq => { write!(f, "cmpxchg2.acq") }
+ Opcode::Cmpxchg4_acq => { write!(f, "cmpxchg4.acq") }
+ Opcode::Cmpxchg8_acq => { write!(f, "cmpxchg8.acq") }
+ Opcode::Cmpxchg1_rel => { write!(f, "cmpxchg1.rel") }
+ Opcode::Cmpxchg2_rel => { write!(f, "cmpxchg2.rel") }
+ Opcode::Cmpxchg4_rel => { write!(f, "cmpxchg4.rel") }
+ Opcode::Cmpxchg8_rel => { write!(f, "cmpxchg8.rel") }
+ Opcode::Xchg1 => { write!(f, "xchg1") }
+ Opcode::Xchg2 => { write!(f, "xchg2") }
+ Opcode::Xchg4 => { write!(f, "xchg4") }
+ Opcode::Xchg8 => { write!(f, "xchg8") }
+ Opcode::Fetchadd4_acq => { write!(f, "fetchadd4.acq") }
+ Opcode::Fetchadd8_acq => { write!(f, "fetchadd8.acq") }
+ Opcode::Fetchadd4_rel => { write!(f, "fetchadd4.rel") }
+ Opcode::Fetchadd8_rel => { write!(f, "fetchadd8.rel") }
+ Opcode::Getf_sig => { write!(f, "getf.sig") }
+ Opcode::Getf_exp => { write!(f, "getf.exp") }
+ Opcode::Getf_s => { write!(f, "getf.s") }
+ Opcode::Getf_d => { write!(f, "getf.d") }
+ Opcode::Cmp8xchg16_acq => { write!(f, "cmp8xchg16.acq") }
+ Opcode::Cmp8xchg16_rel => { write!(f, "cmp8xchg16.rel") }
+ Opcode::Ld16 => { write!(f, "ld16") }
+ Opcode::Ld16_acq => { write!(f, "ld16.acq") }
+ Opcode::St16 => { write!(f, "st16") }
+ Opcode::St16_rel => { write!(f, "st16.rel") }
+ Opcode::Ldfe => { write!(f, "ldfe") }
+ Opcode::Ldf8 => { write!(f, "ldf8") }
+ Opcode::Ldfs => { write!(f, "ldfs") }
+ Opcode::Ldfd => { write!(f, "ldfd") }
+ Opcode::Ldfe_s => { write!(f, "ldfe.s") }
+ Opcode::Ldf8_s => { write!(f, "ldf8.s") }
+ Opcode::Ldfs_s => { write!(f, "ldfs.s") }
+ Opcode::Ldfd_s => { write!(f, "ldfd.s") }
+ Opcode::Ldfe_a => { write!(f, "ldfe.a") }
+ Opcode::Ldf8_a => { write!(f, "ldf8.a") }
+ Opcode::Ldfs_a => { write!(f, "ldfs.a") }
+ Opcode::Ldfd_a => { write!(f, "ldfd.a") }
+ Opcode::Ldfe_sa => { write!(f, "ldfe.sa") }
+ Opcode::Ldf8_sa => { write!(f, "ldf8.sa") }
+ Opcode::Ldfs_sa => { write!(f, "ldfs.sa") }
+ Opcode::Ldfd_sa => { write!(f, "ldfd.sa") }
+ Opcode::Ldf_fill => { write!(f, "ldf.fill") }
+ Opcode::Ldfe_c_clr => { write!(f, "ldfe.c.clr") }
+ Opcode::Ldf8_c_clr => { write!(f, "ldf8.c.clr") }
+ Opcode::Ldfs_c_clr => { write!(f, "ldfs.c.clr") }
+ Opcode::Ldfd_c_clr => { write!(f, "ldfd.c.clr") }
+ Opcode::Ldfp8_c_clr => { write!(f, "ldfp8.c.clr") }
+ Opcode::Ldfps_c_clr => { write!(f, "ldfps.c.clr") }
+ Opcode::Ldfpd_c_clr => { write!(f, "ldfpd.c.clr") }
+ Opcode::Ldfp8_c_nc => { write!(f, "ldfp8.c.nc") }
+ Opcode::Ldfps_c_nc => { write!(f, "ldfps.c.nc") }
+ Opcode::Ldfpd_c_nc => { write!(f, "ldfpd.c.nc") }
+ Opcode::Break_m => { write!(f, "break.m") }
+ Opcode::Invala => { write!(f, "invala") }
+ Opcode::Fwb => { write!(f, "fwb") }
+ Opcode::Srlz_d => { write!(f, "srlz.d") }
+ Opcode::Srlz_i => { write!(f, "srlz.i") }
+ Opcode::Invala_e_int => { write!(f, "invala.e.int") }
+ Opcode::Mf => { write!(f, "mf") }
+ Opcode::Invala_e_fp => { write!(f, "invala.e.fp") }
+ Opcode::Mf_a => { write!(f, "mf.a") }
+ Opcode::Sync_i => { write!(f, "sync.i") }
+ Opcode::Sum => { write!(f, "sum") }
+ Opcode::Rum => { write!(f, "rum") }
+ Opcode::Ssm => { write!(f, "ssm") }
+ Opcode::Rsm => { write!(f, "rsm") }
+ Opcode::Loadrs => { write!(f, "loadrs") }
+ Opcode::Flushrs => { write!(f, "flushrs") }
+ Opcode::Hint_m => { write!(f, "hint.m") }
+ Opcode::Nop_m => { write!(f, "nop.m") }
+ Opcode::Chk_a_nc_int => { write!(f, "chk.a.nc.int") }
+ Opcode::Chk_a_clr_int => { write!(f, "chk.a.clr.int") }
+ Opcode::Chk_a_nc_fp => { write!(f, "chk.a.nc.fp") }
+ Opcode::Chk_a_clr_fp => { write!(f, "chk.a.clr.fp") }
+ Opcode::Mov_to_rr => { write!(f, "mov.to.rr") }
+ Opcode::Mov_from_rr => { write!(f, "mov.from.rr") }
+ Opcode::Fc => { write!(f, "fc") }
+ Opcode::Mov_to_dbr => { write!(f, "mov.to.dbr") }
+ Opcode::Mov_from_dbr => { write!(f, "mov.from.dbr") }
+ Opcode::Mov_from_psr_um => { write!(f, "mov.from.psr.um") }
+ Opcode::Probe_rw_fault_imm => { write!(f, "probe.rw.fault.imm") }
+ Opcode::Mov_to_ibr => { write!(f, "mov.to.ibr") }
+ Opcode::Mov_from_ibr => { write!(f, "mov.from.ibr") }
+ Opcode::Mov_m_from_ar => { write!(f, "mov.m.from.ar") }
+ Opcode::Probe_r_fault_imm => { write!(f, "probe.r.fault.imm") }
+ Opcode::Mov_to_pkr => { write!(f, "mov.to.pkr") }
+ Opcode::Mov_fom_pkr => { write!(f, "mov.fom.pkr") }
+ Opcode::Probe_w_fault_imm => { write!(f, "probe.w.fault.imm") }
+ Opcode::Mov_to_pmc => { write!(f, "mov.to.pmc") }
+ Opcode::Mov_from_pmc => { write!(f, "mov.from.pmc") }
+ Opcode::Mov_from_cr => { write!(f, "mov.from.cr") }
+ Opcode::Ptc_e => { write!(f, "ptc.e") }
+ Opcode::Ldfp_a => { write!(f, "ldfp.a") }
+ Opcode::Ldfp_sa => { write!(f, "ldfp.sa") }
+ Opcode::Ldfe_c_nc => { write!(f, "ldfe.c.nc") }
+ Opcode::Ldf8_c_nc => { write!(f, "ldf8.c.nc") }
+ Opcode::Ldfs_c_nc => { write!(f, "ldfs.c.nc") }
+ Opcode::Ldfd_c_nc => { write!(f, "ldfd.c.nc") }
+ Opcode::Lfetch => { write!(f, "lfetch") }
+ Opcode::Lfetch_excl => { write!(f, "lfetch.excl") }
+ Opcode::Lfetch_fault => { write!(f, "lfetch.fault") }
+ Opcode::Lfetch_fault_excl => { write!(f, "lfetch.fault.excl") }
+ Opcode::Stfe => { write!(f, "stfe") }
+ Opcode::Stf8 => { write!(f, "stf8") }
+ Opcode::Stfs => { write!(f, "stfs") }
+ Opcode::Stfd => { write!(f, "stfd") }
+ Opcode::Stf_spill => { write!(f, "stf.spill") }
+
+ Opcode::Shladd => { write!(f, "shladd") }
+ Opcode::Shladdp4 => { write!(f, "shladdp4") }
+
+ Opcode::Padd1 => { write!(f, "padd1") }
+ Opcode::Padd1_sss => { write!(f, "padd1.sss") }
+ Opcode::Padd1_uuu => { write!(f, "padd1.uuu") }
+ Opcode::Padd1_uus => { write!(f, "padd1.uus") }
+ Opcode::Psub1 => { write!(f, "psub1") }
+ Opcode::Psub1_sss => { write!(f, "psub1.sss") }
+ Opcode::Psub1_uuu => { write!(f, "psub1.uuu") }
+ Opcode::Psub1_uus => { write!(f, "psub1.uus") }
+
+ Opcode::Ldfp8 => { write!(f, "ldfp8") }
+ Opcode::Ldfps => { write!(f, "ldfps") }
+ Opcode::Ldfpd => { write!(f, "ldfpd") }
+ Opcode::Ldfp8_s => { write!(f, "ldfp8.s") }
+ Opcode::Ldfps_s => { write!(f, "ldfps.s") }
+ Opcode::Ldfpd_s => { write!(f, "ldfpd.s") }
+ Opcode::Ldfp8_a => { write!(f, "ldfp8.a") }
+ Opcode::Ldfps_a => { write!(f, "ldfps.a") }
+ Opcode::Ldfpd_a => { write!(f, "ldfpd.a") }
+ Opcode::Ldfp8_sa => { write!(f, "ldfp8.sa") }
+ Opcode::Ldfps_sa => { write!(f, "ldfps.sa") }
+ Opcode::Ldfpd_sa => { write!(f, "ldfpd.sa") }
+
+ Opcode::Mov_m_to_ar_imm => { write!(f, "mov.m.to.ar.imm") }
+ Opcode::Mov_from_pkr => { write!(f, "mov.from.pkr") }
+ Opcode::Setf_sig => { write!(f, "setf.sig") }
+ Opcode::Setf_exp => { write!(f, "setf.exp") }
+ Opcode::Setf_s => { write!(f, "setf.s") }
+ Opcode::Setf_d => { write!(f, "setf.d") }
+ Opcode::Pavg1 => { write!(f, "pavg1") }
+ Opcode::Pavg1_raz => { write!(f, "pavg1.raz") }
+ Opcode::Pavgsub1 => { write!(f, "pavgsub1") }
+ Opcode::Pcmp1_eq => { write!(f, "pcmp1.eq") }
+ Opcode::Pcmp1_gt => { write!(f, "pcmp1.gt") }
+ Opcode::Padd2 => { write!(f, "padd2") }
+ Opcode::Padd2_sss => { write!(f, "padd2.sss") }
+ Opcode::Padd2_uuu => { write!(f, "padd2.uuu") }
+ Opcode::Padd2_uus => { write!(f, "padd2.uus") }
+ Opcode::Psub2 => { write!(f, "psub2") }
+ Opcode::Psub2_sss => { write!(f, "psub2.sss") }
+ Opcode::Psub2_uuu => { write!(f, "psub2.uuu") }
+ Opcode::Psub2_uus => { write!(f, "psub2.uus") }
+ Opcode::Pavg2 => { write!(f, "pavg2") }
+ Opcode::Pavg2_raz => { write!(f, "pavg2.raz") }
+ Opcode::Pavgsub2 => { write!(f, "pavgsub2") }
+ Opcode::Pshladd2 => { write!(f, "pshladd2") }
+ Opcode::Pshradd2 => { write!(f, "pshradd2") }
+ Opcode::Pcmp2_eq => { write!(f, "pcmp2.eq") }
+ Opcode::Pcmp2_gt => { write!(f, "pcmp2.gt") }
+ Opcode::Padd4 => { write!(f, "padd4") }
+ Opcode::Psub4 => { write!(f, "psub4") }
+ Opcode::Pcmp4_eq => { write!(f, "pcmp4.eq") }
+ Opcode::Pcmp4_gt => { write!(f, "pcmp4.gt") }
+ Opcode::Hint_x => { write!(f, "hint.x") }
+ Opcode::Nop_x => { write!(f, "nop.x") }
+ Opcode::Movl => { write!(f, "movl") }
+ Opcode::Brl_cond_bwh_ph_dh => { write!(f, "brl.cond.bwh.ph.dh") }
+ Opcode::Brl_call_bwh_ph_dh => { write!(f, "brl.call.bwh.ph.dh") }
+ Opcode::Br_call_bwh_ph_dh => { write!(f, "br.call.bwh.ph.dh") }
+ Opcode::Brp_ipwh_ih => { write!(f, "brp.ipwh.ih") }
+ Opcode::Break_x => { write!(f, "break.x") }
+ Opcode::Break_i => { write!(f, "break.i") }
+ Opcode::Zxt1 => { write!(f, "zxt1") }
+ Opcode::Mov_from_ip => { write!(f, "mov.from.ip") }
+ Opcode::Zxt2 => { write!(f, "zxt2") }
+ Opcode::Mov_from_b => { write!(f, "mov.from.b") }
+ Opcode::Zxt4 => { write!(f, "zxt4") }
+ Opcode::Mov_i_from_ar => { write!(f, "mov.i.from.ar") }
+ Opcode::Sxt1 => { write!(f, "sxt1") }
+ Opcode::Sxt2 => { write!(f, "sxt2") }
+ Opcode::Sxt4 => { write!(f, "sxt4") }
+ Opcode::Czx1_l => { write!(f, "czx1.l") }
+ Opcode::Czx2_l => { write!(f, "czx2.l") }
+ Opcode::Mov_i_to_ar_imm => { write!(f, "mov.i.to.ar.imm") }
+ Opcode::Mov_i_to_ar => { write!(f, "mov.i.to.ar") }
+ Opcode::Czx1_r => { write!(f, "czx1.r") }
+ Opcode::Czx2_r => { write!(f, "czx2.r") }
+ Opcode::Hint_i => { write!(f, "hint.i") }
+ Opcode::Nop_i => { write!(f, "nop.i") }
+ Opcode::Chk_s_i_int => { write!(f, "chk.s.i.int") }
+ Opcode::Mov_to_pr_rot_imm => { write!(f, "mov.to.pr.rot.imm") }
+ Opcode::Mov_to_pr => { write!(f, "mov.to.pr") }
+ Opcode::Mov_from_pr => { write!(f, "mov.from.pr") }
+ Opcode::Mov_mwh_ih => { write!(f, "mov") }
+ Opcode::Mov_ret_mwh_ih => { write!(f, "mov.ret") }
+ Opcode::Dep => { write!(f, "dep") }
+ Opcode::Tbit_z => { write!(f, "tbit.z") }
+ Opcode::Tnat_z => { write!(f, "tnat.z") }
+ Opcode::Tbit_z_unc => { write!(f, "tbit.z.unc") }
+ Opcode::Tnat_z_unc => { write!(f, "tnat.z.unc") }
+ Opcode::Tbit_z_and => { write!(f, "tbit.z.and") }
+ Opcode::Tnat_z_and => { write!(f, "tnat.z.and") }
+ Opcode::Tbit_nz_and => { write!(f, "tbit.nz.and") }
+ Opcode::Tnat_nz_and => { write!(f, "tnat.nz.and") }
+ Opcode::Tbit_z_or => { write!(f, "tbit.z.or") }
+ Opcode::Tnat_z_or => { write!(f, "tnat.z.or") }
+ Opcode::Tbit_nz_or => { write!(f, "tbit.nz.or") }
+ Opcode::Tnat_nz_or => { write!(f, "tnat.nz.or") }
+ Opcode::Tbit_z_or_andcm => { write!(f, "tbit.z.or.andcm") }
+ Opcode::Tnat_z_or_andcm => { write!(f, "tnat.z.or.andcm") }
+ Opcode::Tbit_nz_or_andcm => { write!(f, "tbit.nz.or.andcm") }
+ Opcode::Tnat_nz_or_andcm => { write!(f, "tnat.nz.or.andcm") }
+ Opcode::Tf_z => { write!(f, "tf.z") }
+ Opcode::Tf_z_nc => { write!(f, "tf.z.nc") }
+ Opcode::Tf_z_and => { write!(f, "tf.z.and") }
+ Opcode::Tf_nz_and => { write!(f, "tf.nz.and") }
+ Opcode::Tf_z_or => { write!(f, "tf.z.or") }
+ Opcode::Tf_nz_or => { write!(f, "tf.nz.or") }
+ Opcode::Tf_z_or_andcm => { write!(f, "tf.z.or.andcm") }
+ Opcode::Tf_nz_or_andcm => { write!(f, "tf.nz.or.andcm") }
+ Opcode::Dep_z_imm => { write!(f, "dep.z.imm") }
+ Opcode::Dep_imm => { write!(f, "dep.imm") }
+ Opcode::Dep_z => { write!(f, "dep.z") }
+ Opcode::Extr => { write!(f, "extr") }
+ Opcode::Shrp => { write!(f, "shrp") }
+ Opcode::Extr_u => { write!(f, "extr.u") }
+ Opcode::Pmin1_u => { write!(f, "pmin1.u") }
+ Opcode::Unpack1_h => { write!(f, "unpack1.h") }
+ Opcode::Pmax1_u => { write!(f, "pmax1.u") }
+ Opcode::Unpack1_l => { write!(f, "unpack1.l") }
+ Opcode::Mix1_r => { write!(f, "mix1.r") }
+ Opcode::Mix1_l => { write!(f, "mix1.l") }
+ Opcode::Psad1 => { write!(f, "psad1") }
+ Opcode::Mux1 => { write!(f, "mux1") }
+ Opcode::Pshr2_u_var => { write!(f, "pshr2.u.var") }
+ Opcode::Pmpyshr2_u => { write!(f, "pmpyshr2.u") }
+ Opcode::Pshr2_var => { write!(f, "pshr2.var") }
+ Opcode::Pmpyshr2 => { write!(f, "pmpyshr2") }
+ Opcode::Pshl1_var => { write!(f, "pshl1.var") }
+ Opcode::Pshr2_u_fixed => { write!(f, "pshr2.u.fixed") }
+ Opcode::Pshr2_fixed => { write!(f, "pshr2.fixed") }
+ Opcode::Popcnt => { write!(f, "popcnt") }
+ Opcode::Clz => { write!(f, "clz") }
+ Opcode::Pack2_uss => { write!(f, "pack2.uss") }
+ Opcode::Pack2_sss => { write!(f, "pack2.sss") }
+ Opcode::Pmin2 => { write!(f, "pmin2") }
+ Opcode::Unpack2_h => { write!(f, "unpack2.h") }
+ Opcode::Unpack2_l => { write!(f, "unpack2.l") }
+ Opcode::Pmax2 => { write!(f, "pmax2") }
+ Opcode::Mix2_r => { write!(f, "mix2.r") }
+ Opcode::Mix2_l => { write!(f, "mix2.l") }
+ Opcode::Pmpy2_r => { write!(f, "pmpy2.r") }
+ Opcode::Pmpy2_l => { write!(f, "pmpy2.l") }
+ Opcode::Pshl2_fixed => { write!(f, "pshl2.fixed") }
+ Opcode::Mux2 => { write!(f, "mux2") }
+ Opcode::Pshr4_u_var => { write!(f, "pshr4.u.var") }
+ Opcode::Pshr4_var => { write!(f, "pshr4.var") }
+ Opcode::Pshl4_var => { write!(f, "pshl4.var") }
+ Opcode::Mpy4 => { write!(f, "mpy4") }
+ Opcode::Mpyshl4 => { write!(f, "mpyshl4") }
+ Opcode::Pshr4_u_fixed => { write!(f, "pshr4.u.fixed") }
+ Opcode::Pshr4_fixed => { write!(f, "pshr4.fixed") }
+ Opcode::Pack4_sss => { write!(f, "pack4.sss") }
+ Opcode::Unpack4_h => { write!(f, "unpack4.h") }
+ Opcode::Unpack4_l => { write!(f, "unpack4.l") }
+ Opcode::Mix4_r => { write!(f, "mix4.r") }
+ Opcode::Mix4_l => { write!(f, "mix4.l") }
+ Opcode::Pshl4_fixed => { write!(f, "pshl4.fixed") }
+ Opcode::Shr_u_var => { write!(f, "shr.u.var") }
+ Opcode::Shr_var => { write!(f, "shr.var") }
+ Opcode::Shl_var => { write!(f, "shl.var") }
+
+ Opcode::Break_b => { write!(f, "break.b") }
+ Opcode::Cover => { write!(f, "cover") }
+ Opcode::Clrrb => { write!(f, "clrrb") }
+ Opcode::Clrrb_pr => { write!(f, "clrrb.pr") }
+ Opcode::Rfi => { write!(f, "rfi") }
+ Opcode::Bsw_0 => { write!(f, "bsw.0") }
+ Opcode::Bsw_1 => { write!(f, "bsw.1") }
+ Opcode::Epc => { write!(f, "epc") }
+ Opcode::Vmsw_0 => { write!(f, "vmsw.0") }
+ Opcode::Vmsw_1 => { write!(f, "vmsw.1") }
+ Opcode::Br_cond => { write!(f, "br.cond") }
+ Opcode::Br_ia => { write!(f, "br.ia") }
+ Opcode::Br_ret => { write!(f, "br.ret") }
+
+ Opcode::Nop_b => { write!(f, "nop.b") }
+ Opcode::Hint_b => { write!(f, "hint.b") }
+ Opcode::Brp => { write!(f, "brp") }
+ Opcode::Brp_ret => { write!(f, "brp.ret") }
+
+ Opcode::Br_wexit => { write!(f, "br.wexit") }
+ Opcode::Br_wtop => { write!(f, "br.wtop") }
+ Opcode::Br_cloop => { write!(f, "br.cloop") }
+ Opcode::Br_cexit => { write!(f, "br.cexit") }
+ Opcode::Br_ctop => { write!(f, "br.ctop") }
+
+ Opcode::Frcpa => { write!(f, "frcpa") }
+ Opcode::Frsqta => { write!(f, "frsqta") }
+ Opcode::Break_f => { write!(f, "break.f") }
+ Opcode::Fsetc => { write!(f, "fsetc") }
+ Opcode::Fclrf => { write!(f, "fclrf") }
+ Opcode::Fchkf => { write!(f, "fchkf") }
+ Opcode::Fmerge_s => { write!(f, "fmerge.s") }
+ Opcode::Fmerge_ns => { write!(f, "fmerge.ns") }
+ Opcode::Fmerge_se => { write!(f, "fmerge.se") }
+
+ Opcode::Fmin => { write!(f, "fmin") }
+ Opcode::Fmax => { write!(f, "fmax") }
+ Opcode::Famin => { write!(f, "famin") }
+ Opcode::Famax => { write!(f, "famax") }
+ Opcode::Fcvt_fx => { write!(f, "fcvt.fx") }
+ Opcode::Fcvt_fxu => { write!(f, "fcvt.fxu") }
+ Opcode::Fcvt_fx_trunc => { write!(f, "fcvt.fx.trunc") }
+ Opcode::Fcvt_fxu_trunc => { write!(f, "fcvt.fxu.trunc") }
+ Opcode::Fcvt_xf => { write!(f, "fcvt.xf") }
+ Opcode::Fpack => { write!(f, "fpack") }
+ Opcode::Fand => { write!(f, "fand") }
+ Opcode::Fandcm => { write!(f, "fandcm") }
+ Opcode::For => { write!(f, "for") }
+ Opcode::Fxor => { write!(f, "fxor") }
+
+ Opcode::Fswap => { write!(f, "fswap") }
+ Opcode::Fswap_nl => { write!(f, "fswap.nl") }
+ Opcode::Fswap_nr => { write!(f, "fswap.nr") }
+ Opcode::Fmix_lr => { write!(f, "fmix.lr") }
+ Opcode::Fmix_r => { write!(f, "fmix.r") }
+ Opcode::Fmix_l => { write!(f, "fmix.l") }
+
+ Opcode::Fsxt_r => { write!(f, "fsxt.r") }
+ Opcode::Fsxt_l => { write!(f, "fsxt.l") }
+
+ Opcode::Hint_f => { write!(f, "hint.f") }
+ Opcode::Nop_f => { write!(f, "nop.f") }
+
+ Opcode::Fprcpa => { write!(f, "fprcpa") }
+ Opcode::Fprsqrta => { write!(f, "fprsqrta") }
+ Opcode::Fpmerge_s => { write!(f, "fpmerge.s") }
+ Opcode::Fpmerge_ns => { write!(f, "fpmerge.ns") }
+ Opcode::Fpmerge_se => { write!(f, "fpmerge.se") }
+
+ Opcode::Fpmin => { write!(f, "fpmin") }
+ Opcode::Fpmax => { write!(f, "fpmax") }
+ Opcode::Fpamin => { write!(f, "fpamin") }
+ Opcode::Fpamax => { write!(f, "fpamax") }
+ Opcode::Fpcvt_fx => { write!(f, "fpcvt.fx") }
+ Opcode::Fpcvt_fxu => { write!(f, "fpcvt.fxu") }
+ Opcode::Fpcvt_fx_trunc => { write!(f, "fpcvt.fx.trunc") }
+ Opcode::Fpcvt_fxu_trunc => { write!(f, "fpcvt.fxu.trunc") }
+ Opcode::Fcmp_eq => { write!(f, "fcmp.eq") }
+ Opcode::Fcmp_lt => { write!(f, "fcmp.lt") }
+ Opcode::Fcmp_le => { write!(f, "fcmp.le") }
+ Opcode::Fcmp_unord => { write!(f, "fcmp.unord") }
+ Opcode::Fcmp_eq_unc => { write!(f, "fcmp.eq.unc") }
+ Opcode::Fcmp_lt_unc => { write!(f, "fcmp.lt.unc") }
+ Opcode::Fcmp_le_unc => { write!(f, "fcmp.le.unc") }
+ Opcode::Fcmp_unord_unc => { write!(f, "fcmp.unord.unc") }
+ Opcode::Fclass_m_unc => { write!(f, "fclass.m.unc") }
+ Opcode::Fclass_m => { write!(f, "fclass.m") }
+ Opcode::Fma_s_sf => { write!(f, "fma.s.sf") }
+ Opcode::Fma_sf => { write!(f, "fma.sf") }
+ Opcode::Fpma_sf => { write!(f, "fpma.sf") }
+ Opcode::Fma_d_sf => { write!(f, "fma.d.sf") }
+ Opcode::Fms_s_sf => { write!(f, "fms.s.sf") }
+ Opcode::Fms_sf => { write!(f, "fms.sf") }
+ Opcode::Fpms_sf => { write!(f, "fpms.sf") }
+ Opcode::Fms_d_sf => { write!(f, "fms.d.sf") }
+ Opcode::Fnma_s_sf => { write!(f, "fnma.s.sf") }
+ Opcode::Fnma_sf => { write!(f, "fnma.sf") }
+ Opcode::Fpnma_sf => { write!(f, "fpnma.sf") }
+ Opcode::Fnma_d_sf => { write!(f, "fnma.d.sf") }
+ Opcode::Xma_l => { write!(f, "xma.l") }
+ Opcode::Xma_hu => { write!(f, "xma.hu") }
+ Opcode::Xma_h => { write!(f, "xma.h") }
+ Opcode::Fselect => { write!(f, "fselect") }
+
+ }
+ }
+}
+
+#[derive(Default, Debug, PartialEq, Eq)]
+pub struct Instruction {
+ opcode: Opcode,
+ // specify which operand, if any, is the last written operand in an instruction
+ dest_boundary: Option<u8>,
+ operands: [Operand; 5],
+ prefetch_hint: Option<PrefetchHint>,
+}
+impl fmt::Display for Instruction {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if let Opcode::Addl = self.opcode {
+ if self.operands[1] == Operand::GPRegister(GPRegister(0)) {
+ return write!(f, "mov {}={}",
+ self.operands[0],
+ self.operands[2]
+ );
+ }
+ }
+ if let Opcode::Br_cond = self.opcode {
+ return write!(f, "br{}{}{} {}",
+ [".few", ".many"][self.operands[1].as_unsigned_imm() as usize],
+ ["", ".spnt", ".dptk", ".dpnt"][self.operands[2].as_unsigned_imm() as usize],
+ ["", ".clr"][self.operands[3].as_unsigned_imm() as usize],
+ self.operands[0],
+ )
+ } else if self.opcode == Opcode::Mov_mwh_ih {
+ return write!(f, "mov{}{} {}={}",
+ ["", "?NONE?", ".dptk", "RESERVED"][self.operands[2].as_unsigned_imm() as usize],
+ ["", ".imp"][self.operands[3].as_unsigned_imm() as usize],
+ self.operands[0],
+ self.operands[1],
+ )
+ } else if self.opcode == Opcode::Mov_ret_mwh_ih {
+ return write!(f, "mov.ret{}{} {}={}",
+ ["", "?NONE?", ".dptk", "RESERVED"][self.operands[2].as_unsigned_imm() as usize],
+ ["", ".imp"][self.operands[3].as_unsigned_imm() as usize],
+ self.operands[0],
+ self.operands[1],
+ )
+ } else {
+ write!(f, "{}", self.opcode)?;
+ }
+ for (i, op) in self.operands.iter().enumerate() {
+ if op == &Operand::None {
+ break;
+ }
+ if i == 0 {
+ write!(f, " {}", op)?;
+ } else {
+ if self.dest_boundary == Some((i - 1) as u8) {
+ write!(f, "={}", op)?;
+ } else {
+ write!(f, ",{}", op)?;
+ }
+ }
+ }
+ Ok(())
+ }
+}
#[derive(Debug, PartialEq, Eq)]
-pub struct Instruction {}
-impl yaxpeax_arch::LengthedInstruction for Instruction {
+pub enum PrefetchHint {
+ None,
+ Nt1,
+ Nt2,
+ Nta,
+}
+#[derive(Debug, PartialEq, Eq)]
+pub struct InstructionBundle {
+ bundle_tag: u8,
+ instructions: [Instruction; 3],
+}
+impl yaxpeax_arch::LengthedInstruction for InstructionBundle {
type Unit = yaxpeax_arch::AddressDiff<u64>;
fn len(&self) -> Self::Unit { AddressDiff::from_const(16) }
fn min_size() -> Self::Unit { AddressDiff::from_const(16) }
}
-impl yaxpeax_arch::Instruction for Instruction {
+impl yaxpeax_arch::Instruction for InstructionBundle {
fn well_defined(&self) -> bool {
true
}
}
-impl Default for Instruction {
+impl Default for InstructionBundle {
fn default() -> Self {
- Instruction { }
+ InstructionBundle {
+ bundle_tag: 0,
+ instructions: Default::default(),
+ }
+ }
+}
+impl fmt::Display for InstructionBundle {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let stops = if let Some((types, stops)) = BUNDLE_TAGS[self.bundle_tag as usize] {
+ write!(f, "[{}{}{}]", types[0], types[1], types[2])?;
+ [(stops & 0b100) > 0, (stops & 0b010) > 0, (stops & 0b001) > 0]
+ } else {
+ return write!(f, "tag: invalid ({})", self.bundle_tag);
+ };
+ write!(f, " {}{}; {}{}; {}{}",
+ &self.instructions[0], if stops[0] { ";" } else { "" },
+ &self.instructions[1], if stops[1] { ";" } else { "" },
+ &self.instructions[2], if stops[2] { ";;" } else { "" },
+ )
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -554,8 +1129,102 @@ impl yaxpeax_arch::DecodeError for DecodeError {
}
#[derive(Default)]
pub struct InstDecoder {}
-#[derive(Debug)]
-pub enum Operand {}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct GPRegister(pub u8); // 128 64-bit registers
+impl fmt::Display for GPRegister {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "r{}", self.0)
+ }
+}
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct FloatRegister(pub u8); // 128 82-bit registers
+impl fmt::Display for FloatRegister {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "f{}", self.0)
+ }
+}
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct PredicateRegister(pub u8); // 64 1-bit registers
+impl fmt::Display for PredicateRegister {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "p{}", self.0)
+ }
+}
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct BranchRegister(pub u8); // 8 64-bit registers
+impl fmt::Display for BranchRegister {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "b{}", self.0)
+ }
+}
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct ApplicationRegister(pub u8); // 128 64-bit(?) registers
+impl fmt::Display for ApplicationRegister {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ar{}", self.0)
+ }
+}
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum Operand {
+ None,
+ GPRegister(GPRegister),
+ FloatRegister(FloatRegister),
+ PredicateRegister(PredicateRegister),
+ ImmI64(i64),
+ ImmU64(u64),
+ Memory(GPRegister),
+// Indirect(IndirectRegisterClass, GPRegister),
+ PSR, // processor status register (see 3.3.2)
+ PR, // predicate register (all 64 bits)
+ IP, // is this an application register? distinct?
+// ControlRegister(ControlRegister),
+ ApplicationRegister(ApplicationRegister),
+ BranchRegister(BranchRegister),
+}
+
+impl Operand {
+ fn as_signed_imm(&self) -> i64 {
+ if let Operand::ImmI64(i) = self {
+ *i
+ } else {
+ panic!("non-imm operand: {:?}", self);
+ }
+ }
+
+ fn as_unsigned_imm(&self) -> u64 {
+ if let Operand::ImmU64(i) = self {
+ *i
+ } else {
+ panic!("non-imm operand: {:?}", self);
+ }
+ }
+}
+
+impl fmt::Display for Operand {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Operand::None => { unreachable!() },
+ Operand::GPRegister(reg) => { write!(f, "{}", reg) },
+ Operand::Memory(reg) => { write!(f, "[{}]", reg) },
+ Operand::ImmU64(imm) => { write!(f, "{}", imm) },
+ Operand::ImmI64(imm) => { write!(f, "{}", imm) },
+ Operand::FloatRegister(reg) => { write!(f, "{}", reg) },
+ Operand::PredicateRegister(reg) => { write!(f, "{}", reg) },
+ Operand::ApplicationRegister(reg) => { write!(f, "{}", reg) },
+ Operand::BranchRegister(reg) => { write!(f, "{}", reg) },
+ Operand::PSR => { write!(f, "psr") },
+ Operand::PR => { write!(f, "pr") },
+ Operand::IP => { write!(f, "ip") },
+ }
+ }
+}
+
+impl Default for Operand {
+ fn default() -> Self {
+ Operand::None
+ }
+}
#[derive(Debug)]
pub enum Register {
@@ -577,72 +1246,104 @@ pub enum Register {
Predicate,
Region,
}
-impl Decoder<Instruction> for InstDecoder {
- type Error = DecodeError;
-
- fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Result<(), Self::Error> {
- #[derive(Debug, Copy, Clone, Eq, PartialEq)]
- enum InstructionType {
- A,
- I,
- M,
- F,
- B,
- LX,
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+enum InstructionType {
+ A,
+ I,
+ M,
+ F,
+ B,
+ L,
+ X,
+}
+impl fmt::Display for InstructionType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ InstructionType::A => write!(f, "A"),
+ InstructionType::I => write!(f, "I"),
+ InstructionType::M => write!(f, "M"),
+ InstructionType::F => write!(f, "F"),
+ InstructionType::B => write!(f, "B"),
+ InstructionType::L => write!(f, "L"),
+ InstructionType::X => write!(f, "X"),
}
+ }
+}
+type BundleDesc = ([InstructionType; 3], u8); // u8 is a bitmap of which instructions are followed by stops.
+const BUNDLE_TAGS: [Option<BundleDesc>; 32] = [
+ Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b000)),
+ Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b001)),
+ Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b010)),
+ Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b011)),
+ Some(([InstructionType::M, InstructionType::L, InstructionType::X], 0b000)),
+ Some(([InstructionType::M, InstructionType::L, InstructionType::X], 0b010)),
+ None,
+ None,
+ Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b000)),
+ Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b001)),
+ Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b100)),
+ Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b101)),
+ Some(([InstructionType::M, InstructionType::F, InstructionType::I], 0b000)),
+ Some(([InstructionType::M, InstructionType::F, InstructionType::I], 0b001)),
+ Some(([InstructionType::M, InstructionType::M, InstructionType::F], 0b000)),
+ Some(([InstructionType::M, InstructionType::M, InstructionType::F], 0b001)),
+ Some(([InstructionType::M, InstructionType::I, InstructionType::B], 0b000)),
+ Some(([InstructionType::M, InstructionType::I, InstructionType::B], 0b001)),
+ Some(([InstructionType::M, InstructionType::B, InstructionType::B], 0b000)),
+ Some(([InstructionType::M, InstructionType::B, InstructionType::B], 0b001)),
+ None,
+ None,
+ Some(([InstructionType::B, InstructionType::B, InstructionType::B], 0b000)),
+ Some(([InstructionType::B, InstructionType::B, InstructionType::B], 0b001)),
+ Some(([InstructionType::M, InstructionType::M, InstructionType::B], 0b000)),
+ Some(([InstructionType::M, InstructionType::M, InstructionType::B], 0b001)),
+ None,
+ None,
+ Some(([InstructionType::M, InstructionType::F, InstructionType::B], 0b000)),
+ Some(([InstructionType::M, InstructionType::F, InstructionType::B], 0b001)),
+ None,
+ None,
+];
+impl Decoder<InstructionBundle> for InstDecoder {
+ type Error = DecodeError;
+
+ fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut InstructionBundle, bytes: T) -> Result<(), Self::Error> {
let mut bytes_iter = bytes.into_iter();
let mut instruction_bytes = bitarr![Lsb0, u8; 0u8; 128];
- for i in 0..0u64.wrapping_offset(Instruction::min_size()).to_linear() {
+ for i in 0..0u64.wrapping_offset(InstructionBundle::min_size()).to_linear() {
instruction_bytes[(i * 8)..(i * 8 + 8)].store(bytes_iter.next().ok_or(DecodeError::ExhaustedInput)?);
}
// let instruction_bits = instruction_bytes.view_bits::<Lsb0>();
let bundle_tag = instruction_bytes[0..5].load::<u8>();
+ inst.bundle_tag = bundle_tag;
eprintln!("{:?}", instruction_bytes);
let instruction_words = [
- &instruction_bytes[87..128],
- &instruction_bytes[46..87],
&instruction_bytes[5..46],
+ &instruction_bytes[46..87],
+ &instruction_bytes[87..128],
];
println!("bundle tag is now {:#05b}", bundle_tag);
- type BundleDesc = ([InstructionType; 3], u8); // u8 is a bitmap of which instructions are followed by stops.
- const BUNDLE_TAGS: [Option<BundleDesc>; 32] = [
- Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b000)),
- Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b001)),
- Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b010)),
- Some(([InstructionType::M, InstructionType::I, InstructionType::I], 0b011)),
- Some(([InstructionType::M, InstructionType::LX, InstructionType::LX], 0b000)),
- Some(([InstructionType::M, InstructionType::LX, InstructionType::LX], 0b010)),
- None,
- None,
- Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b000)),
- Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b001)),
- Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b100)),
- Some(([InstructionType::M, InstructionType::M, InstructionType::I], 0b101)),
- Some(([InstructionType::M, InstructionType::F, InstructionType::I], 0b000)),
- Some(([InstructionType::M, InstructionType::F, InstructionType::I], 0b001)),
- Some(([InstructionType::M, InstructionType::M, InstructionType::F], 0b000)),
- Some(([InstructionType::M, InstructionType::M, InstructionType::F], 0b001)),
- Some(([InstructionType::M, InstructionType::I, InstructionType::B], 0b000)),
- Some(([InstructionType::M, InstructionType::I, InstructionType::B], 0b001)),
- Some(([InstructionType::M, InstructionType::B, InstructionType::B], 0b000)),
- Some(([InstructionType::M, InstructionType::B, InstructionType::B], 0b001)),
- None,
- None,
- Some(([InstructionType::B, InstructionType::B, InstructionType::B], 0b000)),
- Some(([InstructionType::B, InstructionType::B, InstructionType::B], 0b001)),
- Some(([InstructionType::M, InstructionType::M, InstructionType::B], 0b000)),
- Some(([InstructionType::M, InstructionType::M, InstructionType::B], 0b001)),
- None,
- None,
- Some(([InstructionType::M, InstructionType::F, InstructionType::B], 0b000)),
- Some(([InstructionType::M, InstructionType::F, InstructionType::B], 0b001)),
- None,
- None,
- ];
let (instruction_types, stop_mask) = BUNDLE_TAGS[bundle_tag as usize].ok_or(DecodeError::BadBundle)?;
eprintln!("bundle types: {:?}, stop_mask: {:#b}", instruction_types, stop_mask);
+ fn decode_l_instruction(word: &BitSlice<Lsb0, u8>, word2: &BitSlice<Lsb0, u8>) -> Instruction {
+ eprintln!("as slice: {:?}", word);
+ let tag = word[37..41].load::<u8>();
+ eprintln!("tag: {:#x}", tag);
+
+ let (opcode, operand_encoding) = get_l_opcode_and_encoding(tag, word);
+ eprintln!("L({}) {:?}/{:?}", tag, opcode, operand_encoding);
+ let (dest_boundary, operands) = read_l_operands(operand_encoding, word, word2);
+ Instruction {
+ opcode,
+ dest_boundary,
+ operands,
+ // TODO: figure out hints
+ prefetch_hint: None,
+ }
+ }
+
fn decode_instruction(word: &BitSlice<Lsb0, u8>, ty: InstructionType) -> Instruction {
eprintln!("as slice: {:?}", word);
let tag = word[37..41].load::<u8>();
@@ -657,59 +1358,907 @@ impl Decoder<Instruction> for InstDecoder {
match ty {
InstructionType::I => {
let (opcode, operand_encoding) = get_i_opcode_and_encoding(tag, word);
- read_i_operands(operand_encoding, word);
- panic!("i");
+ eprintln!("I({}) {:?}/{:?}", tag, opcode, operand_encoding);
+ let (dest_boundary, operands) = read_i_operands(operand_encoding, word);
+ Instruction {
+ opcode,
+ dest_boundary,
+ operands,
+ // TODO: figure out hints
+ prefetch_hint: None,
+ }
},
InstructionType::F => {
let (opcode, operand_encoding) = get_f_opcode_and_encoding(tag, word);
- read_f_operands(operand_encoding, word);
- panic!("f");
+ eprintln!("F({}) {:?}/{:?}", tag, opcode, operand_encoding);
+ let (dest_boundary, operands) = read_f_operands(operand_encoding, word);
+ Instruction {
+ opcode,
+ dest_boundary,
+ operands,
+ // TODO: figure out hints
+ prefetch_hint: None,
+ }
},
InstructionType::B => {
let (opcode, operand_encoding) = get_b_opcode_and_encoding(tag, word);
- read_b_operands(operand_encoding, word);
- panic!("b");
+ eprintln!("B({}) {:?}/{:?}", tag, opcode, operand_encoding);
+ let (dest_boundary, operands) = read_b_operands(operand_encoding, word);
+ Instruction {
+ opcode,
+ dest_boundary,
+ operands,
+ // TODO: figure out hints
+ prefetch_hint: None,
+ }
},
- InstructionType::LX => {
- let (opcode, operand_encoding) = get_lx_opcode_and_encoding(tag, word);
- read_lx_operands(operand_encoding, word);
- panic!("lx");
+ InstructionType::L => {
+ panic!("use decode_l_instruction");
},
InstructionType::A => {
let (opcode, operand_encoding) = get_a_opcode_and_encoding(tag, word);
- eprintln!("A {:?}/{:?}", opcode, operand_encoding);
- read_a_operands(operand_encoding, word);
- Instruction {}
+ eprintln!("A({}) {:?}/{:?}", tag, opcode, operand_encoding);
+ let (dest_boundary, operands) = read_a_operands(operand_encoding, word);
+ Instruction {
+ opcode,
+ dest_boundary,
+ operands,
+ // TODO: figure out hints
+ prefetch_hint: None,
+ }
}
InstructionType::M => {
let (opcode, operand_encoding) = get_m_opcode_and_encoding(tag, word);
eprintln!("M({}) {:?}/{:?}", tag, opcode, operand_encoding);
- read_m_operands(operand_encoding, word);
- Instruction {}
+ let (dest_boundary, operands) = read_m_operands(operand_encoding, word);
+ Instruction {
+ opcode,
+ dest_boundary,
+ operands,
+ // TODO: figure out hints
+ prefetch_hint: None,
+ }
}
+ InstructionType::X => unreachable!("should never try to decode InstructionType::X, preceded by an InstructionType::L that may have been missed?")
}
}
- for (word, ty) in instruction_words.iter().zip(instruction_types.iter().cloned()) {
- let instruction = decode_instruction(word, ty);
- eprintln!("{:?}/{:#046b}: {:?}", ty, word, instruction);
+ for ((i, word), ty) in instruction_words.iter().enumerate().zip(instruction_types.iter().cloned()) {
+ if ty == InstructionType::L {
+ let instruction = decode_l_instruction(word, &instruction_words[i + 1]);
+ eprintln!("{:?}/{:#046b}: {:?}", ty, word, instruction);
+ inst.instructions[i] = instruction;
+ break;
+ } else {
+ let instruction = decode_instruction(word, ty);
+ eprintln!("{:?}/{:#046b}: {:?}", ty, word, instruction);
+ inst.instructions[i] = instruction;
+ };
}
// from here, `itanium-architecture-vol-1-2-3-4-reference-set-manual.pdf` volume 3 is
// remaining necessary details
Ok(())
}
+ fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Result<InstructionBundle, Self::Error> {
+ let mut inst = InstructionBundle::default();
+ self.decode_into(&mut inst, bytes)?;
+ Ok(inst)
+ }
}
-fn read_lx_operands(encoding: OperandEncodingX, word: &BitSlice<Lsb0, u8>) {
+fn one_op(dest: bool, op: Operand) -> (Option<u8>, [Operand; 5]) {
+ (
+ if dest { Some(0) } else { None },
+ [op, Operand::None, Operand::None, Operand::None, Operand::None]
+ )
}
-fn read_b_operands(encoding: OperandEncodingB, word: &BitSlice<Lsb0, u8>) {
+
+fn two_op(dest: Option<u8>, op1: Operand, op2: Operand) -> (Option<u8>, [Operand; 5]) {
+ (dest, [op1, op2, Operand::None, Operand::None, Operand::None])
}
-fn read_f_operands(encoding: OperandEncodingF, word: &BitSlice<Lsb0, u8>) {
+
+fn three_op(dest: Option<u8>, op1: Operand, op2: Operand, op3: Operand) -> (Option<u8>, [Operand; 5]) {
+ (dest, [op1, op2, op3, Operand::None, Operand::None])
+}
+
+fn four_op(dest: Option<u8>, op1: Operand, op2: Operand, op3: Operand, op4: Operand) -> (Option<u8>, [Operand; 5]) {
+ (dest, [op1, op2, op3, op4, Operand::None])
+}
+
+fn read_l_operands(encoding: OperandEncodingX, word: &BitSlice<Lsb0, u8>, word2: &BitSlice<Lsb0, u8>) -> (Option<u8>, [Operand; 5]) {
+ use OperandEncodingX::*;
+ match encoding {
+ None => {
+ panic!("should not explicitly check OperandEncodingX::None");
+ }
+ X1 => {
+ let imm20a = word[6..26].load::<u64>();
+ let i = word[36];
+ let imm41 = word2[0..41].load::<u64>();
+ let imm = imm41 << 21 + (i as u64) << 20 + imm20a;
+ // TODO: this is certainly assembled incorrectly
+ one_op(false, Operand::ImmU64(imm as u64))
+ }
+ X2 => {
+ let r1 = word[6..13].load::<u8>();
+ let imm7b = word[13..20].load::<u64>();
+ let ic = word[21];
+ let immdc = word[22..36].load::<u64>();
+ let i = word[36];
+ let imm41 = word2[0..41].load::<u64>();
+ // TODO: this is certainly assembled incorrectly
+ let imm = imm41 << 21 + (i as u64) << 20 + imm7b + immdc + (ic as u64);
+ two_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::ImmU64(imm as u64)
+ )
+ }
+ X3 => {
+ let btype = word[6..9].load::<u8>();
+ if btype != 0 {
+ // unclear what happens. invalid instruction?
+ }
+ let p = word[12];
+ let imm20b = word[13..33].load::<u64>();
+ let wh = word[33..35].load::<u64>();
+ let d = word[35];
+ let i = word[36];
+ let imm39 = word2[2..41].load::<u64>();
+ // TODO: this is certainly assembled incorrectly
+ let imm = imm39 << 21 + (i as u64) << 20 + imm20b;
+ eprintln!("x3 operands, btype={}, imm={}, p={}, wh={}, d={}", btype, imm, p, wh, d);
+ one_op(false, Operand::ImmU64(imm as u64))
+ }
+ X4 => {
+ let b1 = word[6..9].load::<u8>();
+ let p = word[12];
+ let imm20b = word[13..33].load::<u64>();
+ let wh = word[33..35].load::<u64>();
+ let d = word[35];
+ let i = word[36];
+ let imm39 = word2[2..41].load::<u64>();
+ // TODO: this is certainly assembled incorrectly
+ let imm = imm39 << 21 + (i as u64) << 20 + imm20b;
+ eprintln!("x4 operands, b1={}, imm={}, p={}, wh={}, d={}", b1, imm, p, wh, d);
+ two_op(
+ Some(0),
+ Operand::BranchRegister(BranchRegister(b1)),
+ Operand::ImmU64(imm as u64)
+ )
+ }
+ X5 => {
+ let imm20 = word[6..26].load::<u64>();
+ let i = word[36];
+ let imm41 = word2[0..41].load::<u64>();
+ // TODO: this is certainly assembled incorrectly
+ let imm = imm41 << 21 + (i as u64) << 20 + imm20;
+ eprintln!("x5 operands, imm={}", imm);
+ one_op(false, Operand::ImmU64(imm as u64))
+ }
+ }
+}
+fn read_b_operands(encoding: OperandEncodingB, word: &BitSlice<Lsb0, u8>) -> (Option<u8>, [Operand; 5]) {
+ use OperandEncodingB::*;
+ match encoding {
+ None => {
+ panic!("should not explicitly check OperandEncodingB::None");
+ }
+ B1 => {
+ let imm = word[13..33].load::<u32>();
+ let wh = word[33..35].load::<u8>();
+ let d = word[35];
+ let p = word[12];
+ eprintln!("b1 operands, imm={}, p={}, wh={}, d={}", imm, p, wh, d);
+ one_op(false, Operand::ImmU64(imm as u64))
+ }
+ B2 => {
+ // TODO: missing four bits?
+ let imm = word[13..33].load::<u32>();
+ let wh = word[33..35].load::<u8>();
+ let d = word[35];
+ let p = word[12];
+ eprintln!("b2 operands, imm={}, p={}, wh={}, d={}", imm, p, wh, d);
+ one_op(false, Operand::ImmU64(imm as u64))
+ }
+ B3 => {
+ // TODO: missing four bits?
+ let imm = word[13..33].load::<u32>();
+ let wh = word[33..35].load::<u8>();
+ let d = word[35];
+ let p = word[12];
+ let b1 = word[6..9].load::<u8>();
+ eprintln!("b3 operands, b1={}, imm={}, p={}, wh={}, d={}", b1, imm, p, wh, d);
+ (
+ Option::None,
+ [
+ Operand::BranchRegister(BranchRegister(b1)),
+ Operand::ImmU64(imm as u64),
+ Operand::ImmU64(p as u64),
+ Operand::ImmU64(wh as u64),
+ Operand::ImmU64(d as u64),
+ ]
+ )
+ }
+ B4 => {
+ let b2 = word[13..16].load::<u8>();
+ let wh = word[33..35].load::<u8>();
+ let d = word[35];
+ let p = word[12];
+ eprintln!("b4 operands, b2={}, p={}, wh={}, d={}", b2, p, wh, d);
+ four_op(
+ Option::None,
+ Operand::BranchRegister(BranchRegister(b2)),
+ Operand::ImmU64(p as u64),
+ Operand::ImmU64(wh as u64),
+ Operand::ImmU64(d as u64),
+ )
+ }
+ B5 => {
+ let b2 = word[13..16].load::<u8>();
+ let wh = word[33..35].load::<u8>();
+ let d = word[35];
+ let p = word[12];
+ let b1 = word[6..9].load::<u8>();
+ eprintln!("b5 operands, b1={}, b2={}, p={}, wh={}, d={}", b1, b2, p, wh, d);
+ (
+ Option::None,
+ [
+ Operand::BranchRegister(BranchRegister(b1)),
+ Operand::BranchRegister(BranchRegister(b2)),
+ Operand::ImmU64(p as u64),
+ Operand::ImmU64(wh as u64),
+ Operand::ImmU64(d as u64),
+ ]
+ )
+ }
+ B6 => {
+ let timm7a = word[6..13].load::<u32>();
+ // TODO: missing some bits
+ // TODO: sign extend?
+ let imm20b = word[13..33].load::<u32>();
+ let wh = word[3..5].load::<u8>();
+ let t2e = word[33..35].load::<u32>();
+ let tag = (t2e << 7) + timm7a;
+ let ih = word[33..35].load::<u8>();
+ let s = word[36] as u8;
+ eprintln!("b6 operands, imm={}, tag={}, ih={}, wh={}", imm20b, tag, ih, s);
+ four_op(
+ Option::None,
+ Operand::ImmI64(imm20b as i64),
+ Operand::ImmU64(tag as u64),
+ Operand::ImmU64(ih as u64),
+ Operand::ImmU64(s as u64),
+ )
+ }
+ B7 => {
+ let timm7a = word[6..13].load::<u32>();
+ // TODO: missing some bits
+ let b2 = word[13..16].load::<u8>();
+ let wh = word[3..5].load::<u8>();
+ let t2e = word[33..35].load::<u32>();
+ let tag = (t2e << 7) + timm7a;
+ let ih = word[35] as u8;
+ eprintln!("b7 operands, b2={}, tag={}, ih={}, wh={}", b2, tag, ih, wh);
+ four_op(
+ Option::None,
+ Operand::BranchRegister(BranchRegister(b2)),
+ Operand::ImmU64(tag as u64),
+ Operand::ImmU64(ih as u64),
+ Operand::ImmU64(wh as u64),
+ )
+ }
+ B8 => {
+ eprintln!("b8 operands");
+ one_op(false, Operand::None)
+ }
+ B9 => {
+ let imm20b = word[6..26].load::<u32>();
+ let imm = (word[20] as u32) << 20 + imm20b;
+ eprintln!("b9 operands, imm={}", imm);
+ one_op(false, Operand::ImmU64(imm as u64))
+ }
+ }
+}
+fn read_f_operands(encoding: OperandEncodingF, word: &BitSlice<Lsb0, u8>) -> (Option<u8>, [Operand; 5]) {
+ use OperandEncodingF::*;
+ match encoding {
+ None => {
+ panic!("should not explicitly check OperandEncodingF::None");
+ }
+ F1 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let f4 = word[27..34].load::<u8>();
+ eprintln!("f1 operands, f1={}, f2={}, f3={}, f4={}", f1, f2, f3, f4);
+ four_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ Operand::FloatRegister(FloatRegister(f4)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ )
+ }
+ F2 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let f4 = word[27..34].load::<u8>();
+ eprintln!("f2 operands, f1={}, f2={}, f3={}, f4={}", f1, f2, f3, f4);
+ four_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ Operand::FloatRegister(FloatRegister(f4)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ )
+ }
+ F3 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let f4 = word[27..34].load::<u8>();
+ eprintln!("f3 operands, f1={}, f2={}, f3={}, f4={}", f1, f2, f3, f4);
+ four_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ Operand::FloatRegister(FloatRegister(f4)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ )
+ }
+ F4 => {
+ let p1 = word[6..12].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("f4 operands, p1={}, f2={}, f3={}, p2={}", p1, f2, f3, p2);
+ four_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ )
+ }
+ F5 => {
+ let p1 = word[6..12].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let fclass7c = word[20..27].load::<u32>();
+ let fc2 = word[33..35].load::<u32>();
+ let fclass = fc2 << 7 + fclass7c;
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("f5 operands, p1={}, f2={}, fclass={}, p2={}", p1, f2, fclass, p2);
+ four_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::ImmU64(fclass as u64),
+ )
+ }
+ F6 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("f6 operands, f1={}, f2={}, f3={}, p2={}", f1, f2, f3, p2);
+ four_op(
+ Some(1),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ )
+ }
+ F7 => {
+ let f1 = word[6..13].load::<u8>();
+ let _ = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("f7 operands, f1={}, f3={}, p2={}", f1, f3, p2);
+ three_op(
+ Some(1),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ )
+ }
+ F8 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let _ = word[27..33].load::<u8>();
+ eprintln!("f8 operands, f1={}, f2={}, f3={}", f1, f2, f3);
+ three_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ )
+ }
+ F9 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let f3 = word[20..27].load::<u8>();
+ let _ = word[27..33].load::<u8>();
+ eprintln!("f9 operands, f1={}, f2={}, f3={}", f1, f2, f3);
+ three_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::FloatRegister(FloatRegister(f3)),
+ )
+ }
+ F10 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let _ = word[20..27].load::<u8>();
+ let _ = word[27..33].load::<u8>();
+ eprintln!("f10 operands, f1={}, f2={}", f1, f2);
+ two_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ )
+ }
+ F11 => {
+ let f1 = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let _ = word[20..27].load::<u8>();
+ let _ = word[27..33].load::<u8>();
+ eprintln!("f11 operands, f1={}, f2={}", f1, f2);
+ two_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ )
+ }
+ F12 => {
+ let _ = word[6..13].load::<u8>();
+ let amask = word[13..20].load::<u8>();
+ let omask = word[20..27].load::<u8>();
+ let _ = word[27..33].load::<u8>();
+ eprintln!("f12 operands, amask={}, omask={}", amask, omask);
+ two_op(
+ Option::None,
+ Operand::ImmU64(amask as u64),
+ Operand::ImmU64(omask as u64),
+ )
+ }
+ F13 => {
+ eprintln!("f13 operands");
+ one_op(false, Operand::None)
+ }
+ F14 => {
+ let imm20a = word[6..26].load::<u32>();
+ // TODO: missing 4 bits?
+ let imm = (word[36] as u32) << 20 + imm20a;
+ eprintln!("f14 operands, imm={}", imm);
+ one_op(
+ false,
+ Operand::ImmU64(imm as u64),
+ )
+ }
+ F15 => {
+ let imm20a = word[6..26].load::<u32>();
+ let imm = (word[36] as u32) << 20 + imm20a;
+ eprintln!("f15 operands, imm={}", imm);
+ one_op(
+ false,
+ Operand::ImmU64(imm as u64),
+ )
+ }
+ F16 => {
+ let imm20a = word[6..26].load::<u32>();
+ let imm = (word[36] as u32) << 20 + imm20a;
+ eprintln!("f16 operands, imm={}", imm);
+ one_op(
+ false,
+ Operand::ImmU64(imm as u64),
+ )
+ }
+ }
}
-fn read_i_operands(encoding: OperandEncodingI, word: &BitSlice<Lsb0, u8>) {
+fn read_i_operands(encoding: OperandEncodingI, word: &BitSlice<Lsb0, u8>) -> (Option<u8>, [Operand; 5]) {
+ use OperandEncodingI::*;
+ match encoding {
+ None => {
+ panic!("should not explicitly check OperandEncodingI::None");
+ }
+ I1 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let count = word[30..32].load::<u8>();
+ eprintln!("i1 operands, r1={}, r2={}, r3={}, count={}", r1, r2, r3, count);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(count as u64),
+ )
+ }
+ I2 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ eprintln!("i2 operands, r1={}, r2={}, r3={}", r1, r2, r3);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
+ }
+ I3 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let mbt = word[20..24].load::<u8>();
+ eprintln!("i3 operands, r1={}, r2={}, mbt={}", r1, r2, mbt);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(mbt as u64),
+ )
+ }
+ I4 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let mht = word[20..28].load::<u8>();
+ eprintln!("i4 operands, r1={}, r2={}, mht={}", r1, r2, mht);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(mht as u64),
+ )
+ }
+ I5 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ eprintln!("i5 operands, r1={}, r2={}, r3={}", r1, r2, r3);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::GPRegister(GPRegister(r2)),
+ )
+ }
+ I6 => {
+ let r1 = word[6..13].load::<u8>();
+ let count = word[14..19].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ eprintln!("i6 operands, r1={}, r3={}, count={}", r1, r3, count);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(count as u64),
+ )
+ }
+ I7 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ eprintln!("i7 operands, r1={}, r2={}, r3={}", r1, r2, r3);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
+ }
+ I8 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let count = word[20..25].load::<u8>();
+ eprintln!("i8 operands, r1={}, r2={}, count={}", r1, r2, count);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(count as u64),
+ )
+ }
+ I9 => {
+ let r1 = word[6..13].load::<u8>();
+ let z = word[13..20].load::<u8>();
+ // TODO: error on this properly? is this a #ud-like?
+ assert_eq!(z, 0);
+ let r3 = word[20..27].load::<u8>();
+ eprintln!("i9 operands, r1={}, r3={}", r1, r3);
+ two_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
+ }
+ I10 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let count = word[27..33].load::<u8>();
+ eprintln!("i10 operands, r1={}, r2={}, r3={}, count={}", r1, r2, r3, count);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(count as u64),
+ )
+ }
+ I11 => {
+ let r1 = word[6..13].load::<u8>();
+ let pos = word[14..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let len = word[27..33].load::<u8>();
+ eprintln!("i11 operands, r1={}, pos={}, r3={}, len={}", r1, pos, r3, len);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(pos as u64),
+ Operand::ImmU64(len as u64),
+ )
+ }
+ I12 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let cpos = word[20..26].load::<u8>();
+ let len = word[27..33].load::<u8>();
+ eprintln!("i12 operands, r1={}, r2={}, cpos={}, len={}", r1, r2, cpos, len);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(cpos as u64),
+ Operand::ImmU64(len as u64),
+ )
+ }
+ I13 => {
+ let r1 = word[6..13].load::<u8>();
+ let imm7b = word[13..20].load::<u8>();
+ let imm = ((word[36] as u8) << 7 + imm7b) as i8;
+ let cpos = word[20..26].load::<u8>();
+ let len = word[27..33].load::<u8>();
+ eprintln!("i13 operands, r1={}, imm={}, cpos={}, len={}", r1, imm, cpos, len);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::ImmU64(imm as u64),
+ Operand::ImmU64(cpos as u64),
+ Operand::ImmU64(len as u64),
+ )
+ }
+ I14 => {
+ let r1 = word[6..13].load::<u8>();
+ let imm = word[36] as u8;
+ let r3 = word[20..27].load::<u8>();
+ let cpos = word[14..20].load::<u8>();
+ let len = word[27..33].load::<u8>();
+ eprintln!("i14 operands, r1={}, imm={}, r3={}, cpos={}, len={}", r1, imm, r3, cpos, len);
+ (
+ Some(0),
+ [
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::ImmU64(imm as u64),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(cpos as u64),
+ Operand::ImmU64(len as u64),
+ ]
+ )
+ }
+ I15 => {
+ let r1 = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let len = word[27..31].load::<u8>();
+ let cpos = word[31..37].load::<u8>();
+ eprintln!("i15 operands, r1={}, r2={}, r3={}, cpos={}, len={}", r1, r2, r3, cpos, len);
+ (
+ Some(0),
+ [
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(cpos as u64),
+ Operand::ImmU64(len as u64),
+ ]
+ )
+ }
+ I16 => {
+ let p1 = word[6..12].load::<u8>();
+ let pos = word[14..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("i16 operands, p1={}, p2={}, r3={}, pos={}", p1, p2, r3, pos);
+ four_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(pos as u64),
+ )
+ }
+ I17 => {
+ let p1 = word[6..12].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("i17 operands, p1={}, p2={}, r3={}", p1, p2, r3);
+ three_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
+ }
+ I18 => {
+ let imm20 = word[6..26].load::<u32>();
+ let imm = imm20 + (word[36] as u32) << 20;
+ eprintln!("i18 operands, imm={}", imm);
+ one_op(
+ false,
+ Operand::ImmU64(imm as u64),
+ )
+ }
+ I19 => {
+ let imm20 = word[6..26].load::<u32>();
+ let imm = imm20 + (word[36] as u32) << 20;
+ eprintln!("i19 operands, imm={}", imm);
+ one_op(
+ false,
+ Operand::ImmU64(imm as u64),
+ )
+ }
+ I20 => {
+ let p1 = word[6..12].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("i20 operands, p1={}, p2={}, r3={}", p1, p2, r3);
+ three_op(
+ Option::None,
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
+ }
+ I21 => {
+ let b1 = word[6..9].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let wh = word[20..22].load::<u8>();
+ let ih = word[23];
+ let tag = word[24..33].load::<u32>();
+ eprintln!("i21 operands, b1={}, r2={}, tag={}, ih={}, wh={}", b1, r2, tag, ih, wh);
+ (
+ Some(0),
+ [
+ Operand::BranchRegister(BranchRegister(b1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(tag as u64),
+ Operand::ImmU64(ih as u64),
+ Operand::ImmU64(wh as u64),
+ ]
+ )
+ }
+ I22 => {
+ let r1 = word[6..13].load::<u8>();
+ let b2 = word[13..16].load::<u8>();
+ eprintln!("i22 operands, r1={}, b2={}", r1, b2);
+ two_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::BranchRegister(BranchRegister(b2)),
+ )
+ }
+ I23 => {
+ let mask7a = word[6..13].load::<u32>();
+ let r2 = word[13..20].load::<u8>();
+ let mask8c = word[24..32].load::<u32>();
+ let _s = word[36] as u32;
+ // TODO: this is .. missing two bits?
+ let mask = (mask8c << 7) + mask7a;
+ eprintln!("i23 operands, r2={}, mask={}", r2, mask);
+ three_op(
+ Some(0),
+ Operand::PR,
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(mask as u64),
+ )
+ }
+ I24 => {
+ let imm = word[6..33].load::<u8>();
+ let _s = word[36] as u32;
+ // TODO: this is missing ... 17 bits? sign extend?
+ eprintln!("i24 operands, imm={}", imm);
+ two_op(
+ Some(0),
+ Operand::PR,
+ Operand::ImmU64(imm as u64),
+ )
+ }
+ I25 => {
+ let r1 = word[6..13].load::<u8>();
+ let x6 = word[27..33].load::<u8>();
+ eprintln!("i25 operands, r1={}, x6={}", r1, x6);
+ let src = match x6 {
+ 30 => Operand::IP,
+ 33 => Operand::PR,
+ _ => {
+ // TODO: what does a bad I25 x6 get you? nop?
+ Operand::None
+ }
+ };
+ two_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ src,
+ )
+ }
+ I26 => {
+ let r2 = word[13..20].load::<u8>();
+ let ar3 = word[20..27].load::<u8>();
+ eprintln!("i26 operands, ar3={}, r2={}", ar3, r2);
+ two_op(
+ Some(0),
+ Operand::ApplicationRegister(ApplicationRegister(ar3)),
+ Operand::GPRegister(GPRegister(r2)),
+ )
+ }
+ I27 => {
+ let imm7b = word[13..20].load::<u8>();
+ let imm = (((word[36] as u8) << 7) + imm7b) as i8;
+ let ar3 = word[20..27].load::<u8>();
+ eprintln!("i27 operands, ar3={}, imm={}", ar3, imm);
+ two_op(
+ Some(0),
+ Operand::ApplicationRegister(ApplicationRegister(ar3)),
+ Operand::ImmI64(imm as i64),
+ )
+ }
+ I28 => {
+ let r1 = word[6..13].load::<u8>();
+ let ar3 = word[20..27].load::<u8>();
+ eprintln!("i28 operands, ar3={}, r1={}", ar3, r1);
+ two_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::ApplicationRegister(ApplicationRegister(ar3)),
+ )
+ }
+ I29 => {
+ let r1 = word[6..13].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ eprintln!("i29 operands, r3={}, r1={}", r3, r1);
+ two_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
+ }
+ I30 => {
+ let p1 = word[6..13].load::<u8>();
+ let imm = word[14..19].load::<u8>();
+ let z = word[20..27].load::<u8>();
+ // TODO: what happens when this field isn't actually zero?
+ assert_eq!(z, 0);
+ let p2 = word[27..33].load::<u8>();
+ eprintln!("i30 operands, p1={}, p2={}, imm={}", p1, p2, imm);
+ three_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::ImmU64(imm as u64)
+ )
+ }
+ }
}
-fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice<Lsb0, u8>) {
+fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice<Lsb0, u8>) -> (Option<u8>, [Operand; 5]) {
use OperandEncodingM::*;
match encoding {
M1 => {
@@ -718,6 +2267,12 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
eprintln!("m1 operands, r1={}, r3={}, hint={}", r1, r3, hint);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::Memory(GPRegister(r3)),
+ Operand::ImmU64(hint as u64)
+ )
},
M2 => {
let r1 = word[6..13].load::<u8>();
@@ -725,27 +2280,135 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
eprintln!("m2 operands, r1={}, r2={}, r3={}, hint={}", r1, r2, r3, hint);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::Memory(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(hint as u64)
+ )
},
- M6 => {
+ M3 => {
+ let r1 = word[6..13].load::<u8>();
+ let imm = word[13..20].load::<u16>() + (word[27] as u16) << 7 + (word[36] as u16) << 8;
+ let r3 = word[20..27].load::<u8>();
+ let hint = word[28..30].load::<u8>();
+ eprintln!("m3 operands, r1={}, imm={}, r3={}, hint={}", r1, imm, r3, hint);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::Memory(GPRegister(r3)),
+ Operand::ImmU64(imm as u64),
+ Operand::ImmU64(hint as u64)
+ )
+ },
+ M4 => {
let _ = word[6..13].load::<u8>();
let r2 = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
- eprintln!("m6 operands, r2={}, r3={}, hint={}", r2, r3, hint);
+ eprintln!("m4 operands, r2={}, r3={}, hint={}", r2, r3, hint);
+ three_op(
+ Some(0),
+ Operand::Memory(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(hint as u64)
+ )
+ },
+ M5 => {
+ let imm7 = word[13..20].load::<u16>();
+ let i = word[27] as u16;
+ let s = word[36] as u16;
+ let imm = imm7 + (i << 7) + (s << 8);
+ let imm = (((imm as i16) << 7) >> 7) as i64;
+ let r2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let hint = word[28..30].load::<u8>();
+ eprintln!("m5 operands, r2={}, r3={}, imm={}, hint={}", r2, r3, imm, hint);
+ four_op(
+ Some(0),
+ Operand::Memory(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmI64(imm),
+ Operand::ImmU64(hint as u64),
+ )
}
- M9 => {
+ M6 => {
let f1 = word[6..13].load::<u8>();
let _ = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
- eprintln!("m9 operands, f1={}, r3={}, hint={}", f1, r3, hint);
+ eprintln!("m6 operands, f1={}, r3={}, hint={}", f1, r3, hint);
+ three_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::Memory(GPRegister(r3)),
+ Operand::ImmU64(hint as u64)
+ )
}
- M10 => {
+ M7 => {
let f1 = word[6..13].load::<u8>();
let r2 = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
- eprintln!("m10 operands, f1={}, r2={}, r3={}, hint={}", f1, r2, r3, hint);
+ eprintln!("m7 operands, f1={}, r3={}, r2={}, hint={}", f1, r3, r2, hint);
+ four_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::Memory(GPRegister(r3)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(hint as u64)
+ )
+ }
+ M8 => {
+ let f1 = word[6..13].load::<u8>();
+ let imm7 = word[13..20].load::<u16>();
+ let i = word[27] as u16;
+ let s = word[36] as u16;
+ let imm = imm7 + (i << 7) + (s << 8);
+ let imm = (((imm as i16) << 7) >> 7) as i64;
+ let r3 = word[20..27].load::<u8>();
+ let hint = word[28..30].load::<u8>();
+ eprintln!("m8 operands, f1={}, r3={}, imm={}, hint={}", f1, r3, imm, hint);
+ four_op(
+ Some(0),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::Memory(GPRegister(r3)),
+ Operand::ImmI64(imm),
+ Operand::ImmU64(hint as u64)
+ )
+ }
+ M9 => {
+ let _ = word[6..13].load::<u8>();
+ let f2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let hint = word[28..30].load::<u8>();
+ eprintln!("m9 operands, f2={}, r3={}, hint={}", f2, r3, hint);
+ three_op(
+ Some(0),
+ Operand::Memory(GPRegister(r3)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::ImmU64(hint as u64)
+ )
+ }
+ M10 => {
+ let imm7 = word[6..13].load::<u16>();
+ let i = word[27] as u16;
+ let s = word[36] as u16;
+ let imm = imm7 + (i << 7) + (s << 8);
+ let imm = (((imm as i16) << 7) >> 7) as i64;
+ let f2 = word[13..20].load::<u8>();
+ let r3 = word[20..27].load::<u8>();
+ let hint = word[28..30].load::<u8>();
+ // TODO: memory operand here?
+ eprintln!("m10 operands, r3={}, f2={}, imm={}, hint={}", r3, f2, imm, hint);
+ four_op(
+ Some(0),
+ Operand::Memory(GPRegister(r3)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::ImmI64(imm),
+ Operand::ImmU64(hint as u64)
+ )
}
M11 => {
let f1 = word[6..13].load::<u8>();
@@ -753,20 +2416,50 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
eprintln!("m11 operands, f1={}, f2={}, r3={}, hint={}", f1, f2, r3, hint);
+ four_op(
+ Some(1),
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::Memory(GPRegister(r3)),
+ Operand::ImmU64(hint as u64)
+ )
}
M12 => {
let f1 = word[6..13].load::<u8>();
let f2 = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
+ // drived from low bit of x6, which is used to pick the opcode associated with the
+ // `M12` pattern. the size here is actually redundant with that opcode, but kept here
+ // for ease of access.
+ let size = if word[30] {
+ 16
+ } else {
+ 8
+ };
let hint = word[28..30].load::<u8>();
eprintln!("m12 operands, f1={}, f2={}, r3={}, hint={}", f1, f2, r3, hint);
+ (
+ Some(1),
+ [
+ Operand::FloatRegister(FloatRegister(f1)),
+ Operand::FloatRegister(FloatRegister(f2)),
+ Operand::Memory(GPRegister(r3)),
+ Operand::ImmU64(size),
+ Operand::ImmU64(hint as u64)
+ ]
+ )
}
M13 => {
let _ = word[6..13].load::<u8>();
- let f2 = word[13..20].load::<u8>();
+ let _ = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
- eprintln!("m13 operands, f2={}, r3={}, hint={}", f2, r3, hint);
+ eprintln!("m13 operands, r3={}, hint={}", r3, hint);
+ two_op(
+ Option::None,
+ Operand::Memory(GPRegister(r3)),
+ Operand::ImmU64(hint as u64)
+ )
}
M14 => {
let _ = word[6..13].load::<u8>();
@@ -774,13 +2467,72 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
eprintln!("m14 operands, r2={}, r3={}, hint={}", r2, r3, hint);
+ three_op(
+ Option::None,
+ Operand::Memory(GPRegister(r3)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::ImmU64(hint as u64)
+ )
}
+ // TODO: m15?
M16 => {
let r1 = word[6..13].load::<u8>();
let r2 = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
let hint = word[28..30].load::<u8>();
eprintln!("m16 operands, r1={}, r2={}, r3={}, hint={}", r1, r2, r3, hint);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::Memory(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(hint as u64)
+ )
+ }
+ M29 => {
+ let _ = word[6..13].load::<u8>();
+ let r2 = word[13..20].load::<u8>();
+ let ar3 = word[20..27].load::<u8>();
+ eprintln!("m29 operands, r2={}, ar3={}", r2, ar3);
+ two_op(
+ Some(0),
+ Operand::ApplicationRegister(ApplicationRegister(ar3)),
+ Operand::GPRegister(GPRegister(r2)),
+ )
+ }
+ M31 => {
+ let r1 = word[6..13].load::<u8>();
+ let _ = word[13..20].load::<u8>();
+ let ar3 = word[20..27].load::<u8>();
+ eprintln!("m31 operands, r1={}, ar3={}", r1, ar3);
+ two_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::ApplicationRegister(ApplicationRegister(ar3)),
+ )
+ }
+ M34 => {
+ let r1 = word[6..13].load::<u8>();
+ let sof = word[13..20].load::<u8>();
+ let sol = word[20..27].load::<u8>();
+ let sor = word[27..31].load::<u8>();
+ eprintln!("m34 operands, r1={}, sof={}, sol={}, sor={}", r1, sof, sol, sor);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ // ar.pfs? which number is pfs?
+ Operand::ImmU64(sof as u64),
+ Operand::ImmU64(sol as u64),
+ Operand::ImmU64(sor as u64),
+ )
+ }
+ M48 => {
+ let i = word[6..26].load::<u32>() + (word[36] as u32) << 20;
+ eprintln!("m48 operands, imm={}", i);
+ one_op(
+ false,
+ Operand::ImmU64(i as u64),
+ )
}
other => {
unimplemented!("unimplemented m operand encoding: {:?}", other);
@@ -788,7 +2540,7 @@ fn read_m_operands(encoding: OperandEncodingM, word: &BitSlice<Lsb0, u8>) {
}
}
-fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
+fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) -> (Option<u8>, [Operand; 5]) {
use OperandEncodingA::*;
match encoding {
None => { unreachable!("none operand encoding"); }
@@ -797,6 +2549,12 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let r2 = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
eprintln!("a1 operands, r1={}, r2={}, r3={}", r1, r2, r3);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
},
A2 => {
let r1 = word[6..13].load::<u8>();
@@ -804,6 +2562,13 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let ct = word[27..29].load::<u8>();
eprintln!("a2 operands, r1={}, r2={}, r3={}, ct={}", r1, r2, r3, ct);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(ct as u64),
+ )
},
A3 => {
let r1 = word[6..13].load::<u8>();
@@ -812,6 +2577,12 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let s = word[36];
let imm = (immb + ((s as u8) << 7)) as i8 as i32;
eprintln!("a3 operands, r1={}, r3={}, imm={}", r1, r3, imm);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmI64(imm as i64),
+ )
},
A4 => {
let r1 = word[6..13].load::<u8>();
@@ -819,9 +2590,16 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let immb = word[13..20].load::<u16>();
let immd = word[27..33].load::<u16>();
let s = word[36];
- let imm = ((s as u16) << 12) + (immd << 7) + immb;
+ eprintln!("immb: {:#b}, immd: {:#b}, s: {}", immb, immd, s);
+ let imm = ((s as u16) << 13) + (immd << 7) + immb;
let imm = (((imm as i16) << 2) >> 2) as i32;
eprintln!("a4 operands, r1={}, r3={}, imm={}", r1, r3, imm);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::ImmI64(imm as i64),
+ Operand::GPRegister(GPRegister(r3)),
+ )
},
A5 => {
let r1 = word[6..13].load::<u8>();
@@ -831,6 +2609,12 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let imm = (immc_d_s << 7) + immb;
let imm = ((imm as i32) << 10) >> 10;
eprintln!("a5 operands, r1={}, r3={}, imm={}", r1, r3, imm);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmI64(imm as i64),
+ )
}
A6 => {
let p1 = word[6..12].load::<u8>();
@@ -838,6 +2622,13 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let p2 = word[27..33].load::<u8>();
eprintln!("a6 operands, r2={}, r3={}, p1={}, p2={}", r2, r3, p1, p2);
+ four_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
},
A7 => {
let p1 = word[6..12].load::<u8>();
@@ -847,6 +2638,13 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let p2 = word[27..33].load::<u8>();
eprintln!("a7 operands, r3={}, p1={}, p2={}", r3, p1, p2);
+ four_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::GPRegister(GPRegister(0)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
},
A8 => {
let p1 = word[6..12].load::<u8>();
@@ -856,12 +2654,25 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let p2 = word[27..33].load::<u8>();
eprintln!("a8 operands, imm={}, r3={}, p1={}, p2={}", imm, r3, p1, p2);
+ four_op(
+ Some(1),
+ Operand::PredicateRegister(PredicateRegister(p1)),
+ Operand::PredicateRegister(PredicateRegister(p2)),
+ Operand::ImmI64(imm as i64),
+ Operand::GPRegister(GPRegister(r3)),
+ )
},
A9 => {
let r1 = word[6..13].load::<u8>();
let r2 = word[13..20].load::<u8>();
let r3 = word[20..27].load::<u8>();
eprintln!("a9 operands, r1={}, r2={}, r3={}", r1, r2, r3);
+ three_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ )
},
A10 => {
let r1 = word[6..13].load::<u8>();
@@ -869,11 +2680,18 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) {
let r3 = word[20..27].load::<u8>();
let ct = word[27..29].load::<u8>();
eprintln!("a10 operands, r1={}, r2={}, r3={}, ct={}", r1, r2, r3, ct);
+ four_op(
+ Some(0),
+ Operand::GPRegister(GPRegister(r1)),
+ Operand::GPRegister(GPRegister(r2)),
+ Operand::GPRegister(GPRegister(r3)),
+ Operand::ImmU64(ct as u64),
+ )
},
}
}
-fn get_lx_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, OperandEncodingX) {
+fn get_l_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, OperandEncodingX) {
use Opcode::*;
use OperandEncodingX::*;
@@ -939,7 +2757,8 @@ fn get_b_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
];
let index = word[27..33].load::<u8>();
- if index == 0b10000 {
+ eprintln!("table 4-48 idx {:#b}", index);
+ if index == 0b100000 {
// `Indirect Branch (Table 4-49)`
const TABLE4_49: [(Opcode, OperandEncodingB); 8] = [
(Br_cond, B4), (Br_ia, B4), (Brown, None), (Brown, None),
@@ -947,7 +2766,7 @@ fn get_b_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
];
let subindex = word[6..9].load::<u8>();
TABLE4_49[subindex as usize]
- } else if index == 0b10001 {
+ } else if index == 0b100001 {
// `Indirect Return (Table 4-50)`
const TABLE4_50: [(Opcode, OperandEncodingB); 8] = [
(Brown, None), (Brown, None), (Brown, None), (Brown, None),
@@ -1182,6 +3001,8 @@ fn get_i_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
use Opcode::*;
use OperandEncodingI::*;
+ eprintln!("i tag {}", tag);
+
match tag {
0 => {
let x3 = word[33..36].load::<u8>();
@@ -1189,24 +3010,12 @@ fn get_i_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
if x3 == 0 {
// SIDEWAYS
// `Table 4-25 Misc I-Unit 6-bit Opcode Extensions`
+ // `1-bit Ext (Table 4-26)` is handled independently
const TABLE4_25: [(Opcode, OperandEncodingI); 64] = [
- (Break_i, I19), (Zxt1, I29), (Purple, None), (Mov_from_ip, I25),
- // `1-bit Ext (Table 4-26)` is handled independently
- (Purple, None), (Zxt2, I29), (Purple, None), (Mov_from_b, I22),
- (Purple, None), (Zxt4, I29), (Purple, None), (Mov_i_from_ar, I28),
- (Purple, None), (Purple, None), (Purple, None), (Mov_from_pr, I25),
- (Purple, None), (Sxt1, I29), (Purple, None), (Purple, None),
- (Purple, None), (Sxt2, I29), (Purple, None), (Purple, None),
- (Purple, None), (Sxt4, I29), (Purple, None), (Purple, None),
- (Purple, None), (Purple, None), (Purple, None), (Purple, None),
- (Purple, None), (Czx1_l, I29), (Purple, None), (Purple, None),
- (Purple, None), (Czx2_l, I29), (Purple, None), (Purple, None),
- (Mov_i_to_ar_imm, I27), (Purple, None), (Mov_i_to_ar, I26), (Purple, None),
- (Purple, None), (Purple, None), (Purple, None), (Purple, None),
- (Purple, None), (Czx1_r, I29), (Purple, None), (Purple, None),
- (Purple, None), (Czx2_r, I29), (Purple, None), (Purple, None),
- (Purple, None), (Purple, None), (Purple, None), (Purple, None),
- (Purple, None), (Purple, None), (Purple, None), (Purple, None),
+ (Break_i, I19), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Mov_i_to_ar_imm, I27), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None),
+ (Zxt1, I29), (Zxt2, I29), (Zxt4, I29), (Purple, None), (Sxt1, I29), (Sxt2, I29), (Sxt4, I29), (Purple, None), (Czx1_l, I29), (Czx2_l, I29), (Purple, None), (Purple, None), (Czx1_r, I29), (Czx2_r, I29), (Purple, None), (Purple, None),
+ (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Mov_i_to_ar, I26), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None),
+ (Mov_from_ip, I25), (Mov_from_b, I22), (Mov_i_from_ar, I28), (Mov_from_pr, I25), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None),
];
let index = word[27..33].load::<u8>();
if index == 0b00001 {
@@ -1220,7 +3029,7 @@ fn get_i_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
TABLE4_25[index as usize]
} else {
// `Table 4-24 Misc I-Unit 3-bit Opcode Extensions`
- const TABLE4_24: [(Opcode, OperandEncodingI); 8] = [
+ const TABLE4_24: [(Opcode, OperandEncodingI); 7] = [
(Purple, None),
(Chk_s_i_int, I20),
(Mov_to_pr_rot_imm, I24),
@@ -1228,9 +3037,16 @@ fn get_i_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
(Purple, None),
(Purple, None),
(Purple, None),
- (Mov_to_b, I21),
];
- TABLE4_24[x3 as usize]
+ if x3 == 7 {
+ if word[22] {
+ (Mov_ret_mwh_ih, I21)
+ } else {
+ (Mov_mwh_ih, I21)
+ }
+ } else {
+ TABLE4_24[x3 as usize]
+ }
}
},
1 => { (Purple, None) },
@@ -1411,6 +3227,8 @@ fn get_m_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
use Opcode::*;
use OperandEncodingM::*;
+ eprintln!("m tag {}", tag);
+
match tag {
0 => {
let x3 = word[33..36].load::<u8>();
@@ -1462,29 +3280,18 @@ fn get_m_opcode_and_encoding(tag: u8, word: &BitSlice<Lsb0, u8>) -> (Opcode, Ope
},
1 => {
let x3 = word[33..36].load::<u8>();
+ eprintln!("x3: {:#b}", x3);
// `Table 4-44 Opcode 1 System/Memory Management 3-bit Opcode Extensions`
if x3 == 0 {
- unimplemented!("table 4-45");
// `Table 4-45 System/Memory Management 6-bit Ext`
const TABLE4_45: [(Opcode, OperandEncodingM); 64] = [
- (Mov_to_rr, M42), (Mov_from_rr, M43), (Purple, None), (Fc, M28),
- (Mov_to_dbr, M42), (Mov_from_dbr, M43), (Mov_from_psr_um, M36), (Probe_rw_fault_imm, M40),
- (Mov_to_ibr, M42), (Mov_from_ibr, M43), (Mov_m_from_ar, M31), (Probe_r_fault_imm, M40),
- (Mov_to_pkr, M43), (Mov_from_pkr, M43), (Purple, None), (Probe_w_fault_imm, M40),
- (Mov_to_pmc, M42), (Mov_from_pmc, M43), (Mov_from_cr, M33), (Ptc_e, M47),
- (Mov_to_pmd, M42), (Mov_from_pmd, M43), (Mov_from_psr, M36), (Purple, None),
- (Purple, None), (Purple, None), (Purple, None), (Purple, None),
- (Purple, None), (Mov_from_cpuid, M43), (Purple, None), (Purple, None),
- (Purple, None), (Probe_r_imm, M39), (Purple, None), (Probe_r, M38),
- (Ptc_l, M45), (Probe_w_imm, M39), (Mov_to_psr_um, M35), (Probe_w, M38),
- (Ptc_g, M45), (Thash, M46), (Mov_m, M29), (Purple, None),
- (Ptc_ga, M45), (Ttag, M46), (Purple, None), (Purple, None),
- (Ptr_d, M45), (Purple, None), (Mov_to_cr, M32), (Purple, None),
- (Ptr_i, M45), (Purple, None), (Mov_to_psr_l, M35), (Purple, None),
- (Itr_d, M42), (Tpa, M46), (Itc_d, M41), (Purple, None),
- (Itr_i, M42), (Tak, M46), (Itc_i, M41), (Purple, None),
+ (Mov_to_rr, M42), (Mov_to_dbr, M42), (Mov_to_ibr, M42), (Mov_to_pkr, M43), (Mov_to_pmc, M42), (Mov_to_pmd, M42), (Purple, None), (Purple, None), (Purple, None), (Ptc_l, M45), (Ptc_g, M45), (Ptc_ga, M45), (Ptr_d, M45), (Ptr_i, M45), (Itr_d, M42), (Itr_i, M42),
+ (Mov_from_rr, M43),(Mov_from_dbr, M43), (Mov_from_ibr, M43), (Mov_from_pkr, M43), (Mov_from_pmc, M43), (Mov_from_pmd, M43), (Purple, None), (Mov_from_cpuid, M43), (Probe_r_imm, M39), (Probe_w_imm, M39), (Thash, M46), (Ttag, M46), (Purple, None), (Purple, None), (Tpa, M46), (Tak, M46),
+ (Purple, None), (Mov_from_psr_um, M36), (Mov_m_from_ar, M31), (Purple, None), (Mov_from_cr, M33), (Mov_from_psr, M36), (Purple, None), (Purple, None), (Purple, None), (Mov_to_psr_um, M35), (Mov_m, M29), (Purple, None), (Mov_to_cr, M32), (Mov_to_psr_l, M35), (Itc_d, M41), (Itc_i, M41),
+ (Fc, M28),(Probe_rw_fault_imm, M40), (Probe_r_fault_imm, M40), (Probe_w_fault_imm, M40), (Ptc_e, M47), (Purple, None), (Purple, None), (Purple, None), (Probe_r, M38), (Probe_w, M38), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None), (Purple, None),
];
let index = word[27..33].load::<u8>();
+ eprintln!("idx2: {:#b}", index);
TABLE4_45[index as usize]
} else {
const TABLE4_44: [(Opcode, OperandEncodingM); 8] = [
@@ -2041,6 +3848,7 @@ enum OperandEncodingF {
F16,
}
+/// the manual is weird. encodings from `L`-unit instructions are named `X1`, `X2`, and so on.
#[derive(Copy, Clone, Debug)]
enum OperandEncodingX {
None,
diff --git a/tests/test.rs b/tests/test.rs
index cac89d0..a035c37 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -7,10 +7,35 @@ fn test_a_bundle() {
// [MMI] addl r15=0,r1;;
// ld8.acq r16=[r15],8
// mov r14=r1;;
- let data = [0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, 0x00, 0x41, 0x3c, 0x70, 0x27, 0xc0, 0x01, 0x08, 0x00, 0x84];
+// let data = [0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, 0x00, 0x41, 0x3c, 0x70, 0x27, 0xc0, 0x01, 0x08, 0x00, 0x84];
+ let data = [0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0];
+ let data = [0x04, 0x10, 0x1c, 0x00, 0x80, 0x45, 0x02, 0x4c, 0x80, 0x09, 0x00, 0x60, 0xf0, 0x13, 0x1a, 0x60];
+ let data = [0x05, 0x10, 0x41, 0x18, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x00, 0x23, 0xc8, 0x6f];
let decoder = InstDecoder::default();
- decoder.decode(data[..].iter().cloned()).unwrap();
+ let inst = decoder.decode(data[..].iter().cloned()).unwrap();
+ println!("{:?}", inst);
+ println!("{}", inst);
+}
+
+#[test]
+fn test_br_cosmetics() {
+ let decoder = InstDecoder::default();
+
+ let data = [0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00];
+ let inst = decoder.decode(data[..].iter().cloned()).unwrap();
+ let stringy = format!("{}", inst);
+// assert_eq!(stringy, "[MIB] ld8 r1=[r15]; mov b6=r16; br.few b6;;");
+
+ let data = [0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0];
+ let inst = decoder.decode(data[..].iter().cloned()).unwrap();
+ let stringy = format!("{}", inst);
+// assert_eq!(stringy, "[MLX] nop.m 0; brl.sptk.few tgt;;");
+
+ let data = [0x19, 0x50, 0x40, 0x19, 0x3f, 0x23, 0x80, 0x00, 0x00, 0x00, 0x48, 0x80, 0x00, 0x00, 0x84, 0x02];
+ let inst = decoder.decode(data[..].iter().cloned()).unwrap();
+ let stringy = format!("{}", inst);
+ assert_eq!(stringy, "[MMB] adds r10=-48,r12; mov r8=0; br.ret.dptk.few b0");
}
// from elf64-ia64-vms.c