Files
2021-10-31 21:20:46 +02:00

1797 lines
57 KiB
C++

#include "st9.hpp"
enum st9_addressing_modes ENUM_SIZE(uint16)
{
A_IMPL, // implied
A_wrd_wrs, // rd,rs
A_wrd_wrsi, // rd,(rs)
A_wrdi_wrs, // (rd),rs
A_wrdi_grs, // (rd),Rs
A_grd_wrsi, // Rd,(rs)
A_grd_grs, // Rd,Rs
A_grs_grd, // Rs,Rd
A_grd_8q, // Rd,#N
A_grpd_grps, // RRd,RRs
A_grpd_16q_0, // RRd,#NN with first byte mask xxxxxxx0
A_grpd_16q_1, // RRd,#NN with first byte mask xxxxxxx1
A_grp_8q, // RR,#N
A_grs, // Rs
A_grsi, // (Rs)
A_grd, // Rd
A_grdi, // (Rd)
A_grp_0, // RR with first byte mask xxxxxxx0
A_grp_1, // RR with first byte mask xxxxxxx1
A_grpi, // (RR)
A_8q, // N
A_16q, // NN
A_grps, // RRs
A_grpd_0, // RRd with first byte mask xxxxxxx0
A_grpd_1, // RRd with first byte mask xxxxxxx1
A_grpdi, // (RRd)
A_wrpd_wrps, // rrd,rrs
A_wrpdi_wrps, // (rrd),rrs
A_wrpd_wrpsi, // rrd,(rrs)
A_wrpdi_wrpsi, // (rrd),(rrs)
A_wrpdip_wrpsip_00, // (rrd)+,(rrs)+ with first byte mask xxx0xxx0
A_wrpdip_wrpsip_10, // (rrd)+,(rrs)+ with first byte mask xxx1xxx0
A_wrpdip_wrpsip_01, // (rrd)+,(rrs)+ with first byte mask xxx0xxx1
A_wrpdip_wrpsip_11, // (rrd)+,(rrs)+ with first byte mask xxx1xxx1
A_wrpd_wrs, // rrd,rs
A_8qxwrp_16q, // Nd(rr),#NNs
A_16qxwrp_16q, // NNd(rr),#NNs
A_8qxwrp_gr, // N(rr),R
A_16qxwrp_gr, // NN(rr),R
A_16q_8q, // NNd,#Ns
A_16q_16q, // NNd,#NNs
A_wr_wrpxwrp, // rd,rrs(rrx)
A_wrpxwrp_wr, // rrd(rrx),rs
A_wrp_wrpxwrp, // rrd,rrs(rrx)
A_wrpxwrp_wrp, // rrd(rrx),rrs
A_gr_wrpi, // Rd,(rrs)
A_wrip_gr, // (rrd),Rs
A_grpi_wrip, // (RRd),(rrs)
A_gri_wrip_01, // (R),(rr) with first byte mask 0100xxxx
A_gri_wrip_11, // (R),(rr) with first byte mask 1100xxxx
A_gr_8qxwrp, // Rd,N(rrx)
A_gr_16qxwrp, // Rd,NN(rrx)
A_grp_wrpi, // RRd,(rrs)
A_8qxwrp_grp, // N(rrx),RRs
A_grp_8qxwrp, // RRs,N(rrx)
A_16qxwrp_grp, // NN(rrx),RRs
A_grp_16qxwrp, // RRs,NN(rrx)
A_8qxgrpi, // N(RRx)
A_16qxgrpi, // NN(RRx)
A_wrd_wrpsi_8q_0, // rd,(rrs),N with first byte mask xxx0xxxx
A_wrd_wrpsi_8q_1, // rd,(rrs),N with first byte mask xxx1xxxx
A_grpd_wrsi, // RRd,(rs)
A_8qxwr_wrs, // N(rx),rs
A_wrs_8qxwr, // rs,N(rx)
A_grd_wrpip, // Rd,(rrs)+
A_wrpip_grd, // (rrs)+,Rd
A_wrd_wrpi, // rd,(rrs)
A_wrpi_wrd, // (rrs),rd
A_wrpi_grp, // (rr),RR
A_wrpi_16q, // (rr),#NN
A_grd_wrpim, // Rd,-(rrs)
A_wrpim_grd, // -(rrs),Rd
A_grpd_wrpim, // RRd,-(rrs)
A_wrpim_grpd, // -(rrs),RRd
A_16q_wrs, // NN,rs
A_wrd_16q, // rd,NN
A_grpd_wrpip, // RRd,(rrs)+
A_wrpip_grpd, // (rrd)+,RRs
A_wrip_wrpip, // (rd)+,(rrs)+
A_wrpip_wrip, // (rrs)+,(rd)+
A_8qxwrip_wrp, // N(rx),rrs
A_wrp_8qxwrip, // rrd,N(rx)
A_wrp_16q, // rrd,NN
A_16q_wrp, // NN,rrs
A_wrp_wrp_grp, // rrh,rrl,RRs
A_wrdi_grp, // (rd),RRs
A_wrpi_8q, // (rrd),#N
A_wrb_wrb_10, // rd.b,rs.b with first word mask xxx1xxxx xxx0xxxx
A_wrb_wrb_11, // rd.b,rs.b with first word mask xxx1xxxx xxx1xxxx
A_wrb_nwrb_10, // rd.b,!rs.b with first word mask xxx1xxxx xxx0xxxx
A_wrb_nwrb_11, // rd.b,!rs.b with first word mask xxx1xxxx xxx1xxxx
A_wrb, // rd.b
A_wrbi, // (rr).bd
A_bwr_8q_0, // b.rd,N with first byte mask xxx0xxxx
A_bwr_8q_1, // b.rd,N with first byte mask xxx1xxxx
A_seg_16q_01, // nnnnnn,NN with first byte mask 01xxxxxx
A_seg_16q_11, // nnnnnn,NN with first byte mask 11xxxxxx
A_rwn_000, // wwwww with first byte mask xxxxx000
A_rwn_100, // wwwww with first byte mask xxxxx100
A_rwn_101, // wwwww with first byte mask xxxxx101
A_rpn, // pppppp
};
struct opcode
{
uint16 code; // opcode
uint16 insn; // insn mnemonic
uint16 addr; // addressing mode
};
static const opcode opcodes[] =
{
{ 0x00, st9_ei, A_IMPL },
{ 0x01, st9_scf, A_IMPL },
{ 0x02, st9_or, A_wrd_wrs },
{ 0x03, st9_or, A_wrd_wrsi },
{ 0x04, st9_or, A_grd_grs },
{ 0x05, st9_or, A_grd_8q },
{ 0x06, st9_aldw, A_8qxwrp_16q },
{ 0x06, st9_aldw, A_16qxwrp_16q },
{ 0x07, st9_orw, A_grpd_grps },
{ 0x07, st9_orw, A_grpd_16q_1 },
{ 0x08, st9_ld, A_grs },
{ 0x09, st9_ld, A_grd },
{ 0x0A, st9_djnz, A_8q },
{ 0x0B, st9_jrcc, A_8q },
{ 0x0C, st9_ld, A_8q },
{ 0x0D, st9_jpcc, A_16q },
{ 0x0E, st9_orw, A_wrpd_wrps },
{ 0x0E, st9_orw, A_wrpdi_wrps },
{ 0x0E, st9_orw, A_wrpd_wrpsi },
{ 0x0E, st9_orw, A_wrpdi_wrpsi },
{ 0x0F, st9_bor, A_wrb_wrb_10 },
{ 0x0F, st9_bor, A_wrb_nwrb_11 },
{ 0x0F, st9_bset, A_wrb },
{ 0x10, st9_di, A_IMPL },
{ 0x11, st9_rcf, A_IMPL },
{ 0x12, st9_and, A_wrd_wrs },
{ 0x13, st9_and, A_wrd_wrsi },
{ 0x14, st9_and, A_grd_grs },
{ 0x15, st9_and, A_grd_8q },
{ 0x16, st9_xch, A_grs_grd },
{ 0x17, st9_andw, A_grpd_grps },
{ 0x17, st9_andw, A_grpd_16q_1 },
{ 0x18, st9_ld, A_grs },
{ 0x19, st9_ld, A_grd },
{ 0x1A, st9_djnz, A_8q },
{ 0x1B, st9_jrcc, A_8q },
{ 0x1C, st9_ld, A_8q },
{ 0x1D, st9_jpcc, A_16q },
{ 0x1E, st9_andw, A_wrpd_wrps },
{ 0x1E, st9_andw, A_wrpdi_wrps },
{ 0x1E, st9_andw, A_wrpd_wrpsi },
{ 0x1E, st9_andw, A_wrpdi_wrpsi },
{ 0x1F, st9_band, A_wrb_wrb_11 },
{ 0x1F, st9_band, A_wrb_nwrb_10 },
{ 0x1F, st9_bres, A_wrb },
{ 0x20, st9_popu, A_grd },
{ 0x21, st9_popu, A_grdi },
{ 0x22, st9_sbc, A_wrd_wrs },
{ 0x23, st9_sbc, A_wrd_wrsi },
{ 0x24, st9_sbc, A_grd_grs },
{ 0x25, st9_sbc, A_grd_8q },
{ 0x26, st9_ald, A_8qxwrp_gr },
{ 0x26, st9_ald, A_16qxwrp_gr },
{ 0x27, st9_sbcw, A_grpd_grps },
{ 0x27, st9_sbcw, A_grpd_16q_1 },
{ 0x28, st9_ld, A_grs },
{ 0x29, st9_ld, A_grd },
{ 0x2A, st9_djnz, A_8q },
{ 0x2B, st9_jrcc, A_8q },
{ 0x2C, st9_ld, A_8q },
{ 0x2D, st9_jpcc, A_16q },
{ 0x2E, st9_sbcw, A_wrpd_wrps },
{ 0x2E, st9_sbcw, A_wrpdi_wrps },
{ 0x2E, st9_sbcw, A_wrpd_wrpsi },
{ 0x2E, st9_sbcw, A_wrpdi_wrpsi },
{ 0x2F, st9_sraw, A_grp_0 },
{ 0x2F, st9_ald, A_16q_8q },
{ 0x30, st9_pushu, A_grd },
{ 0x31, st9_pushu, A_grdi },
{ 0x32, st9_adc, A_wrd_wrs },
{ 0x33, st9_adc, A_wrd_wrsi },
{ 0x34, st9_adc, A_grd_grs },
{ 0x35, st9_adc, A_grd_8q },
{ 0x36, st9_rrcw, A_grp_0 },
{ 0x36, st9_aldw, A_16q_16q },
{ 0x37, st9_adcw, A_grpd_grps },
{ 0x37, st9_adcw, A_grpd_16q_1 },
{ 0x38, st9_ld, A_grs },
{ 0x39, st9_ld, A_grd },
{ 0x3A, st9_djnz, A_8q },
{ 0x3B, st9_jrcc, A_8q },
{ 0x3C, st9_ld, A_8q },
{ 0x3D, st9_jpcc, A_16q },
{ 0x3E, st9_adcw, A_wrpd_wrps },
{ 0x3E, st9_adcw, A_wrpdi_wrps },
{ 0x3E, st9_adcw, A_wrpd_wrpsi },
{ 0x3E, st9_adcw, A_wrpdi_wrpsi },
{ 0x3F, st9_calls, A_seg_16q_01 },
{ 0x3F, st9_jps, A_seg_16q_11 },
{ 0x40, st9_dec, A_grd },
{ 0x41, st9_dec, A_grdi },
{ 0x42, st9_add, A_wrd_wrs },
{ 0x43, st9_add, A_wrd_wrsi },
{ 0x44, st9_add, A_grd_grs },
{ 0x45, st9_add, A_grd_8q },
{ 0x46, st9_ret, A_IMPL },
{ 0x47, st9_addw, A_grpd_grps },
{ 0x47, st9_addw, A_grpd_16q_1 },
{ 0x48, st9_ld, A_grs },
{ 0x49, st9_ld, A_grd },
{ 0x4A, st9_djnz, A_8q },
{ 0x4B, st9_jrcc, A_8q },
{ 0x4C, st9_ld, A_8q },
{ 0x4D, st9_jpcc, A_16q },
{ 0x4E, st9_addw, A_wrpd_wrps },
{ 0x4E, st9_addw, A_wrpdi_wrps },
{ 0x4E, st9_addw, A_wrpd_wrpsi },
{ 0x4E, st9_addw, A_wrpdi_wrpsi },
{ 0x4F, st9_mul, A_wrpd_wrs },
{ 0x50, st9_inc, A_grd },
{ 0x51, st9_inc, A_grdi },
{ 0x52, st9_sub, A_wrd_wrs },
{ 0x53, st9_sub, A_wrd_wrsi },
{ 0x54, st9_sub, A_grd_grs },
{ 0x55, st9_sub, A_grd_8q },
{ 0x56, st9_divws, A_wrp_wrp_grp },
{ 0x57, st9_subw, A_grpd_grps },
{ 0x57, st9_subw, A_grpd_16q_1 },
{ 0x58, st9_ld, A_grs },
{ 0x59, st9_ld, A_grd },
{ 0x5A, st9_djnz, A_8q },
{ 0x5B, st9_jrcc, A_8q },
{ 0x5C, st9_ld, A_8q },
{ 0x5D, st9_jpcc, A_16q },
{ 0x5E, st9_subw, A_wrpd_wrps },
{ 0x5E, st9_subw, A_wrpdi_wrps },
{ 0x5E, st9_subw, A_wrpd_wrpsi },
{ 0x5E, st9_subw, A_wrpdi_wrpsi },
{ 0x5F, st9_div, A_wrpd_wrs },
{ 0x60, st9_ald, A_wr_wrpxwrp },
{ 0x60, st9_ald, A_wrpxwrp_wr },
{ 0x60, st9_aldw, A_wrp_wrpxwrp },
{ 0x60, st9_aldw, A_wrpxwrp_wrp },
{ 0x61, st9_ccf, A_IMPL },
{ 0x62, st9_xor, A_wrd_wrs },
{ 0x63, st9_xor, A_wrd_wrsi },
{ 0x64, st9_xor, A_grd_grs },
{ 0x65, st9_xor, A_grd_8q },
{ 0x66, st9_push, A_grd },
{ 0x67, st9_xorw, A_grpd_grps },
{ 0x67, st9_xorw, A_grpd_16q_1 },
{ 0x68, st9_ld, A_grs },
{ 0x69, st9_ld, A_grd },
{ 0x6A, st9_djnz, A_8q },
{ 0x6B, st9_jrcc, A_8q },
{ 0x6C, st9_ld, A_8q },
{ 0x6D, st9_jpcc, A_16q },
{ 0x6E, st9_xorw, A_wrpd_wrps },
{ 0x6E, st9_xorw, A_wrpdi_wrps },
{ 0x6E, st9_xorw, A_wrpd_wrpsi },
{ 0x6E, st9_xorw, A_wrpdi_wrpsi },
{ 0x6F, st9_bxor, A_wrb_wrb_10 },
{ 0x6F, st9_bxor, A_wrb_nwrb_11 },
{ 0x6F, st9_bcpl, A_wrb },
{ 0x70, st9_da, A_grd },
{ 0x71, st9_da, A_grdi },
{ 0x72, st9_ald, A_gr_wrpi },
{ 0x72, st9_ald, A_wrip_gr },
{ 0x73, st9_calls, A_gri_wrip_01 },
{ 0x73, st9_jps, A_gri_wrip_11 },
{ 0x73, st9_ald, A_grpi_wrip },
{ 0x74, st9_call, A_grpdi },
{ 0x74, st9_pushw, A_grps },
{ 0x75, st9_popw, A_grpd_0 },
{ 0x75, st9_unlink, A_grpd_1 },
{ 0x76, st9_pop, A_grd },
{ 0x77, st9_pop, A_grdi },
{ 0x78, st9_ld, A_grs },
{ 0x79, st9_ld, A_grd },
{ 0x7A, st9_djnz, A_8q },
{ 0x7B, st9_jrcc, A_8q },
{ 0x7C, st9_ld, A_8q },
{ 0x7D, st9_jpcc, A_16q },
{ 0x7E, st9_aldw, A_grp_wrpi },
{ 0x7F, st9_ald, A_gr_8qxwrp },
{ 0x7F, st9_ald, A_gr_16qxwrp },
{ 0x80, st9_cpl, A_grd },
{ 0x81, st9_cpl, A_grdi },
{ 0x82, st9_cp, A_wrd_wrs },
{ 0x83, st9_cp, A_wrd_wrsi },
{ 0x84, st9_cp, A_grd_grs },
{ 0x85, st9_cp, A_grd_8q },
{ 0x86, st9_aldw, A_8qxwrp_grp },
{ 0x86, st9_aldw, A_grp_8qxwrp },
{ 0x86, st9_aldw, A_16qxwrp_grp },
{ 0x86, st9_aldw, A_grp_16qxwrp },
{ 0x87, st9_cpw, A_grpd_grps },
{ 0x87, st9_cpw, A_grpd_16q_1 },
{ 0x88, st9_ld, A_grs },
{ 0x89, st9_ld, A_grd },
{ 0x8A, st9_djnz, A_8q },
{ 0x8B, st9_jrcc, A_8q },
{ 0x8C, st9_ld, A_8q },
{ 0x8D, st9_jpcc, A_16q },
{ 0x8E, st9_cpw, A_wrpd_wrps },
{ 0x8E, st9_cpw, A_wrpdi_wrps },
{ 0x8E, st9_cpw, A_wrpd_wrpsi },
{ 0x8E, st9_cpw, A_wrpdi_wrpsi },
{ 0x8FF1, st9_push, A_8q },
{ 0x8FF3, st9_pushu, A_8q },
{ 0x8FC1, st9_pushw, A_16q },
{ 0x8FC3, st9_pushuw, A_16q },
{ 0x8F01, st9_pea, A_8qxgrpi },
{ 0x8F01, st9_pea, A_16qxgrpi },
{ 0x8F03, st9_peau, A_8qxgrpi },
{ 0x8F03, st9_peau, A_16qxgrpi },
{ 0x8F, st9_rlcw, A_grpd_0 },
{ 0x90, st9_clr, A_grd },
{ 0x91, st9_clr, A_grdi },
{ 0x92, st9_cp, A_wrd_wrs },
{ 0x93, st9_cp, A_wrd_wrsi },
{ 0x94, st9_cp, A_grd_grs },
{ 0x95, st9_cp, A_grd_8q },
{ 0x96, st9_aldw, A_wrdi_grp },
{ 0x97, st9_cpw, A_grpd_grps },
{ 0x97, st9_cpw, A_grpd_16q_1 },
{ 0x98, st9_ld, A_grs },
{ 0x99, st9_ld, A_grd },
{ 0x9A, st9_djnz, A_8q },
{ 0x9B, st9_jrcc, A_8q },
{ 0x9C, st9_ld, A_8q },
{ 0x9D, st9_jpcc, A_16q },
{ 0x9E, st9_cpw, A_wrpd_wrps },
{ 0x9E, st9_cpw, A_wrpdi_wrps },
{ 0x9E, st9_cpw, A_wrpd_wrpsi },
{ 0x9E, st9_cpw, A_wrpdi_wrpsi },
{ 0x9F, st9_cpjfi, A_wrd_wrpsi_8q_0 },
{ 0x9F, st9_cpjti, A_wrd_wrpsi_8q_1 },
{ 0xA0, st9_rol, A_grd },
{ 0xA1, st9_rol, A_grdi },
{ 0xA2, st9_tm, A_wrd_wrs },
{ 0xA3, st9_tm, A_wrd_wrsi },
{ 0xA4, st9_tm, A_grd_grs },
{ 0xA5, st9_tm, A_grd_8q },
{ 0xA6, st9_aldw, A_grpd_wrsi },
{ 0xA7, st9_tmw, A_grpd_grps },
{ 0xA7, st9_tmw, A_grpd_16q_1 },
{ 0xA8, st9_ld, A_grs },
{ 0xA9, st9_ld, A_grd },
{ 0xAA, st9_djnz, A_8q },
{ 0xAB, st9_jrcc, A_8q },
{ 0xAC, st9_ld, A_8q },
{ 0xAD, st9_jpcc, A_16q },
{ 0xAE, st9_tmw, A_wrpd_wrps },
{ 0xAE, st9_tmw, A_wrpdi_wrps },
{ 0xAE, st9_tmw, A_wrpd_wrpsi },
{ 0xAE, st9_tmw, A_wrpdi_wrpsi },
{ 0xAF, st9_btjt, A_bwr_8q_0 },
{ 0xAF, st9_btjf, A_bwr_8q_1 },
{ 0xB0, st9_rlc, A_grd },
{ 0xB1, st9_rlc, A_grdi },
{ 0xB2, st9_ld, A_8qxwr_wrs },
{ 0xB3, st9_ld, A_wrs_8qxwr },
{ 0xB4, st9_ald, A_grd_wrpip },
{ 0xB4, st9_ald, A_wrpip_grd },
{ 0xB5, st9_ld, A_wrd_wrpi },
{ 0xB5, st9_ld, A_wrpi_wrd },
{ 0xB6, st9_pushuw, A_grp_0 },
{ 0xB6, st9_linku, A_grp_8q },
{ 0xB7, st9_popuw, A_grp_0 },
{ 0xB7, st9_unlinku, A_grp_1 },
{ 0xB8, st9_ld, A_grs },
{ 0xB9, st9_ld, A_grd },
{ 0xBA, st9_djnz, A_8q },
{ 0xBB, st9_jrcc, A_8q },
{ 0xBC, st9_ld, A_8q },
{ 0xBD, st9_jpcc, A_16q },
{ 0xBE, st9_aldw, A_wrpi_grp },
{ 0xBE, st9_aldw, A_wrpi_16q },
{ 0xBF01, st9_halt, A_IMPL },
{ 0xBF, st9_ldw, A_grpd_16q_0 },
{ 0xC0, st9_ror, A_grd },
{ 0xC1, st9_ror, A_grdi },
{ 0xC2, st9_ald, A_grd_wrpim },
{ 0xC2, st9_ald, A_wrpim_grd },
{ 0xC3, st9_aldw, A_grpd_wrpim },
{ 0xC3, st9_aldw, A_wrpim_grpd },
{ 0xC4, st9_ald, A_wrd_16q },
{ 0xC5, st9_ald, A_16q_wrs },
{ 0xC6, st9_ext, A_grp_1 },
{ 0xC6, st9_dwjnz, A_grp_8q },
{ 0xC7, st9_srp, A_rwn_000 },
{ 0xC7, st9_srp0, A_rwn_100 },
{ 0xC7, st9_srp1, A_rwn_101 },
{ 0xC7, st9_spp, A_rpn },
{ 0xC8, st9_ld, A_grs },
{ 0xC9, st9_ld, A_grd },
{ 0xCA, st9_djnz, A_8q },
{ 0xCB, st9_jrcc, A_8q },
{ 0xCC, st9_ld, A_8q },
{ 0xCD, st9_jpcc, A_16q },
{ 0xCE, st9_etrap, A_IMPL },
{ 0xCF, st9_decw, A_grpd_0 },
{ 0xD0, st9_rrc, A_grd },
{ 0xD1, st9_rrc, A_grdi },
{ 0xD2, st9_call, A_16q },
{ 0xD3, st9_iret, A_IMPL },
{ 0xD4, st9_jp, A_grpi },
{ 0xD4, st9_link, A_grp_8q },
{ 0xD5, st9_aldw, A_grpd_wrpip },
{ 0xD5, st9_aldw, A_wrpip_grpd },
{ 0xD6, st9_ldpp, A_wrpdip_wrpsip_00 },
{ 0xD6, st9_lddp, A_wrpdip_wrpsip_10 },
{ 0xD6, st9_ldpd, A_wrpdip_wrpsip_01 },
{ 0xD6, st9_lddd, A_wrpdip_wrpsip_11 },
{ 0xD7, st9_ld, A_wrip_wrpip },
{ 0xD7, st9_ld, A_wrpip_wrip },
{ 0xD8, st9_ld, A_grs },
{ 0xD9, st9_ld, A_grd },
{ 0xDA, st9_djnz, A_8q },
{ 0xDB, st9_jrcc, A_8q },
{ 0xDC, st9_ld, A_8q },
{ 0xDD, st9_jpcc, A_16q },
{ 0xDE, st9_ldw, A_8qxwrip_wrp },
{ 0xDE, st9_ldw, A_wrp_8qxwrip },
{ 0xDF, st9_incw, A_grpd_0 },
{ 0xE0, st9_sra, A_grd },
{ 0xE1, st9_sra, A_grdi },
{ 0xE2, st9_aldw, A_wrp_16q },
{ 0xE2, st9_aldw, A_16q_wrp },
{ 0xE3, st9_ldw, A_wrpd_wrps },
{ 0xE3, st9_ldw, A_wrpdi_wrps },
{ 0xE3, st9_ldw, A_wrpd_wrpsi },
{ 0xE3, st9_ldw, A_wrpdi_wrpsi },
{ 0xE4, st9_ld, A_wrd_wrsi },
{ 0xE5, st9_ld, A_wrdi_wrs },
{ 0xE6, st9_ald, A_wrdi_grs },
{ 0xE7, st9_ald, A_grd_wrsi },
{ 0xE8, st9_ld, A_grs },
{ 0xE9, st9_ld, A_grd },
{ 0xEA, st9_djnz, A_8q },
{ 0xEB, st9_jrcc, A_8q },
{ 0xEC, st9_ld, A_8q },
{ 0xED, st9_jpcc, A_16q },
{ 0xEE, st9_spm, A_IMPL },
{ 0xEF01, st9_wfi, A_IMPL },
{ 0xEF31, st9_eret, A_IMPL },
{ 0xEF, st9_ldw, A_grpd_grps },
{ 0xF0, st9_swap, A_grd },
{ 0xF1, st9_swap, A_grdi },
{ 0xF2, st9_bld, A_wrb_wrb_10 },
{ 0xF2, st9_bld, A_wrb_nwrb_11 },
{ 0xF2, st9_btset, A_wrb },
{ 0xF3, st9_ald, A_wrpi_8q },
{ 0xF4, st9_ld, A_grd_grs },
{ 0xF5, st9_ld, A_grd_8q },
{ 0xF601, st9_rets, A_IMPL },
{ 0xF6, st9_btset, A_wrbi },
{ 0xF7, st9_push, A_grsi },
{ 0xF8, st9_ld, A_grs },
{ 0xF9, st9_ld, A_grd },
{ 0xFA, st9_djnz, A_8q },
{ 0xFB, st9_jrcc, A_8q },
{ 0xFC, st9_ld, A_8q },
{ 0xFD, st9_jpcc, A_16q },
{ 0xFE, st9_sdm, A_IMPL },
{ 0xFF, st9_nop, A_IMPL }
};
//----------------------------------------------------------------------
static const opcode *find_opcode(insn_t &insn, int _code)
{
for ( int i = 0; i < qnumber(opcodes); i++ )
{
// is the opcode coded in a word ?
bool need_another_byte = ((opcodes[i].code & 0xFF00) >> 8) != 0;
int code = need_another_byte
? (_code << 8) | get_byte(insn.ea + insn.size)
: _code;
// opcode is wrong
if ( opcodes[i].code != code )
continue;
int next_byte = get_byte(insn.ea + insn.size + (need_another_byte ? 1 : 0));
int mask = 0;
int value = 0;
switch ( opcodes[i].addr )
{
// 0000000X (X == 0)
case A_grpd_grps:
case A_16qxwrp_16q:
case A_16qxwrp_gr:
case A_wrip_gr:
case A_gr_16qxwrp:
case A_grpd_0:
case A_grps:
case A_wrpip_grd:
case A_wrd_wrpi:
case A_grp_0:
case A_wrpi_16q:
case A_grpd_16q_0:
case A_wrpim_grd:
case A_wrpim_grpd:
case A_grpi:
case A_wrpip_grpd:
case A_wrpip_wrip:
case A_wrp_16q:
mask = 0x01;
value = 0x00;
break;
case A_wrb:
mask = 0x10;
value = 0x00;
break;
// 0000000X (X == 1)
case A_grpd_16q_1:
case A_8qxwrp_16q:
case A_8qxwrp_gr:
case A_gr_wrpi:
case A_gr_8qxwrp:
case A_grpd_1:
case A_grpdi:
case A_grd_wrpip:
case A_wrpi_wrd:
case A_grp_1:
case A_wrpi_grp:
case A_grd_wrpim:
case A_grpd_wrpim:
case A_grpd_wrpip:
case A_wrip_wrpip:
case A_16q_wrp:
mask = 0x01;
value = 0x01;
break;
// 00000XXX (XXX = 000)
case A_rwn_000:
mask = 0x07;
value = 0x00;
break;
// 00000XXX (XXX = 100)
case A_rwn_100:
mask = 0x07;
value = 0x04;
break;
// 00000XXX (XXX = 101)
case A_rwn_101:
mask = 0x07;
value = 0x05;
break;
// XY000000 (XY == 01)
case A_seg_16q_01:
mask = 0xC0;
value = 0x40;
break;
// XY000000 (XY == 11)
case A_seg_16q_11:
mask = 0xC0;
value = 0xC0;
break;
// 000000XY (XY = 10)
case A_rpn:
mask = 0x03;
value = 0x02;
break;
// 000X0000 (X == 0)
case A_wrd_wrpsi_8q_0:
case A_wrp_8qxwrip:
case A_bwr_8q_0:
mask = 0x10;
value = 0x00;
break;
// 000X0000 (X == 1)
case A_wrd_wrpsi_8q_1:
case A_8qxwrip_wrp:
case A_bwr_8q_1:
mask = 0x10;
value = 0x10;
break;
// XXXX0000 (XXXX = 0100)
case A_gri_wrip_01:
mask = 0xF0;
value = 0x40;
break;
// XXXX0000 (XXXX = 1100)
case A_gri_wrip_11:
mask = 0xF0;
value = 0xC0;
break;
// 000X000Y (X == 0 && Y == 0)
case A_wrpd_wrps:
case A_wrpdip_wrpsip_00:
case A_wrp_wrpxwrp:
case A_wrbi:
mask = 0x11;
value = 0x00;
break;
// 000X000Y (X == 1 && Y == 0)
case A_wrpdi_wrps:
case A_wrpdip_wrpsip_10:
case A_wr_wrpxwrp:
mask = 0x11;
value = 0x10;
break;
// 000X000Y (X == 0 && Y == 1)
case A_wrpd_wrpsi:
case A_wrpdip_wrpsip_01:
case A_wrpxwrp_wrp:
mask = 0x11;
value = 0x01;
break;
// 000X000Y (X == 1 && Y == 1)
case A_wrpdi_wrpsi:
case A_wrpdip_wrpsip_11:
case A_wrpxwrp_wr:
mask = 0x11;
value = 0x11;
break;
// 0000X (X = 0001)
case A_16q_8q:
case A_16q_16q:
mask = 0x0F;
value = 0x01;
break;
// 0000000X (X == 1) && 3th byte MSB == 1
case A_8qxwrp_grp:
if ( (get_byte(insn.ea + insn.size + 2) & 0x01) == 1 )
{
mask = 0x01;
value = 0x01;
}
else
mask = -1;
break;
// 0000000X (X == 1) && 3th byte MSB == 0
case A_grp_8qxwrp:
if ( (get_byte(insn.ea + insn.size + 2) & 0x01) == 0 )
{
mask = 0x01;
value = 0x01;
}
else
mask = -1;
break;
// 0000000X (X == 1) && 4th byte MSB == 1
case A_16qxwrp_grp:
if ( (get_byte(insn.ea + insn.size + 3) & 0x01) == 1 )
{
mask = 0x01;
value = 0x00;
}
else
mask = -1;
break;
// 0000000X (X == 1) && 4th byte MSB == 0
case A_grp_16qxwrp:
if ( (get_byte(insn.ea + insn.size + 3) & 0x01) == 0 )
{
mask = 0x01;
value = 0x00;
}
else
mask = -1;
break;
// 2nd byte MSB == 0
case A_8qxgrpi:
if ( (get_byte(insn.ea + insn.size + 1) & 0x01) != 0 )
mask = -1;
break;
// 2nd byte MSB == 1
case A_16qxgrpi:
if ( (get_byte(insn.ea + insn.size + 1) & 0x01) != 1 )
mask = -1;
break;
// NOTE: it seems that there is an error in the manual :
// rd.b,rs.b and rd.b,rs.!b opcodes are inversed !
// 000X0000 (X == 1) + 0x000Y0000 (Y == 0)
case A_wrb_wrb_10:
case A_wrb_nwrb_10:
if ( (get_byte(insn.ea + insn.size + 1) & 0x10) == 0 )
{
mask = 0x10;
value = 0x10;
}
else
mask = -1;
break;
// 000X0000 (X == 1) + 0x000Y0000 (Y == 1)
case A_wrb_wrb_11:
case A_wrb_nwrb_11:
if ( (get_byte(insn.ea + insn.size + 1) & 0x10) == 0x10 )
{
mask = 0x10;
value = 0x10;
}
else
mask = -1;
break;
}
// addr mode is wrong
if ( mask != 0 && (mask == -1 || (next_byte & mask) != value) )
continue;
// Yahoo !
if ( need_another_byte )
insn.size++;
return &opcodes[i];
}
return NULL;
}
//----------------------------------------------------------------------
static int get_condition_code(int code)
{
switch ( code )
{
case 0x0B: // JR F,N
case 0x0D: // JP F,NN
return cF;
case 0x1B: // JR LT,N
case 0x1D: // JP LT,NN
return cLT;
case 0x2B: // JR LE,N
case 0x2D: // JP LE,NN
return cLE;
case 0x3B: // JR ULE,N
case 0x3D: // JP ULE,NN
return cULE;
case 0x4B: // JR OV,N
case 0x4D: // JP OV,NN
return cOV;
case 0x5B: // JR MI,N
case 0x5D: // JP MI,NN
return cMI;
case 0x6B: // JR EQ,N
case 0x6D: // JP EQ,NN
return cEQ;
// XXX
// According to the manual, 0x7X is related
// to the UL condition code.
// JRUL/JPUL cannot be assembled (unknown instruction).
// objdump9 disassemble 0x7X with the C condition code,
// therefore we use it instead of UL.
case 0x7B: // JR C,N
case 0x7D: // JP C,NN
return cC;
case 0x8B: // JR T,N
case 0x8D: // JP T,NN
return cT;
case 0x9B: // JR GE,N
case 0x9D: // JP GE,NN
return cGE;
case 0xAB: // JR GT,N
case 0xAD: // JP GT,NN
return cGT;
case 0xBB: // JR UGT,N
case 0xBD: // JP UGT,NN
return cUGT;
case 0xCB: // JR NOV,N
case 0xCD: // JP NOV,NN
return cNOV;
case 0xDB: // JR PL,N
case 0xDD: // JP PL,NN
return cPL;
case 0xEB: // JR NE,N
case 0xED: // JP NE,NN
return cNE;
case 0xFB: // JR NC,N
case 0xFD: // JP NC,NN
return cNC;
}
return cUNKNOWN;
}
//----------------------------------------------------------------------
static uint16 get_working_register(int code)
{
uchar reg_id = (code & 0xF0) >> 4;
return rr0 + reg_id;
}
//----------------------------------------------------------------------
// general register: if the 4 Most Significant Bits (MSB) are Dh then the 4 Least Significant
// Bits (LSB) specify a working register
static uint16 get_general_register(int code, bool pair = false)
{
uchar reg_grp = (code & 0xF0) >> 4;
// group D (R208-R223) refers to working registers
if ( reg_grp == 0xD )
return (pair ? rrr0 : rr0) + (code & 0x0F);
else
return (pair ? rRR0 : rR0) + code;
}
//----------------------------------------------------------------------
static uint16 get_alu_insn(const insn_t &insn, int code)
{
int insn_id = (code & 0xF0) >> 4;
QASSERT(10031, insn.itype == st9_ald || insn.itype == st9_aldw);
bool long_insn = insn.itype == st9_aldw;
if ( !long_insn )
{
switch ( insn_id )
{
case 0x0: return st9_or;
case 0x1: return st9_and;
case 0x2: return st9_sbc;
case 0x3: return st9_adc;
case 0x4: return st9_add;
case 0x5: return st9_sub;
case 0x6: return st9_xor;
case 0x8: return st9_cp;
case 0x9: return st9_cp;
case 0xA: return st9_tm;
case 0xF: return st9_ld;
}
}
else
{
switch ( insn_id )
{
case 0x0: return st9_orw;
case 0x1: return st9_andw;
case 0x2: return st9_sbcw;
case 0x3: return st9_adcw;
case 0x4: return st9_addw;
case 0x5: return st9_subw;
case 0x6: return st9_xorw;
case 0x8: return st9_cpw;
case 0x9: return st9_cpw;
case 0xA: return st9_tmw;
case 0xF: return st9_ldw;
}
}
return st9_null;
}
//----------------------------------------------------------------------
// fill instruction flag
static void set_flag(insn_t &insn, int flag)
{
insn.auxpref |= flag;
}
//----------------------------------------------------------------------
// fill operand flag
static void set_flag(op_t &x, int flag)
{
x.specflag1 |= flag;
}
//----------------------------------------------------------------------
// fill an operand as a register
static void set_reg(op_t &op, uint16 reg, int flag = 0)
{
op.type = o_reg;
op.reg = reg;
op.dtype = dt_byte;
if ( flag )
set_flag(op, flag);
}
//----------------------------------------------------------------------
// fill an operand as an immediate value
static void set_imm(op_t &op, int val, char d_typ, int flag = 0)
{
op.type = o_imm;
op.value = val;
op.dtype = d_typ;
if ( flag )
set_flag(op, flag);
}
//----------------------------------------------------------------------
// fill an operand as a displacement
static void set_displ(op_t &op, optype_t a1_t, uint16 a1, optype_t a2_t, uint16 a2, char dtyp = dt_byte)
{
op.type = o_displ;
op.reg = 0;
switch ( a1_t )
{
case o_reg:
op.reg = a1;
break;
case o_mem:
op.addr = a1;
break;
default:
INTERR(10032);
}
switch ( a2_t )
{
case o_reg:
if ( op.reg == 0 )
op.reg = a2;
else
INTERR(10033);
break;
default:
INTERR(10034);
}
op.dtype = dtyp;
}
//----------------------------------------------------------------------
// fill an operand as a phrase
static void set_phrase(op_t &op, st9_phrases phrase, uint16 reg1, int reg2 = -1, char dtyp = dt_byte)
{
op.type = o_phrase;
op.reg = reg1;
op.specflag2 = phrase;
op.dtype = dtyp;
if ( reg2 != -1 )
{
op.specflag2 = (reg2 & 0xFF00) >> 8;
op.specflag3 = (reg2 & 0x00FF);
}
}
//----------------------------------------------------------------------
// add a bit number to a register operand
static void set_bit(op_t &op, int bit, int flag = 0)
{
op.value = bit;
if ( flag )
set_flag(op, flag);
}
//----------------------------------------------------------------------
// fill an operand as an address (data or code)
static void set_addr(op_t &op, optype_t type, ea_t addr, char dtyp = dt_byte)
{
QASSERT(10035, type == o_mem || type == o_near || type == o_far); // bad optype_t in set_addr()
op.type = type;
op.addr = addr;
op.dtype = dtyp;
}
//----------------------------------------------------------------------
static uint16 my_next_word(insn_t &insn)
{
uchar b1 = insn.get_next_byte();
uchar b2 = insn.get_next_byte();
return b1 | (b2 << 8);
}
//----------------------------------------------------------------------
static void fill_cmd(insn_t &insn, int byte, const opcode *op)
{
QASSERT(10036, op != NULL);
insn.itype = op->insn;
switch ( op->addr )
{
// Implied
case A_IMPL:
// Nothing to do !
break;
// rd,rs
case A_wrd_wrs:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4));
set_reg(insn.Op2, rr0 + (byte & 0x0F));
break;
// rd,(rs)
case A_wrd_wrsi:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4));
set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND);
break;
// (rd),rs
case A_wrdi_wrs:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4), OP_IS_IND);
set_reg(insn.Op2, rr0 + (byte & 0x0F));
break;
// (rd),Rs
case A_wrdi_grs:
QASSERT(10037, insn.itype == st9_ald);
set_reg(insn.Op2, get_general_register(insn.get_next_byte()));
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_IS_IND);
break;
// Rd,(rs)
case A_grd_wrsi:
QASSERT(10038, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND);
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// Rs,Rd
case A_grs_grd:
// Rd,Rs
case A_grd_grs:
set_reg(insn.Op2, get_general_register(insn.get_next_byte()));
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// Rd,#N
case A_grd_8q:
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
set_imm(insn.Op2, insn.get_next_byte(), dt_byte);
break;
// RRd,RRs
case A_grpd_grps:
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true));
set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// RRd,#NN
case A_grpd_16q_0:
case A_grpd_16q_1:
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true));
set_imm(insn.Op2, insn.get_next_word(), dt_word);
break;
// RR,N
case A_grp_8q:
{
byte = insn.get_next_byte();
uint16 reg = get_general_register(byte & 0xFE, true);
if ( insn.itype == st9_dwjnz )
{
set_addr(insn.Op2, o_near, insn.get_next_byte());
insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size;
}
else
{ // link or linku
set_imm(insn.Op2, 0xFF - insn.get_next_byte(), dt_byte);
}
set_reg(insn.Op1, reg);
}
break;
// Rs
case A_grs:
if ( insn.itype == st9_ld )
{
set_reg(insn.Op1, get_working_register(byte));
set_reg(insn.Op2, get_general_register(insn.get_next_byte()));
}
else
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// Rd
case A_grd:
if ( insn.itype == st9_ld )
{
set_reg(insn.Op2, get_working_register(byte));
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
}
else
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// (R)
case A_grdi:
case A_grsi:
set_reg(insn.Op1, get_general_register(insn.get_next_byte()), OP_IS_IND);
break;
// RR
case A_grp_0:
case A_grp_1:
case A_grps:
case A_grpd_0:
case A_grpd_1:
{
byte = insn.get_next_byte();
uint16 reg = get_general_register((byte & 0xFE), true);
set_reg(insn.Op1, reg);
}
break;
// (RR)
case A_grpi:
case A_grpdi:
set_reg(insn.Op1, get_general_register((insn.get_next_byte() & 0xFE), true), OP_IS_IND);
break;
// N
case A_8q:
if ( is_jmp_cc(insn.itype) )
{
set_flag(insn, get_condition_code(byte));
set_addr(insn.Op1, o_near, insn.get_next_byte());
insn.Op1.addr = (signed char) insn.Op1.addr + insn.ip + insn.size;
}
else if ( insn.itype == st9_djnz )
{
set_reg(insn.Op1, get_working_register(byte));
set_addr(insn.Op2, o_near, insn.get_next_byte());
insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size;
}
else if ( insn.itype == st9_ld )
{
set_reg(insn.Op1, get_working_register(byte));
set_imm(insn.Op2, insn.get_next_byte(), dt_byte);
insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size;
}
else if ( insn.itype == st9_push
|| insn.itype == st9_pushu
|| insn.itype == st9_pushw )
{
set_imm(insn.Op1, insn.get_next_byte(), dt_byte);
}
else
{
set_addr(insn.Op1, o_mem, insn.get_next_byte());
insn.Op1.addr = (signed char) insn.Op1.addr + insn.ip + insn.size;
}
break;
// NN
case A_16q:
if ( is_jmp_cc(insn.itype) || insn.itype == st9_call )
{
if ( is_jmp_cc(insn.itype) )
set_flag(insn, get_condition_code(byte));
set_addr(insn.Op1, o_near, insn.get_next_word());
}
else if ( insn.itype == st9_push
|| insn.itype == st9_pushu
|| insn.itype == st9_pushw
|| insn.itype == st9_pushuw )
{
set_imm(insn.Op1, insn.get_next_word(), dt_word);
}
else
{
set_addr(insn.Op1, o_mem, insn.get_next_word());
}
break;
// rrd,rrs
case A_wrpd_wrps:
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4));
set_reg(insn.Op2, rrr0 + (byte & 0x0E));
break;
// (rrd),rrs
case A_wrpdi_wrps:
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND);
set_reg(insn.Op2, rrr0 + (byte & 0x0E));
break;
// rrd,(rrs)
case A_wrpd_wrpsi:
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4));
set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND);
break;
// (rrd),(rrs)
case A_wrpdi_wrpsi:
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND);
set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND);
break;
// rrd,rs
case A_wrpd_wrs:
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4));
set_reg(insn.Op2, rr0 + (byte & 0x0F));
break;
// rd,(rrs)
case A_wrd_wrpi:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4));
set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND);
break;
// (rrs),rd
case A_wrpi_wrd:
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND);
set_reg(insn.Op2, rr0 + ((byte & 0xF0) >> 4));
break;
// Nd(rr),#NNs
case A_8qxwrp_16q:
QASSERT(10039, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word);
set_imm(insn.Op2, insn.get_next_word(), dt_word);
break;
// NNd(rr),#NNs
case A_16qxwrp_16q:
QASSERT(10040, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word);
set_imm(insn.Op2, insn.get_next_word(), dt_word);
break;
// N(rr),R
case A_8qxwrp_gr:
QASSERT(10041, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E));
set_reg(insn.Op2, get_general_register(insn.get_next_byte()));
break;
// NN(rr),R
case A_16qxwrp_gr:
QASSERT(10042, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E));
set_reg(insn.Op2, get_general_register(insn.get_next_byte()));
break;
// NNd,#Ns
case A_16q_8q:
QASSERT(10043, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_imm(insn.Op2, insn.get_next_byte(), dt_byte);
set_addr(insn.Op1, o_mem, insn.get_next_word());
break;
// NNd,#NNs
case A_16q_16q:
QASSERT(10044, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_imm(insn.Op2, insn.get_next_word(), dt_word);
set_addr(insn.Op1, o_mem, insn.get_next_word(), dt_word);
break;
// rd,rrs(rrx)
case A_wr_wrpxwrp:
QASSERT(10045, insn.itype == st9_ald);
byte = insn.get_next_byte();
set_phrase(insn.Op2, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E));
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rr0 + (byte & 0x0F));
break;
// rrd(rrx),rs
case A_wrpxwrp_wr:
QASSERT(10046, insn.itype == st9_ald);
byte = insn.get_next_byte();
set_phrase(insn.Op1, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E));
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rr0 + (byte & 0x0F));
break;
// rrd,rrs(rrx)
case A_wrp_wrpxwrp:
QASSERT(10047, insn.itype == st9_aldw);
byte = insn.get_next_byte();
set_phrase(insn.Op2, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E), dt_word);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rrr0 + (byte & 0x0E));
break;
// rrd(rrx),rrs
case A_wrpxwrp_wrp:
QASSERT(10048, insn.itype == st9_aldw);
byte = insn.get_next_byte();
set_phrase(insn.Op1, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E), dt_word);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rrr0 + (byte & 0x0E));
break;
// Rd,(rrs)
case A_gr_wrpi:
QASSERT(10049, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND);
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// (rrd),Rs
case A_wrip_gr:
QASSERT(10050, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND);
set_reg(insn.Op2, get_general_register(insn.get_next_byte()));
break;
// (RRd),(rrs)
case A_grpi_wrip:
QASSERT(10051, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND);
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true), OP_IS_IND);
break;
// (R),(rr)
case A_gri_wrip_01:
case A_gri_wrip_11:
set_reg(insn.Op2, rrr0 + (insn.get_next_byte() & 0x0E), OP_IS_IND);
set_reg(insn.Op1, get_general_register(insn.get_next_byte()), OP_IS_IND);
break;
// Rd,N(rrx)
case A_gr_8qxwrp:
QASSERT(10052, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E));
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// Rd,NN(rrx)
case A_gr_16qxwrp:
QASSERT(10053, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op2, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E));
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// RRd,(rrs)
case A_grp_wrpi:
QASSERT(10054, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND);
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// N(rrx),RRs
case A_8qxwrp_grp:
QASSERT(10055, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word);
set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// RRd,N(rrx)
case A_grp_8qxwrp:
QASSERT(10056, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word);
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// NN(rrx),RRs
case A_16qxwrp_grp:
QASSERT(10057, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word);
set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// RRd,NN(rrx)
case A_grp_16qxwrp:
QASSERT(10058, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_displ(insn.Op2, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word);
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// N(RRx)
case A_8qxgrpi:
byte = insn.get_next_byte();
set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, get_general_register(byte & 0xFE, true));
break;
// NN(RRx)
case A_16qxgrpi:
byte = insn.get_next_byte();
// this word is coded with little endian
set_displ(insn.Op1, o_mem, short(my_next_word(insn)), o_reg, get_general_register(byte & 0xFE, true));
break;
// rd,(rrs),N
case A_wrd_wrpsi_8q_0:
case A_wrd_wrpsi_8q_1:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + (byte & 0x0F));
set_reg(insn.Op2, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND);
set_imm(insn.Op3, insn.get_next_byte(), dt_byte);
break;
// RRd,(rs)
case A_grpd_wrsi:
QASSERT(10059, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND);
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// N(rx),rs
case A_8qxwr_wrs:
byte = insn.get_next_byte();
set_reg(insn.Op2, rr0 + ((byte & 0xF0) >> 4));
set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F));
break;
// rs,N(rx)
case A_wrs_8qxwr:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4));
set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F));
break;
// Rd,(rrs)+
case A_grd_wrpip:
QASSERT(10060, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E));
set_reg(insn.Op1, get_general_register(insn.get_next_byte()));
break;
// (rrs)+,Rd
case A_wrpip_grd:
QASSERT(10061, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E));
set_reg(insn.Op2, rR0 + insn.get_next_byte());
break;
// (rr),RR
case A_wrpi_grp:
QASSERT(10062, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND);
set_reg(insn.Op2, rRR0 + (insn.get_next_byte() & 0x0E));
break;
// (rr),#NN
case A_wrpi_16q:
QASSERT(10063, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND);
set_imm(insn.Op2, insn.get_next_word(), dt_word);
break;
// Rd,-(rrs)
case A_grd_wrpim:
QASSERT(10064, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op2, fPD, rrr0 + (byte & 0x0E));
set_reg(insn.Op1, rR0 + insn.get_next_byte());
break;
// -(rrs),Rd
case A_wrpim_grd:
QASSERT(10065, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op1, fPD, rrr0 + (byte & 0x0E));
set_reg(insn.Op2, rR0 + insn.get_next_byte());
break;
// RRd,-(rrs)
case A_grpd_wrpim:
QASSERT(10066, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op2, fPD, rrr0 + (byte & 0x0E), -1, dt_word);
set_reg(insn.Op1, rRR0 + insn.get_next_byte());
break;
// -(rrs),RRd
case A_wrpim_grpd:
QASSERT(10067, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op1, fPD, rrr0 + (byte & 0x0E), -1, dt_word);
set_reg(insn.Op2, rRR0 + insn.get_next_byte());
break;
// NN,rs
case A_16q_wrs:
QASSERT(10068, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rr0 + (byte & 0x0F));
set_addr(insn.Op1, o_mem, insn.get_next_word());
break;
// rd,NN
case A_wrd_16q:
QASSERT(10069, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rr0 + (byte & 0x0F));
set_addr(insn.Op2, o_mem, insn.get_next_word());
break;
// (rd)+,(rrs)+
case A_wrip_wrpip:
byte = insn.get_next_byte();
set_phrase(insn.Op1, fPI, rr0 + ((byte & 0xE0) >> 4));
set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E));
break;
// (rrs)+,(rd)+
case A_wrpip_wrip:
byte = insn.get_next_byte();
set_phrase(insn.Op2, fPI, rr0 + ((byte & 0xE0) >> 4));
set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E));
break;
// (rrd)+,(rrs)+
case A_wrpdip_wrpsip_00:
case A_wrpdip_wrpsip_10:
case A_wrpdip_wrpsip_01:
case A_wrpdip_wrpsip_11:
byte = insn.get_next_byte();
set_phrase(insn.Op1, fPI, rrr0 + ((byte & 0xE0) >> 4));
set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E));
break;
// RRd,(rrs)+
case A_grpd_wrpip:
QASSERT(10070, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E), -1, dt_word);
set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// (rrd)+,RRs
case A_wrpip_grpd:
QASSERT(10071, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E), -1, dt_word);
set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true));
break;
// N(rx),rrs
case A_8qxwrip_wrp:
byte = insn.get_next_byte();
set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F));
set_reg(insn.Op2, rrr0 + ((byte & 0xE0) >> 4));
break;
// rrd,N(rx)
case A_wrp_8qxwrip:
byte = insn.get_next_byte();
set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F));
set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4));
break;
// rrd,NN
case A_wrp_16q:
QASSERT(10072, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rrr0 + (byte & 0x0E));
set_addr(insn.Op2, o_mem, insn.get_next_word(), dt_word);
break;
// NN,rrs
case A_16q_wrp:
QASSERT(10073, insn.itype == st9_aldw);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op2, rrr0 + (byte & 0x0E));
set_addr(insn.Op1, o_mem, insn.get_next_word(), dt_word);
break;
// rrh,rrl,RRs
case A_wrp_wrp_grp:
set_reg(insn.Op3, rRR0 + (insn.get_next_byte() & 0x0E));
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4));
set_reg(insn.Op2, rrr0 + (byte & 0x0E));
break;
// (rd),RRs
case A_wrdi_grp:
QASSERT(10074, insn.itype == st9_aldw);
byte = insn.get_next_byte();
set_reg(insn.Op2, rRR0 + (byte & 0x0E));
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_IS_IND);
break;
// (rrd),#N
case A_wrpi_8q:
QASSERT(10075, insn.itype == st9_ald);
byte = insn.get_next_byte();
insn.itype = get_alu_insn(insn, byte);
set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND);
set_imm(insn.Op2, insn.get_next_byte(), dt_byte);
break;
#define BIT_OP_1 (insn.itype != st9_bld ? insn.Op1 : insn.Op2)
#define BIT_OP_2 (insn.itype != st9_bld ? insn.Op2 : insn.Op1)
// rd.b,rs.b
case A_wrb_wrb_10:
case A_wrb_wrb_11:
byte = insn.get_next_byte();
set_reg(BIT_OP_1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT);
set_bit(BIT_OP_1, (byte & 0xE0) >> 5);
byte = insn.get_next_byte();
set_reg(BIT_OP_2, rr0 + (byte & 0x0F), OP_REG_WITH_BIT);
set_bit(BIT_OP_2, (byte & 0xE0) >> 5);
break;
// rd.b,rs.!b
case A_wrb_nwrb_10:
case A_wrb_nwrb_11:
byte = insn.get_next_byte();
set_reg(BIT_OP_1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT);
set_bit(BIT_OP_1, (byte & 0xE0) >> 5, insn.itype == st9_bld ? OP_BIT_COMPL : 0);
byte = insn.get_next_byte();
set_reg(BIT_OP_2, rr0 + (byte & 0x0F), OP_REG_WITH_BIT);
set_bit(BIT_OP_2, (byte & 0xE0) >> 5, insn.itype != st9_bld ? OP_BIT_COMPL : 0);
break;
// rd.b
case A_wrb:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT);
set_bit(insn.Op1, (byte & 0xE0) >> 5);
break;
// (rr).bd
case A_wrbi:
byte = insn.get_next_byte();
set_reg(insn.Op1, rrr0 + (byte & 0x0F), OP_REG_WITH_BIT | OP_IS_IND);
set_bit(insn.Op1, (byte & 0xE0) >> 5);
break;
// b.rd,N
case A_bwr_8q_0:
case A_bwr_8q_1:
byte = insn.get_next_byte();
set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT);
set_bit(insn.Op1, (byte & 0xE0) >> 5);
set_addr(insn.Op2, o_near, insn.get_next_byte());
insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size;
break;
// nnnnnn,NN (calls, jps)
case A_seg_16q_01:
case A_seg_16q_11:
{
uint8 seg = insn.get_next_byte() & 0x3F;
uint16 dst = insn.get_next_word();
ea_t fardest = (seg<<16) |dst;
if ( is_mapped(fardest) )
{
set_addr(insn.Op1, o_far, fardest);
}
else
{
set_imm(insn.Op1, seg, dt_byte, OP_IMM_NO_SHIFT);
set_addr(insn.Op2, o_near, dst);
}
}
break;
// wwwww
case A_rwn_000:
case A_rwn_100:
case A_rwn_101:
set_imm(insn.Op1, (insn.get_next_byte() & 0xF8) >> 3, dt_byte);
break;
// pppppp
case A_rpn:
set_imm(insn.Op1, (insn.get_next_byte() & 0xFC) >> 2, dt_byte);
break;
}
}
//----------------------------------------------------------------------
// analyze an instruction
int idaapi st9_ana(insn_t *_insn)
{
insn_t &insn = *_insn;
int byte = insn.get_next_byte();
const opcode *op = find_opcode(insn, byte);
if ( op == NULL )
return 0;
fill_cmd(insn, byte, op);
return insn.size;
}