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 &params)
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