Last active
June 22, 2020 05:33
-
-
Save brandonros/3e94758f6c7f0c596d34a7d38ec20df9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use crate::{masks}; | |
pub enum Format { | |
// 16 bit formats | |
SB, | |
SBC, | |
SBR, | |
SBRN, | |
SC, | |
SLR, | |
SLRO, | |
SR, | |
SRC, | |
SRO, | |
SRR, | |
SRRS, | |
SSR, | |
SSRO, | |
// 32-bit formats | |
ABS, | |
B, | |
BO, | |
BOL, | |
BRC, | |
BRN, | |
BRR, | |
RC, | |
RCPW, | |
RCR, | |
RLC, | |
RR, | |
RR2, | |
RRPW, | |
} | |
pub struct OpCode { | |
pub size: u8, | |
pub hex: u32, | |
pub op1: u8, | |
pub op2: Option<u8>, | |
pub format: Format, | |
pub const16: Option<u16>, | |
pub const16_sext: Option<i16>, | |
pub const4: Option<u8>, | |
pub const4_sext: Option<i8>, | |
pub const8: Option<u8>, | |
pub const9_sext: Option<u16>, | |
pub d: Option<u8>, | |
pub disp15_sext: Option<i16>, | |
pub disp24_sext: Option<i32>, | |
pub disp4: Option<u8>, | |
pub disp8_sext: Option<i8>, | |
pub n: Option<u8>, | |
pub off10_sext: Option<i16>, | |
pub off16_sext: Option<u16>, | |
pub off18: Option<u32>, | |
pub off4: Option<u8>, | |
pub pos: Option<u8>, | |
pub s1: Option<u8>, | |
pub s1d: Option<u8>, | |
pub s2: Option<u8>, | |
pub s3: Option<u8>, | |
pub width: Option<u8> | |
} | |
// 16-bit OPCM | |
// sr | |
const OPCM_16_SR_SYSTEM: u8 = 0x00; | |
// 32-bit OPCM | |
// abs | |
const OPCM_32_ABS_LDW: u8 = 0x85; | |
const OPCM_32_ABS_STORE: u8 = 0xa5; | |
// bo | |
const OPCM_32_BO_ADDRMODE_LD_POST_PRE_BASE: u8 = 0x09; | |
const OPCM_32_BO_ADDRMODE_POST_PRE_BASE: u8 = 0x89; | |
const OPCM_32_BO_ADDRMODE_STCTX_POST_PRE_BASE: u8 = 0x49; | |
// brc | |
const OPCM_32_BRC_EQ_NEQ: u8 = 0xDF; | |
const OPCM_32_BRC_GE: u8 = 0xFF; | |
const OPCM_32_BRC_JLT: u8 = 0xBF; | |
// brn | |
const OPCM_32_BRN_JTT: u8 = 0x6F; | |
// brr | |
const OPCM_32_BRR_EQ_NEQ: u8 = 0x5f; | |
const OPCM_32_BRR_GE: u8 = 0x7f; | |
const OPCM_32_BRR_JLT: u8 = 0x3F; | |
const OPCM_32_BRR_LOOP: u8 = 0xFD; | |
// rc | |
const OPCM_32_RC_ACCUMULATOR: u8 = 0x8b; | |
const OPCM_32_RC_LOGICAL_SHIFT: u8 = 0x8f; | |
const OPCM_32_RC_MUL: u8 = 0x53; | |
// rcpw | |
const OPCM_32_RCPW_MASK_INSERT: u8 = 0xb7; | |
// rcr | |
const OPCM_32_RCR_MADD: u8 = 0x13; | |
// rr2 | |
const OPCM_32_RR2_MUL: u8 = 0x73; | |
// rr | |
const OPCM_32_RR_ACCUMULATOR: u8 = 0x0b; | |
const OPCM_32_RR_ADDRESS: u8 = 0x01; | |
const OPCM_32_RR_DIVIDE: u8 = 0x4b; | |
const OPCM_32_RR_IDIRECT: u8 = 0x2d; | |
const OPCM_32_RR_LOGICAL_SHIFT: u8 = 0x0f; | |
// rrpw | |
const OPCM_32_RRPW_EXTRACT_INSERT: u8 = 0x37; | |
// sys | |
const OPCM_32_SYS_INTERRUPTS: u8 = 0x0D; | |
fn determine_op2_16(hex: u16, op1: u8) -> Option<u8> { | |
match op1 { | |
OPCM_16_SR_SYSTEM => { masks::mask_op_sr_op2(hex) } | |
_ => { None } | |
} | |
} | |
fn determine_op2_32(hex: u32, op1: u8) -> Option<u8> { | |
match op1 { | |
OPCM_32_ABS_LDW | OPCM_32_ABS_STORE => { | |
masks::mask_op_abs_op2(hex) | |
} | |
OPCM_32_BO_ADDRMODE_LD_POST_PRE_BASE | OPCM_32_BO_ADDRMODE_POST_PRE_BASE | OPCM_32_BO_ADDRMODE_STCTX_POST_PRE_BASE => { | |
masks::mask_op_bo_op2(hex); | |
} | |
OPCM_32_BRC_EQ_NEQ | OPCM_32_BRC_GE | OPCM_32_BRC_JLT => { | |
masks::mask_op_brc_op2(hex); | |
} | |
OPCM_32_BRN_JTT => { | |
masks::mask_op_brn_op2(hex); | |
} | |
OPCM_32_BRR_EQ_NEQ | OPCM_32_BRR_GE | OPCM_32_BRR_JLT | OPCM_32_BRR_LOOP => { | |
masks::mask_op_brr_op2(hex); | |
} | |
OPCM_32_RC_ACCUMULATOR | OPCM_32_RC_LOGICAL_SHIFT | OPCM_32_RC_MUL => { | |
masks::mask_op_rc_op2(hex); | |
} | |
OPCM_32_RCPW_MASK_INSERT => { | |
masks::mask_op_rcpw_op2(hex); | |
} | |
OPCM_32_RCR_MADD => { | |
masks::mask_op_rcr_op2(hex); | |
} | |
OPCM_32_RR2_MUL => { | |
masks::mask_op_rr2_op2(hex); | |
} | |
OPCM_32_RR_ACCUMULATOR | OPCM_32_RR_ADDRESS | OPCM_32_RR_DIVIDE | OPCM_32_RR_IDIRECT | OPCM_32_RR_LOGICAL_SHIFT => { | |
masks::mask_op_rr_op2(hex); | |
} | |
OPCM_32_RRPW_EXTRACT_INSERT => { | |
masks::mask_op_rrpw_op2(hex); | |
} | |
OPCM_32_SYS_INTERRUPTS => { | |
masks::mask_op_sys_op2(hex); | |
} | |
_ => { None } | |
} | |
} | |
fn determine_format_16(op1: u8) -> Format { | |
match op1 { | |
OPC1_16_SB_J | OPC1_16_SB_JNZ | OPC1_16_SB_JZ => SB | |
OPC1_16_SBC_JEQ2 | OPC1_16_SBC_JEQ | OPC1_16_SBC_JNE2 | OPC1_16_SBC_JNE => SBC | |
OPC1_16_SBR_JEQ2 | OPC1_16_SBR_JEQ | OPC1_16_SBR_JNE2 | OPC1_16_SBR_JNE | OPC1_16_SBR_JNZ | OPC1_16_SBR_JZ | OPC1_16_SBR_JZ_A | OPC1_16_SBR_LOOP => SBR | |
OPC1_16_SBRN_JNZ_T | OPC1_16_SBRN_JZ_T => SBRN | |
OPC1_16_SC_AND | OPC1_16_SC_LD_A | OPC1_16_SC_LD_W | OPC1_16_SC_MOV | OPC1_16_SC_OR | OPC1_16_SC_ST_A | OPC1_16_SC_ST_W | OPC1_16_SC_SUB_A => SC | |
OPC1_16_SLR_LD_A | OPC1_16_SLR_LD_BU | OPC1_16_SLR_LD_BU_POSTINC | OPC1_16_SLR_LD_W | OPC1_16_SLR_LD_W_POSTINC => SLR | |
OPC1_16_SLRO_LD_A | OPC1_16_SLRO_LD_BU | OPC1_16_SLRO_LD_W => SLRO | |
OPC1_16_SR_JI | OPC1_16_SRC_ADD | OPC1_16_SRC_ADD_A15 | OPC1_16_SRC_ADD_A | OPC1_16_SRC_CADD | OPC1_16_SRC_EQ | OPC1_16_SRC_MOV | OPC1_16_SRC_MOV_A | OPC1_16_SRC_SH | OPC1_16_SRC_SHA => SRC | |
OPC1_16_SRO_LD_A | OPC1_16_SRO_LD_BU | OPC1_16_SRO_LD_W | OPC1_16_SRO_ST_A | OPC1_16_SRO_ST_B | OPC1_16_SRO_ST_W => SRO | |
OPC1_16_SRR_ADD | OPC1_16_SRR_AND | OPC1_16_SRR_CMOV | OPC1_16_SRR_MOV | OPC1_16_SRR_MOV_A | OPC1_16_SRR_MOV_AA | OPC1_16_SRR_MOV_D | OPC1_16_SRR_MUL | OPC1_16_SRR_OR | OPC1_16_SRR_SUB | OPC1_16_SRR_SUB_A15B | OPC1_16_SRR_XOR => SRR | |
OPC1_16_SRRS_ADDSC_A | OPC1_16_SSR_ST_A | OPC1_16_SSR_ST_B | OPC1_16_SSR_ST_B_POSTINC | OPC1_16_SSR_ST_H | OPC1_16_SSR_ST_W | OPC1_16_SSR_ST_W_POSTINC => SSR | |
OPCM_16_SR_SYSTEM | OPC1_16_SSRO_ST_A | OPC1_16_SSRO_ST_B | OPC1_16_SSRO_ST_H | OPC1_16_SSRO_ST_W => SSRO | |
_ => { panic!("Unknown format"); } | |
} | |
} | |
fn determine_format_32(op1: u8) -> Format { | |
match op1 { | |
OPC1_32_ABS_LEA | OPCM_32_ABS_LDW | OPCM_32_ABS_STORE => ABS | |
OPC1_32_B_J => B | |
OPCM_32_BO_ADDRMODE_LD_POST_PRE_BASE | OPCM_32_BO_ADDRMODE_POST_PRE_BASE | OPCM_32_BO_ADDRMODE_STCTX_POST_PRE_BASE => BO | |
OPC1_32_BOL_LD_A_LONGOFF | OPC1_32_BOL_LD_BU_LONGOFF | OPC1_32_BOL_LD_HU_LONGOFF | OPC1_32_BOL_LD_W_LONGOFF | OPC1_32_BOL_LEA_LONGOFF | OPC1_32_BOL_ST_A_LONGOFF | OPC1_32_BOL_ST_B_LONGOF | OPC1_32_BOL_ST_H_LONGOFF | OPC1_32_BOL_ST_W_LONGOFF => BOL | |
OPCM_32_BRC_EQ_NEQ | OPCM_32_BRC_GE | OPCM_32_BRC_JLT => BRC | |
OPCM_32_BRN_JTT => BRN | |
OPCM_32_BRR_EQ_NEQ | OPCM_32_BRR_GE | OPCM_32_BRR_JLT | OPCM_32_BRR_LOOP => BRR | |
OPCM_32_RC_ACCUMULATOR |OPCM_32_RC_LOGICAL_SHIFT | OPCM_32_RC_MUL => RC | |
OPCM_32_RCPW_MASK_INSERT => RCPW | |
OPCM_32_RCR_MADD => RCR | |
OPC1_32_RLC_ADDIH | OPC1_32_RLC_MFCR | OPC1_32_RLC_MOV | OPC1_32_RLC_MOV_H | OPC1_32_RLC_MOV_U | OPC1_32_RLC_MOVH_A | OPC1_32_RLC_MTCR => RLC | |
OPCM_32_RR2_MUL => RR2 | |
OPCM_32_RR_ACCUMULATOR | OPCM_32_RR_ADDRESS | OPCM_32_RR_DIVIDE | OPCM_32_RR_IDIRECT | OPCM_32_RR_LOGICAL_SHIFT => RR | |
OPCM_32_RRPW_EXTRACT_INSERT => RRPW | |
OPCM_32_SYS_INTERRUPTS => SYS | |
_ => { panic!("Unknown format"); } | |
} | |
} | |
fn extract_const16(hex: u32, format: Format) -> Option<u16> { | |
match format { | |
RLC => { Some(masks::mask_op_rlc_const16(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_const16_sext(hex: u32, format: Format) -> Option<i16> { | |
match format { | |
RLC => { Some(masks::mask_op_rlc_const16_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_const4(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
RCPW => { masks::mask_op_rcpw_const4(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_const4_sext(hex: u32, format: Format) -> Option<i8> { | |
match format { | |
SBC => { Some(masks::mask_op_sbc_const4_sext(hex)) } | |
SRC => { Some(masks::mask_op_src_const4_sext(hex)) } | |
BRC => { Some(masks::mask_op_brc_const4_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_const8(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SC => { Some(masks::mask_op_sc_const8(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_const9_sext(hex: u32, format: Format) -> Option<u16> { | |
match format { | |
RC => { Some(masks::mask_op_rc_const9_sext(hex)) } | |
RCR => { Some(masks::mask_op_rcr_const9_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_d(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SLR => { Some(masks::mask_op_slr_d(hex)) } | |
SLRO => { Some(masks::mask_op_slro_d(hex)) } | |
RC => { Some(masks::mask_op_rc_d(hex)) } | |
RCPW => { Some(masks::mask_op_rcpw_d(hex)) } | |
RCR => { Some(masks::mask_op_rcr_d(hex)) } | |
RLC => { Some(masks::mask_op_rlc_d(hex)) } | |
RR => { Some(masks::mask_op_rr_d(hex)) } | |
RR2 => { Some(masks::mask_op_rr2_d(hex)) } | |
RRPW => { Some(masks::mask_op_rrpw_d(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_disp15_sext(hex: u32, format: Format) -> Option<i16> { | |
match format { | |
BRC => { Some(masks::mask_op_brc_disp15_sext(hex)) } | |
BRN => { Some(masks::mask_op_brn_disp15_sext(hex)) } | |
BRR => { Some(masks::mask_op_brr_disp15_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_disp24_sext(hex: u32, format: Format) -> Option<i32> { | |
match format { | |
B => { Some(masks::mask_op_b_disp24_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_disp4(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SBC => { Some(masks::mask_op_sbc_disp4(hex)) } | |
SBR => { Some(masks::mask_op_sbr_disp4(hex)) } | |
SBRN => { Some(masks::mask_op_sbrn_disp4(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_disp8_sext(hex: u32, format: Format) -> Option<i8> { | |
match format { | |
SB => { Some(masks::mask_op_sb_disp8_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_n(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SBRN => { Some(masks::mask_op_sbrn_n(hex)) } | |
SRRS => { Some(masks::mask_op_srrs_n(hex)) } | |
BRN => { Some(masks::mask_op_brn_n(hex)) } | |
RR => { Some(masks::mask_op_rr_n(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_off10_sext(hex: u32, format: Format) -> Option<i16> { | |
match format { | |
BO => { Some(masks::mask_op_bo_off10_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_off16_sext(hex: u32, format: Format) -> Option<u16> { | |
match format { | |
BOL => { Some(masks::mask_op_bol_off16_sext(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_off18(hex: u32, format: Format) -> Option<u32> { | |
match format { | |
ABS => { Some(masks::mask_op_abs_off18(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_off4(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SLRO => { Some(masks::mask_op_slro_off4(hex)) } | |
SRO => { Some(masks::mask_op_sro_off4(hex)) } | |
SSRO => { Some(masks::mask_op_ssro_off4(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_pos(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
RCPW => { Some(masks::mask_op_rcpw_pos(hex)) } | |
RRPW => { Some(masks::mask_op_rrpw_pos(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_s1(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SSR => { Some(masks::mask_op_ssr_s1(hex)) } | |
SSRO => { Some(masks::mask_op_ssro_s1(hex)) } | |
BRC => { Some(masks::mask_op_brc_s1(hex)) } | |
BRN => { Some(masks::mask_op_brn_s1(hex)) } | |
BRR => { Some(masks::mask_op_brr_s1(hex)) } | |
RC => { Some(masks::mask_op_rc_s1(hex)) } | |
RCPW => { Some(masks::mask_op_rcpw_s1(hex)) } | |
RCR => { Some(masks::mask_op_rcr_s1(hex)) } | |
RLC => { Some(masks::mask_op_rlc_s1(hex)) } | |
RR => { Some(masks::mask_op_rr_s1(hex)) } | |
RR2 => { Some(masks::mask_op_rr2_s1(hex)) } | |
RRPW => { Some(masks::mask_op_rrpw_s1(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_s1d(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SR => { Some(masks::mask_op_sr_s1d(hex)) } | |
SRC => { Some(masks::mask_op_src_s1d(hex)) } | |
SRR => { Some(masks::mask_op_srr_s1d(hex)) } | |
SRRS => { Some(masks::mask_op_srrs_s1d(hex)) } | |
ABS => { Some(masks::mask_op_abs_s1d(hex)) } | |
BO => { Some(masks::mask_op_bo_s1d(hex)) } | |
BOL => { Some(masks::mask_op_bol_s1d(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_s2(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
SBR => { Some(masks::mask_op_sbr_s2(hex)) } | |
SLR => { Some(masks::mask_op_slr_s2(hex)) } | |
SRO => { Some(masks::mask_op_sro_s2(hex)) } | |
SRR => { Some(masks::mask_op_srr_s2(hex)) } | |
SRRS => { Some(masks::mask_op_srrs_s2(hex)) } | |
SSR => { Some(masks::mask_op_ssr_s2(hex)) } | |
BO => { Some(masks::mask_op_bo_s2(hex)) } | |
BOL => { Some(masks::mask_op_bol_s2(hex)) } | |
BRR => { Some(masks::mask_op_brr_s2(hex)) } | |
RR => { Some(masks::mask_op_rr_s2(hex)) } | |
RR2 => { Some(masks::mask_op_rr2_s2(hex)) } | |
RRPW => { Some(masks::mask_op_rrpw_s2(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_s3(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
RCR => { Some(masks::mask_op_rcr_s3(hex)) } | |
_ => { None } | |
} | |
} | |
fn extract_width(hex: u32, format: Format) -> Option<u8> { | |
match format { | |
RCPW => { Some(masks::mask_op_rcpw_width(hex)) } | |
RRPW => { Some(masks::mask_op_rrpw_width(hex)) } | |
_ => { None } | |
} | |
} | |
fn from_hex_16(hex: u16) -> OpCode { | |
let op1 = masks::mask_bits_shift(hex, 0, 7) as u8; | |
let op2 = determine_op2_16(hex, op1); | |
let format = determine_format_16(op1); | |
OpCode { | |
size: 2, | |
hex, | |
op1, | |
op2, | |
format, | |
const16: extract_const16(hex, format), | |
const16_sext: extract_const16_sext(hex, format), | |
const4: extract_const4(hex, format), | |
const4_sext: extract_const4_sext(hex, format), | |
const8: extract_const8(hex, format), | |
const9_sext: extract_const9_sext(hex, format), | |
d: extract_d(hex, format), | |
disp15_sext: extract_disp15_sext(hex, format), | |
disp24_sext: extract_disp24_sext(hex, format), | |
disp4: extract_disp4(hex, format), | |
disp8_sext: extract_disp8_sext(hex, format), | |
n: extract_n(hex, format), | |
off10_sext: extract_off10_sext(hex, format), | |
off16_sext: extract_off16_sext(hex, format), | |
off18: extract_off18(hex, format), | |
off4: extract_off4(hex, format), | |
pos: extract_pos(hex, format), | |
s1: extract_s1(hex, format), | |
s1d: extract_s1d(hex, format), | |
s2: extract_s2(hex, format), | |
s3: extract_s3(hex, format), | |
width: extract_width(hex, format) | |
} | |
} | |
fn from_hex_32(hex: u16) -> OpCode { | |
let op1 = masks::mask_bits_shift(hex, 0, 7) as u8; | |
let op2 = determine_op2_32(hex, op1); | |
let format = determine_format_32(op1); | |
OpCode { | |
size: 4, | |
hex, | |
op1, | |
op2, | |
format, | |
const16: extract_const16(hex, format), | |
const16_sext: extract_const16_sext(hex, format), | |
const4: extract_const4(hex, format), | |
const4_sext: extract_const4_sext(hex, format), | |
const8: extract_const8(hex, format), | |
const9_sext: extract_const9_sext(hex, format), | |
d: extract_d(hex, format), | |
disp15_sext: extract_disp15_sext(hex, format), | |
disp24_sext: extract_disp24_sext(hex, format), | |
disp4: extract_disp4(hex, format), | |
disp8_sext: extract_disp8_sext(hex, format), | |
n: extract_n(hex, format), | |
off10_sext: extract_off10_sext(hex, format), | |
off16_sext: extract_off16_sext(hex, format), | |
off18: extract_off18(hex, format), | |
off4: extract_off4(hex, format), | |
pos: extract_pos(hex, format), | |
s1: extract_s1(hex, format), | |
s1d: extract_s1d(hex, format), | |
s2: extract_s2(hex, format), | |
s3: extract_s3(hex, format), | |
width: extract_width(hex, format) | |
} | |
} | |
pub fn from_hex(hex: u32) -> { | |
let is_16bit = (hex & 0x01) == 0x00; | |
if (is_16bit) { | |
return from_hex_16(hex as u16); | |
} else { | |
return from_hex_32(hex); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment