1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /*********************************\
4 
5  ARCtangent A4 disassembler
6 
7 \*********************************/
8 
9 #include "emu.h"
10 #include "arcdasm.h"
11 
12 /*****************************************************************************/
13 
14 
15 
16 /*****************************************************************************/
17 
18 char const *const arc_disassembler::basic[0x20] =
19 {
20 	/* 00 */ "LD r+r",
21 	/* 01 */ "LD r+o",
22 	/* 02 */ "ST r+o",
23 	/* 03 */ "extended",
24 	/* 04 */ "B",
25 	/* 05 */ "BL",
26 	/* 06 */ "LPcc",
27 	/* 07 */ "Jcc JLcc",
28 	/* 08 */ "ADD",
29 	/* 09 */ "ADC",
30 	/* 0a */ "SUB",
31 	/* 0b */ "SBC",
32 	/* 0c */ "AND",
33 	/* 0d */ "OR",
34 	/* 0e */ "BIC",
35 	/* 0f */ "XOR",
36 	/* 10 */ "ASL",
37 	/* 11 */ "LSR",
38 	/* 12 */ "ASR",
39 	/* 13 */ "ROR",
40 	/* 14 */ "MUL64",
41 	/* 15 */ "MULU64",
42 	/* 16 */ "undefined",
43 	/* 17 */ "undefined",
44 	/* 18 */ "undefined",
45 	/* 19 */ "undefined",
46 	/* 1a */ "undefined",
47 	/* 1b */ "undefined",
48 	/* 1c */ "undefined",
49 	/* 1d */ "undefined",
50 	/* 1e */ "MAX",
51 	/* 1f */ "MIN"
52 };
53 
54 char const *const arc_disassembler::conditions[0x20] =
55 {
56 	/* 00 */ "AL", // (aka RA         - Always)
57 	/* 01 */ "EQ", // (aka Z          - Zero
58 	/* 02 */ "NE", // (aka NZ         - Non-Zero)
59 	/* 03 */ "PL", // (aka P          - Positive)
60 	/* 04 */ "MI", // (aka N          - Negative)
61 	/* 05 */ "CS", // (aka C,  LO     - Carry set / Lower than) (unsigned)
62 	/* 06 */ "CC", // (aka CC, NC, HS - Carry Clear / Higher or Same) (unsigned)
63 	/* 07 */ "VS", // (aka V          - Overflow set)
64 	/* 08 */ "VC", // (aka NV         - Overflow clear)
65 	/* 09 */ "GT", // (               - Greater than) (signed)
66 	/* 0a */ "GE", // (               - Greater than or Equal) (signed)
67 	/* 0b */ "LT", // (               - Less than) (signed)
68 	/* 0c */ "LE", // (               - Less than or Equal) (signed)
69 	/* 0d */ "HI", // (               - Higher than) (unsigned)
70 	/* 0e */ "LS", // (               - Lower or Same) (unsigned)
71 	/* 0f */ "PNZ",// (               - Positive non-0 value)
72 	/* 10 */ "0x10 Reserved", // possible CPU implementation specifics
73 	/* 11 */ "0x11 Reserved",
74 	/* 12 */ "0x12 Reserved",
75 	/* 13 */ "0x13 Reserved",
76 	/* 14 */ "0x14 Reserved",
77 	/* 15 */ "0x15 Reserved",
78 	/* 16 */ "0x16 Reserved",
79 	/* 17 */ "0x17 Reserved",
80 	/* 18 */ "0x18 Reserved",
81 	/* 19 */ "0x19 Reserved",
82 	/* 1a */ "0x1a Reserved",
83 	/* 1b */ "0x1b Reserved",
84 	/* 1c */ "0x1c Reserved",
85 	/* 1d */ "0x1d Reserved",
86 	/* 1e */ "0x1e Reserved",
87 	/* 1f */ "0x1f Reserved"
88 };
89 
90 char const *const arc_disassembler::delaytype[0x4] =
91 {
92 	"ND", // NO DELAY - execute next instruction only when NOT jumping
93 	"D",  // always execute next instruction
94 	"JD", // only execute next instruction when jumping
95 	"Res!", // reserved / invalid
96 };
97 
98 char const *const arc_disassembler::regnames[0x40] =
99 {
100 	/* 0x00 */ "r00",
101 	/* 0x01 */ "r01",
102 	/* 0x02 */ "r02",
103 	/* 0x03 */ "r03",
104 	/* 0x04 */ "r04",
105 	/* 0x05 */ "r05",
106 	/* 0x06 */ "r06",
107 	/* 0x07 */ "r07",
108 	/* 0x08 */ "r08",
109 	/* 0x09 */ "r09",
110 	/* 0x0a */ "r10",
111 	/* 0x0b */ "r11",
112 	/* 0x0c */ "r12",
113 	/* 0x0d */ "r13",
114 	/* 0x0e */ "r14",
115 	/* 0x0f */ "r15",
116 
117 	/* 0x10 */ "r16",
118 	/* 0x11 */ "r17",
119 	/* 0x12 */ "r18",
120 	/* 0x13 */ "r19",
121 	/* 0x14 */ "r20",
122 	/* 0x15 */ "r21",
123 	/* 0x16 */ "r22",
124 	/* 0x17 */ "r23",
125 	/* 0x18 */ "r24",
126 	/* 0x19 */ "r25",
127 	/* 0x1a */ "r26",
128 	/* 0x1b */ "r27",
129 	/* 0x1c */ "r28",
130 	/* 0x1d */ "ILINK1",
131 	/* 0x1e */ "ILINK2",
132 	/* 0x1f */ "BLINK",
133 
134 	/* 0x20 */ "r32res", // reserved for manufacturer specific extensions
135 	/* 0x21 */ "r33res",
136 	/* 0x22 */ "r34res",
137 	/* 0x23 */ "r35res",
138 	/* 0x24 */ "r36res",
139 	/* 0x25 */ "r37res",
140 	/* 0x26 */ "r38res",
141 	/* 0x27 */ "r39res",
142 	/* 0x28 */ "r40res",
143 	/* 0x29 */ "r41res",
144 	/* 0x2a */ "r42res",
145 	/* 0x2b */ "r43res",
146 	/* 0x2c */ "r44res",
147 	/* 0x2d */ "r45res",
148 	/* 0x2e */ "r46res",
149 	/* 0x2f */ "r47res",
150 
151 	/* 0x30 */ "r48res",
152 	/* 0x31 */ "r49res",
153 	/* 0x32 */ "r50res",
154 	/* 0x33 */ "r51res",
155 	/* 0x34 */ "r52res",
156 	/* 0x35 */ "r53res",
157 	/* 0x36 */ "r54res",
158 	/* 0x37 */ "r55res",
159 	/* 0x38 */ "r56res",
160 	/* 0x39 */ "r57res",
161 	/* 0x3a */ "r58res",
162 	/* 0x3b */ "r59res",
163 	/* 0x3c */ "LPCOUNT",
164 	/* 0x3d */ "sImm F",
165 	/* 0x3e */ "lImm",
166 	/* 0x3f */ "sImm NF",
167 };
168 
169 #define ARC_CONDITION ((op & 0x0000001f) >> 0 ) // aka Q
170 
171 // used in jumps
172 #define ARC_BRANCH_DELAY     ((op & 0x00000060) >> 5 ) // aka N
173 #define ARC_BRANCH_ADDR      ((op & 0x07ffff80) >> 7 ) // aka L
174 
175 #define ARC_OPERATION ((op & 0xf8000000) >> 27)
176 
177 #define ARC_REGOP_DEST      ((op & 0x07e00000) >> 21 ) // aka A
178 #define ARC_REGOP_OP1       ((op & 0x001f8000) >> 15 ) // aka B
179 #define ARC_REGOP_OP2       ((op & 0x00007e00) >> 9  ) // aka C
180 #define ARC_REGOP_SHIMM     ((op & 0x000001ff) >> 0  ) // aka D
181 
182 
opcode_alignment() const183 u32 arc_disassembler::opcode_alignment() const
184 {
185 	return 4;
186 }
187 
disassemble(std::ostream & stream,offs_t pc,const data_buffer & opcodes,const data_buffer & params)188 offs_t arc_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
189 {
190 	uint32_t op = opcodes.r32(pc);
191 
192 	uint8_t opcode = ARC_OPERATION;
193 
194 	switch (opcode)
195 	{
196 		case 0x04: // B
197 		case 0x05: // BL
198 		util::stream_format(stream, "%s(%s)(%s) %08x", basic[opcode], conditions[ARC_CONDITION], delaytype[ARC_BRANCH_DELAY], (ARC_BRANCH_ADDR<<2)+pc+4);
199 		break;
200 
201 		case 0x08: // ADD
202 		// todo, short / long immediate formats
203 		util::stream_format(stream, "%s %s , %s , %s (%08x)", basic[opcode], regnames[ARC_REGOP_DEST], regnames[ARC_REGOP_OP1], regnames[ARC_REGOP_OP2], op &~ 0xfffffe00);
204 		break;
205 
206 
207 		default:
208 		util::stream_format(stream, "%s (%08x)", basic[opcode], op &~ 0xf8000000);
209 		break;
210 	}
211 
212 	return 4 | SUPPORTED;
213 }
214