1 /*
2 * Copyright (c) 2015, Marcos Medeiros
3 * Licensed under BSD 3-clause.
4 */
5 #include <string>
6 #include <vector>
7 #include "tms34010.h"
8 #include "memhandler.h"
9
10 #define READ_WORD(addr) tms::read_word(addr)
11 #define READ_DWORD(addr) (READ_WORD(addr) | (READ_WORD(addr + 16) << 16))
12
13 #define BKW_DIR (opcode & (1 << 10))
14 #define OFFS ((opcode >> 5) & 0x1F)
15 #define K fw_lut[((opcode >> 5) & 0x1F)]
16 #define KN ((~opcode >> 5) & 0x1F)
17 #define K2C ((-K) & 0x1F)
18 #define M_BIT (opcode & (1 << 9))
19 #define R_BIT (opcode & 0x10)
20 #define RS (((opcode >> 5) & 0xF) | R_BIT)
21 #define RD ((opcode & 0xF) | R_BIT)
22 #define NF (opcode & 0x1F)
23 #define RS_n ((opcode >> 5) & 0xF)
24 #define RD_n (opcode & 0xF)
25
26 namespace tms
27 {
28
29 const int dasm_buf_size = 128;
30 const int dasm_pc_size = 32;
31
32 const char *reg_names[32] =
33 {
34 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
35 "a8", "a9", "a10", "a11", "a12", "a13", "a14", "sp",
36 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
37 "b8", "b9", "b10", "b11", "b12", "b13", "b14", "sp",
38 };
39
dsjs_pc(dword pc,word opcode)40 static inline dword dsjs_pc(dword pc, word opcode)
41 {
42 int displace = OFFS * 16;
43 if (BKW_DIR)
44 displace = -displace;
45 return pc + displace;
46 }
47
jr_pc(dword pc,word opcode)48 static inline dword jr_pc(dword pc, word opcode)
49 {
50 int displace = (opcode & 0xFF) * 16;
51 if (BKW_DIR)
52 displace = -displace;
53 return pc + displace;
54 }
55
jr_cond(word opcode)56 static inline const char *jr_cond(word opcode)
57 {
58 const char *cond_table[16] = {
59 /* 0000 */ "",
60 /* 0001 */ "p",
61 /* 0010 */ "ls",
62 /* 0011 */ "hi",
63 /* 0100 */ "lt",
64 /* 0101 */ "ge",
65 /* 0110 */ "le",
66 /* 0111 */ "gt",
67 /* 1000 */ "c",
68 /* 1001 */ "nc",
69 /* 1010 */ "eq",
70 /* 1011 */ "ne",
71 /* 1100 */ "v",
72 /* 1101 */ "nv",
73 /* 1110 */ "n",
74 /* 1111 */ "nn"
75 };
76 return cond_table[(opcode >> 8) & 0xF];
77 }
78
79
reg_list(word opcode,word data)80 static const char *reg_list(word opcode, word data)
81 {
82 int inc = (opcode & 0x10) ? 16 : 0;
83 std::vector<std::string> regs;
84 regs.reserve(16);
85
86
87 for (int i = 0; i < 16; i++) {
88 if (data & 0x8000)
89 regs.push_back(reg_names[inc + i]);
90 data <<= 1;
91 }
92
93
94 std::string s;
95 s.reserve(100);
96 for (int i = 0; i < regs.size(); i++) {
97 s.append(regs[i]);
98 if (i != regs.size() - 1)
99 s.append(",");
100 }
101
102 return s.c_str();
103 }
104
reg_list_inv(word opcode,word data)105 static const char *reg_list_inv(word opcode, word data)
106 {
107 int inc = (opcode & 0x10) ? 16 : 0;
108 std::vector<std::string> regs;
109 regs.reserve(16);
110
111
112 for (int i = 0; i < 16; i++) {
113 if (data & 1)
114 regs.push_back(reg_names[inc + i]);
115 data >>= 1;
116 }
117
118
119 std::string s;
120 s.reserve(100);
121 for (int i = 0; i < regs.size(); i++) {
122 s.append(regs[i]);
123 if (i != regs.size() - 1)
124 s.append(",");
125 }
126
127 return s.c_str();
128 }
129
130 #define DASM(...) snprintf(buf, dasm_buf_size, __VA_ARGS__)
131
dasm(dword pc,size_t * szbits)132 std::string dasm(dword pc, size_t *szbits)
133 {
134 const int size = 128;
135 char buf[size];
136 char pcb[dasm_pc_size];
137
138 word opcode = READ_WORD(pc);
139
140 buf[0] = '\0';
141 pcb[0] = '\0';
142
143 snprintf(pcb, dasm_pc_size, "%08X\t%04X\t", pc, opcode);
144 int fs = opcode & 0x1F;
145 int fe = (opcode & (1 << 5)) ? 1 : 0;
146 int f = (opcode & (1 << 9)) ? 1 : 0;
147 int rd = RD;
148 int rs = RS;
149 //int rfile = (opcode >> 5) & 1;
150
151 int words = 1;
152
153 if (!fs)
154 fs = 32;
155
156 switch (opcode >> 12) {
157 case 0x00:
158 switch ((opcode >> 5) & 0x7F) {
159
160 case 0x09: DASM("exgpc %s", reg_names[rd]); break;
161 case 0x0A: DASM("getpc %s", reg_names[rd]); break;
162 case 0x0B: DASM("jump %s", reg_names[rd]); break;
163 case 0x0F: DASM("pushst"); break;
164 case 0x0E: DASM("popst"); break;
165 case 0x1B: DASM("dint"); break;
166 case 0x6B: DASM("eint"); break;
167
168 case 0x1F: DASM("not %s", reg_names[rd]); break;
169
170 case 0x2F: DASM("movb %s, @%x", reg_names[rd], READ_DWORD(pc + 16)); words += 2; break;
171 case 0x3F: DASM("movb @%x, %s", READ_DWORD(pc + 16), reg_names[rd]); words += 2; break;
172
173 case 0x2A:
174 case 0x2B:
175 case 0x3A:
176 case 0x3B: DASM("setf 0x%x, %d, %d", fs, fe, f); break;
177
178 case 0x4D: DASM("mmfm %s, %s", reg_names[rd], reg_list_inv(opcode, READ_WORD(pc + 16))); words++; break;
179
180 case 0x4E: DASM("movi 0x%04x, %s", READ_WORD(pc + 16), reg_names[rd]); words++; break;
181 case 0x4F: DASM("movi 0x%08x, %s", READ_DWORD(pc + 16), reg_names[rd]); words += 2; break;
182
183 case 0x3C:
184 case 0x2C: DASM("move %s, @%x, %d", reg_names[rd], READ_DWORD(pc + 16), f); words += 2; break;
185
186 case 0x3D:
187 case 0x2D: DASM("move @%x, %s, %d", READ_DWORD(pc + 16), reg_names[rd], f); words += 2; break;
188
189 case 0x4B: DASM("rets 0x%x", NF); break;
190 case 0x4C: DASM("mmtm %s, %s", reg_names[rd], reg_list(opcode, READ_WORD(pc + 16))); words++; break;
191
192 case 0x58: DASM("addi 0x%08x, %s", READ_WORD(pc + 16), reg_names[rd]); words++; break;
193 case 0x59: DASM("addi 0x%08x, %s", READ_DWORD(pc + 16), reg_names[rd]); words += 2; break;
194 case 0x5C: DASM("andi 0x%08x, %s", ~READ_DWORD(pc + 16), reg_names[rd]); words += 2; break;
195
196 case 0x5F: DASM("subi 0x%08x, %s", ~(short)READ_WORD(pc + 16), reg_names[rd]); words++; break;
197 case 0x68: DASM("subi 0x%08x, %s", ~READ_DWORD(pc + 16), reg_names[rd]); words += 2; break;
198
199 case 0x5A: DASM("cmpi 0x%08x, %s", ~(short)READ_WORD(pc + 16), reg_names[rd]); words++; break;
200 case 0x5B: DASM("cmpi 0x%08x, %s", ~READ_DWORD(pc + 16), reg_names[rd]); words += 2; break;
201
202 case 0x69: {
203 switch (opcode & 0xFF) {
204 case 0x3F:
205 DASM("callr @%x", pc + 32 + (short)READ_WORD(pc + 16) * 16); words++; break;
206 }
207 }
208 case 0x6A: {
209 switch (opcode & 0xFF) {
210 case 0x5F:
211 DASM("calla @%x", READ_DWORD(pc + 16)); words += 2; break;
212 }
213 break;
214 }
215
216 case 0x6C: DASM("dsj %s, @%x", reg_names[rd], pc + 32 + (short)READ_WORD(pc + 16) * 16); words++; break;
217 case 0x7D: DASM("pixblt b, xy"); break;
218
219
220 default:
221 DASM("[%04X] ??? [0000]", opcode);
222 break;
223 }
224 break;
225
226 case 0x01:
227 switch ((opcode >> 10) & 3) {
228 case 0x03: DASM("btst 0x%x, %s", KN, reg_names[rd]); break;
229 case 0x02: DASM("movk 0x%x, %s", K, reg_names[rd]); break;
230 case 0x01: DASM("subk 0x%x, %s", K, reg_names[rd]); break;
231 case 0x00: DASM("addk 0x%x, %s", K, reg_names[rd]); break;
232 default:
233 DASM("[%04X] ??? [0001]", opcode);
234 break;
235 }
236 break;
237
238 case 0x02:
239 switch ((opcode >> 10) & 3) {
240 case 0x01: DASM("sll 0x%x, %s", K, reg_names[rd]); break;
241 case 0x03: DASM("srl 0x%x, %s", K2C, reg_names[rd]); break;
242 default:
243 DASM("[%04X] ??? [0010]", opcode);
244 break;
245 }
246 break;
247
248 case 0x03:
249 if (opcode & (1 << 11))
250 DASM("dsjs %s, @%x", reg_names[rd], dsjs_pc(pc + 16, opcode));
251 else {
252 DASM("[%04X] ??? [0011]", opcode);
253 }
254 break;
255 case 0x04:
256 switch ((opcode >> 9) & 7) {
257 case 0x0: DASM("add %s, %s", reg_names[rs], reg_names[rd]); break;
258 case 0x2: DASM("sub %s, %s", reg_names[rs], reg_names[rd]); break;
259 case 0x4: DASM("cmp %s, %s", reg_names[rs], reg_names[rd]); break;
260 case 0x6: DASM("move %s, %s", reg_names[rs], reg_names[rd]); break;
261 case 0x7: {
262 int rs_, rd_;
263 if (R_BIT) {
264 rs_ = 16 + RS_n;
265 rd_ = RD_n;
266 } else {
267 rs_ = RS_n;
268 rd_ = 16 + RD_n;
269 }
270 DASM("move %s, %s", reg_names[rs_], reg_names[rd_]);
271 break;
272 }
273
274 default:
275 DASM("[%04X] ??? [0100]", opcode);
276 break;
277 }
278
279 break;
280
281 case 0x05:
282 switch ((opcode >> 9) & 7) {
283 case 0x00: DASM("and %s, %s", reg_names[rs], reg_names[rd]); break;
284 case 0x01: DASM("andn %s, %s", reg_names[rs], reg_names[rd]); break;
285 case 0x02: DASM("or %s, %s", reg_names[rs], reg_names[rd]); break;
286 case 0x03:
287 if (rs == rd)
288 DASM("clr %s", reg_names[rs]);
289 else
290 DASM("xor %s, %s", reg_names[rs], reg_names[rd]);
291 break;
292 case 0x04: DASM("divs %s, %s", reg_names[rs], reg_names[rd]); break;
293 case 0x05: DASM("divu %s, %s", reg_names[rs], reg_names[rd]); break;
294 case 0x06: DASM("mpys %s, %s", reg_names[rs], reg_names[rd]); break;
295 case 0x07: DASM("mpyu %s, %s", reg_names[rs], reg_names[rd]); break;
296 default:
297 DASM("[%04X] ??? [0101]", opcode);
298 }
299
300 break;
301
302 case 0x06:
303 switch ((opcode >> 9) & 7) {
304 case 0x05: DASM("lmo %s, %s", reg_names[rs], reg_names[rd]); break;
305 case 0x07: DASM("modu %s, %s", reg_names[rs], reg_names[rd]); break;
306 default:
307 DASM("[%04X] ??? [0110]", opcode);
308 break;
309 }
310 break;
311
312
313 case 0x08:
314 switch ((opcode >> 9) & 7) {
315 case 0x7: DASM("movb *%s, %s", reg_names[rs], reg_names[rd]); break;
316 case 0x6: DASM("movb %s, *%s", reg_names[rs], reg_names[rd]); break;
317 case 0x2: DASM("move *%s, %s, 0", reg_names[rs], reg_names[rd]); break;
318 case 0x3: DASM("move *%s, %s, 1", reg_names[rs], reg_names[rd]); break;
319 case 0x0: DASM("move %s, *%s, 0", reg_names[rs], reg_names[rd]); break;
320 case 0x1: DASM("move %s, *%s, 1", reg_names[rs], reg_names[rd]); break;
321
322 default:
323 DASM("[%04X] ??? [1000]", opcode);
324 break;
325 }
326
327 break;
328
329
330
331 case 0x09:
332 switch ((opcode >> 9) & 7) {
333 case 0x00: DASM("move %s, *%s+, 0", reg_names[rs], reg_names[rd]); break;
334 case 0x01: DASM("move %s, *%s+, 1", reg_names[rs], reg_names[rd]); break;
335 case 0x02: DASM("move *%s+, %s, 0", reg_names[rs], reg_names[rd]); break;
336 case 0x03: DASM("move *%s+, %s, 1", reg_names[rs], reg_names[rd]); break;
337 case 0x04: DASM("move *%s+, *%s+, 0", reg_names[rs], reg_names[rd]); break;
338 case 0x05: DASM("move *%s+, *%s+, 1", reg_names[rs], reg_names[rd]); break;
339 default:
340 DASM("[%04X] ??? [1001]", opcode);
341 break;
342 }
343 break;
344
345 case 0x0A:
346 switch ((opcode >> 9) & 7) {
347 case 0x00: DASM("move %s, -*%s, 0", reg_names[rs], reg_names[rd]); break;
348 case 0x01: DASM("move %s, -*%s, 1", reg_names[rs], reg_names[rd]); break;
349 case 0x02: DASM("move -%s, *%s, 0", reg_names[rs], reg_names[rd]); break;
350 case 0x03: DASM("move -%s, *%s, 1", reg_names[rs], reg_names[rd]); break;
351 case 0x04: DASM("move -%s, -*%s, 0", reg_names[rs], reg_names[rd]); break;
352 case 0x05: DASM("move -%s, -*%s, 1", reg_names[rs], reg_names[rd]); break;
353 case 0x06: DASM("movb %s, *%s(%x), 1", reg_names[rs], reg_names[rd],READ_WORD(pc+16)); words++; break;
354 case 0x07: DASM("movb %s(%x), *%s, 1", reg_names[rs], READ_WORD(pc+16),reg_names[rd]); words++; break;
355 default:
356 DASM("[%04X] ??? [1010]", opcode);
357 break;
358 }
359 break;
360
361 case 0x0B:
362 switch ((opcode >> 9) & 7) {
363 case 0x00: DASM("move %s, *%s(%x), 0", reg_names[rs], reg_names[rd],READ_WORD(pc+16)); words++; break;
364 case 0x01: DASM("move %s, *%s(%x), 1", reg_names[rs], reg_names[rd],READ_WORD(pc+16)); words++; break;
365 case 0x02: DASM("move *%s(%x), %s, 0", reg_names[rs], READ_WORD(pc+16), reg_names[rd]); words++; break;
366 case 0x03: DASM("move *%s(%x), %s, 1", reg_names[rs], READ_WORD(pc+16), reg_names[rd]); words++; break;
367 case 0x04: DASM("move *%s(%x), *%s(%x), 0", reg_names[rs], READ_WORD(pc+16),reg_names[rd],READ_WORD(pc+32)); words+=2; break;
368 case 0x05: DASM("move *%s(%x), *%s(%x), 1", reg_names[rs], READ_WORD(pc+16),reg_names[rd],READ_WORD(pc+32)); words+=2; break;
369 default:
370 DASM("[%04X] ??? [1011]", opcode);
371 break;
372 }
373 break;
374
375
376 case 0x0C:
377 if (opcode & 0xFF) {
378 if ((opcode & 0xFF) == 0x80) { // JA addr
379 DASM("ja%s @%x", jr_cond(opcode), READ_DWORD(pc + 16));
380 words += 2;
381 break;
382 }
383 // JR shor addr
384 DASM("jr%s @%x", jr_cond(opcode), pc + 16 + ((int8_t)(opcode & 0xFF)) * 16);
385 } else {
386 // JR rel cond
387 DASM("jr%s @%x", jr_cond(opcode), pc + 32 + (short)READ_WORD(pc + 16) * 16);
388 words++;
389 }
390 break;
391
392
393 case 0x0E:
394 switch ((opcode >> 9) & 7) {
395 case 0x6: DASM("movx %s, %s", reg_names[rs], reg_names[rd]); break;
396 case 0x7: DASM("movy %s, %s", reg_names[rs], reg_names[rd]); break;
397 default:
398 DASM("[%04X] ??? [1110]", opcode);
399 break;
400 }
401
402 break;
403
404 default:
405 DASM("[%04X] ???", opcode);
406 break;
407 }
408
409 if (szbits)
410 *szbits = words * 16;
411
412 return std::string(buf);
413 }
414
415 }
416
417