1 /* ======================================================================== */
2 /* =============================== COPYRIGHT ============================== */
3 /* ======================================================================== */
4 /*
5
6 SPC700 CPU Emulator V0.90
7
8 Copyright (c) 2000 Karl Stenerud
9 All rights reserved.
10
11 Permission is granted to use this source code for non-commercial purposes.
12 To use this code for commercial purposes, you must get permission from the
13 author (Karl Stenerud) at karl@higashiyama-unet.ocn.ne.jp.
14
15
16 */
17
18
19 #include "spc700ds.h"
20 #include <stdio.h>
21
22 #include <retro_inline.h>
23
24
25
26 typedef struct
27 {
28 unsigned char name;
29 unsigned char args[2];
30 } opcode_struct;
31
32 enum
33 {
34 IMP , A , X , Y , YA , SP , PSW , C , REL , UPAG, IMM , XI ,
35 XII , YI , DP , DPX , DPY , DPI , DXI , DIY , ABS , ABX , ABY , AXI , N0 ,
36 N1 , N2 , N3 , N4 , N5 , N6 , N7 , N8 , N9 , N10 , N11 , N12 ,
37 N13 , N14 , N15 , DP0 , DP1 , DP2 , DP3 , DP4 , DP5 , DP6 , DP7 , MEMN,
38 MEMI
39 };
40
41
42 enum
43 {
44 ADC , ADDW , AND , AND1 , ASL , BBC , BBS , BCC ,
45 BCS , BEQ , BMI , BNE , BPL , BRA , BRK , BVC ,
46 BVS , CALL , CBNE , CLR1 , CLRC , CLRP , CLRV , CMP ,
47 CMPW , DAA , DAS , DBNZ , DEC , DECW , DI , DIV ,
48 EI , EOR , EOR1 , INC , INCW , JMP , LSR , MOV ,
49 MOV1 , MOVW , MUL , NOP , NOT1 , NOTQ , NOTC , OR ,
50 OR1 , PCALL , POP , PUSH , RET , RETI , ROL , ROR ,
51 SBC , SET1 , SETC , SETP , SLEEP , STOP , SUBW , TCALL ,
52 TCLR1 , TSET1 , XCN
53 };
54
55
56 static const char* g_opnames[] =
57 {
58 "ADC ", "ADDW ", "AND ", "AND1 ", "ASL ", "BBC ", "BBS ", "BCC ",
59 "BCS ", "BEQ ", "BMI ", "BNE ", "BPL ", "BRA ", "BRK ", "BVC ",
60 "BVS ", "CALL ", "CBNE ", "CLR1 ", "CLRC ", "CLRP ", "CLRV ", "CMP ",
61 "CMPW ", "DAA ", "DAS ", "DBNZ ", "DEC ", "DECW ", "DI ", "DIV ",
62 "EI ", "EOR ", "EOR1 ", "INC ", "INCW ", "JMP ", "LSR ", "MOV ",
63 "MOV1 ", "MOVW ", "MUL ", "NOP ", "NOT1 ", "NOTQ ", "NOTC ", "OR ",
64 "OR1 ", "PCALL", "POP ", "PUSH ", "RET ", "RETI ", "ROL ", "ROR ",
65 "SBC ", "SET1 ", "SETC ", "SETP ", "SLEEP", "STOP ", "SUBW ", "TCALL",
66 "TCLR1", "TSET1", "XCN "
67 };
68
69 static opcode_struct g_opcodes[256] =
70 {
71 /* 00 */ {NOP , {IMP , IMP }},
72 /* 01 */ {TCALL , {N0 , IMP }},
73 /* 02 */ {SET1 , {DP0 , IMP }},
74 /* 03 */ {BBS , {DP0 , REL }},
75 /* 04 */ {OR , {A , DP }},
76 /* 05 */ {OR , {A , ABS }},
77 /* 06 */ {OR , {A , XI }},
78 /* 07 */ {OR , {A , DXI }},
79 /* 08 */ {OR , {A , IMM }},
80 /* 09 */ {OR , {DP , DP }},
81 /* 0A */ {OR1 , {C , MEMN}},
82 /* 0B */ {ASL , {DP , IMP }},
83 /* 0C */ {ASL , {ABS , IMP }},
84 /* 0D */ {PUSH , {PSW , IMP }},
85 /* 0E */ {TSET1 , {ABS , IMP }},
86 /* 0F */ {BRK , {IMM , IMP }},
87 /* 10 */ {BPL , {REL , IMP }},
88 /* 11 */ {TCALL , {N1 , IMP }},
89 /* 12 */ {CLR1 , {DP0 , IMP }},
90 /* 13 */ {BBC , {DP0 , REL }},
91 /* 14 */ {OR , {A , DPX }},
92 /* 15 */ {OR , {A , ABX }},
93 /* 16 */ {OR , {A , ABY }},
94 /* 17 */ {OR , {A , DIY }},
95 /* 18 */ {OR , {DP , IMM }},
96 /* 19 */ {OR , {XI , YI }},
97 /* 1A */ {DECW , {DP , IMP }},
98 /* 1B */ {ASL , {DPX , IMP }},
99 /* 1C */ {ASL , {A , IMP }},
100 /* 1D */ {DEC , {X , IMP }},
101 /* 1E */ {CMP , {X , ABS }},
102 /* 1F */ {JMP , {AXI , IMP }},
103 /* 20 */ {CLRP , {IMP , IMP }},
104 /* 21 */ {TCALL , {N2 , IMP }},
105 /* 22 */ {SET1 , {DP1 , IMP }},
106 /* 23 */ {BBS , {DP1 , REL }},
107 /* 24 */ {AND , {A , DP }},
108 /* 25 */ {AND , {A , ABS }},
109 /* 26 */ {AND , {A , XI }},
110 /* 27 */ {AND , {A , DXI }},
111 /* 28 */ {AND , {A , IMM }},
112 /* 29 */ {AND , {DP , DP }},
113 /* 2A */ {OR1 , {C , MEMI}},
114 /* 2B */ {ROL , {DP , IMP }},
115 /* 2C */ {ROL , {ABS , IMP }},
116 /* 2D */ {PUSH , {A , IMP }},
117 /* 2E */ {CBNE , {DP , REL }},
118 /* 2F */ {BRA , {REL , IMP }},
119 /* 30 */ {BMI , {REL , IMP }},
120 /* 31 */ {TCALL , {N3 , IMP }},
121 /* 32 */ {CLR1 , {DP1 , IMP }},
122 /* 33 */ {BBC , {DP1 , REL }},
123 /* 34 */ {AND , {A , DPX }},
124 /* 35 */ {AND , {A , ABX }},
125 /* 36 */ {AND , {A , ABY }},
126 /* 37 */ {AND , {A , DIY }},
127 /* 38 */ {AND , {DP , IMM }},
128 /* 39 */ {AND , {XI , YI }},
129 /* 3A */ {INCW , {DI , IMP }},
130 /* 3B */ {ROL , {DPX , IMP }},
131 /* 3C */ {ROL , {A , IMP }},
132 /* 3D */ {INC , {X , IMP }},
133 /* 3E */ {CMP , {X , DP }},
134 /* 3F */ {CALL , {ABS , IMP }},
135 /* 40 */ {SETP , {IMP , IMP }},
136 /* 41 */ {TCALL , {N4 , IMP }},
137 /* 42 */ {SET1 , {DP2 , IMP }},
138 /* 43 */ {BBS , {DP2 , REL }},
139 /* 44 */ {EOR , {A , DP }},
140 /* 45 */ {EOR , {A , ABS }},
141 /* 46 */ {EOR , {A , XI }},
142 /* 47 */ {EOR , {A , DXI }},
143 /* 48 */ {EOR , {A , IMM }},
144 /* 49 */ {EOR , {DP , DP }},
145 /* 4A */ {AND1 , {C , MEMN}},
146 /* 4B */ {LSR , {DP , IMP }},
147 /* 4C */ {LSR , {ABS , IMP }},
148 /* 4D */ {PUSH , {X , IMP }},
149 /* 4E */ {TCLR1 , {ABS , IMP }},
150 /* 4F */ {PCALL , {UPAG, IMP }},
151 /* 50 */ {BVC , {REL , IMP }},
152 /* 51 */ {TCALL , {N5 , IMP }},
153 /* 52 */ {CLR1 , {DP2 , IMP }},
154 /* 53 */ {BBC , {DP2 , REL }},
155 /* 54 */ {EOR , {A , DPX }},
156 /* 55 */ {EOR , {A , ABX }},
157 /* 56 */ {EOR , {A , ABY }},
158 /* 57 */ {EOR , {A , DIY }},
159 /* 58 */ {EOR , {DP , IMM }},
160 /* 59 */ {EOR , {XI , YI }},
161 /* 5A */ {CMPW , {DP , IMP }},
162 /* 5B */ {LSR , {DPX , IMP }},
163 /* 5C */ {LSR , {A , IMP }},
164 /* 5D */ {MOV , {X , A }},
165 /* 5E */ {CMP , {Y , ABS }},
166 /* 5F */ {JMP , {ABS , IMP }},
167 /* 60 */ {CLRC , {IMP , IMP }},
168 /* 61 */ {TCALL , {N6 , IMP }},
169 /* 62 */ {SET1 , {DP3 , IMP }},
170 /* 63 */ {BBS , {DP3 , REL }},
171 /* 64 */ {CMP , {A , DP }},
172 /* 65 */ {CMP , {A , ABS }},
173 /* 66 */ {CMP , {A , XI }},
174 /* 67 */ {CMP , {A , DXI }},
175 /* 68 */ {CMP , {A , IMM }},
176 /* 69 */ {CMP , {DP , DP }},
177 /* 6A */ {AND1 , {C , MEMI}},
178 /* 6B */ {ROR , {DP , IMP }},
179 /* 6C */ {ROR , {ABS , IMP }},
180 /* 6D */ {PUSH , {Y , IMP }},
181 /* 6E */ {DBNZ , {DP , REL }},
182 /* 6F */ {RET , {IMP , IMP }},
183 /* 70 */ {BVS , {REL , IMP }},
184 /* 71 */ {TCALL , {N7 , IMP }},
185 /* 72 */ {CLR1 , {DP3 , IMP }},
186 /* 73 */ {BBC , {DP3 , REL }},
187 /* 74 */ {CMP , {A , DPX }},
188 /* 75 */ {CMP , {A , ABX }},
189 /* 76 */ {CMP , {A , ABY }},
190 /* 77 */ {CMP , {A , DIY }},
191 /* 78 */ {CMP , {DP , IMM }},
192 /* 79 */ {CMP , {XI , YI }},
193 /* 7A */ {ADDW , {DI , IMP }},
194 /* 7B */ {ROR , {DPX , IMP }},
195 /* 7C */ {ROR , {A , IMP }},
196 /* 7D */ {MOV , {A , X }},
197 /* 7E */ {CMP , {Y , DP }},
198 /* 7F */ {RETI , {IMP , IMP }},
199 /* 80 */ {SETC , {IMP , IMP }},
200 /* 81 */ {TCALL , {N8 , IMP }},
201 /* 82 */ {SET1 , {DP4 , IMP }},
202 /* 83 */ {BBS , {DP4 , REL }},
203 /* 84 */ {ADC , {A , DP }},
204 /* 85 */ {ADC , {A , ABS }},
205 /* 86 */ {ADC , {A , XI }},
206 /* 87 */ {ADC , {A , DXI }},
207 /* 88 */ {ADC , {A , IMM }},
208 /* 89 */ {ADC , {DP , DP }},
209 /* 8A */ {EOR1 , {C , MEMN}},
210 /* 8B */ {DEC , {DP , IMP }},
211 /* 8C */ {DEC , {ABS , IMP }},
212 /* 8D */ {MOV , {Y , IMM }},
213 /* 8E */ {POP , {PSW , IMP }},
214 /* 8F */ {MOV , {DP , IMM }},
215 /* 90 */ {BCC , {REL , IMP }},
216 /* 91 */ {TCALL , {N9 , IMP }},
217 /* 92 */ {CLR1 , {DP4 , IMP }},
218 /* 93 */ {BBC , {DP4 , REL }},
219 /* 94 */ {ADC , {A , DPX }},
220 /* 95 */ {ADC , {A , ABX }},
221 /* 96 */ {ADC , {A , ABY }},
222 /* 97 */ {ADC , {A , DIY }},
223 /* 98 */ {ADC , {DP , IMM }},
224 /* 99 */ {ADC , {XI , YI }},
225 /* 9A */ {SUBW , {DP , IMP }},
226 /* 9B */ {DEC , {DPX , IMP }},
227 /* 9C */ {DEC , {A , IMP }},
228 /* 9D */ {MOV , {X , SP }},
229 /* 9E */ {DIV , {YA , X }},
230 /* 9F */ {XCN , {A , IMP }},
231 /* A0 */ {EI , {IMP , IMP }},
232 /* A1 */ {TCALL , {N10 , IMP }},
233 /* A2 */ {SET1 , {DP5 , IMP }},
234 /* A3 */ {BBS , {DP5 , REL }},
235 /* A4 */ {SBC , {A , DP }},
236 /* A5 */ {SBC , {A , ABS }},
237 /* A6 */ {SBC , {A , XI }},
238 /* A7 */ {SBC , {A , DXI }},
239 /* A8 */ {SBC , {A , IMM }},
240 /* A9 */ {SBC , {DP , DP }},
241 /* AA */ {MOV1 , {C , MEMN}},
242 /* AB */ {INC , {DP , IMP }},
243 /* AC */ {INC , {ABS , IMP }},
244 /* AD */ {CMP , {Y , IMM }},
245 /* AE */ {POP , {A , IMP }},
246 /* AF */ {MOV , {XII , A }},
247 /* B0 */ {BCS , {REL , IMP }},
248 /* B1 */ {TCALL , {N11 , IMP }},
249 /* B2 */ {CLR1 , {DP5 , IMP }},
250 /* B3 */ {BBC , {DP5 , REL }},
251 /* B4 */ {SBC , {A , DPX }},
252 /* B5 */ {SBC , {A , ABX }},
253 /* B6 */ {SBC , {A , ABY }},
254 /* B7 */ {SBC , {A , DIY }},
255 /* B8 */ {SBC , {DP , IMM }},
256 /* B9 */ {SBC , {XI , YI }},
257 /* BA */ {MOVW , {YA , DP }},
258 /* BB */ {INC , {DPX , IMP }},
259 /* BC */ {INC , {A , IMP }},
260 /* BD */ {MOV , {SP , X }},
261 /* BE */ {DAS , {A , IMP }},
262 /* BF */ {MOV , {A , XII }},
263 /* C0 */ {DI , {IMP , IMP }},
264 /* C1 */ {TCALL , {N12 , IMP }},
265 /* C2 */ {SET1 , {DP6 , IMP }},
266 /* C3 */ {BBS , {DP6 , REL }},
267 /* C4 */ {MOV , {DP , A }},
268 /* C5 */ {MOV , {ABS , A }},
269 /* C6 */ {MOV , {XI , A }},
270 /* C7 */ {MOV , {DXI , A }},
271 /* C8 */ {CMP , {X , IMM }},
272 /* C9 */ {MOV , {ABS , X }},
273 /* CA */ {MOV1 , {MEMN, C }},
274 /* CB */ {MOV , {DP , Y }},
275 /* CC */ {MOV , {ABS , Y }},
276 /* CD */ {MOV , {X , IMM }},
277 /* CE */ {POP , {X , IMP }},
278 /* CF */ {MUL , {YA , IMP }},
279 /* D0 */ {BNE , {REL , IMP }},
280 /* D1 */ {TCALL , {N13 , IMP }},
281 /* D2 */ {CLR1 , {DP6 , IMP }},
282 /* D3 */ {BBC , {DP6 , REL }},
283 /* D4 */ {MOV , {DPX , A }},
284 /* D5 */ {MOV , {ABX , A }},
285 /* D6 */ {MOV , {ABY , A }},
286 /* D7 */ {MOV , {DIY , A }},
287 /* D8 */ {MOV , {DP , X }},
288 /* D9 */ {MOV , {DPY , X }},
289 /* DA */ {MOVW , {DP , YA }},
290 /* DB */ {MOV , {DPX , Y }},
291 /* DC */ {DEC , {Y , IMP }},
292 /* DD */ {MOV , {A , Y }},
293 /* DE */ {CBNE , {DPX , REL }},
294 /* DF */ {DAA , {IMP , IMP }},
295 /* E0 */ {CLRV , {IMP , IMP }},
296 /* E1 */ {TCALL , {N14 , IMP }},
297 /* E2 */ {SET1 , {DP7 , IMP }},
298 /* E3 */ {BBS , {DP7 , REL }},
299 /* E4 */ {MOV , {A , DP }},
300 /* E5 */ {MOV , {A , ABS }},
301 /* E6 */ {MOV , {A , XI }},
302 /* E7 */ {MOV , {A , DXI }},
303 /* E8 */ {MOV , {A , IMM }},
304 /* E9 */ {MOV , {X , ABS }},
305 /* EA */ {NOT1 , {IMP , IMP }},
306 /* EB */ {MOV , {Y , DP }},
307 /* EC */ {MOV , {Y , ABS }},
308 /* ED */ {NOTC , {IMP , IMP }},
309 /* EE */ {POP , {Y , IMP }},
310 /* EF */ {SLEEP , {IMP , IMP }},
311 /* F0 */ {BEQ , {REL , IMP }},
312 /* F1 */ {TCALL , {N15 , IMP }},
313 /* F2 */ {CLR1 , {DP7 , IMP }},
314 /* F3 */ {BBC , {DP7 , REL }},
315 /* F4 */ {MOV , {A , DPX }},
316 /* F5 */ {MOV , {A , ABX }},
317 /* F6 */ {MOV , {A , ABY }},
318 /* F7 */ {MOV , {A , DIY }},
319 /* F8 */ {MOV , {X , DP }},
320 /* F9 */ {MOV , {X , DPY }},
321 /* FA */ {MOV , {DP , DP }},
322 /* FB */ {MOV , {Y , DPX }},
323 /* FC */ {INC , {Y , IMP }},
324 /* FD */ {MOV , {Y , A }},
325 /* FE */ {DBNZ , {Y , REL }},
326 /* FF */ {STOP , {IMP , IMP }},
327 };
328
329 static unsigned int g_pc;
330
read_8_immediate(void)331 static INLINE unsigned int read_8_immediate(void)
332 {
333 g_pc++;
334 return spc700_read_8_disassembler(g_pc-1);
335 }
336
read_16_immediate(void)337 static INLINE unsigned int read_16_immediate(void)
338 {
339 g_pc += 2;
340 return spc700_read_8_disassembler(g_pc-2) |
341 (spc700_read_8_disassembler(g_pc-1)<<8);
342 }
343
spc700_disassemble(char * buff,unsigned int pc)344 int spc700_disassemble(char* buff, unsigned int pc)
345 {
346 opcode_struct* opcode;
347 char* ptr;
348 int var;
349 int i;
350
351 g_pc = pc;
352 opcode = g_opcodes + read_8_immediate();
353
354 sprintf(buff, "%s ", g_opnames[opcode->name]);
355 ptr = buff + strlen(buff);
356
357 for(i=0;i<2;i++)
358 {
359 if(i == 1 && opcode->args[0] != IMP && opcode->args[1] != IMP)
360 {
361 sprintf(ptr, ",");
362 ptr += strlen(ptr);
363 }
364
365 switch(opcode->args[i])
366 {
367 case IMP: break;
368 case A: sprintf(ptr, "A"); break;
369 case X: sprintf(ptr, "X"); break;
370 case Y: sprintf(ptr, "Y"); break;
371 case YA: sprintf(ptr, "YA"); break;
372 case SP: sprintf(ptr, "SP"); break;
373 case PSW: sprintf(ptr, "PSW"); break;
374 case C: sprintf(ptr, "C"); break;
375 case REL: sprintf(ptr, "%04x", ((g_pc + (char)read_8_immediate())&0xffff)); break;
376 case UPAG: sprintf(ptr, "$%02x", read_8_immediate()); break;
377 case IMM: sprintf(ptr, "#$%02x", read_8_immediate()); break;
378 case XI: sprintf(ptr, "(X)"); break;
379 case XII: sprintf(ptr, "(X)+"); break;
380 case YI: sprintf(ptr, "(Y)"); break;
381 case DP: sprintf(ptr, "$%02x", read_8_immediate()); break;
382 case DPX: sprintf(ptr, "$%02x+X", read_8_immediate()); break;
383 case DPY: sprintf(ptr, "$%02x+Y", read_8_immediate()); break;
384 case DPI: sprintf(ptr, "($%02x)", read_8_immediate()); break;
385 case DXI: sprintf(ptr, "($%02x+X)", read_8_immediate()); break;
386 case DIY: sprintf(ptr, "($%02x)+Y", read_8_immediate()); break;
387 case ABS: sprintf(ptr, "$%04x", read_16_immediate()); break;
388 case ABX: sprintf(ptr, "$%04x+X", read_16_immediate()); break;
389 case ABY: sprintf(ptr, "$%04x+Y", read_16_immediate()); break;
390 case AXI: sprintf(ptr, "($%04x+X)", read_16_immediate()); break;
391 case N0: sprintf(ptr, "0"); break;
392 case N1: sprintf(ptr, "1"); break;
393 case N2: sprintf(ptr, "2"); break;
394 case N3: sprintf(ptr, "3"); break;
395 case N4: sprintf(ptr, "4"); break;
396 case N5: sprintf(ptr, "5"); break;
397 case N6: sprintf(ptr, "6"); break;
398 case N7: sprintf(ptr, "7"); break;
399 case N8: sprintf(ptr, "8"); break;
400 case N9: sprintf(ptr, "9"); break;
401 case N10: sprintf(ptr, "10"); break;
402 case N11: sprintf(ptr, "11"); break;
403 case N12: sprintf(ptr, "12"); break;
404 case N13: sprintf(ptr, "13"); break;
405 case N14: sprintf(ptr, "14"); break;
406 case N15: sprintf(ptr, "15"); break;
407 case DP0: sprintf(ptr, "$%02x.0", read_8_immediate()); break;
408 case DP1: sprintf(ptr, "$%02x.1", read_8_immediate()); break;
409 case DP2: sprintf(ptr, "$%02x.2", read_8_immediate()); break;
410 case DP3: sprintf(ptr, "$%02x.3", read_8_immediate()); break;
411 case DP4: sprintf(ptr, "$%02x.4", read_8_immediate()); break;
412 case DP5: sprintf(ptr, "$%02x.5", read_8_immediate()); break;
413 case DP6: sprintf(ptr, "$%02x.6", read_8_immediate()); break;
414 case DP7: sprintf(ptr, "$%02x.7", read_8_immediate()); break;
415 case MEMN:
416 var = read_16_immediate();
417 sprintf(ptr, "%04x.%d", var&0x1fff, var>>13);
418 break;
419 case MEMI:
420 var = read_16_immediate();
421 sprintf(ptr, "/%04x.%d", var&0x1fff, var>>13);
422 break;
423 }
424 ptr += strlen(ptr);
425 }
426 return g_pc - pc;
427 }
428