1 /******************************************************************************/
2 /* Mednafen - Multi-system Emulator */
3 /******************************************************************************/
4 /* gen.cpp - Table Generator for Motorola 68000 CPU Emulator
5 ** Copyright (C) 2015-2016 Mednafen Team
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software Foundation, Inc.,
19 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 // g++ -std=gnu++14 -Wall -O2 -o gen gen.cpp && ./gen > m68k_instr.inc
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <assert.h>
27
28 #include <string>
29 #include <map>
30 #include <list>
31 #include <vector>
32
s(const char * format,...)33 static std::string s(const char* format, ...)
34 {
35 static char buf[65536];
36 va_list ap;
37
38 va_start(ap, format);
39 vsnprintf(buf, sizeof(buf), format, ap);
40 va_end(ap);
41
42 return std::string(buf);
43 }
44
45 /*
46 DATA_REG_DIR,
47 ADDR_REG_DIR,
48
49 ADDR_REG_INDIR,
50 ADDR_REG_INDIR_POST,
51 ADDR_REG_INDIR_PRE,
52
53 ADDR_REG_INDIR_DISP,
54
55 ADDR_REG_INDIR_INDX,
56
57 ABS_SHORT,
58 ABS_LONG,
59
60 PC_DISP,
61 PC_INDEX,
62
63 IMMEDIATE
64 */
65 enum
66 {
67 AMA_DATA = 0x0001,
68 AMA_MEMORY = 0x0002,
69 AMA_CONTROL = 0x0004,
70 AMA_ALTERABLE = 0x0008,
71 };
72
bsize_to_type(unsigned size)73 static const char* bsize_to_type(unsigned size)
74 {
75 if(size == 0)
76 return "std::tuple<>";
77
78 if(size == 1)
79 return "uint8";
80
81 if(size == 2)
82 return "uint16";
83
84 if(size == 4)
85 return "uint32";
86
87 return NULL;
88 }
89
90 template<bool move_dest = false>
decode_ea(unsigned allowed,int size,unsigned instr,const char * ham_name,std::string * ham_out)91 bool decode_ea(unsigned allowed, int size, unsigned instr, const char* ham_name, std::string* ham_out)
92 {
93 const unsigned mode = (instr >> (move_dest ? 6 : 3)) & 0x7;
94 const unsigned reg = (instr >> (move_dest ? 9 : 0)) & 0x7;
95
96 if(size == -1)
97 {
98 if(mode == 0)
99 size = 4;
100 else
101 size = 1;
102 }
103
104 if((size != 0 && size != 1 && size != 2 && size != 4) || (size == 0 && allowed != AMA_CONTROL))
105 return false;
106
107 static const struct
108 {
109 const char* name;
110 unsigned flags;
111 } ams[2][0x8] =
112 {
113 {
114 { "DATA_REG_DIR", AMA_DATA | AMA_ALTERABLE },
115 { "ADDR_REG_DIR", AMA_ALTERABLE },
116 { "ADDR_REG_INDIR", AMA_DATA | AMA_MEMORY | AMA_ALTERABLE | AMA_CONTROL },
117 { "ADDR_REG_INDIR_POST", AMA_DATA | AMA_MEMORY | AMA_ALTERABLE },
118 { "ADDR_REG_INDIR_PRE", AMA_DATA | AMA_MEMORY | AMA_ALTERABLE },
119 { "ADDR_REG_INDIR_DISP", AMA_DATA | AMA_MEMORY | AMA_ALTERABLE | AMA_CONTROL },
120 { "ADDR_REG_INDIR_INDX", AMA_DATA | AMA_MEMORY | AMA_ALTERABLE | AMA_CONTROL },
121 { NULL, 0 },
122 },
123 {
124 { "ABS_SHORT", AMA_DATA | AMA_MEMORY | AMA_ALTERABLE | AMA_CONTROL },
125 { "ABS_LONG", AMA_DATA | AMA_MEMORY | AMA_ALTERABLE | AMA_CONTROL },
126 { "PC_DISP", AMA_DATA | AMA_MEMORY | AMA_CONTROL },
127 { "PC_INDEX", AMA_DATA | AMA_MEMORY | AMA_CONTROL },
128 { "IMMEDIATE", AMA_DATA | AMA_MEMORY },
129 { NULL, 0 },
130 { NULL, 0 },
131 { NULL, 0 },
132 }
133 };
134
135 auto const* const am = &ams[mode == 0x7][(mode == 0x7) ? reg : mode];
136
137 if((am->flags & allowed) != allowed)
138 return false;
139
140 if(mode == 0x1 && size == 1)
141 return false;
142
143 if(mode < 0x7)
144 {
145 *ham_out += s("HAM<%s, %s> %s(this, %s)", bsize_to_type(size), am->name, ham_name, (move_dest ? "instr_b11_b9" : "instr_b2_b0"));
146
147 return true;
148 }
149 else if(am->name)
150 {
151 *ham_out += s("HAM<%s, %s> %s(this)", bsize_to_type(size), am->name, ham_name);
152
153 return true;
154 }
155
156 return false;
157 }
158
PrivilegeWrap(std::string * str,bool mfsr=false)159 static void PrivilegeWrap(std::string *str, bool mfsr = false)
160 {
161 if(mfsr)
162 *str = s("if(!Revision_E || CheckPrivilege()) { %s }", str->c_str());
163 else
164 *str = s("if(CheckPrivilege()) { %s }", str->c_str());
165 }
166
167 static const char* size_names[4] = { "uint8", "uint16", "uint32", NULL };
168
169 //
170 // Bit manipulation, MOVEP, immediate
171 //
Instr0(const unsigned i)172 static std::string Instr0(const unsigned i)
173 {
174 std::string ret;
175
176 if(i & 0x100)
177 {
178 // MOVEP
179 if((i & 0x38) == 0x08)
180 {
181 assert(ret.size() == 0);
182 const char* sn = (i & 0x40) ? "uint32" : "uint16";
183
184 ret += s("MOVEP<%s, %s>(instr_b2_b0, instr_b11_b9);", sn, (i & 0x80) ? "true" : "false");
185 }
186 }
187 else
188 {
189 static const char* op_names[8] = { "OR", "AND", "SUB", "ADD", NULL, "EOR", "CMP", NULL };
190 const unsigned opi = (i >> 9) & 0x7;
191 const unsigned szi = (i >> 6) & 0x3;
192
193 std::string tmp;
194
195 if(decode_ea(AMA_DATA | AMA_ALTERABLE, 1 << szi, i, "dst", &tmp))
196 {
197 if(op_names[opi] && size_names[szi])
198 {
199 assert(ret.size() == 0);
200 ret += s("HAM<%s, IMMEDIATE> src(this); %s; %s(src, dst);", size_names[szi], tmp.c_str(), op_names[opi]); //, size_names[szi]);
201 }
202 }
203 // FEDCBA9876543210 FEDCBA9876543210
204 if((i & 0b1111111110111111) == 0b0000000000111100)
205 {
206 assert(ret.size() == 0);
207 ret += s("ORI_%s();", (i & 0x40) ? "SR" : "CCR" );
208 if(i & 0x40)
209 PrivilegeWrap(&ret);
210 }
211
212 // FEDCBA9876543210 FEDCBA9876543210
213 if((i & 0b1111111110111111) == 0b0000001000111100)
214 {
215 assert(ret.size() == 0);
216 ret += s("ANDI_%s();", (i & 0x40) ? "SR" : "CCR" );
217 if(i & 0x40)
218 PrivilegeWrap(&ret);
219 }
220
221 // FEDCBA9876543210 FEDCBA9876543210
222 if((i & 0b1111111110111111) == 0b0000101000111100)
223 {
224 assert(ret.size() == 0);
225 ret += s("EORI_%s();", (i & 0x40) ? "SR" : "CCR" );
226 if(i & 0x40)
227 PrivilegeWrap(&ret);
228 }
229 }
230
231
232 // bit
233 {
234 static const char* op_names[4] = { "BTST", "BCHG", "BCLR", "BSET" };
235 const unsigned type = (i >> 6) & 0x3;
236 const unsigned allowed = AMA_DATA | ((type == 0) ? 0 : AMA_ALTERABLE);
237 std::string tmp;
238
239 if(decode_ea(allowed, -1, i, "targ", &tmp))
240 {
241 if(i & 0x100) // Dynamic
242 {
243 assert(ret.size() == 0);
244 ret += s("%s; %s(targ, D[instr_b11_b9]);", tmp.c_str(), op_names[type]);
245 }
246 else if(((i >> 9) & 0x7) == 0x4 && ((i & 0x3F) != 0x3C)) // Static
247 {
248 //printf("%04x -- %s\n", i, ret.c_str());
249 assert(ret.size() == 0);
250 ret += s("unsigned wb = ReadOp(); %s; %s(targ, wb);", tmp.c_str(), op_names[type]);
251 }
252 }
253 }
254
255 return ret;
256 }
257
258
259 //
260 // MOVEB
261 //
Instr1(const unsigned i)262 static std::string Instr1(const unsigned i)
263 {
264 std::string ret;
265 std::string src_tmp;
266 std::string dst_tmp;
267
268 if(decode_ea(AMA_DATA, 1, i, "src", &src_tmp) && decode_ea<true>(AMA_DATA | AMA_ALTERABLE, 1, i, "dst", &dst_tmp))
269 {
270 ret += s("%s; %s; MOVE(src, dst);", src_tmp.c_str(), dst_tmp.c_str());
271 }
272
273 return ret;
274 }
275
276 //
277 // MOVEL MOVEW
278 //
Instr23(const unsigned i)279 static std::string Instr23(const unsigned i)
280 {
281 std::string ret;
282 std::string src_tmp;
283 std::string dst_tmp;
284 const unsigned size = ((i >> 12) == 0x2) ? 4 : 2;
285
286 if(decode_ea(0, size, i, "src", &src_tmp))
287 {
288 if(decode_ea<true>(AMA_DATA | AMA_ALTERABLE, size, i, "dst", &dst_tmp))
289 {
290 ret += s("%s; %s; MOVE(src, dst);", src_tmp.c_str(), dst_tmp.c_str());
291 }
292 else if(((i >> 6) & 0x7) == 0x1)
293 {
294 ret += s("%s; MOVEA(src, instr_b11_b9);", src_tmp.c_str());
295 }
296 }
297 return ret;
298 }
299
300 template<bool AllowA = false, bool AllowX = false, bool AllowASource = true, bool AllowToDR = false>
form_dar_opm_ea(const unsigned i,const char * name)301 static std::string form_dar_opm_ea(const unsigned i, const char* name)
302 {
303 std::string ret;
304 const unsigned opm = (i >> 6) & 0x7;
305 unsigned szi;
306 bool to_mem;
307 bool is_a = false;
308
309 if(opm == 0x3 || opm == 0x7)
310 {
311 to_mem = false;
312 szi = (opm & 0x4) ? 2 : 1;
313 is_a = true;
314
315 if(!AllowA)
316 return "";
317 }
318 else
319 {
320 to_mem = (bool)(opm & 0x4);
321 szi = opm & 0x3;
322 }
323
324 std::string tmp_ea, tmp_reg;
325 unsigned allowed;
326
327 if(to_mem)
328 {
329 if(AllowToDR)
330 allowed = AMA_DATA | AMA_ALTERABLE;
331 else
332 allowed = AMA_MEMORY | AMA_ALTERABLE;
333 }
334 else
335 {
336 if(AllowASource)
337 allowed = 0;
338 else
339 allowed = AMA_DATA;
340 }
341
342 if(decode_ea(allowed, 1U << szi, i, to_mem ? "dst" : "src", &tmp_ea))
343 {
344 tmp_ea += "; ";
345 tmp_reg = s("HAM<%s, %s> %s\(this, instr_b11_b9); ", is_a ? "uint32" : size_names[szi], is_a ? "ADDR_REG_DIR" : "DATA_REG_DIR", to_mem ? "src" : "dst");
346
347 if(to_mem)
348 ret += tmp_reg + tmp_ea;
349 else
350 ret += tmp_ea + tmp_reg;
351
352 ret += s("%s(src, dst);", name);
353 }
354 else if(AllowX && ((i >> 8) & 0x1) == 0x1 && ((i >> 4) & 0x3) == 0x0)
355 {
356 const bool rm = (i >> 3) & 1;
357 const unsigned szi = (i >> 6) & 0x3;
358
359 if(szi != 0x3)
360 {
361 if(rm) // address register, predecrement addressing mode
362 {
363 ret += s("HAM<%s, ADDR_REG_INDIR_PRE> src(this, instr_b2_b0); HAM<%s, ADDR_REG_INDIR_PRE> dst(this, instr_b11_b9); %sX(src, dst);", size_names[szi], size_names[szi], name);
364 }
365 else
366 {
367 ret += s("HAM<%s, DATA_REG_DIR> src(this, instr_b2_b0); HAM<%s, DATA_REG_DIR> dst(this, instr_b11_b9); %sX(src, dst);", size_names[szi], size_names[szi], name);
368 }
369 }
370 }
371 return ret;
372 }
373
form_destr_rm_srcr(const unsigned i,const char * name,const unsigned szi,const char * mem_am="ADDR_REG_INDIR_PRE")374 static std::string form_destr_rm_srcr(const unsigned i, const char* name, const unsigned szi, const char* mem_am = "ADDR_REG_INDIR_PRE")
375 {
376 const bool rm = (i >> 3) & 1;
377 std::string ret;
378
379 if(rm) // address register, predecrement addressing mode
380 ret = s("HAM<%s, %s> src(this, instr_b2_b0); HAM<%s, %s> dst(this, instr_b11_b9); %s(src, dst);", size_names[szi], mem_am, size_names[szi], mem_am, name);
381 else
382 ret = s("HAM<%s, DATA_REG_DIR> src(this, instr_b2_b0); HAM<%s, DATA_REG_DIR> dst(this, instr_b11_b9); %s(src, dst);", size_names[szi], size_names[szi], name);
383
384 return ret;
385 }
386
Instr4(const unsigned instr)387 static std::string Instr4(const unsigned instr)
388 {
389 std::string ret;
390 std::string tmp;
391
392 if(((instr >> 7) & 0x1F) == 0x1D && decode_ea(AMA_CONTROL, 0, instr, "targ", &tmp))
393 {
394 assert(ret.size() == 0);
395
396 ret = s("%s; %s(targ);", tmp.c_str(), (instr & 0x40) ? "JMP" : "JSR");
397 }
398
399 if(((instr >> 7) & 0x7) == 0x1 && ((instr >> 11) & 0x1) == 0x1)
400 {
401 const bool dr = (instr >> 10) & 1; // 0 = reg->mem, 1 = mem->reg
402 const bool sz = (instr >> 6) & 1; // 0 = word, 1 = long
403 std::string rls = "const uint16 reglist = ReadOp()";
404 unsigned instr_adj = instr;
405
406 if(!dr)
407 {
408 bool pseudo_predec = false;
409 if(((instr_adj >> 3) & 0x7) == 4)
410 {
411 instr_adj = (instr_adj &~ (0x7 << 3)) | (0x2 << 3);
412 pseudo_predec = true;
413 }
414
415 if(decode_ea(AMA_CONTROL | AMA_ALTERABLE, 2 << sz, instr_adj, "dst", &tmp))
416 {
417 assert(ret.size() == 0);
418 ret += s("%s; %s; MOVEM_to_MEM<%s>(reglist, dst);", rls.c_str(), tmp.c_str(), pseudo_predec ? "true" : "false");
419 }
420 }
421 else
422 {
423 bool pseudo_postinc = false;
424
425 if(((instr_adj >> 3) & 0x7) == 3)
426 {
427 instr_adj = (instr_adj &~ (0x7 << 3)) | (0x2 << 3);
428 pseudo_postinc = true;
429 }
430
431 if(decode_ea(AMA_CONTROL, 2 << sz, instr_adj, "src", &tmp))
432 {
433 assert(ret.size() == 0);
434 ret += s("%s; %s; MOVEM_to_REGS<%s>(src, reglist);", rls.c_str(), tmp.c_str(), pseudo_postinc ? "true" : "false");
435 }
436 }
437 }
438
439
440 if((instr & 0xF00) == 0x000)
441 {
442 const unsigned szi = (instr >> 6) & 0x3;
443
444 if(szi == 0x3)
445 {
446 // MOVE from SR
447 if(decode_ea(AMA_DATA | AMA_ALTERABLE, 2, instr, "dst", &tmp))
448 {
449 assert(ret.size() == 0);
450
451 ret += s("%s; MOVE_from_SR(dst);", tmp.c_str());
452 PrivilegeWrap(&ret, true);
453 }
454 }
455 else
456 {
457 // NEGX
458 if(decode_ea(AMA_DATA | AMA_ALTERABLE, 1U << szi, instr, "dst", &tmp))
459 {
460 assert(ret.size() == 0);
461
462 ret += s("%s; NEGX(dst);", tmp.c_str());
463 }
464 }
465 }
466
467
468
469 //
470 //
471 //
472 {
473 const unsigned type = (instr >> 6) & 0x7;
474
475 if(type == 0x6)
476 {
477 // CHK
478 if(decode_ea(AMA_DATA, 2, instr, "src", &tmp))
479 {
480 assert(ret.size() == 0);
481
482 ret += s("%s; HAM<uint16, DATA_REG_DIR> dst(this, instr_b11_b9); CHK(src, dst);", tmp.c_str());
483 }
484 }
485 else if(type == 0x7)
486 {
487 // LEA
488 if(decode_ea(AMA_CONTROL, 0, instr, "src", &tmp))
489 {
490 assert(ret.size() == 0);
491
492 ret += s("%s; LEA(src, instr_b11_b9);", tmp.c_str());
493 }
494 }
495 }
496
497
498 if((instr & 0xF00) == 0x200)
499 {
500 const unsigned szi = (instr >> 6) & 0x3;
501
502 if(szi == 0x3)
503 {
504
505 }
506 else
507 {
508 // CLR
509 if(decode_ea(AMA_DATA | AMA_ALTERABLE, 1U << szi, instr, "dst", &tmp))
510 {
511 assert(ret.size() == 0);
512
513 ret += s("%s; CLR(dst);", tmp.c_str());
514 }
515 }
516 }
517
518 if((instr & 0xD00) == 0x400)
519 {
520 const unsigned szi = (instr >> 6) & 0x3;
521
522 if(szi == 0x3)
523 {
524 if(decode_ea(AMA_DATA, 2, instr, "src", &tmp))
525 {
526 assert(ret.size() == 0);
527
528 if(instr & 0x200) // MOVE to SR
529 {
530 ret += s("%s; MOVE_to_SR(src);", tmp.c_str());
531 PrivilegeWrap(&ret);
532 }
533 else // MOVE to CCR
534 ret += s("%s; MOVE_to_CCR(src);", tmp.c_str());
535 }
536 }
537 else
538 {
539 // NOT
540 if(decode_ea(AMA_DATA | AMA_ALTERABLE, 1U << szi, instr, "dst", &tmp))
541 {
542 assert(ret.size() == 0);
543
544 if(instr & 0x200) // NOT
545 ret += s("%s; NOT(dst);", tmp.c_str());
546 else // NEG
547 ret += s("%s; NEG(dst);", tmp.c_str());
548 }
549 }
550 }
551
552 // NBCD
553 if((instr & 0xFC0) == 0x800 && decode_ea(AMA_DATA | AMA_ALTERABLE, 1, instr, "dst", &tmp))
554 {
555 assert(ret.size() == 0);
556
557 ret += s("%s; NBCD(dst);", tmp.c_str());
558 }
559
560 // SWAP
561 if((instr & 0xFF8) == 0x840)
562 {
563 assert(ret.size() == 0);
564
565 ret += s("SWAP(instr_b2_b0);");
566 }
567
568 // PEA
569 if((instr & 0xFC0) == 0x840 && decode_ea(AMA_CONTROL, 0, instr, "src", &tmp))
570 {
571 assert(ret.size() == 0);
572
573 ret += s("%s; PEA(src);", tmp.c_str());
574 }
575
576 // EXT
577 if(((instr >> 9) & 0x7) == 0x4 && ((instr >> 3) & 0x7) == 0x0)
578 {
579 const unsigned type = (instr >> 6) & 0x7;
580
581 if(type == 0x2 || type == 0x3)
582 {
583 assert(ret.size() == 0);
584
585 ret = s("HAM<%s, DATA_REG_DIR> dst(this, instr_b2_b0); EXT(dst);", (type & 0x1) ? "uint32" : "uint16");
586 }
587 }
588
589
590 // MOVEM EA to Regs
591 // TODO!
592 if((instr & 0xF80) == 0xC80)
593 {
594 //assert(ret.size() == 0);
595 }
596
597 // MOVEM regs to EA
598 // TODO!
599 if((instr & 0xF80) == 0x880)
600 {
601 //assert(ret.size() == 0);
602 }
603
604 if((instr & 0xF00) == 0xA00)
605 {
606 const unsigned szi = (instr >> 6) & 0x3;
607
608 if(szi == 0x3)
609 {
610 // TAS
611 if(decode_ea(AMA_DATA | AMA_ALTERABLE, 1, instr, "dst", &tmp))
612 {
613 assert(ret.size() == 0);
614 ret += s("%s; TAS(dst);", tmp.c_str());
615 }
616 }
617 else
618 {
619 // TST
620 if(decode_ea(AMA_DATA | AMA_ALTERABLE, 1U << szi, instr, "dst", &tmp))
621 {
622 assert(ret.size() == 0);
623 ret += s("%s; TST(dst);", tmp.c_str());
624 }
625 }
626 }
627
628
629 // TRAP
630 if((instr & 0xFF0) == 0xE40)
631 {
632 assert(ret.size() == 0);
633 ret += s("TRAP(instr & 0xF);");
634 }
635
636 // MOVE to/from USP
637 if((instr & 0xFF0) == 0xE60)
638 {
639 assert(ret.size() == 0);
640 ret += s("MOVE_USP<%d>(instr_b2_b0);", (bool)(instr & 0x8));
641 PrivilegeWrap(&ret);
642 }
643
644 // LINK
645 if((instr & 0xFF8) == 0xE50)
646 {
647 assert(ret.size() == 0);
648 ret += s("LINK(instr_b2_b0);");
649 }
650
651 // UNLK
652 if((instr & 0xFF8) == 0xE58)
653 {
654 assert(ret.size() == 0);
655 ret += s("UNLK(instr_b2_b0);");
656 }
657
658 // RTR
659 // FEDCBA9876543210
660 if(instr == 0b0100111001110111)
661 {
662 assert(ret.size() == 0);
663 ret += s("RTR();");
664 }
665
666
667 // TRAPV
668 // FEDCBA9876543210
669 if(instr == 0b0100111001110110)
670 {
671 assert(ret.size() == 0);
672 ret += s("TRAPV();");
673 }
674
675 // RTS
676 // FEDCBA9876543210
677 if(instr == 0b0100111001110101)
678 {
679 assert(ret.size() == 0);
680 ret += s("RTS();");
681 }
682
683 // RTE
684 // FEDCBA9876543210
685 if(instr == 0b0100111001110011)
686 {
687 assert(ret.size() == 0);
688 ret += s("RTE();");
689 PrivilegeWrap(&ret);
690 }
691
692 // STOP
693 // FEDCBA9876543210
694 if(instr == 0b0100111001110010)
695 {
696 assert(ret.size() == 0);
697 ret += s("STOP();");
698 PrivilegeWrap(&ret);
699 }
700
701 // NOP
702 // FEDCBA9876543210
703 if(instr == 0b0100111001110001)
704 {
705 assert(ret.size() == 0);
706 ret += s("NOP();");
707 }
708
709 // RESET
710 // FEDCBA9876543210
711 if(instr == 0b0100111001110000)
712 {
713 assert(ret.size() == 0);
714 ret += s("RESET();");
715 PrivilegeWrap(&ret);
716 }
717
718
719 return ret;
720 }
721
Instr5(const unsigned i)722 static std::string Instr5(const unsigned i)
723 {
724 std::string ret;
725 std::string tmp;
726 const unsigned szi = (i >> 6) & 0x3;
727
728 if(szi == 0x3)
729 {
730 if(((i >> 3) & 0x7) == 0x1) // DBcc
731 {
732 ret = s("DBcc<0x%02x>(instr_b2_b0);", (i >> 8) & 0xF);
733 }
734 else if(decode_ea(AMA_DATA | AMA_ALTERABLE, 1, i, "dst", &tmp)) // Scc
735 {
736 ret = s("%s; Scc<0x%02x>(dst);", tmp.c_str(), (i >> 8) & 0xF);
737 }
738 }
739 else if(decode_ea(AMA_ALTERABLE, (((i >> 3) & 0x7) == 1) ? 4 : (1U << szi), i, "dst", &tmp)) // ADDQ and SUBQ
740 {
741 ret = s("HAM<%s, IMMEDIATE> src(this, instr_b11_b9 ? instr_b11_b9 : 8); ", size_names[szi]);
742 ret += s("%s; %s(src, dst);", tmp.c_str(), (i & 0x100) ? "SUB" : "ADD");
743 }
744
745
746 return ret;
747 }
748
Instr6(const unsigned i)749 static std::string Instr6(const unsigned i)
750 {
751 return s("Bxx<0x%02x>((int8)instr);", (i >> 8) & 0xF);
752 }
753
Instr7(const unsigned i)754 static std::string Instr7(const unsigned i)
755 {
756 std::string ret;
757
758 // MOVEQ
759 if(((i >> 8) & 0x1) == 0x0)
760 {
761 ret = s("HAM<uint32, IMMEDIATE> src(this, (int8)instr); HAM<uint32, DATA_REG_DIR> dst(this, instr_b11_b9); MOVE(src, dst);");
762 }
763
764 return ret;
765 }
766
Instr8(const unsigned i)767 static std::string Instr8(const unsigned i)
768 {
769 std::string ret;
770
771 ret = form_dar_opm_ea<false, false, false>(i, "OR");
772
773 // DIVU/DIVS
774 if(((i >> 6) & 0x3) == 0x3)
775 {
776 std::string tmp;
777
778 if(decode_ea(AMA_DATA, 2, i, "src", &tmp))
779 {
780 assert(ret.size() == 0);
781
782 ret = s("%s; DIV%s(src, instr_b11_b9);", tmp.c_str(), ((i >> 8) & 1) ? "S" : "U");
783 }
784 }
785 else if(((i >> 4) & 0x1F) == 0x10) // SBCD
786 {
787 assert(ret.size() == 0);
788
789 ret = form_destr_rm_srcr(i, "SBCD", 0);
790 }
791 return ret;
792 }
793
Instr9(const unsigned i)794 static std::string Instr9(const unsigned i)
795 {
796 return form_dar_opm_ea<true, true>(i, "SUB");
797 }
798
InstrB(const unsigned i)799 static std::string InstrB(const unsigned i)
800 {
801 std::string ret;
802
803 switch((i >> 6) & 0x7)
804 {
805 case 0x4: case 0x5: case 0x6:
806 ret = form_dar_opm_ea<false, false, false, true>(i, "EOR");
807 break;
808
809 case 0x0: case 0x1: case 0x2: case 0x3: case 0x7:
810 ret = form_dar_opm_ea<true, false>(i, "CMP");
811 break;
812 }
813
814 // CMPM
815 if(((i >> 8) & 0x1) == 0x1 && ((i >> 3) & 0x7) == 0x1)
816 {
817 const unsigned szi = (i >> 6) & 0x3;
818
819 if(szi != 0x3)
820 {
821 assert(ret.size() == 0);
822 ret = form_destr_rm_srcr(i, "CMP", szi, "ADDR_REG_INDIR_POST");
823 }
824 }
825
826 return ret;
827 }
828
InstrC(const unsigned i)829 static std::string InstrC(const unsigned i)
830 {
831 std::string ret;
832
833 ret = form_dar_opm_ea<false, false, false>(i, "AND");
834
835 if(((i >> 4) & 0x1F) == 0x10) // ABCD
836 {
837 assert(ret.size() == 0);
838
839 ret = form_destr_rm_srcr(i, "ABCD", 0);
840 }
841
842 // MULU/MULS
843 if(((i >> 6) & 0x3) == 0x3)
844 {
845 std::string tmp;
846
847 if(decode_ea(AMA_DATA, 2, i, "src", &tmp))
848 {
849 assert(ret.size() == 0);
850
851 ret = s("%s; MUL%s(src, instr_b11_b9);", tmp.c_str(), ((i >> 8) & 1) ? "S" : "U");
852 }
853 }
854
855 {
856 const unsigned exgm = (i >> 3) & 0x3F;
857 switch(exgm)
858 {
859 case 0x28:
860 assert(ret.size() == 0);
861 ret = s("EXG(&D[instr_b11_b9], &D[instr_b2_b0]); /* EXG Dx, Dy */");
862 break;
863
864 case 0x29:
865 assert(ret.size() == 0);
866 ret = s("EXG(&A[instr_b11_b9], &A[instr_b2_b0]); /* EXG Ax, Ay */");
867 break;
868
869 case 0x31:
870 assert(ret.size() == 0);
871 ret = s("EXG(&D[instr_b11_b9], &A[instr_b2_b0]); /* EXG Dx, Ay */");
872 break;
873 }
874 }
875
876 return ret;
877 }
878
InstrD(const unsigned i)879 static std::string InstrD(const unsigned i)
880 {
881 return form_dar_opm_ea<true, true>(i, "ADD");
882 }
883
InstrE(const unsigned i)884 static std::string InstrE(const unsigned i)
885 {
886 std::string ret;
887
888 const unsigned szi = (i >> 6) & 0x3;
889 static const char* op_bases[4] = { "AS", "LS", "ROX", "RO" };
890 static const char* op_suffixes[2] = { "R", "L" };
891 const bool dr = (i >> 8) & 1; // Direction, 0=right, 1=left
892
893 if(szi == 0x3)
894 {
895 if(((i >> 11) & 1) == 0)
896 {
897 std::string tmp;
898
899 if(decode_ea(AMA_MEMORY | AMA_ALTERABLE, 2, i, "targ", &tmp))
900 {
901 const unsigned type = (i >> 9) & 0x3;
902
903 ret += s("%s; %s%s(targ, 1);", tmp.c_str(), op_bases[type], op_suffixes[dr]);
904 }
905 }
906 }
907 else
908 {
909 const unsigned type = (i >> 3) & 0x3;
910 const bool lr = (i >> 5) & 1;
911 std::string cnt;
912
913 if(lr)
914 cnt = s("D[instr_b11_b9]");
915 else
916 cnt = s("instr_b11_b9 ? instr_b11_b9 : 8");
917
918 ret += s("HAM<%s, DATA_REG_DIR> targ(this, instr_b2_b0); %s%s(targ, %s);", size_names[szi], op_bases[type], op_suffixes[dr], cnt.c_str());
919 }
920
921 return ret;
922 }
923
InstrA(const unsigned instr)924 static std::string InstrA(const unsigned instr)
925 {
926 return "LINEA();";
927 }
928
InstrF(const unsigned instr)929 static std::string InstrF(const unsigned instr)
930 {
931 return "LINEF();";
932 }
933
934
main()935 int main()
936 {
937 std::map<std::string, std::vector<unsigned>> bm;
938
939 for(unsigned i = 0; i < 65536; i++)
940 {
941 std::string body;
942
943 switch(i >> 12)
944 {
945 case 0x0: body += Instr0(i); break;
946 case 0x1: body += Instr1(i); break;
947 case 0x2:
948 case 0x3: body += Instr23(i); break;
949 case 0x4: body += Instr4(i); break;
950 case 0x5: body += Instr5(i); break;
951 case 0x6: body += Instr6(i); break;
952 case 0x7: body += Instr7(i); break;
953 case 0x8: body += Instr8(i); break;
954 case 0x9: body += Instr9(i); break;
955 case 0xA: body += InstrA(i); break;
956 case 0xB: body += InstrB(i); break;
957 case 0xC: body += InstrC(i); break;
958 case 0xD: body += InstrD(i); break;
959 case 0xE: body += InstrE(i); break;
960 case 0xF: body += InstrF(i); break;
961 }
962 if(body.size() > 0)
963 bm[body].push_back(i);
964 }
965
966 for(auto const& bme : bm)
967 {
968 for(auto const& ve : bme.second)
969 {
970 printf("case 0x%04x:\n", ve);
971 }
972
973 printf("\t{\n\t %s\n\t}\n\tbreak;\n\n", bme.first.c_str());
974 }
975 }
976