New simulator.
[deliverable/binutils-gdb.git] / sim / m68hc11 / gencode.c
CommitLineData
e0709f50
AC
1/* gencode.c -- Motorola 68hc11 Emulator Generator
2 Copyright 1999, 2000 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5This file is part of GDB, GAS, and the GNU binutils.
6
7GDB, GAS, and the GNU binutils are free software; you can redistribute
8them and/or modify them under the terms of the GNU General Public
9License as published by the Free Software Foundation; either version
102, or (at your option) any later version.
11
12GDB, GAS, and the GNU binutils are distributed in the hope that they
13will be useful, but WITHOUT ANY WARRANTY; without even the implied
14warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15the GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 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
69struct 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 */
83struct 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| \
134M6811_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| \
137M6811_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);\
162dst8 = dst8 - src8", 0 },
163 { "add8", "cpu_ccr_update_add8 (proc, dst8 + src8, dst8, src8);\
164dst8 = 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\
170else\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\
180else\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);\
195dst16 = dst16 - src16", 0 },
196 { "add16", "cpu_ccr_update_add16 (proc, dst16 + src16, dst16, src16);\
197dst16 = 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\
229dst16 = 0xffff;\
230}\nelse\n{\n\
231cpu_set_d (proc, dst16 % src16);\
232dst16 = dst16 / src16;\
233}",
234 "cpu_set_ccr_Z (proc, dst16 == 0); cpu_set_ccr_V (proc, 0);\
235cpu_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\
241dst16 = 0xffff;\n\
242cpu_set_ccr_Z (proc, 0);\n\
243cpu_set_ccr_V (proc, 1);\n\
244cpu_set_ccr_C (proc, dst16 == 0);\n\
245}\nelse\n{\n\
246unsigned long l = (unsigned long) (dst16) << 16;\n\
247cpu_set_d (proc, (uint16) (l % (unsigned long) (src16)));\n\
248dst16 = (uint16) (l / (unsigned long) (src16));\n\
249cpu_set_ccr_V (proc, 0);\n\
250cpu_set_ccr_C (proc, 0);\n\
251cpu_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. */
275struct 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 */
309const 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 */
574const 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 */
654const 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 */
677const 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
687void fatal_error (const struct m6811_opcode_def*, const char*);
688void print (FILE*, int, const char*,...);
689int gen_fetch_operands (FILE*, int, const struct m6811_opcode_def*,
690 const char*);
691void gen_save_result (FILE*, int, const struct m6811_opcode_def*,
692 int, const char*);
693const struct m6811_opcode_pattern*
694find_opcode_pattern (const struct m6811_opcode_def*);
695void gen_interp (FILE*, int, const struct m6811_opcode_def*);
696void gen_interpreter_for_table (FILE*, int,
697 const struct m6811_opcode_def*,
698 int, const char*);
699void gen_interpreter (FILE*);
700
701
702static int indent_level = 2;
703static 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. */
707void
708fatal_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). */
721void
722print (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. */
830int
831gen_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. */
1068void
1069gen_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. */
1228const struct m6811_opcode_pattern*
1229find_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'. */
1251void
1252gen_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. */
1310void
1311gen_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. */
1351void
1352gen_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
1404void
1405gen_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
1418void
1419gen_function_close (FILE *fp)
1420{
1421 print (fp, 0, "}\n");
1422}
1423
1424void
1425gen_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
1473int
1474main (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}
This page took 0.079884 seconds and 4 git commands to generate.