1 // license:BSD-3-Clause
2 // copyright-holders:hap
3 /*
4
5 NEC uCOM-4 MCU family disassembler
6
7 */
8
9 #include "emu.h"
10 #include "ucom4d.h"
11
12 const char *const ucom4_disassembler::s_mnemonics[] =
13 {
14 "LI", "L", "LM", "LDI", "LDZ", "S", "TAL", "TLA",
15 "X", "XI", "XD", "XM", "XMI", "XMD", "AD", "ADC", "ADS", "DAA", "DAS",
16 "EXL", "CLA", "CMA", "CIA", "CLC", "STC", "TC", "INC", "DEC", "IND", "DED",
17 "RMB", "SMB", "REB", "SEB", "RPB", "SPB", "JMP", "JCP", "JPA", "CAL", "CZP", "RT", "RTS",
18 "CI", "CM", "CMB", "TAB", "CLI", "TMB", "TPA", "TPB",
19 "TIT", "IA", "IP", "OE", "OP", "OCD", "NOP",
20 "?",
21 "TAW", "TAZ", "THX", "TLY", "XAW", "XAZ", "XHR", "XHX", "XLS", "XLY", "XC",
22 "SFB", "RFB", "FBT", "FBF", "RAR", "INM", "DEM", "STM", "TTM", "EI", "DI"
23 };
24
25 // number of bits per opcode parameter, 2 digits means opcode is 2 bytes
26 const u8 ucom4_disassembler::s_bits[] =
27 {
28 4, 0, 2, 80, 4, 0, 0, 0,
29 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0,
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 2, 2, 2, 2, 2, 2, 83, 6, 0, 83, 4, 0, 0,
32 40, 0, 2, 2, 40, 2, 2, 2,
33 0, 0, 0, 0, 0, 80, 0,
34 0,
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 2, 2, 2, 2, 0, 0, 0, 80, 0, 0, 0
37 };
38
39 const u32 ucom4_disassembler::s_flags[] =
40 {
41 0, 0, 0, 0, 0, 0, 0, 0,
42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 0, 0, 0, STEP_OVER, STEP_OVER, STEP_OUT, STEP_OUT,
45 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0,
47 0,
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
50 };
51
52
53 const u8 ucom4_disassembler::ucom4_mnemonic[0x100] =
54 {
55 /* 0x00 */
56 mNOP, mDI, mS, mTIT, mTC, mTTM, mDAA, mTAL,
57 mAD, mADS, mDAS, mCLC, mCM, mINC, mOP, mDEC,
58 mCMA, mCIA, mTLA, mDED, mSTM, mLDI, mCLI, mCI,
59 mEXL, mADC, mXC, mSTC, mILL, mINM, mOCD, mDEM,
60 /* 0x20 */
61 mFBF, mFBF, mFBF, mFBF, mTAB, mTAB, mTAB, mTAB,
62 mX, mXM, mXM, mXM, mXD, mXMD, mXMD, mXMD,
63 mRAR, mEI, mIP, mIND, mCMB, mCMB, mCMB, mCMB,
64 mL, mLM, mLM, mLM, mXI, mXMI, mXMI, mXMI,
65 /* 0x40 */
66 mIA, mJPA, mTAZ, mTAW, mOE, mILL, mTLY, mTHX,
67 mRT, mRTS, mXAZ, mXAW, mXLS, mXHR, mXLY, mXHX,
68 mTPB, mTPB, mTPB, mTPB, mTPA, mTPA, mTPA, mTPA,
69 mTMB, mTMB, mTMB, mTMB, mFBT, mFBT, mFBT, mFBT,
70 /* 0x60 */
71 mRPB, mRPB, mRPB, mRPB, mREB, mREB, mREB, mREB,
72 mRMB, mRMB, mRMB, mRMB, mRFB, mRFB, mRFB, mRFB,
73 mSPB, mSPB, mSPB, mSPB, mSEB, mSEB, mSEB, mSEB,
74 mSMB, mSMB, mSMB, mSMB, mSFB, mSFB, mSFB, mSFB,
75 /* 0x80 */
76 mLDZ, mLDZ, mLDZ, mLDZ, mLDZ, mLDZ, mLDZ, mLDZ,
77 mLDZ, mLDZ, mLDZ, mLDZ, mLDZ, mLDZ, mLDZ, mLDZ,
78 mCLA, mLI, mLI, mLI, mLI, mLI, mLI, mLI,
79 mLI, mLI, mLI, mLI, mLI, mLI, mLI, mLI,
80 /* 0xa0 */
81 mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP,
82 mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL,
83 mCZP, mCZP, mCZP, mCZP, mCZP, mCZP, mCZP, mCZP,
84 mCZP, mCZP, mCZP, mCZP, mCZP, mCZP, mCZP, mCZP,
85 /* 0xc0 */
86 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP,
87 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP,
88 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP,
89 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP,
90 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP,
91 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP,
92 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP,
93 mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP, mJCP
94 };
95
96
opcode_alignment() const97 u32 ucom4_disassembler::opcode_alignment() const
98 {
99 return 1;
100 }
101
interface_flags() const102 u32 ucom4_disassembler::interface_flags() const
103 {
104 return PAGED2LEVEL;
105 }
106
page_address_bits() const107 u32 ucom4_disassembler::page_address_bits() const
108 {
109 return 6;
110 }
111
page2_address_bits() const112 u32 ucom4_disassembler::page2_address_bits() const
113 {
114 return 2;
115 }
116
117
disassemble(std::ostream & stream,offs_t pc,const data_buffer & opcodes,const data_buffer & params)118 offs_t ucom4_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
119 {
120 offs_t pos = pc;
121 u8 op = opcodes.r8(pos++);
122 u8 instr = ucom4_mnemonic[op];
123
124 util::stream_format(stream,"%-4s ", s_mnemonics[instr]);
125
126 // opcode parameter
127 int bits = s_bits[instr];
128 if (bits)
129 {
130 u16 param = op & ((1 << (bits % 10)) - 1);
131 if (bits / 10)
132 {
133 u8 op2 = opcodes.r8(pos++);
134 param = (param << (bits / 10)) | (op2 & ((1 << (bits / 10)) - 1));
135 bits = (bits % 10) + (bits / 10);
136 }
137
138 // special case for CZP
139 if (instr == mCZP)
140 {
141 param <<= 2;
142 bits += 2;
143 }
144
145 if (bits <= 4)
146 util::stream_format(stream, "%d", param);
147 else if (bits <= 8)
148 util::stream_format(stream, "$%02X", param);
149 else
150 util::stream_format(stream, "$%03X", param);
151 }
152
153 return (pos - pc) | s_flags[instr] | SUPPORTED;
154 }
155