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