Skip to content

Instantly share code, notes, and snippets.

@brandonros
Last active June 22, 2020 05:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brandonros/3e94758f6c7f0c596d34a7d38ec20df9 to your computer and use it in GitHub Desktop.
Save brandonros/3e94758f6c7f0c596d34a7d38ec20df9 to your computer and use it in GitHub Desktop.
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