New simulator.
[external/binutils.git] / sim / m68hc11 / gencode.c
1 /* gencode.c -- Motorola 68hc11 Emulator Generator
2    Copyright 1999, 2000 Free Software Foundation, Inc.
3    Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
7 GDB, GAS, and the GNU binutils are free software; you can redistribute
8 them and/or modify them under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either version
10 2, or (at your option) any later version.
11
12 GDB, GAS, and the GNU binutils are distributed in the hope that they
13 will be useful, but WITHOUT ANY WARRANTY; without even the implied
14 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15 the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include <errno.h>
25
26 #include "ansidecl.h"
27 #include "opcode/m68hc11.h"
28
29 #define TABLE_SIZE(X)       (sizeof(X) / sizeof(X[0]))
30
31 /* Combination of CCR flags.  */
32 #define M6811_ZC_BIT    M6811_Z_BIT|M6811_C_BIT
33 #define M6811_NZ_BIT    M6811_N_BIT|M6811_Z_BIT
34 #define M6811_NZV_BIT   M6811_N_BIT|M6811_Z_BIT|M6811_V_BIT
35 #define M6811_NVC_BIT   M6811_N_BIT|M6811_V_BIT|M6811_C_BIT
36 #define M6811_ZVC_BIT   M6811_Z_BIT|M6811_V_BIT|M6811_C_BIT
37 #define M6811_NZVC_BIT  M6811_ZVC_BIT|M6811_N_BIT
38 #define M6811_HNZVC_BIT M6811_NZVC_BIT|M6811_H_BIT
39
40 /* Flags when the insn only changes some CCR flags.  */
41 #define CHG_NONE        0,0,0
42 #define CHG_Z           0,0,M6811_Z_BIT
43 #define CHG_C           0,0,M6811_C_BIT
44 #define CHG_ZVC         0,0,M6811_ZVC_BIT
45 #define CHG_NZV         0,0,M6811_NZV_BIT
46 #define CHG_NZVC        0,0,M6811_NZVC_BIT
47 #define CHG_HNZVC       0,0,M6811_HNZVC_BIT
48 #define CHG_ALL         0,0,0xff
49
50 /* The insn clears and changes some flags.  */
51 #define CLR_I           0,M6811_I_BIT,0
52 #define CLR_C           0,M6811_C_BIT,0
53 #define CLR_V           0,M6811_V_BIT,0
54 #define CLR_V_CHG_ZC    0,M6811_V_BIT,M6811_ZC_BIT
55 #define CLR_V_CHG_NZ    0,M6811_V_BIT,M6811_NZ_BIT
56 #define CLR_V_CHG_ZVC   0,M6811_V_BIT,M6811_ZVC_BIT
57 #define CLR_N_CHG_ZVC   0,M6811_N_BIT,M6811_ZVC_BIT /* Used by lsr */
58
59 /* The insn sets some flags.  */
60 #define SET_I           M6811_I_BIT,0,0
61 #define SET_C           M6811_C_BIT,0,0
62 #define SET_V           M6811_V_BIT,0,0
63 #define SET_Z_CLR_NVC   M6811_Z_BIT,M6811_NVC_BIT,0
64 #define SET_C_CLR_V_CHG_NZ M6811_C_BIT,M6811_V_BIT,M6811_NZ_BIT
65
66 #define _M 0xff
67
68
69 struct m6811_opcode_pattern 
70 {
71   const char *name;
72   const char *pattern;
73   const char *ccr_update;
74 };
75
76 /*
77  *  { "test", M6811_OP_NONE, 1, 0x00, 5, _M,  CHG_NONE },
78  * Name -+                                       +---- Insn CCR changes
79  * Format  ------+                         +---------- Max # cycles
80  * Size     -----------------+        +--------------- Min # cycles
81  *                               +-------------------- Opcode
82  */
83 struct m6811_opcode_pattern m6811_opcode_patterns[] = {
84   /* Move 8 and 16 bits.  We need two implementations: one that sets the
85      flags and one that preserve them.  */
86   { "movtst8",  "dst8 = src8",   "cpu_ccr_update_tst8 (proc, dst8)" },
87   { "movtst16", "dst16 = src16", "cpu_ccr_update_tst16 (proc, dst16)" },
88   { "mov8",     "dst8 = src8" },
89   { "mov16",    "dst16 = src16" },
90
91   /* Conditional branches.  'addr' is the address of the branch.  */
92   { "bra", "cpu_set_pc (proc, addr)" },
93   { "bhi",
94    "if ((cpu_get_ccr (proc) & (M6811_C_BIT|M6811_Z_BIT)) == 0)\n@ \
95      cpu_set_pc (proc, addr)" },
96   { "bls",
97     "if ((cpu_get_ccr (proc) & (M6811_C_BIT|M6811_Z_BIT)))\n@ \
98      cpu_set_pc (proc, addr)" },
99   { "bcc", "if (!cpu_get_ccr_C (proc))\n@ cpu_set_pc (proc, addr)" },
100   { "bcs", "if (cpu_get_ccr_C (proc))\n@ cpu_set_pc (proc, addr)" },
101   { "bne", "if (!cpu_get_ccr_Z (proc))\n@ cpu_set_pc (proc, addr)" },
102   { "beq", "if (cpu_get_ccr_Z (proc))\n@ cpu_set_pc (proc, addr)" },
103   { "bvc", "if (!cpu_get_ccr_V (proc))\n@ cpu_set_pc (proc, addr)" },
104   { "bvs", "if (cpu_get_ccr_V (proc))\n@ cpu_set_pc (proc, addr)" },
105   { "bpl", "if (!cpu_get_ccr_N (proc))\n@ cpu_set_pc (proc, addr)" },
106   { "bmi", "if (cpu_get_ccr_N (proc))\n@ cpu_set_pc (proc, addr)" },
107   { "bge", "if ((cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc)) == 0)\n@ cpu_set_pc (proc, addr)" },
108   { "blt", "if ((cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc)))\n@ cpu_set_pc (proc, addr)" },
109   { "bgt",
110     "if ((cpu_get_ccr_Z (proc) | (cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc))) == 0)\n@ \
111      cpu_set_pc (proc, addr)" },
112   { "ble",
113     "if ((cpu_get_ccr_Z (proc) | (cpu_get_ccr_N (proc) ^ cpu_get_ccr_V (proc))))\n@ \
114      cpu_set_pc (proc, addr)" },
115
116   /* brclr and brset perform a test and a conditional jump at the same
117      time.  Flags are not changed.  */
118   { "brclr8",
119     "if ((src8 & dst8) == 0)\n@  cpu_set_pc (proc, addr)" },
120   { "brset8",
121     "if (((~src8) & dst8) == 0)\n@  cpu_set_pc (proc, addr)" },
122   
123
124   { "rts",  "addr = cpu_pop_uint16 (proc); cpu_set_pc (proc, addr); cpu_return(proc)" },
125
126   { "mul16", "dst16 = ((uint16) src8 & 0x0FF) * ((uint16) dst8 & 0x0FF)",
127     "cpu_set_ccr_C (proc, src8 & 0x80)" },
128   { "neg8", "dst8 = - src8",
129     "cpu_set_ccr_C (proc, src8 == 0); cpu_ccr_update_tst8 (proc, dst8)" },
130   { "com8", "dst8 = ~src8",
131     "cpu_set_ccr_C (proc, 1); cpu_ccr_update_tst8 (proc, dst8);" },
132   { "clr8", "dst8 = 0",
133     "cpu_set_ccr (proc, (cpu_get_ccr (proc) & (M6811_S_BIT|M6811_X_BIT|M6811_H_BIT| \
134 M6811_I_BIT)) | M6811_Z_BIT)"},
135   { "clr16","dst16 = 0",
136     "cpu_set_ccr (proc, (cpu_get_ccr (proc) & (M6811_S_BIT|M6811_X_BIT|M6811_H_BIT| \
137 M6811_I_BIR)) | M6811_Z_BIT)"},
138
139   /* 8-bits shift and rotation.  */
140   { "lsr8",  "dst8 = src8 >> 1",
141     "cpu_set_ccr_C (proc, src8 & 1); cpu_ccr_update_shift8 (proc, dst8)" },
142   { "lsl8",  "dst8 = src8 << 1",
143     "cpu_set_ccr_C (proc, (src8 & 0x80) >> 7); cpu_ccr_update_shift8 (proc, dst8)" },
144   { "asr8",  "dst8 = (src8 >> 1) | (src8 & 0x80)",
145     "cpu_set_ccr_C (proc, src8 & 1); cpu_ccr_update_shift8 (proc, dst8)" },
146   { "ror8",  "dst8 = (src8 >> 1) | (cpu_get_ccr_C (proc) << 7)",
147     "cpu_set_ccr_C (proc, src8 & 1); cpu_ccr_update_shift8 (proc, dst8)" },
148   { "rol8",  "dst8 = (src8 << 1) | (cpu_get_ccr_C (proc))",
149     "cpu_set_ccr_C (proc, (src8 & 0x80) >> 7); cpu_ccr_update_shift8 (proc, dst8)" },
150
151   /* 16-bits shift instructions.  */
152   { "lsl16",  "dst16 = src16 << 1",
153     "cpu_set_ccr_C (proc, (src16&0x8000) >> 15); cpu_ccr_update_shift16 (proc, dst16)"},
154   { "lsr16",  "dst16 = src16 >> 1",
155     "cpu_set_ccr_C (proc, src16 & 1); cpu_ccr_update_shift16 (proc, dst16)"},
156
157   { "dec8", "dst8 = src8 - 1", "cpu_ccr_update_tst8 (proc, dst8)" },
158   { "inc8", "dst8 = src8 + 1", "cpu_ccr_update_tst8 (proc, dst8)" },
159   { "tst8", 0, "cpu_set_ccr_C (proc, 0); cpu_ccr_update_tst8 (proc, src8)" },
160
161   { "sub8", "cpu_ccr_update_sub8 (proc, dst8 - src8, dst8, src8);\
162 dst8 = dst8 - src8", 0 },
163   { "add8", "cpu_ccr_update_add8 (proc, dst8 + src8, dst8, src8);\
164 dst8 = dst8 + src8", 0 },
165   { "sbc8", "if (cpu_get_ccr_C (proc))\n@ \
166 {\n\
167   cpu_ccr_update_sub8 (proc, dst8 - src8 - 1, dst8, src8);\n\
168   dst8 = dst8 - src8 - 1;\n\
169 }\n\
170 else\n\
171 {\n\
172   cpu_ccr_update_sub8 (proc, dst8 - src8, dst8, src8);\n\
173   dst8 = dst8 - src8;\n\
174 }", 0 },
175   { "adc8", "if (cpu_get_ccr_C (proc))\n@ \
176 {\n\
177   cpu_ccr_update_add8 (proc, dst8 + src8 + 1, dst8, src8);\n\
178   dst8 = dst8 + src8 + 1;\n\
179 }\n\
180 else\n\
181 {\n\
182   cpu_ccr_update_add8 (proc, dst8 + src8, dst8, src8);\n\
183   dst8 = dst8 + src8;\n\
184 }",
185     0 },
186
187   /* 8-bits logical operations.  */
188   { "and8", "dst8 = dst8 & src8", "cpu_ccr_update_tst8 (proc, dst8)" },
189   { "eor8", "dst8 = dst8 ^ src8", "cpu_ccr_update_tst8 (proc, dst8)" },
190   { "or8",  "dst8 = dst8 | src8", "cpu_ccr_update_tst8 (proc, dst8)" },
191   { "bclr8","dst8 = (~dst8) & src8", "cpu_ccr_update_tst8 (proc, dst8)" },
192
193   /* 16-bits add and subtract instructions.  */
194   { "sub16", "cpu_ccr_update_sub16 (proc, dst16 - src16, dst16, src16);\
195 dst16 = dst16 - src16", 0 },
196   { "add16", "cpu_ccr_update_add16 (proc, dst16 + src16, dst16, src16);\
197 dst16 = dst16 + src16", 0 },
198   { "inc16", "dst16 = src16 + 1", "cpu_set_ccr_Z (proc, dst16 == 0)" },
199   { "dec16", "dst16 = src16 - 1", "cpu_set_ccr_Z (proc, dst16 == 0)" },
200
201   /* Special increment/decrement for the stack pointer:
202      flags are not changed.  */
203   { "ins16", "dst16 = src16 + 1" },
204   { "des16", "dst16 = src16 - 1" },
205   
206   { "jsr16", "cpu_push_uint16 (proc, cpu_get_pc (proc)); cpu_call (proc, addr)"},
207
208   /* xgdx and xgdx patterns. Flags are not changed.  */
209   { "xgdxy16", "dst16 = cpu_get_d (proc); cpu_set_d (proc, src16)"},
210   { "stop", ""},
211
212   /* tsx, tsy, txs, tys don't affect the flags.  Sp value is corrected
213      by +/- 1.  */
214   { "tsxy16", "dst16 = src16 + 1;"},
215   { "txys16", "dst16 = src16 - 1;"},
216
217   /* Add b to X or Y with an unsigned extension 8->16.  Flags not changed.  */
218   { "abxy16","dst16 = dst16 + (uint16) src8"},
219
220   /* After 'daa', the Z flag is undefined. Mark it as changed.  */
221   { "daa8",  "" },
222   { "nop",  0 },
223
224
225   /* Integer divide:
226      (parallel (set IX (div D IX))
227                (set D  (mod D IX)))  */
228   { "idiv16", "if (src16 == 0)\n{\n\
229 dst16 = 0xffff;\
230 }\nelse\n{\n\
231 cpu_set_d (proc, dst16 % src16);\
232 dst16 = dst16 / src16;\
233 }",
234   "cpu_set_ccr_Z (proc, dst16 == 0); cpu_set_ccr_V (proc, 0);\
235 cpu_set_ccr_C (proc, src16 == 0)" },
236
237   /* Fractional divide:
238      (parallel (set IX (div (mul D 65536) IX)
239                (set D  (mod (mul D 65536) IX))))  */
240   { "fdiv16", "if (src16 <= dst16 )\n{\n\
241 dst16 = 0xffff;\n\
242 cpu_set_ccr_Z (proc, 0);\n\
243 cpu_set_ccr_V (proc, 1);\n\
244 cpu_set_ccr_C (proc, dst16 == 0);\n\
245 }\nelse\n{\n\
246 unsigned long l = (unsigned long) (dst16) << 16;\n\
247 cpu_set_d (proc, (uint16) (l % (unsigned long) (src16)));\n\
248 dst16 = (uint16) (l / (unsigned long) (src16));\n\
249 cpu_set_ccr_V (proc, 0);\n\
250 cpu_set_ccr_C (proc, 0);\n\
251 cpu_set_ccr_Z (proc, dst16 == 0);\n\
252 }", 0 },
253
254   /* Operations to get/set the CCR.  */
255   { "clv",  0, "cpu_set_ccr_V (proc, 0)" },
256   { "sev",  0, "cpu_set_ccr_V (proc, 1)" },
257   { "clc",  0, "cpu_set_ccr_C (proc, 0)" },
258   { "sec",  0, "cpu_set_ccr_C (proc, 1)" },
259   { "cli",  0, "cpu_set_ccr_I (proc, 0)" },
260   { "sei",  0, "cpu_set_ccr_I (proc, 1)" },
261
262   /* Some special instructions are implemented by 'cpu_special'.  */
263   { "rti",  "cpu_special (proc, M6811_RTI)" },
264   { "wai",  "cpu_special (proc, M6811_WAI)" },
265   { "test", "cpu_special (proc, M6811_TEST)" },
266   { "swi",  "cpu_special (proc, M6811_SWI)" },
267   { "syscall","cpu_special (proc, M6811_EMUL_SYSCALL)" },
268
269   { "page2", "cpu_page2_interp (proc)", 0 },
270   { "page3", "cpu_page3_interp (proc)", 0 },
271   { "page4", "cpu_page4_interp (proc)", 0 }
272 };
273
274 /* Definition of an opcode of the 68HC11.  */
275 struct m6811_opcode_def
276 {
277   const char     *name;
278   const char     *operands;
279   const char     *insn_pattern;
280   unsigned char  insn_size;
281   unsigned char  insn_code;
282   unsigned char  insn_min_cycles;
283   unsigned char  insn_max_cycles;
284   unsigned char  set_flags_mask;
285   unsigned char  clr_flags_mask;
286   unsigned char  chg_flags_mask;
287 };
288
289
290 /*
291  *  { "dex", "x->x", "dec16", 1, 0x00, 5, _M,  CHG_NONE },
292  * Name -+                                       +----- Insn CCR changes
293  * Operands  ---+                         +------------ Max # cycles
294  * Pattern   -----------+              +--------------- Min # cycles
295  * Size      -----------------+   +-------------------- Opcode
296  *
297  * Operands   Fetch operand             Save result
298  * -------    --------------            ------------
299  * x->x       src16 = x                 x = dst16
300  * d->d       src16 = d                 d = dst16
301  * b,a->a     src8 = b dst8 = a         a = dst8
302  * sp->x      src16 = sp                x = dst16
303  * (sp)->a    src8 = pop8               a = dst8
304  * a->(sp)    src8 = a                  push8 dst8
305  * (x)->(x)   src8 = (IND, X)           (IND, X) = dst8
306  * (y)->a     src8 = (IND, Y)           a = dst8
307  * ()->b      src8 = (EXT)              b = dst8
308  */
309 const struct m6811_opcode_def m6811_page1_opcodes[] = {
310   { "test", 0,          0,           1, 0x00,  5, _M,  CHG_NONE },
311   { "nop",  0,          0,           1, 0x01,  2,  2,  CHG_NONE },
312   { "idiv", "x,d->x",   "idiv16",    1, 0x02,  3, 41,  CLR_V_CHG_ZC},
313   { "fdiv", "x,d->x",   "fdiv16",    1, 0x03,  3, 41,  CHG_ZVC},
314   { "lsrd", "d->d",     "lsr16",     1, 0x04,  3,  3,  CLR_N_CHG_ZVC },
315   { "asld", "d->d",     "lsl16",     1, 0x05,  3,  3,  CHG_NZVC },
316   { "lsld", "d->d",     "lsl16",     1, 0x05,  3,  3,  CHG_NZVC },
317   { "tap",  "a->ccr",   "mov8",      1, 0x06,  2,  2,  CHG_ALL},
318   { "tpa",  "ccr->a",   "mov8",      1, 0x07,  2,  2,  CHG_NONE },
319   { "inx",  "x->x",     "inc16",     1, 0x08,  3,  3,  CHG_Z },
320   { "dex",  "x->x",     "dec16",     1, 0x09,  3,  3,  CHG_Z },
321   { "clv",  0,          0,           1, 0x0a,  2,  2,  CLR_V },
322   { "sev",  0,          0,           1, 0x0b,  2,  2,  SET_V },
323   { "clc",  0,          0,           1, 0x0c,  2,  2,  CLR_C },
324   { "sec",  0,          0,           1, 0x0d,  2,  2,  SET_C },
325   { "cli",  0,          0,           1, 0x0e,  2,  2,  CLR_I },
326   { "sei",  0,          0,           1, 0x0f,  2,  2,  SET_I },
327   { "sba",  "b,a->a",   "sub8",      1, 0x10,  2,  2,  CHG_NZVC },
328   { "cba",  "b,a",      "sub8",      1, 0x11,  2,  2,  CHG_NZVC },
329   { "brset","*,#,r",    "brset8",    4, 0x12,  6,  6, CHG_NONE },
330   { "brclr","*,#,r",    "brclr8",    4, 0x13,  6,  6, CHG_NONE },
331   { "bset", "*,#->*",   "or8",       3, 0x14,  6,  6, CLR_V_CHG_NZ },
332   { "bclr", "*,#->*",   "bclr8",     3, 0x15,  6,  6, CLR_V_CHG_NZ },
333   { "tab",  "a->b",     "movtst8",   1, 0x16,  2,  2, CLR_V_CHG_NZ },
334   { "tba",  "b->a",     "movtst8",   1, 0x17,  2,  2, CLR_V_CHG_NZ },
335   { "page2", 0,         "page2",     1, 0x18,  0,  0, CHG_NONE },
336   { "page3", 0,         "page3",     1, 0x1a,  0,  0, CHG_NONE },
337
338   /* After 'daa', the Z flag is undefined.  Mark it as changed.  */
339   { "daa",  "a->a",     "daa8",      1, 0x19,  2,  2, CHG_NZVC },
340   { "aba",  "b,a->a",   "add8",      1, 0x1b,  2,  2, CHG_HNZVC},
341   { "bset", "(x),#->(x)","or8",      3, 0x1c,  7,  7, CLR_V_CHG_NZ },
342   { "bclr", "(x),#->(x)","bclr8",    3, 0x1d,  7,  7, CLR_V_CHG_NZ },
343   { "brset","(x),#,r",  "brset8",    4, 0x1e,  7,  7, CHG_NONE },
344   { "brclr","(x),#,r",  "brclr8",    4, 0x1f,  7,  7, CHG_NONE },
345
346   /* Relative branch.  All of them take 3 bytes.  Flags not changed.  */
347   { "bra",  "r",        0,           2, 0x20,  3,  3, CHG_NONE },
348   { "brn",  "r",        "nop",       2, 0x21,  3,  3, CHG_NONE },
349   { "bhi",  "r",        0,           2, 0x22,  3,  3, CHG_NONE },
350   { "bls",  "r",        0,           2, 0x23,  3,  3, CHG_NONE },
351   { "bcc",  "r",        0,           2, 0x24,  3,  3, CHG_NONE },
352   { "bhs",  "r",        0,           2, 0x24,  3,  3, CHG_NONE },
353   { "bcs",  "r",        0,           2, 0x25,  3,  3, CHG_NONE },
354   { "blo",  "r",        0,           2, 0x25,  3,  3, CHG_NONE },
355   { "bne",  "r",        0,           2, 0x26,  3,  3, CHG_NONE },
356   { "beq",  "r",        0,           2, 0x27,  3,  3, CHG_NONE },
357   { "bvc",  "r",        0,           2, 0x28,  3,  3, CHG_NONE },
358   { "bvs",  "r",        0,           2, 0x29,  3,  3, CHG_NONE },
359   { "bpl",  "r",        0,           2, 0x2a,  3,  3, CHG_NONE },
360   { "bmi",  "r",        0,           2, 0x2b,  3,  3, CHG_NONE },
361   { "bge",  "r",        0,           2, 0x2c,  3,  3, CHG_NONE },
362   { "blt",  "r",        0,           2, 0x2d,  3,  3, CHG_NONE },
363   { "bgt",  "r",        0,           2, 0x2e,  3,  3, CHG_NONE },
364   { "ble",  "r",        0,           2, 0x2f,  3,  3, CHG_NONE },
365
366   { "tsx",  "sp->x",    "tsxy16",    1, 0x30,  3,  3, CHG_NONE },
367   { "ins",  "sp->sp",   "ins16",     1, 0x31,  3,  3, CHG_NONE },
368   { "pula", "(sp)->a",  "mov8",      1, 0x32,  4,  4, CHG_NONE },
369   { "pulb", "(sp)->b",  "mov8",      1, 0x33,  4,  4, CHG_NONE },
370   { "des",  "sp->sp",   "des16",     1, 0x34,  3,  3, CHG_NONE },
371   { "txs",  "x->sp",    "txys16",    1, 0x35,  3,  3, CHG_NONE },
372   { "psha", "a->(sp)",  "mov8",      1, 0x36,  3,  3, CHG_NONE },
373   { "pshb", "b->(sp)",  "mov8",      1, 0x37,  3,  3, CHG_NONE },
374   { "pulx", "(sp)->x",  "mov16",     1, 0x38,  5,  5, CHG_NONE },
375   { "rts",  0,          0,           1, 0x39,  5,  5, CHG_NONE },
376   { "abx",  "b,x->x",   "abxy16",    1, 0x3a,  3,  3, CHG_NONE },
377   { "rti",  0,          0,           1, 0x3b, 12, 12, CHG_ALL},
378   { "pshx", "x->(sp)",  "mov16",     1, 0x3c,  4,  4, CHG_NONE },
379   { "mul",  "b,a->d",   "mul16",     1, 0x3d,  3, 10, CHG_C },
380   { "wai",  0,          0,           1, 0x3e, 14, _M, CHG_NONE },
381   { "swi",  0,          0,           1, 0x3f, 14, _M, CHG_NONE },
382   { "nega", "a->a",     "neg8",      1, 0x40,  2,  2, CHG_NZVC },
383   { "syscall", "",      "syscall",   1, 0x41,  2,  2, CHG_NONE },
384   { "coma", "a->a",     "com8",      1, 0x43,  2,  2, SET_C_CLR_V_CHG_NZ },
385   { "lsra", "a->a",     "lsr8",      1, 0x44,  2,  2, CLR_N_CHG_ZVC},
386   { "rora", "a->a",     "ror8",      1, 0x46,  2,  2, CHG_NZVC },
387   { "asra", "a->a",     "asr8",      1, 0x47,  2,  2, CHG_NZVC },
388   { "asla", "a->a",     "lsl8",      1, 0x48,  2,  2, CHG_NZVC },
389   { "lsla", "a->a",     "lsl8",      1, 0x48,  2,  2, CHG_NZVC },
390   { "rola", "a->a",     "rol8",      1, 0x49,  2,  2, CHG_NZVC },
391   { "deca", "a->a",     "dec8",      1, 0x4a,  2,  2, CHG_NZV },
392   { "inca", "a->a",     "inc8",      1, 0x4c,  2,  2, CHG_NZV },
393   { "tsta", "a",        "tst8",      1, 0x4d,  2,  2, CLR_V_CHG_NZ },
394   { "clra", "->a",      "clr8",      1, 0x4f,  2,  2, SET_Z_CLR_NVC },
395   { "negb", "b->b",     "neg8",      1, 0x50,  2,  2, CHG_NZVC },
396   { "comb", "b->b",     "com8",      1, 0x53,  2,  2, SET_C_CLR_V_CHG_NZ },
397   { "lsrb", "b->b",     "lsr8",      1, 0x54,  2,  2, CLR_N_CHG_ZVC },
398   { "rorb", "b->b",     "ror8",      1, 0x56,  2,  2, CHG_NZVC },
399   { "asrb", "b->b",     "asr8",      1, 0x57,  2,  2, CHG_NZVC },
400   { "aslb", "b->b",     "lsl8",      1, 0x58,  2,  2, CHG_NZVC },
401   { "lslb", "b->b",     "lsl8",      1, 0x58,  2,  2, CHG_NZVC },
402   { "rolb", "b->b",     "rol8",      1, 0x59,  2,  2, CHG_NZVC },
403   { "decb", "b->b",     "dec8",      1, 0x5a,  2,  2, CHG_NZV },
404   { "incb", "b->b",     "inc8",      1, 0x5c,  2,  2, CHG_NZV },
405   { "tstb", "b",        "tst8",      1, 0x5d,  2,  2, CLR_V_CHG_NZ },
406   { "clrb", "->b",      "clr8",      1, 0x5f,  2,  2, SET_Z_CLR_NVC },
407   { "neg",  "(x)->(x)", "neg8",      2, 0x60,  6,  6, CHG_NZVC },
408   { "com",  "(x)->(x)", "com8",      2, 0x63,  6,  6, SET_C_CLR_V_CHG_NZ },
409   { "lsr",  "(x)->(x)", "lsr8",      2, 0x64,  6,  6, CLR_N_CHG_ZVC },
410   { "ror",  "(x)->(x)", "ror8",      2, 0x66,  6,  6, CHG_NZVC },
411   { "asr",  "(x)->(x)", "asr8",      2, 0x67,  6,  6, CHG_NZVC },
412   { "asl",  "(x)->(x)", "lsl8",      2, 0x68,  6,  6, CHG_NZVC },
413   { "lsl",  "(x)->(x)", "lsl8",      2, 0x68,  6,  6, CHG_NZVC },
414   { "rol",  "(x)->(x)", "rol8",      2, 0x69,  6,  6, CHG_NZVC },
415   { "dec",  "(x)->(x)", "dec8",      2, 0x6a,  6,  6, CHG_NZV },
416   { "inc",  "(x)->(x)", "inc8",      2, 0x6c,  6,  6, CHG_NZV },
417   { "tst",  "(x)",      "tst8",      2, 0x6d,  6,  6, CLR_V_CHG_NZ },
418   { "jmp",  "&(x)",     "bra",       2, 0x6e,  3,  3, CHG_NONE },
419   { "clr",  "->(x)",    "clr8",      2, 0x6f,  6,  6, SET_Z_CLR_NVC },
420   { "neg",  "()->()",   "neg8",      3, 0x70,  6,  6, CHG_NZVC },
421   { "com",  "()->()",   "com8",      3, 0x73,  6,  6, SET_C_CLR_V_CHG_NZ },
422   { "lsr",  "()->()",   "lsr8",      3, 0x74,  6,  6, CLR_V_CHG_ZVC },
423   { "ror",  "()->()",   "ror8",      3, 0x76,  6,  6, CHG_NZVC },
424   { "asr",  "()->()",   "asr8",      3, 0x77,  6,  6, CHG_NZVC },
425   { "asl",  "()->()",   "lsl8",      3, 0x78,  6,  6, CHG_NZVC },
426   { "lsl",  "()->()",   "lsl8",      3, 0x78,  6,  6, CHG_NZVC },
427   { "rol",  "()->()",   "rol8",      3, 0x79,  6,  6, CHG_NZVC },
428   { "dec",  "()->()",   "dec8",      3, 0x7a,  6,  6, CHG_NZV },
429   { "inc",  "()->()",   "inc8",      3, 0x7c,  6,  6, CHG_NZV },
430   { "tst",  "()",       "tst8",      3, 0x7d,  6,  6, CLR_V_CHG_NZ },
431   { "jmp",  "&()",      "bra",       3, 0x7e,  3,  3, CHG_NONE },
432   { "clr",  "->()",     "clr8",      3, 0x7f,  6,  6, SET_Z_CLR_NVC },
433   { "suba", "#,a->a",   "sub8",      2, 0x80,  2,  2, CHG_NZVC },
434   { "cmpa", "#,a",      "sub8",      2, 0x81,  2,  2, CHG_NZVC },
435   { "sbca", "#,a->a",   "sbc8",      2, 0x82,  2,  2, CHG_NZVC },
436   { "subd", "#,d->d",   "sub16",     3, 0x83,  4,  4, CHG_NZVC },
437   { "anda", "#,a->a",   "and8",      2, 0x84,  2,  2, CLR_V_CHG_NZ },
438   { "bita", "#,a",      "and8",      2, 0x85,  2,  2, CLR_V_CHG_NZ },
439   { "ldaa", "#->a",     "movtst8",   2, 0x86,  2,  2, CLR_V_CHG_NZ },
440   { "eora", "#,a->a",   "eor8",      2, 0x88,  2,  2, CLR_V_CHG_NZ },
441   { "adca", "#,a->a",   "adc8",      2, 0x89,  2,  2, CHG_HNZVC },
442   { "oraa", "#,a->a",   "or8",       2, 0x8a,  2,  2, CLR_V_CHG_NZ },
443   { "adda", "#,a->a",   "add8",      2, 0x8b,  2,  2, CHG_HNZVC },
444   { "cmpx", "#,x",      "sub16",     3, 0x8c,  4,  4, CHG_NZVC },
445   { "cpx",  "#,x",      "sub16",     3, 0x8c,  4,  4, CHG_NZVC },
446   { "bsr",  "r",        "jsr16",     2, 0x8d,  6,  6, CHG_NONE },
447   { "lds",  "#->sp",    "movtst16",  3, 0x8e,  3,  3, CLR_V_CHG_NZ },
448   { "xgdx", "x->x",     "xgdxy16",   1, 0x8f,  3,  3, CHG_NONE },
449   { "suba", "*,a->a",   "sub8",      2, 0x90,  3,  3, CHG_NZVC },
450   { "cmpa", "*,a",      "sub8",      2, 0x91,  3,  3, CHG_NZVC },
451   { "sbca", "*,a->a",   "sbc8",      2, 0x92,  3,  3, CHG_NZVC },
452   { "subd", "*,d->d",   "sub16",     2, 0x93,  5,  5, CHG_NZVC },
453   { "anda", "*,a->a",   "and8",      2, 0x94,  3,  3, CLR_V_CHG_NZ },
454   { "bita", "*,a",      "and8",      2, 0x95,  3,  3, CLR_V_CHG_NZ },
455   { "ldaa", "*->a",     "movtst8",   2, 0x96,  3,  3, CLR_V_CHG_NZ },
456   { "staa", "a->*",     "movtst8",   2, 0x97,  3,  3, CLR_V_CHG_NZ },
457   { "eora", "*,a->a",   "eor8",      2, 0x98,  3,  3, CLR_V_CHG_NZ },
458   { "adca", "*,a->a",   "adc8",      2, 0x99,  3,  3, CHG_HNZVC },
459   { "oraa", "*,a->a",   "or8",       2, 0x9a,  3,  3, CLR_V_CHG_NZ },
460   { "adda", "*,a->a",   "add8",      2, 0x9b,  3,  3, CHG_HNZVC },
461   { "cmpx", "*,x",      "sub16",     2, 0x9c,  5,  5, CHG_NZVC },
462   { "cpx",  "*,x",      "sub16",     2, 0x9c,  5,  5, CHG_NZVC },
463   { "jsr",  "*",        "jsr16",     2, 0x9d,  5,  5, CHG_NONE },
464   { "lds",  "*->sp",    "movtst16",  2, 0x9e,  4,  4, CLR_V_CHG_NZ },
465   { "sts",  "sp->*",    "movtst16",  2, 0x9f,  4,  4, CLR_V_CHG_NZ },
466   { "suba", "(x),a->a", "sub8",      2, 0xa0,  4,  4, CHG_NZVC },
467   { "cmpa", "(x),a",    "sub8",      2, 0xa1,  4,  4, CHG_NZVC },
468   { "sbca", "(x),a->a", "sbc8",      2, 0xa2,  4,  4, CHG_NZVC },
469   { "subd", "(x),d->d", "sub16",     2, 0xa3,  6,  6, CHG_NZVC },
470   { "anda", "(x),a->a", "and8",      2, 0xa4,  4,  4, CLR_V_CHG_NZ },
471   { "bita", "(x),a",    "and8",      2, 0xa5,  4,  4, CLR_V_CHG_NZ },
472   { "ldaa", "(x)->a",   "movtst8",   2, 0xa6,  4,  4, CLR_V_CHG_NZ },
473   { "staa", "a->(x)",   "movtst8",   2, 0xa7,  4,  4, CLR_V_CHG_NZ },
474   { "eora", "(x),a->a", "eor8",      2, 0xa8,  4,  4, CLR_V_CHG_NZ },
475   { "adca", "(x),a->a", "adc8",      2, 0xa9,  4,  4, CHG_HNZVC },
476   { "oraa", "(x),a->a", "or8",       2, 0xaa,  4,  4, CLR_V_CHG_NZ },
477   { "adda", "(x),a->a", "add8",      2, 0xab,  4,  4, CHG_HNZVC },
478   { "cmpx", "(x),x",    "sub16",     2, 0xac,  6,  6, CHG_NZVC },
479   { "cpx",  "(x),x",    "sub16",     2, 0xac,  6,  6, CHG_NZVC },
480   { "jsr",  "&(x)",     "jsr16",     2, 0xad,  6,  6, CHG_NONE },
481   { "lds",  "(x)->sp",  "movtst16",  2, 0xae,  5,  5, CLR_V_CHG_NZ },
482   { "sts",  "sp->(x)",  "movtst16",  2, 0xaf,  5,  5, CLR_V_CHG_NZ },
483   { "suba", "(),a->a",  "sub8",      3, 0xb0,  4,  4, CHG_NZVC },
484   { "cmpa", "(),a",     "sub8",      3, 0xb1,  4,  4, CHG_NZVC },
485   { "sbca", "(),a->a",  "sbc8",      3, 0xb2,  4,  4, CHG_NZVC },
486   { "subd", "(),d->d",  "sub16",     3, 0xb3,  6,  6, CHG_NZVC },
487   { "anda", "(),a->a",  "and8",      3, 0xb4,  4,  4, CLR_V_CHG_NZ },
488   { "bita", "(),a",     "and8",      3, 0xb5,  4,  4, CLR_V_CHG_NZ },
489   { "ldaa", "()->a",    "movtst8",   3, 0xb6,  4,  4, CLR_V_CHG_NZ },
490   { "staa", "a->()",    "movtst8",   3, 0xb7,  4,  4, CLR_V_CHG_NZ },
491   { "eora", "(),a->a",  "eor8",      3, 0xb8,  4,  4, CLR_V_CHG_NZ },
492   { "adca", "(),a->a",  "adc8",      3, 0xb9,  4,  4, CHG_HNZVC },
493   { "oraa", "(),a->a",  "or8",       3, 0xba,  4,  4, CLR_V_CHG_NZ },
494   { "adda", "(),a->a",  "add8",      3, 0xbb,  4,  4, CHG_HNZVC },
495   { "cmpx", "(),x",     "sub16",     3, 0xbc,  5,  5, CHG_NZVC },
496   { "cpx",  "(),x",     "sub16",     3, 0xbc,  5,  5, CHG_NZVC },
497   { "jsr",  "&()",      "jsr16",     3, 0xbd,  6,  6, CHG_NONE },
498   { "lds",  "()->sp",   "movtst16",  3, 0xbe,  5,  5, CLR_V_CHG_NZ },
499   { "sts",  "sp->()",   "movtst16",  3, 0xbf,  5,  5, CLR_V_CHG_NZ },
500   { "subb", "#,b->b",   "sub8",      2, 0xc0,  2,  2, CHG_NZVC },
501   { "cmpb", "#,b",      "sub8",      2, 0xc1,  2,  2, CHG_NZVC },
502   { "sbcb", "#,b->b",   "sbc8",      2, 0xc2,  2,  2, CHG_NZVC },
503   { "addd", "#,d->d",   "add16",     3, 0xc3,  4,  4, CHG_NZVC },
504   { "andb", "#,b->b",   "and8",      2, 0xc4,  2,  2, CLR_V_CHG_NZ },
505   { "bitb", "#,b",      "and8",      2, 0xc5,  2,  2, CLR_V_CHG_NZ },
506   { "ldab", "#->b",     "movtst8",   2, 0xc6,  2,  2, CLR_V_CHG_NZ },
507   { "eorb", "#,b->b",   "eor8",      2, 0xc8,  2,  2, CLR_V_CHG_NZ },
508   { "adcb", "#,b->b",   "adc8",      2, 0xc9,  2,  2, CHG_HNZVC },
509   { "orab", "#,b->b",   "or8",       2, 0xca,  2,  2, CLR_V_CHG_NZ },
510   { "addb", "#,b->b",   "add8",      2, 0xcb,  2,  2, CHG_HNZVC },
511   { "ldd",  "#->d",     "movtst16",  3, 0xcc,  3,  3, CLR_V_CHG_NZ },
512   { "page4",0,          "page4",     1, 0xcd,  0,  0, CHG_NONE },
513   { "ldx",  "#->x",     "movtst16",  3, 0xce,  3,  3, CLR_V_CHG_NZ },
514   { "stop", 0,          0,           1, 0xcf,  2,  2, CHG_NONE },
515   { "subb", "*,b->b",   "sub8",      2, 0xd0,  3,  3, CHG_NZVC },
516   { "cmpb", "*,b",      "sub8",      2, 0xd1,  3,  3, CHG_NZVC },
517   { "sbcb", "*,b->b",   "sbc8",      2, 0xd2,  3,  3, CHG_NZVC },
518   { "addd", "*,d->d",   "add16",     2, 0xd3,  5,  5, CHG_NZVC },
519   { "andb", "*,b->b",   "and8",      2, 0xd4,  3,  3, CLR_V_CHG_NZ },
520   { "bitb", "*,b",      "and8",      2, 0xd5,  3,  3, CLR_V_CHG_NZ },
521   { "ldab", "*->b",     "movtst8",   2, 0xd6,  3,  3, CLR_V_CHG_NZ },
522   { "stab", "b->*",     "movtst8",   2, 0xd7,  3,  3, CLR_V_CHG_NZ },
523   { "eorb", "*,b->b",   "eor8",      2, 0xd8,  3,  3, CLR_V_CHG_NZ },
524   { "adcb", "*,b->b",   "adc8",      2, 0xd9,  3,  3, CHG_HNZVC },
525   { "orab", "*,b->b",   "or8",       2, 0xda,  3,  3, CLR_V_CHG_NZ },
526   { "addb", "*,b->b",   "add8",      2, 0xdb,  3,  3, CHG_HNZVC },
527   { "ldd",  "*->d",     "movtst16",  2, 0xdc,  4,  4, CLR_V_CHG_NZ },
528   { "std",  "d->*",     "movtst16",  2, 0xdd,  4,  4, CLR_V_CHG_NZ },
529   { "ldx",  "*->x",     "movtst16",  2, 0xde,  4,  4, CLR_V_CHG_NZ },
530   { "stx",  "x->*",     "movtst16",  2, 0xdf,  4,  4, CLR_V_CHG_NZ },
531   { "subb", "(x),b->b", "sub8",      2, 0xe0,  4,  4, CHG_NZVC },
532   { "cmpb", "(x),b",    "sub8",      2, 0xe1,  4,  4, CHG_NZVC },
533   { "sbcb", "(x),b->b", "sbc8",      2, 0xe2,  4,  4, CHG_NZVC },
534   { "addd", "(x),d->d", "add16",     2, 0xe3,  6,  6, CHG_NZVC },
535   { "andb", "(x),b->b", "and8",      2, 0xe4,  4,  4, CLR_V_CHG_NZ },
536   { "bitb", "(x),b",    "and8",      2, 0xe5,  4,  4, CLR_V_CHG_NZ },
537   { "ldab", "(x)->b",   "movtst8",   2, 0xe6,  4,  4, CLR_V_CHG_NZ },
538   { "stab", "b->(x)",   "movtst8",   2, 0xe7,  4,  4, CLR_V_CHG_NZ },
539   { "eorb", "(x),b->b", "eor8",      2, 0xe8,  4,  4, CLR_V_CHG_NZ },
540   { "adcb", "(x),b->b", "adc8",      2, 0xe9,  4,  4, CHG_HNZVC },
541   { "orab", "(x),b->b", "or8",       2, 0xea,  4,  4, CLR_V_CHG_NZ },
542   { "addb", "(x),b->b", "add8",      2, 0xeb,  4,  4, CHG_HNZVC },
543   { "ldd",  "(x)->d",   "movtst16",  2, 0xec,  5,  5, CLR_V_CHG_NZ },
544   { "std",  "d->(x)",   "movtst16",  2, 0xed,  5,  5, CLR_V_CHG_NZ },
545   { "ldx",  "(x)->x",   "movtst16",  2, 0xee,  5,  5, CLR_V_CHG_NZ },
546   { "stx",  "x->(x)",   "movtst16",  2, 0xef,  5,  5, CLR_V_CHG_NZ },
547   { "subb", "(),b->b",  "sub8",      3, 0xf0,  4,  4, CHG_NZVC },
548   { "cmpb", "(),b",     "sub8",      3, 0xf1,  4,  4, CHG_NZVC },
549   { "sbcb", "(),b->b",  "sbc8",      3, 0xf2,  4,  4, CHG_NZVC },
550   { "addd", "(),d->d",  "add16",     3, 0xf3,  6,  6, CHG_NZVC },
551   { "andb", "(),b->b",  "and8",      3, 0xf4,  4,  4, CLR_V_CHG_NZ },
552   { "bitb", "(),b",     "and8",      3, 0xf5,  4,  4, CLR_V_CHG_NZ },
553   { "ldab", "()->b",    "movtst8",   3, 0xf6,  4,  4, CLR_V_CHG_NZ },
554   { "stab", "b->()",    "movtst8",   3, 0xf7,  4,  4, CLR_V_CHG_NZ },
555   { "eorb", "(),b->b",  "eor8",      3, 0xf8,  4,  4, CLR_V_CHG_NZ },
556   { "adcb", "(),b->b",  "eor8",      3, 0xf9,  4,  4, CHG_HNZVC },
557   { "orab", "(),b->b",  "or8",       3, 0xfa,  4,  4, CLR_V_CHG_NZ },
558   { "addb", "(),b->b",  "add8",      3, 0xfb,  4,  4, CHG_HNZVC },
559   { "ldd",  "()->d",    "movtst16",  3, 0xfc,  5,  5, CLR_V_CHG_NZ },
560   { "std",  "d->()",    "movtst16",  3, 0xfd,  5,  5, CLR_V_CHG_NZ },
561   { "ldx",  "()->x",    "movtst16",  3, 0xfe,  5,  5, CLR_V_CHG_NZ },
562   { "stx",  "x->()",    "movtst16",  3, 0xff,  5,  5, CLR_V_CHG_NZ }
563 };
564
565
566 /* Page 2 opcodes */
567 /*
568  *  { "dex", "x->x", "dec16", 1, 0x00, 5, _M,  CHG_NONE },
569  * Name -+                                       +----- Insn CCR changes
570  * Operands  ---+                         +------------ Max # cycles
571  * Pattern   -----------+              +--------------- Min # cycles
572  * Size      -----------------+   +-------------------- Opcode
573  */
574 const struct m6811_opcode_def m6811_page2_opcodes[] = {
575   { "iny",  "y->y",     "inc16",     2, 0x08, 4, 4, CHG_Z },
576   { "dey",  "y->y",     "dec16",     2, 0x09, 4, 4, CHG_Z },
577   { "bset", "(y),#->(y)","or8",      4, 0x1c, 8, 8, CLR_V_CHG_NZ },
578   { "bclr", "(y),#->(y)","bclr8",    4, 0x1d, 8, 8, CLR_V_CHG_NZ },
579   { "brset","(y),#,r",   "brset8",   5, 0x1e, 8, 8, CHG_NONE },
580   { "brclr","(y),#,r",  "brclr8",    5, 0x1f, 8, 8, CHG_NONE },
581   { "tsy",  "sp->y",    "tsxy16",    2, 0x30, 4, 4, CHG_NONE },
582   { "tys",  "y->sp",    "txys16",    2, 0x35, 4, 4, CHG_NONE },
583   { "puly", "(sp)->y",  "mov16",     2, 0x38, 6, 6, CHG_NONE },
584   { "aby",  "b,y->y",   "abxy16",    2, 0x3a, 4, 4, CHG_NONE },
585   { "pshy", "y->(sp)",  "mov16",     2, 0x3c, 5, 5, CHG_NONE },
586   { "neg",  "(y)->(y)", "neg8",      3, 0x60, 7, 7, CHG_NZVC },
587   { "com",  "(y)->(y)", "com8",      3, 0x63, 7, 7, SET_C_CLR_V_CHG_NZ},
588   { "lsr",  "(y)->(y)", "lsr8",      3, 0x64, 7, 7, CLR_V_CHG_ZVC },
589   { "ror",  "(y)->(y)", "ror8",      3, 0x66, 7, 7, CHG_NZVC },
590   { "asr",  "(y)->(y)", "asr8",      3, 0x67, 7, 7, CHG_NZVC },
591   { "asl",  "(y)->(y)", "lsl8",      3, 0x68, 7, 7, CHG_NZVC },
592   { "lsl",  "(y)->(y)", "lsl8",      3, 0x68, 7, 7, CHG_NZVC },
593   { "rol",  "(y)->(y)", "rol8",      3, 0x69, 7, 7, CHG_NZVC },
594   { "dec",  "(y)->(y)", "dec8",      3, 0x6a, 7, 7, CHG_NZV },
595   { "inc",  "(y)->(y)", "inc8",      3, 0x6c, 7, 7, CHG_NZV },
596   { "tst",  "(y)",      "tst8",      3, 0x6d, 7, 7, CLR_V_CHG_NZ },
597   { "jmp",  "&(y)",     "bra",       3, 0x6e, 4, 4, CHG_NONE },
598   { "clr",  "->(y)",    "clr8",      3, 0x6f, 7, 7, SET_Z_CLR_NVC },
599   { "cmpy", "#,y",      "sub16",     4, 0x8c, 5, 5, CHG_NZVC },
600   { "cpy",  "#,y",      "sub16",     4, 0x8c, 5, 5, CHG_NZVC },
601   { "xgdy", "y->y",     "xgdxy16",   2, 0x8f, 4, 4, CHG_NONE },
602   { "cmpy", "*,y",      "sub16",     3, 0x9c, 6, 6, CHG_NZVC },
603   { "cpy",  "*,y",      "sub16",     3, 0x9c, 6, 6, CHG_NZVC },
604   { "suba", "(y),a->a", "sub8",      3, 0xa0, 5, 5, CHG_NZVC },
605   { "cmpa", "(y),a",    "sub8",      3, 0xa1, 5, 5, CHG_NZVC },
606   { "sbca", "(y),a->a", "sbc8",      3, 0xa2, 5, 5, CHG_NZVC },
607   { "subd", "(y),d->d", "sub16",     3, 0xa3, 7, 7, CHG_NZVC },
608   { "anda", "(y),a->a", "and8",      3, 0xa4, 5, 5, CLR_V_CHG_NZ },
609   { "bita", "(y),a",    "and8",      3, 0xa5, 5, 5, CLR_V_CHG_NZ },
610   { "ldaa", "(y)->a",   "movtst8",   3, 0xa6, 5, 5, CLR_V_CHG_NZ },
611   { "staa", "a->(y)",   "movtst8",   3, 0xa7, 5, 5, CLR_V_CHG_NZ },
612   { "eora", "(y),a->a", "eor8",      3, 0xa8, 5, 5, CLR_V_CHG_NZ },
613   { "adca", "(y),a->a", "adc8",      3, 0xa9, 5, 5, CHG_HNZVC },
614   { "oraa", "(y),a->a", "or8",       3, 0xaa, 5, 5, CLR_V_CHG_NZ },
615   { "adda", "(y),a->a", "add8",      3, 0xab, 5, 5, CHG_HNZVC },
616   { "cmpy", "(y),y",    "sub16",     3, 0xac, 7, 7, CHG_NZVC },
617   { "cpy",  "(y),y",    "sub16",     3, 0xac, 7, 7, CHG_NZVC },
618   { "jsr",  "&(y)",     "jsr16",     3, 0xad, 6, 6, CHG_NONE },
619   { "lds",  "(y)->sp",  "movtst16",  3, 0xae, 6, 6, CLR_V_CHG_NZ },
620   { "sts",  "sp->(y)",  "movtst16",  3, 0xaf, 6, 6, CLR_V_CHG_NZ },
621   { "cmpy", "(),y",     "sub16",     4, 0xbc, 7, 7, CHG_NZVC },
622   { "cpy",  "(),y",     "sub16",     4, 0xbc, 7, 7, CHG_NZVC },
623   { "ldy",  "#->y",     "movtst16",  4, 0xce, 4, 4, CLR_V_CHG_NZ },
624   { "ldy",  "*->y",     "movtst16",  3, 0xde, 5, 5, CLR_V_CHG_NZ },
625   { "sty",  "y->*",     "movtst16",  3, 0xdf, 5, 5, CLR_V_CHG_NZ },
626   { "subb", "(y),b->b", "sub8",      3, 0xe0, 5, 5, CHG_NZVC },
627   { "cmpb", "(y),b",    "sub8",      3, 0xe1, 5, 5, CHG_NZVC },
628   { "sbcb", "(y),b->b", "sbc8",      3, 0xe2, 5, 5, CHG_NZVC },
629   { "addd", "(y),d->d", "add16",     3, 0xe3, 7, 7, CHG_NZVC },
630   { "andb", "(y),b->b", "and8",      3, 0xe4, 5, 5, CLR_V_CHG_NZ },
631   { "bitb", "(y),b",    "and8",      3, 0xe5, 5, 5, CLR_V_CHG_NZ },
632   { "ldab", "(y)->b",   "movtst8",   3, 0xe6, 5, 5, CLR_V_CHG_NZ },
633   { "stab", "b->(y)",   "movtst8",   3, 0xe7, 5, 5, CLR_V_CHG_NZ },
634   { "eorb", "(y),b->b", "eor8",      3, 0xe8, 5, 5, CLR_V_CHG_NZ },
635   { "adcb", "(y),b->b", "adc8",      3, 0xe9, 5, 5, CHG_HNZVC },
636   { "orab", "(y),b->b", "or8",       3, 0xea, 5, 5, CLR_V_CHG_NZ },
637   { "addb", "(y),b->b", "add8",      3, 0xeb, 5, 5, CHG_HNZVC },
638   { "ldd",  "(y)->d",   "movtst16",  3, 0xec, 6, 6, CLR_V_CHG_NZ },
639   { "std",  "d->(y)",   "movtst16",  3, 0xed, 6, 6, CLR_V_CHG_NZ },
640   { "ldy",  "(y)->y",   "movtst16",  3, 0xee, 6, 6, CLR_V_CHG_NZ },
641   { "sty",  "y->(y)",   "movtst16",  3, 0xef, 6, 6, CLR_V_CHG_NZ },
642   { "ldy",  "()->y",    "movtst16",  4, 0xfe, 6, 6, CLR_V_CHG_NZ },
643   { "sty",  "y->()",    "movtst16",  4, 0xff, 6, 6, CLR_V_CHG_NZ }
644 };
645
646 /* Page 3 opcodes */
647 /*
648  *  { "dex", "x->x", "dec16", 1, 0x00, 5, _M,  CHG_NONE },
649  * Name -+                                       +----- Insn CCR changes
650  * Operands  ---+                         +------------ Max # cycles
651  * Pattern   -----------+              +--------------- Min # cycles
652  * Size      -----------------+   +-------------------- Opcode
653  */
654 const struct m6811_opcode_def m6811_page3_opcodes[] = {
655   { "cmpd", "#,d",      "sub16",     4, 0x83, 5, 5, CHG_NZVC },
656   { "cpd",  "#,d",      "sub16",     4, 0x83, 5, 5, CHG_NZVC },
657   { "cmpd", "*,d",      "sub16",     3, 0x93, 6, 6, CHG_NZVC },
658   { "cpd",  "*,d",      "sub16",     3, 0x93, 6, 6, CHG_NZVC },
659   { "cmpd", "(x),d",    "sub16",     3, 0xa3, 7, 7, CHG_NZVC },
660   { "cpd",  "(x),d",    "sub16",     3, 0xa3, 7, 7, CHG_NZVC },
661   { "cmpy", "(x),y",    "sub16",     3, 0xac, 7, 7, CHG_NZVC },
662   { "cpy",  "(x),y",    "sub16",     3, 0xac, 7, 7, CHG_NZVC },
663   { "cmpd", "(),d",     "sub16",     4, 0xb3, 7, 7, CHG_NZVC },
664   { "cpd",  "(),d",     "sub16",     4, 0xb3, 7, 7, CHG_NZVC },
665   { "ldy",  "(x)->y",   "movtst16",  3, 0xee, 6, 6, CLR_V_CHG_NZ },
666   { "sty",  "y->(x)",   "movtst16",  3, 0xef, 6, 6, CLR_V_CHG_NZ }
667 };
668
669 /* Page 4 opcodes */
670 /*
671  *  { "dex", "x->x", "dec16", 1, 0x00, 5, _M,  CHG_NONE },
672  * Name -+                                       +----- Insn CCR changes
673  * Operands  ---+                         +------------ Max # cycles
674  * Pattern   -----------+              +--------------- Min # cycles
675  * Size      -----------------+   +-------------------- Opcode
676  */
677 const struct m6811_opcode_def m6811_page4_opcodes[] = {
678   { "syscall", "",      "syscall",   2, 0x03, 6, 6, CHG_NONE },
679   { "cmpd", "(y),d",    "sub16",     3, 0xa3, 7, 7, CHG_NZVC },
680   { "cpd",  "(y),d",    "sub16",     3, 0xa3, 7, 7, CHG_NZVC },
681   { "cmpx", "(y),x",    "sub16",     3, 0xac, 7, 7, CHG_NZVC },
682   { "cpx",  "(y),x",    "sub16",     3, 0xac, 7, 7, CHG_NZVC },
683   { "ldx",  "(y)->x",   "movtst16",  3, 0xee, 6, 6, CLR_V_CHG_NZ },
684   { "stx",  "x->(y)",   "movtst16",  3, 0xef, 6, 6, CLR_V_CHG_NZ }
685 };
686
687 void fatal_error (const struct m6811_opcode_def*, const char*);
688 void print (FILE*, int, const char*,...);
689 int gen_fetch_operands (FILE*, int, const struct m6811_opcode_def*,
690                         const char*);
691 void gen_save_result (FILE*, int, const struct m6811_opcode_def*,
692                       int, const char*);
693 const struct m6811_opcode_pattern*
694 find_opcode_pattern (const struct m6811_opcode_def*);
695 void gen_interp (FILE*, int, const struct m6811_opcode_def*);
696 void gen_interpreter_for_table (FILE*, int,
697                                 const struct m6811_opcode_def*,
698                                 int, const char*);
699 void gen_interpreter (FILE*);
700
701
702 static int indent_level = 2;
703 static int current_insn_size = 0;
704
705 /* Fatal error message and exit.  This method is called when an inconsistency
706    is detected in the generation table.  */
707 void
708 fatal_error (const struct m6811_opcode_def *opcode, const char *msg)
709 {
710   fprintf (stderr, "Fatal error: %s\n", msg);
711   if (opcode)
712     {
713       fprintf (stderr, "Opcode: 0x%02x %s %s\n",
714                opcode->insn_code, opcode->name, opcode->operands);
715     }
716   exit (1);
717 }
718
719
720 /* Format and pretty print for the code generation.  (printf like format).  */
721 void
722 print (FILE *fp, int col, const char *msg, ...)
723 {
724   va_list argp;
725   char buf[1024];
726   int cur_col = -1;
727   int i;
728
729   /* Format in a buffer.  */
730   va_start (argp, msg);
731   vsprintf (buf, msg, argp);
732   va_end (argp);
733
734   /* Basic pretty print:
735      - Every line is indented at column 'col',
736      - Indentation is updated when '{' and '}' are found,
737      - Indentation is incremented by the special character '@' (not displayed).
738      - New lines inserted automatically after ';'  */
739   for (i = 0; buf[i]; i++)
740     {
741       if (buf[i] == '{')
742         col += indent_level;
743       else if (buf[i] == '}')
744         col -= indent_level;
745       else if (buf[i] == '@')
746         {
747           col += indent_level;
748           continue;
749         }
750       if (cur_col == -1 && buf[i] != ' ' && buf[i] != '\t' && buf[i] != '\n')
751         {
752           cur_col = 0;
753           while (cur_col < col)
754             {
755               fputc (' ', fp);
756               cur_col++;
757             }
758         }
759       if (buf[i] == '}')
760         col -= indent_level;
761       else if (buf[i] == '{')
762         col += indent_level;
763       else if (buf[i] == '\n')
764         cur_col = -1;
765
766       if (cur_col != -1 || buf[i] == '\n')
767         fputc (buf[i], fp);
768
769       if (buf[i] == ';')
770         {
771           fputc ('\n', fp);
772           cur_col = -1;
773         }
774     }
775 }
776
777
778 /* Generate the code to obtain the operands before execution of the
779    instruction.  Operands are copied in local variables.  This allows to
780    have the same instruction pattern and different operand formats.
781    There is a maximum of 3 variables:
782  
783                        8-bits          16-bits
784    1st operand:         src8            src16
785    2nd operand:         dst8            dst16
786    alt operand:         addr            addr
787   
788    The operand string is interpreted as follows:
789  
790    a    Copy A register in the local 8-bits variable.
791    b    "    B "
792    ccr  "    ccr "
793    d    "    D "        "      "    16-bits variable.
794    x    "    X "
795    y    "    Y "
796    sp   "    SP "
797    *    68HC11 page0 memory pointer.
798         Get 8-bits page0 offset from program, set up 'addr' local
799         variable to refer to the location in page0.
800         Copy the 8/16-bits value pointed to by 'addr' in a 8/16-bits variable.
801    (x)  68HC11 indirect access with X register.
802         Get 8-bits unsigned offset from program, set up 'addr' = X + offset.
803         Copy the 8/16-bits value pointed to by 'addr' in a 8/16-bits variable.
804    (y)  Same as (x) with Y register.
805    ()   68HC11 extended address mode (global variable).
806         Get 16-bits address from program and set 'addr'.
807         Copy the 8/16-bits value pointed to by 'addr' in a 8/16-bits variable.
808    (sp) Pop
809         Pop a 8/16-bits value from stack and set in a 8/16-bits variable.
810    r    Relative branch
811         Get 8-bits relative branch, compute absolute address and set 'addr'
812    #    68HC11 immediate value
813         Get a 8/16-bits value from program and set a 8/16-bits variable.
814    &(x)
815    &(y)
816    &()  Similar to (x), (y) and () except that we don't read the
817         value pointed to by 'addr' (ie, only 'addr' is setup). Used by jmp/jsr.
818    ,    Operand separator.
819    -    End of input operands.
820   
821    Example:
822        (x),a->a       addr = x + (uint16) (fetch8 (proc));
823                       src8 = a
824        *,#,r          addr = (uint16) (fetch8 (proc))  <- Temporary 'addr'
825                       src8 = read_mem8 (proc, addr)
826                       dst8 = fetch8 (proc)
827                       addr = fetch_relbranch (proc)    <- Final 'addr'
828   
829    Returns 1 if the 'addr' operand is set, 0 otherwise.  */
830 int
831 gen_fetch_operands (FILE *fp, int col,
832                     const struct m6811_opcode_def *opcode,
833                     const char *operand_size)
834 {
835   static char *vars[2] = {
836     "src",
837     "dst"
838   };
839   char c;
840   int addr_set = 0;
841   int cur_var = 0;
842   const char *operands = opcode->operands;
843   
844   if (operands == 0)
845     operands = "";
846
847   while ((c = *operands++) != 0)
848     {
849       switch (c)
850         {
851         case 'a':
852           if (cur_var >= 2)
853             fatal_error (opcode, "Too many locals");
854           
855           print (fp, col, "%s8 = cpu_get_a (proc);", vars[cur_var]);
856           break;
857
858         case 'b':
859           if (cur_var >= 2)
860             fatal_error (opcode, "Too many locals");
861
862           print (fp, col, "%s8 = cpu_get_b (proc);", vars[cur_var]);
863           break;
864
865         case 'd':
866           if (cur_var >= 2)
867             fatal_error (opcode, "Too many locals");
868
869           print (fp, col, "%s16 = cpu_get_d (proc);", vars[cur_var]);
870           break;
871
872         case 'x':
873           if (cur_var >= 2)
874             fatal_error (opcode, "Too many locals");
875
876           print (fp, col, "%s16 = cpu_get_x (proc);", vars[cur_var]);
877           break;
878
879         case 'y':
880           if (cur_var >= 2)
881             fatal_error (opcode, "Too many locals");
882
883           print (fp, col, "%s16 = cpu_get_y (proc);", vars[cur_var]);
884           break;
885
886         case '*':
887           if (cur_var >= 2)
888             fatal_error (opcode, "Too many locals");
889
890           if (addr_set)
891             fatal_error (opcode, "Wrong use of '*', 'addr' already used");
892           
893           addr_set = 1;
894           current_insn_size += 1;
895           print (fp, col, "addr = (uint16) cpu_fetch8 (proc);");
896           print (fp, col, "%s%s = memory_read%s (proc, addr);",
897                  vars[cur_var], operand_size, operand_size);
898           break;
899
900         case '&':
901           if (addr_set)
902             fatal_error (opcode, "Wrong use of '&', 'addr' already used");
903           
904           addr_set = 1;
905           if (strncmp (operands, "(x)", 3) == 0)
906             {
907               current_insn_size += 1;
908               print (fp, col, "addr = cpu_get_x (proc) + (uint16) cpu_fetch8 (proc);");
909               operands += 3;
910             }
911           else if (strncmp (operands, "(y)", 3) == 0)
912             {
913               current_insn_size += 1;
914               print (fp, col, "addr = cpu_get_y (proc) + (uint16) cpu_fetch8 (proc);");
915               operands += 3;
916             }
917           else if (strncmp (operands, "()", 2) == 0)
918             {
919               current_insn_size += 2;
920               print (fp, col, "addr = cpu_fetch16 (proc);");
921               operands += 2;
922             }
923           else
924             {
925               fatal_error (opcode, "Unknown operand");
926             }
927           break;
928           
929         case '(':
930           if (cur_var >= 2)
931             fatal_error (opcode, "Too many locals");
932           
933           if (addr_set)
934             fatal_error (opcode, "Wrong use of '(', 'addr' already used");
935           
936           if (strncmp (operands, "x)", 2) == 0)
937             {
938               addr_set = 1;
939               current_insn_size += 1;
940               print (fp, col, "addr = cpu_get_x (proc) + (uint16) cpu_fetch8 (proc);");
941               print (fp, col, "%s%s = memory_read%s (proc, addr);",
942                      vars[cur_var], operand_size, operand_size);
943               operands += 2;
944             }
945           else if (strncmp (operands, "y)", 2) == 0)
946             {
947               addr_set = 1;
948               current_insn_size += 1;
949               print (fp, col, "addr = cpu_get_y (proc) + (uint16) cpu_fetch8 (proc);");
950               print (fp, col, "%s%s = memory_read%s (proc, addr);",
951                      vars[cur_var], operand_size, operand_size);
952               operands += 2;
953             }
954           else if (strncmp (operands, ")", 1) == 0)
955             {
956               addr_set = 1;
957               current_insn_size += 2;
958               print (fp, col, "addr = cpu_fetch16 (proc);");
959               print (fp, col, "%s%s = memory_read%s (proc, addr);",
960                      vars[cur_var], operand_size, operand_size);
961               operands++;
962             }
963           else if (strncmp (operands, "sp)", 3) == 0)
964             {
965               print (fp, col, "%s%s = cpu_pop_uint%s (proc);",
966                      vars[cur_var], operand_size, operand_size);
967               operands += 3;
968             }
969           else
970             {
971               fatal_error (opcode, "Unknown operand");
972             }
973           break;
974
975         case 's':
976           if (cur_var >= 2)
977             fatal_error (opcode, "Too many locals");
978           
979           if (strncmp (operands, "p", 1) == 0)
980             {
981               print (fp, col, "%s16 = cpu_get_sp (proc);", vars[cur_var]);
982               operands++;
983             }
984           else
985             {
986               fatal_error (opcode, "Unknown operands");
987             }
988           break;
989
990         case 'c':
991           if (strncmp (operands, "cr", 2) == 0)
992             {
993               print (fp, col, "%s8 = cpu_get_ccr (proc);", vars[cur_var]);
994               operands += 2;
995             }
996           else
997             {
998               fatal_error (opcode, "Unknown operands");
999             }
1000           break;
1001           
1002         case 'r':
1003           if (addr_set && cur_var != 2)
1004             fatal_error (opcode, "Wrong use of 'r'");
1005
1006           addr_set = 1;
1007           current_insn_size += 1;
1008           print (fp, col, "addr = cpu_fetch_relbranch (proc);");
1009           break;
1010
1011         case '#':
1012           if (strcmp (operand_size, "8") == 0)
1013             {
1014               current_insn_size += 1;
1015             }
1016           else
1017             {
1018               current_insn_size += 2;
1019             }
1020           print (fp, col, "%s%s = cpu_fetch%s (proc);", vars[cur_var],
1021                  operand_size, operand_size);
1022           break;
1023           
1024         case ',':
1025           cur_var ++;
1026           break;
1027
1028         case '-':
1029           return addr_set;
1030
1031         default:
1032           fatal_error (opcode, "Invalid operands");
1033           break;
1034         }
1035     }
1036   return addr_set;
1037 }
1038
1039
1040 /* Generate the code to save the instruction result.  The result is in
1041    a local variable: either 'dst8' or 'dst16'.
1042    There may be only one result.  Instructions with 2 results (ie idiv
1043    and fdiv), take care of saving the first value.
1044   
1045    The operand string is the same as for 'gen_fetch_operands'.
1046    Everything before '->' is ignored.  If the '->' is not found, it
1047    is assumed that there is nothing to save.  After '->', the operand
1048    string is interpreted as follows:
1049   
1050    a    Save 'dst8' in A register
1051    b    "              B "
1052    ccr  "              CCR "
1053    d    "    'dst16'   D "
1054    x    "              X "
1055    y    "              Y "
1056    sp   "              SP "
1057    *    68HC11 page0 memory pointer.
1058    (x)  68HC11 indirect access with X register.
1059    (y)  Same as (x) with Y register.
1060    ()   68HC11 extended address mode (global variable).
1061         For these modes, if they were used as an input operand,
1062         the 'addr' variable contains the address of memory where
1063         the result must be saved.
1064         If they were not used an input operand, 'addr' is computed
1065         (as in gen_fetch_operands()), and the result is saved.
1066    (sp) Push
1067         Push the 8/16-bits result on the stack.  */
1068 void
1069 gen_save_result (FILE *fp, int col,
1070                  const struct m6811_opcode_def *opcode,
1071                  int addr_set,
1072                  const char *operand_size)
1073 {
1074   char c;
1075   const char *operands = opcode->operands;
1076
1077   /* When the result is saved, 'result_size' is a string which
1078      indicates the size of the saved result ("8" or "16").  This
1079      is a sanity check with 'operand_size' to detect inconsistencies
1080      in the different tables.  */
1081   const char *result_size = 0;
1082   
1083   if (operands == 0)
1084     operands = "";
1085
1086   operands = strchr (operands, '-');
1087   if (operands == 0)
1088     return;
1089
1090   operands++;
1091   if (*operands++ != '>')
1092     {
1093       fatal_error (opcode, "Invalid operand");
1094     }
1095
1096   c = *operands++;
1097   switch (c)
1098     {
1099     case 'a':
1100       result_size = "8";
1101       print (fp, col, "cpu_set_a (proc, dst8);");
1102       break;
1103
1104     case 'b':
1105       result_size = "8";
1106       print (fp, col, "cpu_set_b (proc, dst8);");
1107       break;
1108
1109     case 'd':
1110       result_size = "16";
1111       print (fp, col, "cpu_set_d (proc, dst16);");
1112       break;
1113
1114     case 'x':
1115       result_size = "16";
1116       print (fp, col, "cpu_set_x (proc, dst16);");
1117       break;
1118
1119     case 'y':
1120       result_size = "16";
1121       print (fp, col, "cpu_set_y (proc, dst16);");
1122       break;
1123
1124     case '*':
1125       if (addr_set == 0)
1126         {
1127           current_insn_size += 1;
1128           print (fp, col, "addr = (uint16) cpu_fetch8 (proc);");
1129         }
1130       result_size = operand_size;
1131       print (fp, col, "memory_write%s (proc, addr, dst%s);",
1132              operand_size, operand_size);
1133       break;
1134
1135     case '(':
1136       if (strncmp (operands, "x)", 2) == 0)
1137         {
1138           if (addr_set == 0)
1139             {
1140               current_insn_size += 1;
1141               print (fp, col, "addr = cpu_get_x (proc) + cpu_fetch8 (proc);");
1142             }
1143           print (fp, col, "memory_write%s (proc, addr, dst%s);",
1144                  operand_size, operand_size);
1145           operands += 2;
1146           result_size = operand_size;
1147         }
1148       else if (strncmp (operands, "y)", 2) == 0)
1149         {
1150           if (addr_set == 0)
1151             {
1152               current_insn_size += 1;
1153               print (fp, col, "addr = cpu_get_y (proc) + cpu_fetch8 (proc);");
1154             }
1155           print (fp, col, "memory_write%s (proc, addr, dst%s);",
1156                  operand_size, operand_size);
1157           operands += 2;
1158           result_size = operand_size;
1159         }
1160       else if (strncmp (operands, ")", 1) == 0)
1161         {
1162           if (addr_set == 0)
1163             {
1164               current_insn_size += 2;
1165               print (fp, col, "addr = cpu_fetch16 (proc);");
1166             }
1167           print (fp, col, "memory_write%s (proc, addr, dst%s);",
1168                  operand_size, operand_size);
1169           operands++;
1170           result_size = operand_size;
1171         }
1172       else if (strncmp (operands, "sp)", 3) == 0)
1173         {
1174           print (fp, col, "cpu_push_uint%s (proc, dst%s);",
1175                  operand_size, operand_size);
1176           operands += 3;
1177           result_size = operand_size;
1178         }
1179       else
1180         {
1181           fatal_error (opcode, "Invalid operand");
1182         }
1183       break;
1184
1185     case 's':
1186       if (strncmp (operands, "p", 1) == 0)
1187         {
1188           print (fp, col, "cpu_set_sp (proc, dst16);");
1189           operands++;
1190           result_size = "16";
1191         }
1192       else
1193         {
1194           fatal_error (opcode, "Invalid operand");
1195         }
1196       break;
1197
1198     case 'c':
1199       if (strncmp (operands, "cr", 2) == 0)
1200         {
1201           print (fp, col, "cpu_set_ccr (proc, dst8);");
1202           operands += 2;
1203           result_size = "8";
1204         }
1205       else
1206         {
1207           fatal_error (opcode, "Invalid operand");
1208         }
1209       break;
1210           
1211     default:
1212       fatal_error (opcode, "Invalid operand");
1213       break;
1214     }
1215
1216   if (*operands != 0)
1217     fatal_error (opcode, "Garbage at end of operand");
1218   
1219   if (result_size == 0)
1220     fatal_error (opcode, "? No result seems to be saved");
1221
1222   if (strcmp (result_size, operand_size) != 0)
1223     fatal_error (opcode, "Result saved different than pattern size");
1224 }
1225
1226
1227 /* Find the instruction pattern for a given instruction.  */
1228 const struct m6811_opcode_pattern*
1229 find_opcode_pattern (const struct m6811_opcode_def *opcode)
1230 {
1231   int i;
1232   const char *pattern = opcode->insn_pattern;
1233   
1234   if (pattern == 0)
1235     {
1236       pattern = opcode->name;
1237     }
1238   for (i = 0; i < TABLE_SIZE(m6811_opcode_patterns); i++)
1239     {
1240       if (strcmp (m6811_opcode_patterns[i].name, pattern) == 0)
1241         {
1242           return &m6811_opcode_patterns[i];
1243         }
1244     }
1245   fatal_error (opcode, "Unknown instruction pattern");
1246   return 0;
1247 }
1248
1249
1250 /* Generate the code for interpretation of instruction 'opcode'.  */
1251 void
1252 gen_interp (FILE *fp, int col, const struct m6811_opcode_def *opcode)
1253 {
1254   const char *operands = opcode->operands;
1255   int addr_set;
1256   const char *pattern = opcode->insn_pattern;
1257   const struct m6811_opcode_pattern *op;
1258   const char *operand_size;
1259   
1260   if (pattern == 0)
1261     {
1262       pattern = opcode->name;
1263     }
1264
1265   /* Find out the size of the operands: 8 or 16-bits.  */
1266   if (strcmp(&pattern[strlen(pattern) - 1], "8") == 0)
1267     {
1268       operand_size = "8";
1269     }
1270   else if (strcmp (&pattern[strlen(pattern) - 2], "16") == 0)
1271     {
1272       operand_size = "16";
1273     }
1274   else
1275     {
1276       operand_size = "";
1277     }
1278   
1279   if (operands == 0)
1280     operands = "";
1281
1282   /* Generate entry point for the instruction.  */
1283   print (fp, col, "case 0x%02x: /* %s %s */\n", opcode->insn_code,
1284          opcode->name, operands);
1285   col += indent_level;
1286
1287   /* Generate the code to get the instruction operands.  */
1288   addr_set = gen_fetch_operands (fp, col, opcode, operand_size);
1289
1290   /* Generate instruction interpretation.  */
1291   op = find_opcode_pattern (opcode);
1292   if (op->pattern)
1293     {
1294       print (fp, col, "%s;", op->pattern);
1295     }
1296
1297   /* Generate the code to save the result.  */
1298   gen_save_result (fp, col, opcode, addr_set, operand_size);
1299
1300   /* For some instructions, generate the code to update the flags.  */
1301   if (op && op->ccr_update)
1302     {
1303       print (fp, col, "%s;", op->ccr_update);
1304     }
1305   print (fp, col, "break;");
1306 }
1307
1308
1309 /* Generate the interpretor for a given 68HC11 page set.  */
1310 void
1311 gen_interpreter_for_table (FILE *fp, int col,
1312                            const struct m6811_opcode_def *table,
1313                            int size,
1314                            const char *cycles_table_name)
1315 {
1316   int i;
1317   int init_size;
1318
1319   init_size = table == m6811_page1_opcodes ? 1 : 2;
1320   
1321   /* Get the opcode and dispatch directly.  */
1322   print (fp, col, "op = cpu_fetch8 (proc);");
1323   print (fp, col, "cpu_add_cycles (proc, %s[op]);", cycles_table_name);
1324   
1325   print (fp, col, "switch (op)\n");
1326   col += indent_level;
1327   print (fp, col, "{\n");
1328   
1329   for (i = 0; i < size; i++)
1330     {
1331       /* The table contains duplicate entries (ie, instruction aliases).  */
1332       if (i > 0 && table[i].insn_code == table[i - 1].insn_code)
1333         continue;
1334
1335       current_insn_size = init_size;
1336       gen_interp (fp, col, &table[i]);
1337       if (current_insn_size != table[i].insn_size)
1338         {
1339           fatal_error (&table[i], "Insn size inconsistency");
1340         }
1341     }
1342
1343   print (fp, col, "default:\n");
1344   print (fp, col + indent_level, "cpu_special (proc, M6811_ILLEGAL);");
1345   print (fp, col + indent_level, "break;");
1346   print (fp, col, "}\n");
1347 }
1348
1349 /* Generate the table of instruction cycle.  These tables are indexed
1350    by the opcode number to allow a fast cycle time computation.  */
1351 void
1352 gen_cycle_table (FILE *fp, const char *name,
1353                  const struct m6811_opcode_def *table,
1354                  int size)
1355 {
1356   int i;
1357   char cycles[256];
1358   int page1;
1359
1360   page1 = table == m6811_page1_opcodes;
1361
1362   /* Build the cycles table.  The table is indexed by the opcode.  */
1363   memset (cycles, 0, sizeof (cycles));
1364   while (--size >= 0)
1365     {
1366       if (table->insn_min_cycles > table->insn_max_cycles)
1367         fatal_error (table, "Wrong insn cycles");
1368
1369       if (table->insn_max_cycles == _M)
1370         cycles[table->insn_code] = table->insn_min_cycles;
1371       else
1372         cycles[table->insn_code] = table->insn_max_cycles;
1373
1374       table++;
1375     }
1376
1377   /* Some check: for the page1 opcode, the cycle type of the page2/3/4
1378      opcode must be 0.  */
1379   if (page1 && (cycles[M6811_OPCODE_PAGE2] != 0
1380                 || cycles[M6811_OPCODE_PAGE3] != 0
1381                 || cycles[M6811_OPCODE_PAGE4] != 0))
1382       fatal_error (0, "Invalid cycle table");
1383
1384   /* Generates the cycles table.  */
1385   print (fp, 0, "static const unsigned char %s[256] = {\n", name);
1386   for (i = 0; i < 256; i++)
1387     {
1388       if ((i % 16) == 0)
1389         {
1390           print (fp, indent_level, "/* %3d */ ", i);
1391         }
1392       fprintf (fp, "%2d", cycles[i]);
1393       if (i != 255)
1394         fprintf (fp, ",");
1395
1396       if ((i % 16) != 15)
1397         fprintf (fp, " ");
1398       else
1399         fprintf (fp, "\n");
1400     }
1401   print (fp, 0, "};\n\n");
1402 }
1403
1404 void
1405 gen_function_entry (FILE *fp, const char *name)
1406 {
1407   /* Generate interpretor entry point.  */
1408   print (fp, 0, "%s (proc)\n", name);
1409   print (fp, indent_level, "struct _sim_cpu* proc;");
1410   print (fp, indent_level, "{\n");
1411
1412   /* Interpretor local variables.  */
1413   print (fp, indent_level, "unsigned char op;");
1414   print (fp, indent_level, "uint16 addr, src16, dst16;");
1415   print (fp, indent_level, "uint8 src8, dst8;\n");
1416 }
1417
1418 void
1419 gen_function_close (FILE *fp)
1420 {
1421   print (fp, 0, "}\n");
1422 }
1423
1424 void
1425 gen_interpreter (FILE *fp)
1426 {
1427   int col = 0;
1428
1429   /* Generate header of interpretor.  */
1430   print (fp, col, "/* File generated automatically by gencode. */\n");
1431   print (fp, col, "#include \"sim-main.h\"\n\n");
1432
1433   gen_cycle_table (fp, "cycles_page1", m6811_page1_opcodes,
1434                    TABLE_SIZE (m6811_page1_opcodes));
1435   gen_cycle_table (fp, "cycles_page2", m6811_page2_opcodes,
1436                    TABLE_SIZE (m6811_page2_opcodes));
1437   gen_cycle_table (fp, "cycles_page3", m6811_page3_opcodes,
1438                    TABLE_SIZE (m6811_page3_opcodes));
1439   gen_cycle_table (fp, "cycles_page4", m6811_page4_opcodes,
1440                    TABLE_SIZE (m6811_page4_opcodes));
1441
1442   /* Generate the page 2, 3 and 4 handlers.  */
1443   gen_function_entry (fp, "static void\ncpu_page2_interp");
1444   gen_interpreter_for_table (fp, indent_level,
1445                              m6811_page2_opcodes,
1446                              TABLE_SIZE(m6811_page2_opcodes),
1447                              "cycles_page2");
1448   gen_function_close (fp);
1449   
1450   gen_function_entry (fp, "static void\ncpu_page3_interp");
1451   gen_interpreter_for_table (fp, indent_level,
1452                              m6811_page3_opcodes,
1453                              TABLE_SIZE(m6811_page3_opcodes),
1454                              "cycles_page3");
1455   gen_function_close (fp);
1456   
1457   gen_function_entry (fp, "static void\ncpu_page4_interp");
1458   gen_interpreter_for_table (fp, indent_level,
1459                              m6811_page4_opcodes,
1460                              TABLE_SIZE(m6811_page4_opcodes),
1461                              "cycles_page4");
1462   gen_function_close (fp);
1463
1464   /* Generate the interpretor entry point.  */
1465   gen_function_entry (fp, "void\ncpu_interp");
1466
1467   gen_interpreter_for_table (fp, indent_level, m6811_page1_opcodes,
1468                              TABLE_SIZE(m6811_page1_opcodes),
1469                              "cycles_page1");
1470   gen_function_close (fp);
1471 }
1472
1473 int
1474 main (int argc, char *argv[])
1475 {
1476   gen_interpreter (stdout);
1477   if (fclose (stdout) != 0)
1478     {
1479       fprintf (stderr, "Error while generating the interpreter: %d\n",
1480                errno);
1481       return 1;
1482     }
1483   return 0;
1484 }