1 /*
2  * emu68k.c
3  *
4  * emulation of the 68000
5  */
6 
7 /* $Id: emu68k.c,v 1.64 2001/03/31 19:51:57 nyef Exp $ */
8 
9 #include <stdlib.h>
10 #include "cal.h"
11 #include "ui.h"
12 #include "emu68k.h"
13 #include "tool.h"
14 #include "types.h"
15 
16 /*  #define USE_UNTESTED */
17 
18 /*
19  * Instruction handler interface
20  */
21 
22 typedef void (*m68k_instr_handler)(struct emu68k_context *, u16);
23 
24 struct m68k_instr {
25     u16 mask;
26     u16 pattern;
27     m68k_instr_handler handler;
28     char *name;
29 };
30 
31 struct m68k_instr *m68k_instrs[16];
32 
33 /*
34  * Register and memory access
35  */
36 
37 #define WRITE_D_REG_BYTE(context, reg, data) {context->regs_d[reg] &= ~0xff; context->regs_d[reg] |= data;}
38 #define WRITE_D_REG_WORD(context, reg, data) {context->regs_d[reg] &= ~0xffff; context->regs_d[reg] |= data;}
39 #define WRITE_D_REG_LONG(context, reg, data) {context->regs_d[reg] = data;}
40 
emu68k_read_8(struct emu68k_context * context,u32 addr)41 u8 emu68k_read_8(struct emu68k_context *context, u32 addr)
42 {
43     context->cycles_left -= 4;
44 
45     return context->read8table[(addr >> context->memshift)
46 			      & context->memmask](context->cpu, addr);
47 }
48 
emu68k_read_16(struct emu68k_context * context,u32 addr)49 u16 emu68k_read_16(struct emu68k_context *context, u32 addr)
50 {
51     /* FIXME: BUS error check goes here */
52 
53     context->cycles_left -= 4;
54 
55     return context->read16table[(addr >> context->memshift)
56 			       & context->memmask](context->cpu, addr);
57 }
58 
emu68k_read_32(struct emu68k_context * context,u32 addr)59 u32 emu68k_read_32(struct emu68k_context *context, u32 addr)
60 {
61     u16 tmp1;
62     u16 tmp2;
63 
64     /* FIXME: BUS error check goes here */
65 
66     /* FIXME: check if this is the correct order */
67     tmp1 = emu68k_read_16(context, addr);
68     tmp2 = emu68k_read_16(context, addr + 2);
69 
70     return (tmp1 << 16) | tmp2;
71 }
72 
emu68k_write_8(struct emu68k_context * context,u32 addr,u8 data)73 void emu68k_write_8(struct emu68k_context *context, u32 addr, u8 data)
74 {
75     context->cycles_left -= 4;
76 
77     context->write8table[(addr >> context->memshift)
78 			& context->memmask](context->cpu, addr, data);
79 }
80 
emu68k_write_16(struct emu68k_context * context,u32 addr,u16 data)81 void emu68k_write_16(struct emu68k_context *context, u32 addr, u16 data)
82 {
83     /* FIXME: BUS error check goes here */
84 
85     context->cycles_left -= 4;
86 
87     context->write16table[(addr >> context->memshift)
88 			& context->memmask](context->cpu, addr, data);
89 }
90 
emu68k_write_32(struct emu68k_context * context,u32 addr,u32 data)91 void emu68k_write_32(struct emu68k_context *context, u32 addr, u32 data)
92 {
93     /* FIXME: BUS error check goes here */
94 
95     /* FIXME: check if this is the correct order */
96     emu68k_write_16(context, addr, data >> 16);
97     emu68k_write_16(context, addr + 2, data & 0xffff);
98 }
99 
100 /*
101  * Main loop and support code
102  */
103 
emu68k_opfetch_16(struct emu68k_context * context)104 u16 emu68k_opfetch_16(struct emu68k_context *context)
105 {
106     u16 retval;
107 
108     retval = emu68k_read_16(context, context->pc);
109     context->pc += 2;
110 
111     return retval;
112 }
113 
emu68k_opfetch_32(struct emu68k_context * context)114 u32 emu68k_opfetch_32(struct emu68k_context *context)
115 {
116     u32 retval;
117 
118     retval = emu68k_read_32(context, context->pc);
119     context->pc += 4;
120 
121     return retval;
122 }
123 
emu68k_step(struct emu68k_context * context)124 void emu68k_step(struct emu68k_context *context)
125 {
126     u16 opword;
127     struct m68k_instr *cur_instr;
128 
129     if (context->pc & 1) {
130 	/* FIXME: bad things happen here */
131     }
132     opword = emu68k_opfetch_16(context);
133     cur_instr = m68k_instrs[opword >> 12];
134     while ((opword & cur_instr->mask) != cur_instr->pattern) {
135 	cur_instr++;
136     }
137     cur_instr->handler(context, opword);
138 }
139 
emu68k_run(struct emu68k_context * context)140 void emu68k_run(struct emu68k_context *context)
141 {
142     while (context->cycles_left > 0) {
143 	emu68k_step(context);
144 
145 	if (system_flags & F_UNIMPL) {
146 	    return;
147 	}
148     }
149 }
150 
emu68k_reset(struct emu68k_context * context)151 void emu68k_reset(struct emu68k_context *context)
152 {
153     context->regs_a[7] = emu68k_read_32(context, 0);
154 
155     context->pc = emu68k_read_32(context, 4);
156 
157 #if 0
158     context->flags = 0x2000; /* FIXME: may be wrong */
159 #else
160     emu68k_set_flags(context, 0x2000); /* FIXME: may be wrong */
161 #endif
162 }
163 
164 /*
165  * CAL interface
166  */
167 
cal_junk68k_reset(cal_cpu cpu)168 void cal_junk68k_reset(cal_cpu cpu)
169 {
170     emu68k_reset(cpu->data.d_junk68k);
171 }
172 
cal_junk68k_run(cal_cpu cpu)173 void cal_junk68k_run(cal_cpu cpu)
174 {
175 /*      emu68k_step(cpu->data.d_junk68k); */
176     emu68k_run(cpu->data.d_junk68k);
177 }
178 
cal_junk68k_runfor(cal_cpu cpu,int cycles)179 void cal_junk68k_runfor(cal_cpu cpu, int cycles)
180 {
181     cpu->data.d_junk68k->cycles_left += cycles;
182 }
183 
cal_junk68k_irq(cal_cpu cpu,int irqno)184 void cal_junk68k_irq(cal_cpu cpu, int irqno)
185 {
186 /*     emuz80_IRQ(cpu->data.d_emuz80); */
187 }
188 
cal_junk68k_nmi(cal_cpu cpu)189 void cal_junk68k_nmi(cal_cpu cpu)
190 {
191 /*     emuz80_NMI(cpu->data.d_emuz80); */
192 }
193 
cal_junk68k_setzpage(cal_cpu cpu,void * page0)194 void cal_junk68k_setzpage(cal_cpu cpu, void *page0)
195 {
196 }
197 
cal_junk68k_timeleft(cal_cpu cpu)198 int cal_junk68k_timeleft(cal_cpu cpu)
199 {
200 /*     return cpu->data.d_emuz80->cycles_left; */
201     return 0;
202 }
203 
cal_junk68k_setmmu8(cal_cpu cpu,int shift,int mask,memread8_t * rtbl,memwrite8_t * wtbl)204 void cal_junk68k_setmmu8(cal_cpu cpu, int shift, int mask, memread8_t *rtbl, memwrite8_t *wtbl)
205 {
206     cpu->data.d_junk68k->memshift = shift;
207     cpu->data.d_junk68k->memmask = mask;
208     cpu->data.d_junk68k->read8table = rtbl;
209     cpu->data.d_junk68k->write8table = wtbl;
210 }
211 
cal_junk68k_setmmu16(cal_cpu cpu,int shift,int mask,memread16_t * rtbl,memwrite16_t * wtbl)212 void cal_junk68k_setmmu16(cal_cpu cpu, int shift, int mask, memread16_t *rtbl, memwrite16_t *wtbl)
213 {
214     cpu->data.d_junk68k->read16table = rtbl;
215     cpu->data.d_junk68k->write16table = wtbl;
216 }
217 
cal_junk68k_init(cal_cpu * cpu)218 void cal_junk68k_init(cal_cpu *cpu)
219 {
220     (*cpu)->data.d_junk68k = calloc(1, sizeof(struct emu68k_context));
221     if (!(*cpu)->data.d_junk68k) {
222 	deb_printf("Insufficient memory to create CPU.\n");
223 	free(*cpu);
224 	*cpu = NULL;
225 	return;
226     }
227     (*cpu)->reset = cal_junk68k_reset;
228     (*cpu)->run = cal_junk68k_run;
229     (*cpu)->runfor = cal_junk68k_runfor;
230     (*cpu)->irq = cal_junk68k_irq;
231     (*cpu)->nmi = cal_junk68k_nmi;
232     (*cpu)->setzpage = cal_junk68k_setzpage;
233     (*cpu)->timeleft = cal_junk68k_timeleft;
234     (*cpu)->setmmu8 = cal_junk68k_setmmu8;
235     (*cpu)->setmmu16 = cal_junk68k_setmmu16;
236     (*cpu)->data.d_junk68k->cpu = *cpu;
237 /*     emuz80_init((*cpu)->data.d_junk68k); */
238 }
239 
240 /*
241  * Condition flag code and macros
242  */
243 
244 #define FLAG_NZ_byte(context, data) {context->flag_z = data; context->flag_n = data; context->flag_c = 0; context->flag_v = 0;}
245 #define FLAG_NZ_word(context, data) {context->flag_z = data; context->flag_n = data >> 8; context->flag_c = 0; context->flag_v = 0;}
246 #define FLAG_NZ_long(context, data) {context->flag_z = data; context->flag_n = data >> 24; context->flag_c = 0; context->flag_v = 0;}
247 
248 /* FIXME: I don't understand these next few macros */
249 
250 #define FLAG_VC_ADD_byte(context, dest, src1, src2) {context->flag_c = (dest < src1); context->flag_v = (((dest) ^ (src1)) & ((dest) ^ (src2)) & 0x80);}
251 #define FLAG_VC_ADD_word(context, dest, src1, src2) {context->flag_c = (dest < src1); context->flag_v = (((dest) ^ (src1)) & ((dest) ^ (src2)) & 0x8000);}
252 #define FLAG_VC_ADD_long(context, dest, src1, src2) {context->flag_c = (dest < src1); context->flag_v = (((dest) ^ (src1)) & ((dest) ^ (src2)) & 0x80000000);}
253 
254 #define FLAG_VC_SUB_byte(context, dest, src1, src2) {context->flag_c = (src1 > src2); context->flag_v = (((dest) ^ (src2)) & ((src1) ^ (src2)) & 0x80);}
255 #define FLAG_VC_SUB_word(context, dest, src1, src2) {context->flag_c = (src1 > src2); context->flag_v = (((dest) ^ (src2)) & ((src1) ^ (src2)) & 0x8000);}
256 #define FLAG_VC_SUB_long(context, dest, src1, src2) {context->flag_c = (src1 > src2); context->flag_v = (((dest) ^ (src2)) & ((src1) ^ (src2)) & 0x80000000);}
257 
258 #define FLAG_X(context) {context->flag_x = context->flag_c;}
259 
emu68k_get_flags(struct emu68k_context * context)260 u16 emu68k_get_flags(struct emu68k_context *context)
261 {
262     u16 retval;
263 
264     retval = context->flags & ~0x001f;
265 
266     if (!context->flag_z) {
267 	retval |= 0x0004;
268     }
269 
270     if (context->flag_n & 0x80) {
271 	retval |= 0x0008;
272     }
273 
274     if (context->flag_c) {
275 	retval |= 0x0001;
276     }
277 
278     if (context->flag_x) {
279 	retval |= 0x0010;
280     }
281 
282     if (context->flag_v) {
283 	retval |= 0x0002;
284     }
285 
286     return retval;
287 }
288 
emu68k_set_flags(struct emu68k_context * context,u16 flags)289 void emu68k_set_flags(struct emu68k_context *context, u16 flags)
290 {
291     context->flags = flags & ~0x001f;
292 
293     context->flag_z = !(flags & 0x04);
294     context->flag_n = flags << 4;
295     context->flag_x = flags & 0x10;
296     context->flag_c = flags & 0x01;
297     context->flag_v = flags & 0x02;
298 }
299 
300 /*
301  * Addressing modes
302  */
303 
304 #define AMT_DATA      0x1
305 #define AMT_MEMORY    0x2
306 #define AMT_CONTROL   0x4
307 #define AMT_ALTERABLE 0x8
308 
309 #define AMT_DA (AMT_DATA | AMT_ALTERABLE)
310 #define AMT_MA (AMT_MEMORY | AMT_ALTERABLE)
311 #define AMT_CA (AMT_CONTROL | AMT_ALTERABLE)
312 
313 #define AMODE_IS(amode, am_type) ((amode.type & am_type) == am_type)
314 
315 struct m68k_amode {
316     u8 type;
317     u32 data;
318     u32 flags;
319     int reg;
320     struct emu68k_context *context;
321     struct m68k_amode_api *api;
322 };
323 
324 typedef void (*m68k_amode_resolver)(struct m68k_amode *, struct emu68k_context *, int);
325 typedef u8 (*m68k_amode_read_byte)(struct m68k_amode *);
326 typedef u16 (*m68k_amode_read_word)(struct m68k_amode *);
327 typedef u32 (*m68k_amode_read_long)(struct m68k_amode *);
328 typedef void (*m68k_amode_write_byte)(struct m68k_amode *, u8);
329 typedef void (*m68k_amode_write_word)(struct m68k_amode *, u16);
330 typedef void (*m68k_amode_write_long)(struct m68k_amode *, u32);
331 typedef void (*m68k_amode_after)(struct m68k_amode *);
332 
333 struct m68k_amode_api {
334     m68k_amode_resolver resolve;
335     m68k_amode_read_byte readbyte;
336     m68k_amode_read_word readword;
337     m68k_amode_read_long readlong;
338     m68k_amode_write_byte writebyte;
339     m68k_amode_write_word writeword;
340     m68k_amode_write_long writelong;
341     m68k_amode_after after;
342 };
343 
344 #define AMS_BOGUS 0
345 #define AMS_BYTE 1
346 #define AMS_WORD 2
347 #define AMS_LONG 3
348 
m68k_amode_none_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)349 void m68k_amode_none_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
350 {
351     deb_printf("m68k: unimplemented amode (api: 0x%08x).\n", amode->api);
352     system_flags |= F_UNIMPL;
353 }
354 
m68k_control_amode_readbyte(struct m68k_amode * amode)355 u8 m68k_control_amode_readbyte(struct m68k_amode *amode)
356 {
357     return emu68k_read_8(amode->context, amode->data);
358 }
359 
m68k_control_amode_readword(struct m68k_amode * amode)360 u16 m68k_control_amode_readword(struct m68k_amode *amode)
361 {
362     return emu68k_read_16(amode->context, amode->data);
363 }
364 
m68k_control_amode_readlong(struct m68k_amode * amode)365 u32 m68k_control_amode_readlong(struct m68k_amode *amode)
366 {
367     return emu68k_read_32(amode->context, amode->data);
368 }
369 
m68k_control_amode_writebyte(struct m68k_amode * amode,u8 data)370 void m68k_control_amode_writebyte(struct m68k_amode *amode, u8 data)
371 {
372     emu68k_write_8(amode->context, amode->data, data);
373 }
374 
m68k_control_amode_writeword(struct m68k_amode * amode,u16 data)375 void m68k_control_amode_writeword(struct m68k_amode *amode, u16 data)
376 {
377     emu68k_write_16(amode->context, amode->data, data);
378 }
379 
m68k_control_amode_writelong(struct m68k_amode * amode,u32 data)380 void m68k_control_amode_writelong(struct m68k_amode *amode, u32 data)
381 {
382     emu68k_write_32(amode->context, amode->data, data);
383 }
384 
m68k_control_amode_after(struct m68k_amode * amode)385 void m68k_control_amode_after(struct m68k_amode *amode)
386 {
387 }
388 
389 #define CONTROL_AMODE_API \
390     m68k_control_amode_readbyte, \
391     m68k_control_amode_readword, \
392     m68k_control_amode_readlong, \
393     m68k_control_amode_writebyte, \
394     m68k_control_amode_writeword, \
395     m68k_control_amode_writelong, \
396     m68k_control_amode_after
397 
m68k_amode_0_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)398 void m68k_amode_0_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
399 {
400     amode->context = context;
401 }
402 
m68k_amode_0_readbyte(struct m68k_amode * amode)403 u8 m68k_amode_0_readbyte(struct m68k_amode *amode)
404 {
405     return (u8)amode->context->regs_d[amode->reg];
406 }
407 
m68k_amode_0_readword(struct m68k_amode * amode)408 u16 m68k_amode_0_readword(struct m68k_amode *amode)
409 {
410     return (u16)amode->context->regs_d[amode->reg];
411 }
412 
m68k_amode_0_readlong(struct m68k_amode * amode)413 u32 m68k_amode_0_readlong(struct m68k_amode *amode)
414 {
415     return amode->context->regs_d[amode->reg];
416 }
417 
m68k_amode_0_writebyte(struct m68k_amode * amode,u8 data)418 void m68k_amode_0_writebyte(struct m68k_amode *amode, u8 data)
419 {
420     WRITE_D_REG_BYTE(amode->context, amode->reg, data);
421 }
422 
m68k_amode_0_writeword(struct m68k_amode * amode,u16 data)423 void m68k_amode_0_writeword(struct m68k_amode *amode, u16 data)
424 {
425     WRITE_D_REG_WORD(amode->context, amode->reg, data);
426 }
427 
m68k_amode_0_writelong(struct m68k_amode * amode,u32 data)428 void m68k_amode_0_writelong(struct m68k_amode *amode, u32 data)
429 {
430     WRITE_D_REG_LONG(amode->context, amode->reg, data);
431 }
432 
m68k_amode_0_after(struct m68k_amode * amode)433 void m68k_amode_0_after(struct m68k_amode *amode)
434 {
435 }
436 
437 struct m68k_amode_api m68k_amode_api_0 = {
438     m68k_amode_0_resolve,
439     m68k_amode_0_readbyte,
440     m68k_amode_0_readword,
441     m68k_amode_0_readlong,
442     m68k_amode_0_writebyte,
443     m68k_amode_0_writeword,
444     m68k_amode_0_writelong,
445     m68k_amode_0_after,
446 };
447 
m68k_amode_1_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)448 void m68k_amode_1_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
449 {
450     amode->context = context;
451 }
452 
m68k_amode_1_readbyte(struct m68k_amode * amode)453 u8 m68k_amode_1_readbyte(struct m68k_amode *amode)
454 {
455     /* FIXME: signal exception */
456     return 0;
457 }
458 
m68k_amode_1_readword(struct m68k_amode * amode)459 u16 m68k_amode_1_readword(struct m68k_amode *amode)
460 {
461     return (u16)amode->context->regs_a[amode->reg];
462 }
463 
m68k_amode_1_readlong(struct m68k_amode * amode)464 u32 m68k_amode_1_readlong(struct m68k_amode *amode)
465 {
466     return amode->context->regs_a[amode->reg];
467 }
468 
m68k_amode_1_writebyte(struct m68k_amode * amode,u8 data)469 void m68k_amode_1_writebyte(struct m68k_amode *amode, u8 data)
470 {
471     /* FIXME: signal exception */
472 }
473 
m68k_amode_1_writeword(struct m68k_amode * amode,u16 data)474 void m68k_amode_1_writeword(struct m68k_amode *amode, u16 data)
475 {
476     amode->context->regs_a[amode->reg] &= ~0xffff;
477     amode->context->regs_a[amode->reg] |= data;
478 }
479 
m68k_amode_1_writelong(struct m68k_amode * amode,u32 data)480 void m68k_amode_1_writelong(struct m68k_amode *amode, u32 data)
481 {
482     amode->context->regs_a[amode->reg] = data;
483 }
484 
m68k_amode_1_after(struct m68k_amode * amode)485 void m68k_amode_1_after(struct m68k_amode *amode)
486 {
487 }
488 
489 struct m68k_amode_api m68k_amode_api_1 = {
490     m68k_amode_1_resolve,
491     m68k_amode_1_readbyte,
492     m68k_amode_1_readword,
493     m68k_amode_1_readlong,
494     m68k_amode_1_writebyte,
495     m68k_amode_1_writeword,
496     m68k_amode_1_writelong,
497     m68k_amode_1_after,
498 };
499 
m68k_amode_2_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)500 void m68k_amode_2_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
501 {
502     amode->context = context;
503     amode->data = context->regs_a[amode->reg];
504 }
505 
506 struct m68k_amode_api m68k_amode_api_2 = {
507     m68k_amode_2_resolve,
508     CONTROL_AMODE_API
509 };
510 
m68k_amode_3_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)511 void m68k_amode_3_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
512 {
513     amode->context = context;
514     if (size == AMS_BYTE) {
515 	if (amode->reg != 7) {
516 	    amode->flags = 1;
517 	} else {
518 	    amode->flags = 2;
519 	}
520     } else if (size == AMS_WORD) {
521 	amode->flags = 2;
522     } else if (size == AMS_LONG) {
523 	amode->flags = 4;
524     } else {
525 	deb_printf("m68k: BUG: bogus size passed to amode 3.\n");
526     }
527     amode->data = context->regs_a[amode->reg];
528 }
529 
m68k_amode_3_readbyte(struct m68k_amode * amode)530 u8 m68k_amode_3_readbyte(struct m68k_amode *amode)
531 {
532     return emu68k_read_8(amode->context, amode->data);
533 }
534 
m68k_amode_3_readword(struct m68k_amode * amode)535 u16 m68k_amode_3_readword(struct m68k_amode *amode)
536 {
537     return emu68k_read_16(amode->context, amode->data);
538 }
539 
m68k_amode_3_readlong(struct m68k_amode * amode)540 u32 m68k_amode_3_readlong(struct m68k_amode *amode)
541 {
542     return emu68k_read_32(amode->context, amode->data);
543 }
544 
m68k_amode_3_writebyte(struct m68k_amode * amode,u8 data)545 void m68k_amode_3_writebyte(struct m68k_amode *amode, u8 data)
546 {
547     emu68k_write_8(amode->context, amode->data, data);
548 }
549 
m68k_amode_3_writeword(struct m68k_amode * amode,u16 data)550 void m68k_amode_3_writeword(struct m68k_amode *amode, u16 data)
551 {
552     emu68k_write_16(amode->context, amode->data, data);
553 }
554 
m68k_amode_3_writelong(struct m68k_amode * amode,u32 data)555 void m68k_amode_3_writelong(struct m68k_amode *amode, u32 data)
556 {
557     emu68k_write_32(amode->context, amode->data, data);
558 }
559 
m68k_amode_3_after(struct m68k_amode * amode)560 void m68k_amode_3_after(struct m68k_amode *amode)
561 {
562     amode->context->regs_a[amode->reg] += amode->flags;
563     amode->data += amode->flags;
564 }
565 
566 struct m68k_amode_api m68k_amode_api_3 = {
567     m68k_amode_3_resolve,
568     m68k_amode_3_readbyte,
569     m68k_amode_3_readword,
570     m68k_amode_3_readlong,
571     m68k_amode_3_writebyte,
572     m68k_amode_3_writeword,
573     m68k_amode_3_writelong,
574     m68k_amode_3_after,
575 };
576 
m68k_amode_4_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)577 void m68k_amode_4_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
578 {
579     /* FIXME: this may not do the right thing for MOVE.L A7, -(A7) */
580     amode->context = context;
581     if (size == AMS_BYTE) {
582 	if (amode->reg != 7) {
583 	    amode->flags = 1;
584 	} else {
585 	    amode->flags = 2;
586 	}
587     } else if (size == AMS_WORD) {
588 	amode->flags = 2;
589     } else if (size == AMS_LONG) {
590 	amode->flags = 4;
591     } else {
592 	deb_printf("m68k: BUG: bogus size passed to amode 4.\n");
593     }
594     amode->data = context->regs_a[amode->reg] - amode->flags;
595 }
596 
m68k_amode_4_readbyte(struct m68k_amode * amode)597 u8 m68k_amode_4_readbyte(struct m68k_amode *amode)
598 {
599     amode->context->cycles_left -= 2;
600 
601     return emu68k_read_8(amode->context, amode->data);
602 }
603 
m68k_amode_4_readword(struct m68k_amode * amode)604 u16 m68k_amode_4_readword(struct m68k_amode *amode)
605 {
606     amode->context->cycles_left -= 2;
607 
608     return emu68k_read_16(amode->context, amode->data);
609 }
610 
m68k_amode_4_readlong(struct m68k_amode * amode)611 u32 m68k_amode_4_readlong(struct m68k_amode *amode)
612 {
613     amode->context->cycles_left -= 2;
614 
615     return emu68k_read_32(amode->context, amode->data);
616 }
617 
m68k_amode_4_writebyte(struct m68k_amode * amode,u8 data)618 void m68k_amode_4_writebyte(struct m68k_amode *amode, u8 data)
619 {
620     emu68k_write_8(amode->context, amode->data, data);
621 }
622 
m68k_amode_4_writeword(struct m68k_amode * amode,u16 data)623 void m68k_amode_4_writeword(struct m68k_amode *amode, u16 data)
624 {
625     emu68k_write_16(amode->context, amode->data, data);
626 }
627 
m68k_amode_4_writelong(struct m68k_amode * amode,u32 data)628 void m68k_amode_4_writelong(struct m68k_amode *amode, u32 data)
629 {
630     emu68k_write_32(amode->context, amode->data, data);
631 }
632 
m68k_amode_4_after(struct m68k_amode * amode)633 void m68k_amode_4_after(struct m68k_amode *amode)
634 {
635     amode->context->regs_a[amode->reg] -= amode->flags;
636     amode->data = amode->context->regs_a[amode->reg] - amode->flags;
637 }
638 
639 struct m68k_amode_api m68k_amode_api_4 = {
640     m68k_amode_4_resolve,
641     m68k_amode_4_readbyte,
642     m68k_amode_4_readword,
643     m68k_amode_4_readlong,
644     m68k_amode_4_writebyte,
645     m68k_amode_4_writeword,
646     m68k_amode_4_writelong,
647     m68k_amode_4_after,
648 };
649 
m68k_amode_5_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)650 void m68k_amode_5_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
651 {
652     s16 data;
653 
654     amode->context = context;
655     amode->data = context->regs_a[amode->reg];
656 
657     data = emu68k_opfetch_16(context);
658 
659     amode->data += (signed long)data;
660 }
661 
662 struct m68k_amode_api m68k_amode_api_5 = {
663     m68k_amode_5_resolve,
664     CONTROL_AMODE_API
665 };
666 
m68k_amode_6_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)667 void m68k_amode_6_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
668 {
669     s16 data;
670 
671     amode->context = context;
672     amode->data = context->regs_a[amode->reg];
673 
674     data = emu68k_opfetch_16(context);
675 
676     amode->data += (s8)data;
677 
678     if (data & 0x0800) {
679 	if (data & 0x8000) {
680 	    /* A.L */
681 	    amode->data += amode->context->regs_a[(data >> 12) & 7];
682 	} else {
683 	    /* D.L */
684 	    amode->data += amode->context->regs_d[(data >> 12) & 7];
685 	}
686     } else {
687 	if (data & 0x8000) {
688 	    /* A.W */
689 	    amode->data += (s16)amode->context->regs_a[(data >> 12) & 7];
690 	} else {
691 	    /* D.W */
692 	    amode->data += (s16)amode->context->regs_d[(data >> 12) & 7];
693 	}
694     }
695 
696     amode->context->cycles_left -= 2;
697 }
698 
699 struct m68k_amode_api m68k_amode_api_6 = {
700     m68k_amode_6_resolve,
701     CONTROL_AMODE_API
702 };
703 
m68k_amode_7_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)704 void m68k_amode_7_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
705 {
706     s16 tmp;
707 
708     amode->context = context;
709 
710     tmp = emu68k_opfetch_16(context);
711 
712     amode->data = tmp; /* needed for sign extension */
713 }
714 
715 struct m68k_amode_api m68k_amode_api_7 = {
716     m68k_amode_7_resolve,
717     CONTROL_AMODE_API
718 };
719 
m68k_amode_8_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)720 void m68k_amode_8_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
721 {
722     amode->context = context;
723 
724     amode->data = emu68k_opfetch_32(context);
725 }
726 
727 struct m68k_amode_api m68k_amode_api_8 = {
728     m68k_amode_8_resolve,
729     CONTROL_AMODE_API
730 };
731 
m68k_amode_9_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)732 void m68k_amode_9_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
733 {
734     s16 data;
735 
736     amode->context = context;
737     amode->data = context->pc; /* FIXME: may be too small by 2 */
738 
739     data = emu68k_opfetch_16(context);
740 
741     amode->data += (signed long)data;
742 }
743 
744 struct m68k_amode_api m68k_amode_api_9 = {
745     m68k_amode_9_resolve,
746     CONTROL_AMODE_API
747 };
748 
m68k_amode_10_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)749 void m68k_amode_10_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
750 {
751     s16 data;
752 
753     amode->context = context;
754     amode->data = context->pc;
755 
756     data = emu68k_opfetch_16(context);
757 
758     amode->data += (s8)data;
759 
760     if (data & 0x0800) {
761 	if (data & 0x8000) {
762 	    /* A.L */
763 	    amode->data += amode->context->regs_a[(data >> 12) & 7];
764 	} else {
765 	    /* D.L */
766 	    amode->data += amode->context->regs_d[(data >> 12) & 7];
767 	}
768     } else {
769 	if (data & 0x8000) {
770 	    /* A.W */
771 	    amode->data += (s16)amode->context->regs_a[(data >> 12) & 7];
772 	} else {
773 	    /* D.W */
774 	    amode->data += (s16)amode->context->regs_d[(data >> 12) & 7];
775 	}
776     }
777 
778     context->cycles_left -= 2;
779 }
780 
781 struct m68k_amode_api m68k_amode_api_10 = {
782     m68k_amode_10_resolve,
783     CONTROL_AMODE_API
784 };
785 
m68k_amode_11_resolve(struct m68k_amode * amode,struct emu68k_context * context,int size)786 void m68k_amode_11_resolve(struct m68k_amode *amode, struct emu68k_context *context, int size)
787 {
788     amode->context = context;
789 
790     if ((size == AMS_BYTE) || (size == AMS_WORD)) {
791 	amode->data = emu68k_opfetch_16(context);
792     } else if (size == AMS_LONG) {
793 	amode->data = emu68k_opfetch_32(context);
794     } else {
795 	deb_printf("m68k: BUG: amode 11 reports illegal size %d.\n", size);
796 	amode->data = 0;
797     }
798 }
799 
m68k_amode_11_readbyte(struct m68k_amode * amode)800 u8 m68k_amode_11_readbyte(struct m68k_amode *amode)
801 {
802     return amode->data & 0xff;
803 }
804 
m68k_amode_11_readword(struct m68k_amode * amode)805 u16 m68k_amode_11_readword(struct m68k_amode *amode)
806 {
807     return amode->data;
808 }
809 
m68k_amode_11_readlong(struct m68k_amode * amode)810 u32 m68k_amode_11_readlong(struct m68k_amode *amode)
811 {
812     return amode->data;
813 }
814 
m68k_amode_11_writebyte(struct m68k_amode * amode,u8 data)815 void m68k_amode_11_writebyte(struct m68k_amode *amode, u8 data)
816 {
817     deb_printf("m68k: CPU BUG: Write to non-alterable.\n");
818     abort();
819 }
820 
m68k_amode_11_writeword(struct m68k_amode * amode,u16 data)821 void m68k_amode_11_writeword(struct m68k_amode *amode, u16 data)
822 {
823     deb_printf("m68k: CPU BUG: Write to non-alterable.\n");
824     abort();
825 }
826 
m68k_amode_11_writelong(struct m68k_amode * amode,u32 data)827 void m68k_amode_11_writelong(struct m68k_amode *amode, u32 data)
828 {
829     deb_printf("m68k: CPU BUG: Write to non-alterable.\n");
830     abort();
831 }
832 
m68k_amode_11_after(struct m68k_amode * amode)833 void m68k_amode_11_after(struct m68k_amode *amode)
834 {
835 }
836 
837 struct m68k_amode_api m68k_amode_api_11 = {
838     m68k_amode_11_resolve,
839     m68k_amode_11_readbyte,
840     m68k_amode_11_readword,
841     m68k_amode_11_readlong,
842     m68k_amode_11_writebyte,
843     m68k_amode_11_writeword,
844     m68k_amode_11_writelong,
845     m68k_amode_11_after,
846 };
847 
848 struct m68k_amode m68k_amodes[] = {
849     {0x09, 0, 0, 0, NULL, &m68k_amode_api_0},  /* Dn */
850     {0x08, 0, 0, 0, NULL, &m68k_amode_api_1},  /* An */
851     {0x0f, 0, 0, 0, NULL, &m68k_amode_api_2},  /* (An) */
852     {0x0b, 0, 0, 0, NULL, &m68k_amode_api_3},  /* (An)+ */
853     {0x0b, 0, 0, 0, NULL, &m68k_amode_api_4},  /* -(An) */
854     {0x0f, 0, 0, 0, NULL, &m68k_amode_api_5},  /* d(An) */
855     {0x0f, 0, 0, 0, NULL, &m68k_amode_api_6},  /* d(An,Ri) */
856     {0x0f, 0, 0, 0, NULL, &m68k_amode_api_7},  /* xxxx */
857     {0x0f, 0, 0, 0, NULL, &m68k_amode_api_8},  /* xxxxxxxx */
858     {0x07, 0, 0, 0, NULL, &m68k_amode_api_9},  /* d */
859     {0x07, 0, 0, 0, NULL, &m68k_amode_api_10}, /* d(Ri) */
860     {0x03, 0, 0, 0, NULL, &m68k_amode_api_11}, /* #xxxx */
861     {0x00, 0, 0, 0, NULL, NULL},               /* <invalid> */
862 };
863 
m68k_get_src_amode(u16 opword)864 struct m68k_amode m68k_get_src_amode(u16 opword)
865 {
866     struct m68k_amode retval;
867 
868     if ((opword & 0x38) == 0x38) {
869 	if ((opword & 7) > 4) {
870 	    retval = m68k_amodes[12];
871 	} else {
872 	    retval = m68k_amodes[7 + (opword & 7)];
873 	}
874     } else {
875 	retval = m68k_amodes[(opword & 0x38) >> 3];
876     }
877     retval.reg = opword & 7;
878     return retval;
879 }
880 
m68k_get_dest_amode(u16 opword)881 struct m68k_amode m68k_get_dest_amode(u16 opword)
882 {
883     struct m68k_amode retval;
884 
885     if ((opword & 0x1c0) == 0x1c0) {
886 	if ((opword & 0xe00) > 0x800) {
887 	    retval = m68k_amodes[12];
888 	} else {
889 	    retval = m68k_amodes[7 + ((opword & 0xe00) >> 9)];
890 	}
891     } else {
892 	retval = m68k_amodes[(opword & 0x1c0) >> 6];
893     }
894     retval.reg = (opword & 0xe00) >> 9;
895     return retval;
896 }
897 
898 /*
899  * Stack operations
900  */
901 
902 /* FIXME: Why do the word stack ops use long data? */
903 
m68k_push_word(struct emu68k_context * context,u32 data)904 void m68k_push_word(struct emu68k_context *context, u32 data)
905 {
906     context->regs_a[7] -= 2;
907     emu68k_write_16(context, context->regs_a[7], data);
908 }
909 
m68k_pop_word(struct emu68k_context * context)910 u32 m68k_pop_word(struct emu68k_context *context)
911 {
912     u16 retval;
913 
914     retval = emu68k_read_16(context, context->regs_a[7]);
915     context->regs_a[7] += 2;
916 
917     return retval;
918 }
919 
m68k_push_long(struct emu68k_context * context,u32 data)920 void m68k_push_long(struct emu68k_context *context, u32 data)
921 {
922     context->regs_a[7] -= 4;
923     emu68k_write_32(context, context->regs_a[7], data);
924 }
925 
m68k_pop_long(struct emu68k_context * context)926 u32 m68k_pop_long(struct emu68k_context *context)
927 {
928     u32 retval;
929 
930     retval = emu68k_read_32(context, context->regs_a[7]);
931     context->regs_a[7] += 4;
932 
933     return retval;
934 }
935 
936 /*
937  * Opcode handlers
938  */
939 
940 #define BEGIN_OPHANDLER(instr) \
941 void m68k_do_##instr(struct emu68k_context *context, u16 opword)
942 
m68k_do_unimp(struct emu68k_context * context,u16 opword)943 void m68k_do_unimp(struct emu68k_context *context, u16 opword)
944 {
945     deb_printf("emu68k: unimplemented opcode 0x%04hx at 0x%06x.\n", opword, context->pc);
946     system_flags |= F_UNIMPL;
947     /* FIXME: signal invalid opcode */
948 }
949 
m68k_do_alinetrap(struct emu68k_context * context,u16 opword)950 void m68k_do_alinetrap(struct emu68k_context *context, u16 opword)
951 {
952     deb_printf("emu68k: A-Line trap 0x%04hx at 0x%06x.\n", opword, context->pc);
953     /* FIXME: signal a-line trap */
954 }
955 
m68k_do_flinetrap(struct emu68k_context * context,u16 opword)956 void m68k_do_flinetrap(struct emu68k_context *context, u16 opword)
957 {
958     deb_printf("emu68k: F-Line trap 0x%04hx at 0x%06x.\n", opword, context->pc);
959     /* FIXME: signal f-line trap */
960 }
961 
962 #define AMODE_CHECK_DA(side) \
963     side = m68k_get_##side##_amode(opword); \
964     if (!AMODE_IS(side, AMT_DA)) { m68k_do_unimp(context, opword); return; }
965 
966 #define AMODE_CHECK_MA(side) \
967     side = m68k_get_##side##_amode(opword); \
968     if (!AMODE_IS(side, AMT_MA)) { m68k_do_unimp(context, opword); return; }
969 
970 #define AMODE_CHECK_DATA(side) \
971     side = m68k_get_##side##_amode(opword); \
972     if (!AMODE_IS(side, AMT_DA)) { m68k_do_unimp(context, opword); return; }
973 
974 #define AMODE_CHECK_ANY(side) \
975     side = m68k_get_##side##_amode(opword); \
976     if (!side.type) { m68k_do_unimp(context, opword); return; }
977 
978 
979 #define ALU_FLAG_VC_TEST_NONE(size)
980 #define ALU_FLAG_VC_TEST_CMP(size) \
981     FLAG_VC_SUB_##size(context, data3, data2, data);
982 #define ALU_FLAG_VC_TEST_SUB(size) \
983     FLAG_VC_SUB_##size(context, data3, data2, data); FLAG_X(context);
984 #define ALU_FLAG_VC_TEST_ADD(size) \
985     FLAG_VC_ADD_##size(context, data3, data2, data); FLAG_X(context);
986 
987 
988 #define ALU_IMMED_FUNCTION(instr, size1, size2, size3, size4, op, vc_test, cycle_penalty, amode) \
989 BEGIN_OPHANDLER(instr##_##size1) { \
990     size2 data; size2 data2; size2 data3; struct m68k_amode src; \
991     AMODE_CHECK_##amode(src); \
992     data2 = emu68k_opfetch_##size4(context); \
993     src.api->resolve(&src, context, AMS_##size3); \
994     data = src.api->read##size1(&src); \
995     src.api->after(&src); \
996     data3 = data op data2; \
997     ALU_IMMED_WRITE_##amode(size1); \
998     FLAG_NZ_##size1(context, data3); \
999     ALU_FLAG_VC_TEST_##vc_test(size1); \
1000     ALU_IMMED_CYCLE_ADJUST_##size3(cycle_penalty); }
1001 
1002 #define ALU_IMMED_CYCLE_ADJUST_BYTE(cycles)
1003 #define ALU_IMMED_CYCLE_ADJUST_WORD(cycles)
1004 #define ALU_IMMED_CYCLE_ADJUST_LONG(cycles) \
1005     if (src.api == &m68k_amode_api_0) { \
1006 	context->cycles_left -= cycles; }
1007 
1008 #define ALU_IMMED_WRITE_DA(size) \
1009     src.api->write##size(&src, data3);
1010 #define ALU_IMMED_WRITE_DATA(size)
1011 
1012 ALU_IMMED_FUNCTION(SUBI, byte, u8,  BYTE, 16, -, SUB,  4, DA);
1013 ALU_IMMED_FUNCTION(SUBI, word, u16, WORD, 16, -, SUB,  4, DA);
1014 ALU_IMMED_FUNCTION(SUBI, long, u32, LONG, 32, -, SUB,  4, DA);
1015 
1016 ALU_IMMED_FUNCTION(ADDI, byte, u8,  BYTE, 16, +, ADD,  4, DA);
1017 ALU_IMMED_FUNCTION(ADDI, word, u16, WORD, 16, +, ADD,  4, DA);
1018 ALU_IMMED_FUNCTION(ADDI, long, u32, LONG, 32, +, ADD,  4, DA);
1019 
1020 ALU_IMMED_FUNCTION(ANDI, byte, u8,  BYTE, 16, &, NONE, 2, DA);
1021 ALU_IMMED_FUNCTION(ANDI, word, u16, WORD, 16, &, NONE, 2, DA);
1022 ALU_IMMED_FUNCTION(ANDI, long, u32, LONG, 32, &, NONE, 2, DA);
1023 
1024 ALU_IMMED_FUNCTION(ORI,  byte, u8,  BYTE, 16, |, NONE, 4, DA);
1025 ALU_IMMED_FUNCTION(ORI,  word, u16, WORD, 16, |, NONE, 4, DA);
1026 ALU_IMMED_FUNCTION(ORI,  long, u32, LONG, 32, |, NONE, 4, DA);
1027 
1028 ALU_IMMED_FUNCTION(EORI, byte, u8,  BYTE, 16, ^, NONE, 4, DA);
1029 ALU_IMMED_FUNCTION(EORI, word, u16, WORD, 16, ^, NONE, 4, DA);
1030 ALU_IMMED_FUNCTION(EORI, long, u32, LONG, 32, ^, NONE, 4, DA);
1031 
1032 ALU_IMMED_FUNCTION(CMPI, byte, u8,  BYTE, 16, -, CMP,  2, DATA);
1033 ALU_IMMED_FUNCTION(CMPI, word, u16, WORD, 16, -, CMP,  2, DATA);
1034 ALU_IMMED_FUNCTION(CMPI, long, u32, LONG, 32, -, CMP,  2, DATA);
1035 
1036 
1037 #define ALU_REG_FUNCTION(instr, size1, size2, size3, op, vc_test, amode, is_rmw) \
1038 BEGIN_OPHANDLER(instr##_reg_##size1) { \
1039     size2 data; size2 data2; size2 data3; struct m68k_amode src; \
1040     AMODE_CHECK_##amode(src); \
1041     src.api->resolve(&src, context, AMS_##size3); \
1042     data = context->regs_d[(opword >> 9) & 7]; \
1043     data2 = src.api->read##size1(&src); \
1044     data3 = data op data2; \
1045     FLAG_NZ_##size1(context, data3); \
1046     ALU_REG_WRITE_##is_rmw(size3); \
1047     src.api->after(&src); \
1048     ALU_FLAG_VC_TEST_##vc_test(size1); \
1049     ALU_REG_CYCLE_ADJUST_##size3; }
1050 
1051 #define ALU_REG_WRITE_YES(size) \
1052     WRITE_D_REG_##size(context, (opword >> 9) & 7, data3)
1053 #define ALU_REG_WRITE_NO(size)
1054 
1055 #define ALU_REG_CYCLE_ADJUST_BYTE
1056 #define ALU_REG_CYCLE_ADJUST_WORD
1057 #define ALU_REG_CYCLE_ADJUST_LONG \
1058     if ((src.type == 3) || ((src.type & 0xe) == 8)) { /* reg direct, immed */ \
1059 	context->cycles_left -= 4; } else { context->cycles_left -= 2; }
1060 
1061 ALU_REG_FUNCTION(AND, byte, u8,  BYTE, &, NONE, DATA, YES);
1062 ALU_REG_FUNCTION(AND, word, u16, WORD, &, NONE, DATA, YES);
1063 ALU_REG_FUNCTION(AND, long, u32, LONG, &, NONE, DATA, YES);
1064 
1065 ALU_REG_FUNCTION(OR,  byte, u8,  BYTE, |, NONE, DATA, YES);
1066 ALU_REG_FUNCTION(OR,  word, u16, WORD, |, NONE, DATA, YES);
1067 ALU_REG_FUNCTION(OR,  long, u32, LONG, |, NONE, DATA, YES);
1068 
1069 ALU_REG_FUNCTION(ADD, byte, u8,  BYTE, +, ADD,  ANY,  YES);
1070 ALU_REG_FUNCTION(ADD, word, u16, WORD, +, ADD,  ANY,  YES);
1071 ALU_REG_FUNCTION(ADD, long, u32, LONG, +, ADD,  ANY,  YES);
1072 
1073 ALU_REG_FUNCTION(SUB, byte, u8,  BYTE, -, SUB,  ANY,  YES);
1074 ALU_REG_FUNCTION(SUB, word, u16, WORD, -, SUB,  ANY,  YES);
1075 ALU_REG_FUNCTION(SUB, long, u32, LONG, -, SUB,  ANY,  YES);
1076 
1077 ALU_REG_FUNCTION(CMP, byte, u8,  BYTE, -, CMP,  DATA, NO);
1078 ALU_REG_FUNCTION(CMP, word, u16, WORD, -, CMP,  DATA, NO);
1079 ALU_REG_FUNCTION(CMP, long, u32, LONG, -, CMP,  DATA, NO);
1080 
1081 
1082 #define ALU_MEM_CYCLE_ADJUST_MA(size)
1083 #define ALU_MEM_CYCLE_ADJUST_DA(size) \
1084     ALU_MEM_CYCLE_ADJUST_DA_##size
1085 
1086 #define ALU_MEM_CYCLE_ADJUST_DA_BYTE
1087 #define ALU_MEM_CYCLE_ADJUST_DA_WORD
1088 #define ALU_MEM_CYCLE_ADJUST_DA_LONG \
1089     if (src.type == 9) { /* Dn */ context->cycles_left -= 4; }
1090 
1091 #define ALU_MEM_FUNCTION(instr, size1, size2, size3, op, vc_test, amode) \
1092 BEGIN_OPHANDLER(instr##_mem_##size1) { \
1093     size2 data; size2 data2; size2 data3; struct m68k_amode src; \
1094     AMODE_CHECK_##amode(src); \
1095     src.api->resolve(&src, context, AMS_##size3); \
1096     data2 = context->regs_d[(opword >> 9) & 7]; \
1097     data = src.api->read##size1(&src); \
1098     data3 = data op data2; \
1099     FLAG_NZ_##size1(context, data3); \
1100     src.api->write##size1(&src, data3); \
1101     src.api->after(&src); \
1102     ALU_FLAG_VC_TEST_##vc_test(size1); \
1103     ALU_MEM_CYCLE_ADJUST_##amode(size3); }
1104 
1105 
1106 ALU_MEM_FUNCTION(AND, byte,  u8, BYTE, &, NONE, MA);
1107 ALU_MEM_FUNCTION(AND, word, u16, WORD, &, NONE, MA);
1108 ALU_MEM_FUNCTION(AND, long, u32, LONG, &, NONE, MA);
1109 
1110 ALU_MEM_FUNCTION(OR,  byte,  u8, BYTE, |, NONE, MA);
1111 ALU_MEM_FUNCTION(OR,  word, u16, WORD, |, NONE, MA);
1112 ALU_MEM_FUNCTION(OR,  long, u32, LONG, |, NONE, MA);
1113 
1114 ALU_MEM_FUNCTION(ADD, byte,  u8, BYTE, +, ADD,  MA);
1115 ALU_MEM_FUNCTION(ADD, word, u16, WORD, +, ADD,  MA);
1116 ALU_MEM_FUNCTION(ADD, long, u32, LONG, +, ADD,  MA);
1117 
1118 ALU_MEM_FUNCTION(SUB, byte,  u8, BYTE, -, SUB,  MA);
1119 ALU_MEM_FUNCTION(SUB, word, u16, WORD, -, SUB,  MA);
1120 ALU_MEM_FUNCTION(SUB, long, u32, LONG, -, SUB,  MA);
1121 
1122 ALU_MEM_FUNCTION(EOR, byte,  u8, BYTE, ^, NONE, DA);
1123 ALU_MEM_FUNCTION(EOR, word, u16, WORD, ^, NONE, DA);
1124 ALU_MEM_FUNCTION(EOR, long, u32, LONG, ^, NONE, DA);
1125 
1126 
m68k_do_MOVE_byte(struct emu68k_context * context,u16 opword)1127 void m68k_do_MOVE_byte(struct emu68k_context *context, u16 opword)
1128 {
1129     struct m68k_amode src;
1130     struct m68k_amode dest;
1131     u8 data;
1132 
1133     src = m68k_get_src_amode(opword);
1134     dest = m68k_get_dest_amode(opword);
1135 
1136     if (!(AMODE_IS(dest, AMT_DA) && (src.type))) {
1137 	m68k_do_unimp(context, opword);
1138 	return;
1139     }
1140 
1141     src.api->resolve(&src, context, AMS_BYTE);
1142     dest.api->resolve(&dest, context, AMS_BYTE);
1143     data = src.api->readbyte(&src);
1144     dest.api->writebyte(&dest, data);
1145     src.api->after(&src);
1146     dest.api->after(&dest);
1147     FLAG_NZ_byte(context, data);
1148 }
1149 
m68k_do_MOVE_word(struct emu68k_context * context,u16 opword)1150 void m68k_do_MOVE_word(struct emu68k_context *context, u16 opword)
1151 {
1152     struct m68k_amode src;
1153     struct m68k_amode dest;
1154     u16 data;
1155 
1156     src = m68k_get_src_amode(opword);
1157     dest = m68k_get_dest_amode(opword);
1158 
1159     if (!(AMODE_IS(dest, AMT_DA) && (src.type))) {
1160 	m68k_do_unimp(context, opword);
1161 	return;
1162     }
1163 
1164     src.api->resolve(&src, context, AMS_WORD);
1165     dest.api->resolve(&dest, context, AMS_WORD);
1166     data = src.api->readword(&src);
1167     dest.api->writeword(&dest, data);
1168     src.api->after(&src);
1169     dest.api->after(&dest);
1170     FLAG_NZ_word(context, data);
1171 }
1172 
m68k_do_MOVEA_word(struct emu68k_context * context,u16 opword)1173 void m68k_do_MOVEA_word(struct emu68k_context *context, u16 opword)
1174 {
1175     struct m68k_amode src;
1176     s32 data;
1177 
1178     src = m68k_get_src_amode(opword);
1179 
1180     if (!src.type) {
1181 	m68k_do_unimp(context, opword);
1182 	return;
1183     }
1184 
1185     src.api->resolve(&src, context, AMS_WORD);
1186     data = (s16)src.api->readword(&src);
1187     src.api->after(&src);
1188 
1189     context->regs_a[(opword >> 9) & 7] = data;
1190 }
1191 
m68k_do_MOVE_long(struct emu68k_context * context,u16 opword)1192 void m68k_do_MOVE_long(struct emu68k_context *context, u16 opword)
1193 {
1194     struct m68k_amode src;
1195     struct m68k_amode dest;
1196     u32 data;
1197 
1198     src = m68k_get_src_amode(opword);
1199     dest = m68k_get_dest_amode(opword);
1200 
1201     if (!(AMODE_IS(dest, AMT_DA) && (src.type))) {
1202 	m68k_do_unimp(context, opword);
1203 	return;
1204     }
1205 
1206     src.api->resolve(&src, context, AMS_LONG);
1207     dest.api->resolve(&dest, context, AMS_LONG);
1208     data = src.api->readlong(&src);
1209     dest.api->writelong(&dest, data);
1210     src.api->after(&src);
1211     dest.api->after(&dest);
1212     FLAG_NZ_long(context, data);
1213 }
1214 
m68k_do_MOVEA_long(struct emu68k_context * context,u16 opword)1215 void m68k_do_MOVEA_long(struct emu68k_context *context, u16 opword)
1216 {
1217     struct m68k_amode src;
1218     u32 data;
1219 
1220     src = m68k_get_src_amode(opword);
1221 
1222     if (!src.type) {
1223 	m68k_do_unimp(context, opword);
1224 	return;
1225     }
1226 
1227     src.api->resolve(&src, context, AMS_LONG);
1228     data = src.api->readlong(&src);
1229     src.api->after(&src);
1230 
1231     context->regs_a[(opword >> 9) & 7] = data;
1232 }
1233 
m68k_do_CLR_byte(struct emu68k_context * context,u16 opword)1234 void m68k_do_CLR_byte(struct emu68k_context *context, u16 opword)
1235 {
1236     struct m68k_amode src;
1237 
1238     src = m68k_get_src_amode(opword);
1239 
1240     if (!AMODE_IS(src, AMT_DA)) {
1241 	m68k_do_unimp(context, opword);
1242 	return;
1243     }
1244 
1245     src.api->resolve(&src, context, AMS_BYTE);
1246     src.api->writebyte(&src, 0);
1247     src.api->after(&src);
1248     FLAG_NZ_byte(context, 0);
1249 }
1250 
m68k_do_CLR_word(struct emu68k_context * context,u16 opword)1251 void m68k_do_CLR_word(struct emu68k_context *context, u16 opword)
1252 {
1253     struct m68k_amode src;
1254 
1255     src = m68k_get_src_amode(opword);
1256 
1257     if (!AMODE_IS(src, AMT_DA)) {
1258 	m68k_do_unimp(context, opword);
1259 	return;
1260     }
1261 
1262     src.api->resolve(&src, context, AMS_WORD);
1263     src.api->writeword(&src, 0);
1264     src.api->after(&src);
1265     FLAG_NZ_word(context, 0);
1266 }
1267 
m68k_do_CLR_long(struct emu68k_context * context,u16 opword)1268 void m68k_do_CLR_long(struct emu68k_context *context, u16 opword)
1269 {
1270     struct m68k_amode src;
1271 
1272     src = m68k_get_src_amode(opword);
1273 
1274     if (!AMODE_IS(src, AMT_DA)) {
1275 	m68k_do_unimp(context, opword);
1276 	return;
1277     }
1278 
1279     src.api->resolve(&src, context, AMS_LONG);
1280     src.api->writelong(&src, 0);
1281     src.api->after(&src);
1282     FLAG_NZ_long(context, 0);
1283 
1284     context->cycles_left -= 2;
1285 }
1286 
m68k_do_TST_byte(struct emu68k_context * context,u16 opword)1287 void m68k_do_TST_byte(struct emu68k_context *context, u16 opword)
1288 {
1289     struct m68k_amode src;
1290     u8 data;
1291 
1292     src = m68k_get_src_amode(opword);
1293 
1294     if (!src.type) {
1295 	m68k_do_unimp(context, opword);
1296 	return;
1297     }
1298 
1299     src.api->resolve(&src, context, AMS_BYTE);
1300     data = src.api->readbyte(&src);
1301     src.api->after(&src);
1302     FLAG_NZ_byte(context, data);
1303 }
1304 
m68k_do_TST_word(struct emu68k_context * context,u16 opword)1305 void m68k_do_TST_word(struct emu68k_context *context, u16 opword)
1306 {
1307     struct m68k_amode src;
1308     u16 data;
1309 
1310     src = m68k_get_src_amode(opword);
1311 
1312     if (!src.type) {
1313 	m68k_do_unimp(context, opword);
1314 	return;
1315     }
1316 
1317     src.api->resolve(&src, context, AMS_WORD);
1318     data = src.api->readword(&src);
1319     src.api->after(&src);
1320     FLAG_NZ_word(context, data);
1321 }
1322 
m68k_do_TST_long(struct emu68k_context * context,u16 opword)1323 void m68k_do_TST_long(struct emu68k_context *context, u16 opword)
1324 {
1325     struct m68k_amode src;
1326     u32 data;
1327 
1328     src = m68k_get_src_amode(opword);
1329 
1330     if (!src.type) {
1331 	m68k_do_unimp(context, opword);
1332 	return;
1333     }
1334 
1335     src.api->resolve(&src, context, AMS_LONG);
1336     data = src.api->readlong(&src);
1337     src.api->after(&src);
1338     FLAG_NZ_long(context, data);
1339 }
1340 
m68k_do_NOT_byte(struct emu68k_context * context,u16 opword)1341 void m68k_do_NOT_byte(struct emu68k_context *context, u16 opword)
1342 {
1343     struct m68k_amode src;
1344     u8 data;
1345 
1346     src = m68k_get_src_amode(opword);
1347 
1348     if (!AMODE_IS(src, AMT_DA)) {
1349 	m68k_do_unimp(context, opword);
1350 	return;
1351     }
1352 
1353     src.api->resolve(&src, context, AMS_BYTE);
1354     data = src.api->readbyte(&src);
1355     data ^= 0xff;
1356     src.api->writebyte(&src, data);
1357     src.api->after(&src);
1358     FLAG_NZ_byte(context, data);
1359 }
1360 
m68k_do_NOT_word(struct emu68k_context * context,u16 opword)1361 void m68k_do_NOT_word(struct emu68k_context *context, u16 opword)
1362 {
1363     struct m68k_amode src;
1364     u16 data;
1365 
1366     src = m68k_get_src_amode(opword);
1367 
1368     if (!AMODE_IS(src, AMT_DA)) {
1369 	m68k_do_unimp(context, opword);
1370 	return;
1371     }
1372 
1373     src.api->resolve(&src, context, AMS_WORD);
1374     data = src.api->readword(&src);
1375     data ^= 0xffff;
1376     src.api->writeword(&src, data);
1377     src.api->after(&src);
1378     FLAG_NZ_word(context, data);
1379 }
1380 
m68k_do_NOT_long(struct emu68k_context * context,u16 opword)1381 void m68k_do_NOT_long(struct emu68k_context *context, u16 opword)
1382 {
1383     struct m68k_amode src;
1384     u32 data;
1385 
1386     src = m68k_get_src_amode(opword);
1387 
1388     if (!AMODE_IS(src, AMT_DA)) {
1389 	m68k_do_unimp(context, opword);
1390 	return;
1391     }
1392 
1393     src.api->resolve(&src, context, AMS_LONG);
1394     data = src.api->readlong(&src);
1395     data ^= 0xffffffff;
1396     src.api->writelong(&src, data);
1397     src.api->after(&src);
1398     FLAG_NZ_long(context, data);
1399     context->cycles_left -= 2;
1400 }
1401 
m68k_do_TAS(struct emu68k_context * context,u16 opword)1402 void m68k_do_TAS(struct emu68k_context *context, u16 opword)
1403 {
1404     struct m68k_amode src;
1405     u8 data;
1406 
1407     src = m68k_get_src_amode(opword);
1408 
1409     if (!AMODE_IS(src, AMT_DA)) {
1410 	m68k_do_unimp(context, opword);
1411 	return;
1412     }
1413 
1414     src.api->resolve(&src, context, AMS_BYTE);
1415     data = src.api->readbyte(&src);
1416     src.api->writebyte(&src, data | 0x80);
1417     src.api->after(&src);
1418     FLAG_NZ_byte(context, data);
1419 }
1420 
m68k_handle_Bcc(struct emu68k_context * context,u16 opword,int take_branch)1421 void m68k_handle_Bcc(struct emu68k_context *context, u16 opword, int take_branch)
1422 {
1423     s16 offset;
1424 
1425     if (!take_branch) {
1426 	if (!(opword & 0xff)) {
1427 	    offset = emu68k_opfetch_16(context);
1428 	}
1429 	context->cycles_left -= 4;
1430     } else {
1431 	offset = emu68k_opfetch_16(context);
1432 	context->pc -= 2; /* cheating, but what can you do? */
1433 
1434 	if (opword & 0xff) {
1435 	    offset = (s8)opword;
1436 	}
1437 
1438 	context->pc += offset;
1439 	context->cycles_left -= 2;
1440     }
1441 }
1442 
1443 #define Bcc_FUNCTION(instr, test) \
1444     void m68k_do_##instr(struct emu68k_context *context, u16 opword) { \
1445         m68k_handle_Bcc(context, opword, test); }
1446 
1447 Bcc_FUNCTION(BRA, 1);
1448 Bcc_FUNCTION(BHI, (!context->flag_c) && context->flag_z);
1449 Bcc_FUNCTION(BLS, (context->flag_c) || (!context->flag_z));
1450 Bcc_FUNCTION(BCC, !context->flag_c);
1451 Bcc_FUNCTION(BCS, context->flag_c);
1452 Bcc_FUNCTION(BVC, !context->flag_v);
1453 Bcc_FUNCTION(BVS, context->flag_v);
1454 Bcc_FUNCTION(BNE, context->flag_z);
1455 Bcc_FUNCTION(BEQ, !context->flag_z);
1456 Bcc_FUNCTION(BGE, (context->flag_n & 0x80)? context->flag_v: !context->flag_v);
1457 Bcc_FUNCTION(BLT, (context->flag_n & 0x80)? !context->flag_v: context->flag_v);
1458 Bcc_FUNCTION(BGT, (!context->flag_z)? 0: (context->flag_n & 0x80)? context->flag_v: !context->flag_v);
1459 Bcc_FUNCTION(BLE, (!context->flag_z)? 1: (context->flag_n & 0x80)? !context->flag_v: context->flag_v);
1460 Bcc_FUNCTION(BPL, !(context->flag_n & 0x80));
1461 Bcc_FUNCTION(BMI, context->flag_n & 0x80);
1462 
1463 
m68k_do_BSR(struct emu68k_context * context,u16 opword)1464 void m68k_do_BSR(struct emu68k_context *context, u16 opword)
1465 {
1466     s16 offset;
1467 
1468     if (opword & 0xff) {
1469 	offset = ((s8)opword);
1470 
1471 	m68k_push_long(context, context->pc);
1472     } else {
1473 	offset = emu68k_opfetch_16(context);
1474 
1475 	m68k_push_long(context, context->pc);
1476 
1477 	context->pc -= 2;
1478     }
1479 
1480     context->pc += offset;
1481 }
1482 
m68k_do_LEA(struct emu68k_context * context,u16 opword)1483 void m68k_do_LEA(struct emu68k_context *context, u16 opword)
1484 {
1485     struct m68k_amode src;
1486 
1487     src = m68k_get_src_amode(opword);
1488 
1489     if (!AMODE_IS(src, AMT_CONTROL)) {
1490 	m68k_do_unimp(context, opword);
1491 	return;
1492     }
1493 
1494     src.api->resolve(&src, context, AMS_BOGUS);
1495     context->regs_a[(opword >> 9) & 7] = src.data;
1496     src.api->after(&src);
1497 }
1498 
m68k_do_PEA(struct emu68k_context * context,u16 opword)1499 void m68k_do_PEA(struct emu68k_context *context, u16 opword)
1500 {
1501     struct m68k_amode src;
1502 
1503     src = m68k_get_src_amode(opword);
1504 
1505     if (!AMODE_IS(src, AMT_CONTROL)) {
1506 	m68k_do_unimp(context, opword);
1507 	return;
1508     }
1509 
1510     src.api->resolve(&src, context, AMS_BOGUS);
1511     m68k_push_long(context, src.data);
1512     src.api->after(&src);
1513 }
1514 
m68k_do_MOVEQ(struct emu68k_context * context,u16 opword)1515 void m68k_do_MOVEQ(struct emu68k_context *context, u16 opword)
1516 {
1517     s32 data;
1518 
1519     data = (s8)(opword & 0xff); /* NOTE: this had better work */
1520     WRITE_D_REG_LONG(context, (opword >> 9) & 7, data);
1521     FLAG_NZ_long(context, data);
1522 }
1523 
m68k_do_DBF(struct emu68k_context * context,u16 opword)1524 void m68k_do_DBF(struct emu68k_context *context, u16 opword)
1525 {
1526     s16 offset;
1527     u16 tmp;
1528     u32 new_pc;
1529 
1530     new_pc = context->pc;
1531     offset = emu68k_opfetch_16(context);
1532     new_pc += offset;
1533 
1534     tmp = context->regs_d[opword & 7] & 0xffff;
1535     tmp--;
1536     WRITE_D_REG_WORD(context, opword & 7, tmp);
1537 
1538     if (tmp == 0xffff) {
1539 	emu68k_read_16(context, new_pc); /* Stupid pipeline */
1540     } else {
1541 	context->pc = new_pc;
1542     }
1543 
1544     context->cycles_left -= 2;
1545 }
1546 
m68k_do_SF(struct emu68k_context * context,u16 opword)1547 void m68k_do_SF(struct emu68k_context *context, u16 opword)
1548 {
1549     struct m68k_amode src;
1550 
1551     src = m68k_get_src_amode(opword);
1552 
1553     if (!AMODE_IS(src, AMT_DA)) {
1554 	m68k_do_unimp(context, opword);
1555 	return;
1556     }
1557 
1558     src.api->resolve(&src, context, AMS_BYTE);
1559     src.api->writebyte(&src, 0);
1560     src.api->after(&src);
1561 }
1562 
m68k_do_BTST_dyn(struct emu68k_context * context,u16 opword)1563 void m68k_do_BTST_dyn(struct emu68k_context *context, u16 opword)
1564 {
1565     struct m68k_amode src;
1566     u16 tmp;
1567     u32 data;
1568 
1569     src = m68k_get_src_amode(opword);
1570 
1571     if (!AMODE_IS(src, AMT_DATA)) {
1572 	m68k_do_unimp(context, opword);
1573 	return;
1574     }
1575 
1576     tmp = context->regs_d[(opword >> 9) & 7];
1577 
1578     if (src.api == &m68k_amode_api_0) {
1579 	src.api->resolve(&src, context, AMS_LONG);
1580 	data = src.api->readlong(&src);
1581 	tmp &= 0x1f;
1582     } else {
1583 	src.api->resolve(&src, context, AMS_BYTE);
1584 	data = src.api->readbyte(&src);
1585 	tmp &= 7;
1586     }
1587     src.api->after(&src);
1588 
1589     context->flag_z = (data & (1 << tmp));
1590 
1591     context->cycles_left -= 2;
1592 }
1593 
m68k_do_BTST_stat(struct emu68k_context * context,u16 opword)1594 void m68k_do_BTST_stat(struct emu68k_context *context, u16 opword)
1595 {
1596     struct m68k_amode src;
1597     u16 tmp;
1598     u32 data;
1599 
1600     src = m68k_get_src_amode(opword);
1601 
1602     if (!AMODE_IS(src, AMT_DATA)) {
1603 	m68k_do_unimp(context, opword);
1604 	return;
1605     }
1606 
1607     tmp = emu68k_opfetch_16(context);
1608 
1609     if (src.api == &m68k_amode_api_0) {
1610 	src.api->resolve(&src, context, AMS_LONG);
1611 	data = src.api->readlong(&src);
1612 	tmp &= 0x1f;
1613     } else {
1614 	src.api->resolve(&src, context, AMS_BYTE);
1615 	data = src.api->readbyte(&src);
1616 	tmp &= 7;
1617     }
1618     src.api->after(&src);
1619 
1620     context->flag_z = (data & (1 << tmp));
1621 }
1622 
m68k_do_NEG_byte(struct emu68k_context * context,u16 opword)1623 void m68k_do_NEG_byte(struct emu68k_context *context, u16 opword)
1624 {
1625     struct m68k_amode src;
1626     u8 data2;
1627     u8 data3;
1628 
1629     src = m68k_get_src_amode(opword);
1630 
1631     if (!AMODE_IS(src, AMT_DA)) {
1632 	m68k_do_unimp(context, opword);
1633 	return;
1634     }
1635 
1636     src.api->resolve(&src, context, AMS_BYTE);
1637     data2 = src.api->readbyte(&src);
1638 
1639     data3 = 0 - data2;
1640     FLAG_NZ_byte(context, data3);
1641     FLAG_VC_SUB_byte(context, data3, data2, 0);
1642     FLAG_X(context);
1643 
1644     src.api->writebyte(&src, data3);
1645     src.api->after(&src);
1646 }
1647 
m68k_do_NEG_word(struct emu68k_context * context,u16 opword)1648 void m68k_do_NEG_word(struct emu68k_context *context, u16 opword)
1649 {
1650     struct m68k_amode src;
1651     u16 data2;
1652     u16 data3;
1653 
1654     src = m68k_get_src_amode(opword);
1655 
1656     if (!AMODE_IS(src, AMT_DA)) {
1657 	m68k_do_unimp(context, opword);
1658 	return;
1659     }
1660 
1661     src.api->resolve(&src, context, AMS_WORD);
1662     data2 = src.api->readword(&src);
1663 
1664     data3 = 0 - data2;
1665     FLAG_NZ_word(context, data3);
1666     FLAG_VC_SUB_word(context, data3, data2, 0);
1667     FLAG_X(context);
1668 
1669     src.api->writeword(&src, data3);
1670     src.api->after(&src);
1671 }
1672 
m68k_do_NEG_long(struct emu68k_context * context,u16 opword)1673 void m68k_do_NEG_long(struct emu68k_context *context, u16 opword)
1674 {
1675     struct m68k_amode src;
1676     u32 data2;
1677     u32 data3;
1678 
1679     src = m68k_get_src_amode(opword);
1680 
1681     if (!AMODE_IS(src, AMT_DA)) {
1682 	m68k_do_unimp(context, opword);
1683 	return;
1684     }
1685 
1686     src.api->resolve(&src, context, AMS_LONG);
1687     data2 = src.api->readlong(&src);
1688 
1689     data3 = 0 - data2;
1690     FLAG_NZ_long(context, data3);
1691     FLAG_VC_SUB_long(context, data3, data2, 0);
1692     FLAG_X(context);
1693 
1694     src.api->writelong(&src, data3);
1695     src.api->after(&src);
1696 
1697     context->cycles_left -= 2; /* FIXME: should only be for register mode */
1698 }
1699 
m68k_do_SUBA_word(struct emu68k_context * context,u16 opword)1700 void m68k_do_SUBA_word(struct emu68k_context *context, u16 opword)
1701 {
1702     struct m68k_amode src;
1703     s16 data;
1704 
1705     src = m68k_get_src_amode(opword);
1706 
1707     if (!src.type) {
1708 	m68k_do_unimp(context, opword);
1709 	return;
1710     }
1711 
1712     src.api->resolve(&src, context, AMS_WORD);
1713     data = src.api->readword(&src);
1714     src.api->after(&src);
1715     context->regs_a[(opword >> 9) & 7] -= data;
1716     context->cycles_left -= 4;
1717 }
1718 
m68k_do_SUBA_long(struct emu68k_context * context,u16 opword)1719 void m68k_do_SUBA_long(struct emu68k_context *context, u16 opword)
1720 {
1721     struct m68k_amode src;
1722     u32 data;
1723 
1724     src = m68k_get_src_amode(opword);
1725 
1726     if (!src.type) {
1727 	m68k_do_unimp(context, opword);
1728 	return;
1729     }
1730 
1731     src.api->resolve(&src, context, AMS_LONG);
1732     data = src.api->readlong(&src);
1733     src.api->after(&src);
1734     context->regs_a[(opword >> 9) & 7] -= data;
1735     context->cycles_left -= 4;
1736 }
1737 
m68k_do_SUBQ_byte(struct emu68k_context * context,u16 opword)1738 void m68k_do_SUBQ_byte(struct emu68k_context *context, u16 opword)
1739 {
1740     struct m68k_amode src;
1741     u8 data;
1742     u8 data2;
1743     u8 data3;
1744 
1745     src = m68k_get_src_amode(opword);
1746 
1747     if (!AMODE_IS(src, AMT_DA)) {
1748 	m68k_do_unimp(context, opword);
1749 	return;
1750     }
1751 
1752     data2 = (opword >> 9) & 7;
1753     if (!data2) {
1754 	data2 = 8;
1755     }
1756     src.api->resolve(&src, context, AMS_BYTE);
1757     data = src.api->readbyte(&src);
1758     data3 = data - data2;
1759     FLAG_NZ_byte(context, data3);
1760     FLAG_VC_SUB_byte(context, data3, data2, data);
1761     FLAG_X(context);
1762     src.api->writebyte(&src, data3);
1763     src.api->after(&src);
1764 }
1765 
m68k_do_SUBQ_word(struct emu68k_context * context,u16 opword)1766 void m68k_do_SUBQ_word(struct emu68k_context *context, u16 opword)
1767 {
1768     struct m68k_amode src;
1769     u16 data;
1770     u16 data2;
1771     u16 data3;
1772 
1773     src = m68k_get_src_amode(opword);
1774 
1775     if (!AMODE_IS(src, AMT_ALTERABLE)) {
1776 	m68k_do_unimp(context, opword);
1777 	return;
1778     }
1779 
1780     data2 = (opword >> 9) & 7;
1781     if (!data2) {
1782 	data2 = 8;
1783     }
1784     src.api->resolve(&src, context, AMS_WORD);
1785     data = src.api->readword(&src);
1786     data3 = data - data2;
1787     FLAG_NZ_word(context, data3);
1788     FLAG_VC_SUB_word(context, data3, data2, data);
1789     FLAG_X(context);
1790     src.api->writeword(&src, data3);
1791     src.api->after(&src);
1792 }
1793 
m68k_do_SUBQ_long(struct emu68k_context * context,u16 opword)1794 void m68k_do_SUBQ_long(struct emu68k_context *context, u16 opword)
1795 {
1796     struct m68k_amode src;
1797     u32 data;
1798     u32 data2;
1799     u32 data3;
1800 
1801     src = m68k_get_src_amode(opword);
1802 
1803     if (!AMODE_IS(src, AMT_ALTERABLE)) {
1804 	m68k_do_unimp(context, opword);
1805 	return;
1806     }
1807 
1808     data2 = (opword >> 9) & 7;
1809     if (!data2) {
1810 	data2 = 8;
1811     }
1812     src.api->resolve(&src, context, AMS_LONG);
1813     data = src.api->readlong(&src);
1814     data3 = data - data2;
1815     FLAG_NZ_long(context, data3);
1816     FLAG_VC_SUB_long(context, data3, data2, data);
1817     FLAG_X(context);
1818     src.api->writelong(&src, data3);
1819     src.api->after(&src);
1820 
1821     context->cycles_left -= 4;
1822 }
1823 
m68k_do_SUBQ_An(struct emu68k_context * context,u16 opword)1824 void m68k_do_SUBQ_An(struct emu68k_context *context, u16 opword)
1825 {
1826     u32 data;
1827 
1828     data = (opword >> 9) & 7;
1829     if (!data) {
1830 	data = 8;
1831     }
1832     context->regs_a[opword & 7] -= data;
1833     context->cycles_left -= 4;
1834 }
1835 
m68k_do_ADDQ_byte(struct emu68k_context * context,u16 opword)1836 void m68k_do_ADDQ_byte(struct emu68k_context *context, u16 opword)
1837 {
1838     struct m68k_amode src;
1839     u8 data;
1840     u8 data2;
1841     u8 data3;
1842 
1843     src = m68k_get_src_amode(opword);
1844 
1845     if (!AMODE_IS(src, AMT_DA)) {
1846 	m68k_do_unimp(context, opword);
1847 	return;
1848     }
1849 
1850     data = (opword >> 9) & 7;
1851     if (!data) {
1852 	data = 8;
1853     }
1854     src.api->resolve(&src, context, AMS_BYTE);
1855     data2 = src.api->readbyte(&src);
1856     data3 = data2 + data;
1857     FLAG_NZ_byte(context, data3);
1858     FLAG_VC_ADD_byte(context, data3, data2, data);
1859     FLAG_X(context);
1860     src.api->writebyte(&src, data3);
1861     src.api->after(&src);
1862 }
1863 
m68k_do_ADDQ_word(struct emu68k_context * context,u16 opword)1864 void m68k_do_ADDQ_word(struct emu68k_context *context, u16 opword)
1865 {
1866     struct m68k_amode src;
1867     u16 data;
1868     u16 data2;
1869     u16 data3;
1870 
1871     src = m68k_get_src_amode(opword);
1872 
1873     if (!AMODE_IS(src, AMT_ALTERABLE)) {
1874 	m68k_do_unimp(context, opword);
1875 	return;
1876     }
1877 
1878     data = (opword >> 9) & 7;
1879     if (!data) {
1880 	data = 8;
1881     }
1882     src.api->resolve(&src, context, AMS_WORD);
1883     data2 = src.api->readword(&src);
1884     data3 = data2 + data;
1885     FLAG_NZ_word(context, data3);
1886     FLAG_VC_ADD_word(context, data3, data2, data);
1887     FLAG_X(context);
1888     src.api->writeword(&src, data3);
1889     src.api->after(&src);
1890 }
1891 
m68k_do_ADDQ_long(struct emu68k_context * context,u16 opword)1892 void m68k_do_ADDQ_long(struct emu68k_context *context, u16 opword)
1893 {
1894     struct m68k_amode src;
1895     u32 data;
1896     u32 data2;
1897     u32 data3;
1898 
1899     src = m68k_get_src_amode(opword);
1900 
1901     if (!AMODE_IS(src, AMT_ALTERABLE)) {
1902 	m68k_do_unimp(context, opword);
1903 	return;
1904     }
1905 
1906     data = (opword >> 9) & 7;
1907     if (!data) {
1908 	data = 8;
1909     }
1910     src.api->resolve(&src, context, AMS_LONG);
1911     data2 = src.api->readlong(&src);
1912     data3 = data2 + data;
1913     FLAG_NZ_long(context, data3);
1914     FLAG_VC_ADD_long(context, data3, data2, data);
1915     FLAG_X(context);
1916     src.api->writelong(&src, data3);
1917     src.api->after(&src);
1918 }
1919 
m68k_do_ADDQ_An(struct emu68k_context * context,u16 opword)1920 void m68k_do_ADDQ_An(struct emu68k_context *context, u16 opword)
1921 {
1922     struct m68k_amode src;
1923     u32 data;
1924     u32 data2;
1925     u32 data3;
1926 
1927     src = m68k_get_src_amode(opword);
1928 
1929     if (!AMODE_IS(src, AMT_ALTERABLE)) {
1930 	m68k_do_unimp(context, opword);
1931 	return;
1932     }
1933 
1934     data = (opword >> 9) & 7;
1935     if (!data) {
1936 	data = 8;
1937     }
1938     src.api->resolve(&src, context, AMS_LONG);
1939     data2 = src.api->readlong(&src);
1940     data3 = data2 + data;
1941     src.api->writelong(&src, data3);
1942     src.api->after(&src);
1943 }
1944 
m68k_do_MOVE_to_CCR(struct emu68k_context * context,u16 opword)1945 void m68k_do_MOVE_to_CCR(struct emu68k_context *context, u16 opword)
1946 {
1947     struct m68k_amode src;
1948     u16 data;
1949 
1950     src = m68k_get_src_amode(opword);
1951 
1952     if (!AMODE_IS(src, AMT_DATA)) {
1953 	m68k_do_unimp(context, opword);
1954 	return;
1955     }
1956 
1957     src.api->resolve(&src, context, AMS_WORD);
1958     data = src.api->readword(&src);
1959     src.api->after(&src);
1960 
1961     data &= 0x001f;
1962     data |= emu68k_get_flags(context) & 0xffe0;
1963     emu68k_set_flags(context, data);
1964 
1965     context->cycles_left -= 8;
1966 }
1967 
m68k_do_MOVE_to_SR(struct emu68k_context * context,u16 opword)1968 void m68k_do_MOVE_to_SR(struct emu68k_context *context, u16 opword)
1969 {
1970     struct m68k_amode src;
1971     u16 data;
1972 
1973     src = m68k_get_src_amode(opword);
1974 
1975     if (!AMODE_IS(src, AMT_DATA)) {
1976 	m68k_do_unimp(context, opword);
1977 	return;
1978     }
1979 
1980     if (!(context->flags & 0x2000)) {
1981 	/* FIXME: raise TRAP */
1982 	deb_printf("m68k_do_MOVE_to_SR(): TRAP!\n");
1983 	return;
1984     }
1985 
1986     src.api->resolve(&src, context, AMS_WORD);
1987     data = src.api->readword(&src);
1988     src.api->after(&src);
1989     emu68k_set_flags(context, data);
1990     if (!(data & 0x2000)) {
1991 	u32 data2;
1992 	data2 = context->regs_a[7];
1993 	context->regs_a[7] = context->other_sp;
1994 	context->other_sp = data2;
1995     }
1996     context->cycles_left -= 8;
1997 }
1998 
m68k_do_MOVE_from_SR(struct emu68k_context * context,u16 opword)1999 void m68k_do_MOVE_from_SR(struct emu68k_context *context, u16 opword)
2000 {
2001     struct m68k_amode src;
2002 
2003     src = m68k_get_src_amode(opword);
2004 
2005     if (!AMODE_IS(src, AMT_DA)) {
2006 	m68k_do_unimp(context, opword);
2007 	return;
2008     }
2009 
2010     src.api->resolve(&src, context, AMS_WORD);
2011     src.api->writeword(&src, emu68k_get_flags(context));
2012     src.api->after(&src);
2013 
2014     context->cycles_left -= 2;
2015 }
2016 
m68k_do_MOVEM_RM_word(struct emu68k_context * context,u16 opword)2017 void m68k_do_MOVEM_RM_word(struct emu68k_context *context, u16 opword)
2018 {
2019     struct m68k_amode src;
2020     u16 reglist;
2021     u16 data;
2022     int i;
2023 
2024     src = m68k_get_src_amode(opword);
2025 
2026     if (!(AMODE_IS(src, AMT_DA) || (src.api == &m68k_amode_api_4))) {
2027 	m68k_do_unimp(context, opword);
2028 	return;
2029     }
2030 
2031     reglist = emu68k_opfetch_16(context);
2032     src.api->resolve(&src, context, AMS_WORD);
2033     if (src.api == &m68k_amode_api_4) {
2034 	for (i = 0; i < 16; i++) {
2035 	    if (reglist & (1 << i)) {
2036 		if (i & 8) {
2037 		    data = context->regs_d[(7 - i) & 7];
2038 		} else {
2039 		    data = context->regs_a[(7 - i) & 7];
2040 		}
2041 		src.api->writeword(&src, data);
2042 		src.api->after(&src);
2043 	    }
2044 	}
2045     } else {
2046 	for (i = 0; i < 16; i++) {
2047 	    if (reglist & (1 << i)) {
2048 		if (i & 8) {
2049 		    data = context->regs_a[i & 7];
2050 		} else {
2051 		    data = context->regs_d[i & 7];
2052 		}
2053 		src.api->writeword(&src, data);
2054 		src.api->after(&src);
2055 		if (src.api != &m68k_amode_api_3) {
2056 		    src.data += 2;
2057 		}
2058 	    }
2059 	}
2060     }
2061 }
2062 
m68k_do_MOVEM_RM_long(struct emu68k_context * context,u16 opword)2063 void m68k_do_MOVEM_RM_long(struct emu68k_context *context, u16 opword)
2064 {
2065     struct m68k_amode src;
2066     u32 data;
2067     u16 reglist;
2068     int i;
2069 
2070     src = m68k_get_src_amode(opword);
2071 
2072     if (!(AMODE_IS(src, AMT_DA) || (src.api == &m68k_amode_api_4))) {
2073 	m68k_do_unimp(context, opword);
2074 	return;
2075     }
2076 
2077     reglist = emu68k_opfetch_16(context);
2078     src.api->resolve(&src, context, AMS_LONG);
2079     if (src.api == &m68k_amode_api_4) {
2080 	for (i = 0; i < 16; i++) {
2081 	    if (reglist & (1 << i)) {
2082 		if (i & 8) {
2083 		    data = context->regs_d[(7 - i) & 7];
2084 		} else {
2085 		    data = context->regs_a[(7 - i) & 7];
2086 		}
2087 		src.api->writelong(&src, data);
2088 		src.api->after(&src);
2089 	    }
2090 	}
2091     } else {
2092 	for (i = 0; i < 16; i++) {
2093 	    if (reglist & (1 << i)) {
2094 		if (i & 8) {
2095 		    data = context->regs_a[i & 7];
2096 		} else {
2097 		    data = context->regs_d[i & 7];
2098 		}
2099 		src.api->writelong(&src, data);
2100 		src.api->after(&src);
2101 		if (src.api != &m68k_amode_api_3) {
2102 		    src.data += 4;
2103 		}
2104 	    }
2105 	}
2106     }
2107 }
2108 
m68k_do_MOVEM_MR_word(struct emu68k_context * context,u16 opword)2109 void m68k_do_MOVEM_MR_word(struct emu68k_context *context, u16 opword)
2110 {
2111     struct m68k_amode src;
2112     s16 data;
2113     u16 reglist;
2114     int i;
2115 
2116     src = m68k_get_src_amode(opword);
2117 
2118     if (!(AMODE_IS(src, AMT_CONTROL) || (src.api == &m68k_amode_api_3))) {
2119 	m68k_do_unimp(context, opword);
2120 	return;
2121     }
2122 
2123     reglist = emu68k_opfetch_16(context);
2124     src.api->resolve(&src, context, AMS_WORD);
2125     for (i = 0; i < 16; i++) {
2126 	if (reglist & (1 << i)) {
2127 	    data = src.api->readword(&src);
2128 	    if (i & 8) {
2129 		context->regs_a[i & 7] = data;
2130 	    } else {
2131 		context->regs_d[i & 7] = data;
2132 	    }
2133 	    src.api->after(&src);
2134 	    if (src.api != &m68k_amode_api_3) {
2135 		src.data += 2;
2136 	    }
2137 	}
2138     }
2139 }
2140 
m68k_do_MOVEM_MR_long(struct emu68k_context * context,u16 opword)2141 void m68k_do_MOVEM_MR_long(struct emu68k_context *context, u16 opword)
2142 {
2143     struct m68k_amode src;
2144     u32 data;
2145     u16 reglist;
2146     int i;
2147 
2148     src = m68k_get_src_amode(opword);
2149 
2150     if (!(AMODE_IS(src, AMT_CONTROL) || (src.api == &m68k_amode_api_3))) {
2151 	m68k_do_unimp(context, opword);
2152 	return;
2153     }
2154 
2155     reglist = emu68k_opfetch_16(context);
2156     src.api->resolve(&src, context, AMS_LONG);
2157     for (i = 0; i < 16; i++) {
2158 	if (reglist & (1 << i)) {
2159 	    data = src.api->readlong(&src);
2160 	    if (i & 8) {
2161 		context->regs_a[i & 7] = data;
2162 	    } else {
2163 		context->regs_d[i & 7] = data;
2164 	    }
2165 	    src.api->after(&src);
2166 	    if (src.api != &m68k_amode_api_3) {
2167 		src.data += 4;
2168 	    }
2169 	}
2170     }
2171 }
2172 
m68k_do_MOVE_to_USP(struct emu68k_context * context,u16 opword)2173 void m68k_do_MOVE_to_USP(struct emu68k_context *context, u16 opword)
2174 {
2175     if (!context->flags & 0x2000) {
2176 	/* FIXME: raise TRAP */
2177 	deb_printf("m68k_do_MOVE_to_USP(): TRAP!\n");
2178 	return;
2179     }
2180 
2181     context->other_sp = context->regs_a[opword & 7];
2182 }
2183 
m68k_do_MOVE_from_USP(struct emu68k_context * context,u16 opword)2184 void m68k_do_MOVE_from_USP(struct emu68k_context *context, u16 opword)
2185 {
2186     if (!context->flags & 0x2000) {
2187 	/* FIXME: raise TRAP */
2188 	deb_printf("m68k_do_MOVE_from_USP(): TRAP!\n");
2189 	return;
2190     }
2191 
2192     context->regs_a[opword & 7] = context->other_sp;
2193 }
2194 
m68k_do_ADDA_word(struct emu68k_context * context,u16 opword)2195 void m68k_do_ADDA_word(struct emu68k_context *context, u16 opword)
2196 {
2197     struct m68k_amode src;
2198     s32 data;
2199     s16 data2;
2200     s32 data3;
2201 
2202     src = m68k_get_src_amode(opword);
2203 
2204     if (!src.type) {
2205 	m68k_do_unimp(context, opword);
2206 	return;
2207     }
2208 
2209     src.api->resolve(&src, context, AMS_WORD);
2210 
2211     data = context->regs_a[(opword >> 9) & 7];
2212     data2 = src.api->readword(&src);
2213     data3 = data2 + data;
2214     context->regs_a[(opword >> 9) & 7] = data3;
2215 
2216     src.api->after(&src);
2217 
2218     context->cycles_left -= 4;
2219 }
2220 
m68k_do_ADDA_long(struct emu68k_context * context,u16 opword)2221 void m68k_do_ADDA_long(struct emu68k_context *context, u16 opword)
2222 {
2223     struct m68k_amode src;
2224     s32 data;
2225     s32 data2;
2226     s32 data3;
2227 
2228     src = m68k_get_src_amode(opword);
2229 
2230     if (!src.type) {
2231 	m68k_do_unimp(context, opword);
2232 	return;
2233     }
2234 
2235     src.api->resolve(&src, context, AMS_LONG);
2236 
2237     data = context->regs_a[(opword >> 9) & 7];
2238     data2 = src.api->readlong(&src);
2239     data3 = data2 + data;
2240     context->regs_a[(opword >> 9) & 7] = data3;
2241 
2242     src.api->after(&src);
2243 
2244     context->cycles_left -= 4;
2245 }
2246 
m68k_do_RTS(struct emu68k_context * context,u16 opword)2247 void m68k_do_RTS(struct emu68k_context *context, u16 opword)
2248 {
2249     context->pc = m68k_pop_long(context);
2250     context->cycles_left -= 4;
2251 }
2252 
m68k_do_RTE(struct emu68k_context * context,u16 opword)2253 void m68k_do_RTE(struct emu68k_context *context, u16 opword)
2254 {
2255     u16 new_flags;
2256 
2257     if (!(context->flags & 0x2000)) {
2258 	/* FIXME: raise TRAP */
2259 	deb_printf("m68k_do_MOVE_from_USP(): TRAP!\n");
2260 	return;
2261     }
2262 
2263     new_flags = m68k_pop_word(context);
2264     context->pc = m68k_pop_long(context);
2265     if ((new_flags ^ context->flags) & 0x2000) {
2266 	u32 tmp;
2267 
2268 	tmp = context->regs_a[7];
2269 	context->regs_a[7] = context->other_sp;
2270 	context->other_sp = tmp;
2271     }
2272     emu68k_set_flags(context, new_flags);
2273     context->cycles_left -= 4;
2274 }
2275 
m68k_do_SWAP(struct emu68k_context * context,u16 opword)2276 void m68k_do_SWAP(struct emu68k_context *context, u16 opword)
2277 {
2278     int reg;
2279     u32 data;
2280 
2281     reg = opword & 7;
2282     data = context->regs_d[reg];
2283     data = (data << 16) | (data >> 16);
2284     context->regs_d[reg] = data;
2285 
2286     FLAG_NZ_long(context, data);
2287 }
2288 
m68k_do_RESET(struct emu68k_context * context,u16 opword)2289 void m68k_do_RESET(struct emu68k_context *context, u16 opword)
2290 {
2291     /* FIXME: We should probably do something here. */
2292     deb_printf("emu68k: RESET.\n");
2293 }
2294 
m68k_do_NOP(struct emu68k_context * context,u16 opword)2295 void m68k_do_NOP(struct emu68k_context *context, u16 opword)
2296 {
2297 }
2298 
m68k_do_JMP(struct emu68k_context * context,u16 opword)2299 void m68k_do_JMP(struct emu68k_context *context, u16 opword)
2300 {
2301     struct m68k_amode src;
2302 
2303     src = m68k_get_src_amode(opword);
2304 
2305     if (!AMODE_IS(src, AMT_CONTROL)) {
2306 	m68k_do_unimp(context, opword);
2307 	return;
2308     }
2309 
2310     src.api->resolve(&src, context, AMS_BOGUS);
2311     context->pc = src.data;
2312     src.api->after(&src);
2313     context->cycles_left -= 4;
2314 }
2315 
m68k_do_JSR(struct emu68k_context * context,u16 opword)2316 void m68k_do_JSR(struct emu68k_context *context, u16 opword)
2317 {
2318     struct m68k_amode src;
2319 
2320     src = m68k_get_src_amode(opword);
2321 
2322     if (!AMODE_IS(src, AMT_CONTROL)) {
2323 	m68k_do_unimp(context, opword);
2324 	return;
2325     }
2326 
2327     src.api->resolve(&src, context, AMS_BOGUS);
2328     m68k_push_long(context, context->pc);
2329     context->pc = src.data;
2330     src.api->after(&src);
2331     context->cycles_left -= 4;
2332 }
2333 
m68k_do_LINK(struct emu68k_context * context,u16 opword)2334 void m68k_do_LINK(struct emu68k_context *context, u16 opword)
2335 {
2336     s16 tmp;
2337 
2338     tmp = emu68k_opfetch_16(context);
2339 
2340     m68k_push_long(context, context->regs_a[opword & 7]);
2341     context->regs_a[opword & 7] = context->regs_a[7];
2342     context->regs_a[7] += tmp; /* FIXME: make sure this sign-extends */
2343 }
2344 
m68k_do_UNLK(struct emu68k_context * context,u16 opword)2345 void m68k_do_UNLK(struct emu68k_context *context, u16 opword)
2346 {
2347     context->regs_a[7] = context->regs_a[opword & 7];
2348     context->regs_a[opword & 7] = m68k_pop_long(context);
2349 }
2350 
2351 #define GET_SHIFT_COUNT(count, opword) \
2352     if (opword & 0x0020) {             \
2353         count = context->regs_d[(opword >> 9) & 7] & 0x3f; \
2354     } else {                           \
2355         data = (opword >> 9) & 7;      \
2356         if (!data) {                   \
2357             data = 8;                  \
2358         }                              \
2359     }
2360 
2361 #define SHIFT_FUNCTION(instr, size1, size2, size3, xcheck, cycles) \
2362 BEGIN_OPHANDLER(instr##_r_##size1) { \
2363     size2 data; size2 data2; size2 data3; \
2364     GET_SHIFT_COUNT(data, opword); \
2365     data2 = context->regs_d[opword & 7]; \
2366     instr##_OPERATION(size3); \
2367     FLAG_NZ_##size1(context, data3); \
2368     instr##_FLAG_C_CHECK(size3, size2); \
2369     SHIFT_FLAG_X_CHECK_##xcheck; \
2370     WRITE_D_REG_##size3(context, opword & 7, data3); \
2371     context->cycles_left -= cycles + (data + data); \
2372 }
2373 
2374 #define HIGHBIT_BYTE 0x80
2375 #define HIGHBIT_WORD 0x8000
2376 #define HIGHBIT_LONG 0x80000000
2377 
2378 #define HIGHBYTE_BYTE 0xff
2379 #define HIGHBYTE_WORD 0xff00
2380 #define HIGHBYTE_LONG 0xff000000
2381 
2382 #define NUMBITS_BYTE 8
2383 #define NUMBITS_WORD 16
2384 #define NUMBITS_LONG 32
2385 
2386 /*
2387  * Flags here are a mess. LSL, LSR, ASL and ASR all set X and C the same
2388  * except when the shift count is 0, in which case X is unchanged and C
2389  * is cleared. ROL and ROR are the same as above with respect to C, but
2390  * don't affect X at all. ROXL and ROXR are the same as LSL, etc. with
2391  * respect to X and C except when the shift count is 0, in which case X
2392  * is again unchanged, but X is also copied into C. To top this off, all
2393  * of these instructions clear V, except ASL and ASR, which set it if the
2394  * most significant bit changes during the shift operation.
2395  *
2396  * For more fun, our current set of tests don't reflect this, and neither
2397  * does the code.
2398  *
2399  * So, there are three possible behaviors for X, and two for C and V. This
2400  * is made more complex by the fact that the behavior of C and X also vary
2401  * by the operation type (although in our case the specific difference only
2402  * affects one flag's operations, since they can be defined in terms of
2403  * each other).
2404  *
2405  *                 X          C         V
2406  * ASL/ASR:    SOMETIMES   ZEROZERO   MAYSET
2407  * LSL/LSR:    SOMETIMES   ZEROZERO   CLEAR
2408  * ROL/ROR:    NEVER       ZEROZERO   CLEAR
2409  * ROXL/ROXR:  SOMETIMES   COPYZERO   CLEAR
2410  *
2411  * Interestingly, V may only be set during ASL operations (ASR can't change
2412  * the state of the MSB by it's very nature).
2413  */
2414 
2415 #define SHIFT_FLAG_X_CHECK_NEVER
2416 #define SHIFT_FLAG_X_CHECK_SOMETIMES if (data) FLAG_X(context) \
2417                                      else context->flag_c = 0;
2418 #define SHIFT_FLAG_X_CHECK_FLAGCOPY  if (data) FLAG_X(context) \
2419                                      else context->flag_c = context->flag_x;
2420 
2421 #define LSL_OPERATION(width) \
2422     data3 = data2 << data
2423 
2424 #define LSL_FLAG_C_CHECK(width, size) \
2425     if (data2 & (HIGHBIT_##width >> (data - 1))) { \
2426         context->flag_c = 1; }
2427 
2428 SHIFT_FUNCTION(LSL, byte, u8,  BYTE, SOMETIMES, 2);
2429 SHIFT_FUNCTION(LSL, word, u16, WORD, SOMETIMES, 2);
2430 SHIFT_FUNCTION(LSL, long, u32, LONG, SOMETIMES, 4);
2431 
2432 
2433 #define LSR_OPERATION(width) \
2434     data3 = data2 >> data
2435 
2436 #define LSR_FLAG_C_CHECK(width, size) \
2437     if (data2 & (1 << (data - 1))) { \
2438 	context->flag_c = 1; }
2439 
2440 SHIFT_FUNCTION(LSR, byte, u8,  BYTE, SOMETIMES, 2);
2441 SHIFT_FUNCTION(LSR, word, u16, WORD, SOMETIMES, 2);
2442 SHIFT_FUNCTION(LSR, long, u32, LONG, SOMETIMES, 4);
2443 
2444 
2445 u8 emu68k_asl_vflag_mask_BYTE[64] = {
2446     0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
2447     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2448 
2449     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2450     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2451 
2452     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2453     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2454 
2455     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2456     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2457 };
2458 
2459 u16 emu68k_asl_vflag_mask_WORD[64] = {
2460     0x0000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
2461     0xff80, 0xffc0, 0xffe0, 0xfff0, 0xff80, 0xffc0, 0xffe0, 0xffff,
2462 
2463     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2464     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2465 
2466     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2467     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2468 
2469     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2470     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2471 };
2472 
2473 u32 emu68k_asl_vflag_mask_LONG[64] = {
2474     0x00000000, 0xc0000000, 0xe0000000, 0xf0000000,
2475     0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
2476     0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
2477     0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
2478 
2479     0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
2480     0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
2481     0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
2482     0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff,
2483 
2484     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2485     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2486     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2487     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2488 
2489     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2490     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2491     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2492     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2493 };
2494 
2495 #define ASL_OPERATION(width) LSL_OPERATION(width)
2496 #define ASL_FLAG_C_CHECK(width, size) \
2497     LSL_FLAG_C_CHECK(width, size); \
2498     if ((data3 ^ data2) & HIGHBIT_##width) { \
2499         context->flag_v = 1; \
2500     } else { \
2501         size mask; \
2502         mask = emu68k_asl_vflag_mask_##width[data]; \
2503         if (!(((data2 & mask) == 0) || ((data2 & mask) == mask))) \
2504             context->flag_v = 1; \
2505     }
2506 
2507 SHIFT_FUNCTION(ASL, byte, u8,  BYTE, SOMETIMES, 2);
2508 SHIFT_FUNCTION(ASL, word, u16, WORD, SOMETIMES, 2);
2509 SHIFT_FUNCTION(ASL, long, u32, LONG, SOMETIMES, 4);
2510 
2511 
2512 #define ASR_OPERATION(width) \
2513     data3 = data2 >> data; \
2514     if (data2 & HIGHBIT_##width) { \
2515 	data3 |= (HIGHBYTE_##width << (8 - data)); }
2516 
2517 #define ASR_FLAG_C_CHECK(width, size) LSR_FLAG_C_CHECK(width, size)
2518 
2519 SHIFT_FUNCTION(ASR, byte, u8,  BYTE, SOMETIMES, 2);
2520 SHIFT_FUNCTION(ASR, word, u16, WORD, SOMETIMES, 2);
2521 SHIFT_FUNCTION(ASR, long, u32, LONG, SOMETIMES, 4);
2522 
2523 
2524 #define ROL_OPERATION(width) \
2525     data3 = data2 << data; \
2526     data3 |= data2 >> (NUMBITS_##width - data);
2527 
2528 #define ROL_FLAG_C_CHECK(width, size) \
2529     context->flag_c = data3 & 1;
2530 
2531 SHIFT_FUNCTION(ROL, byte, u8,  BYTE, NEVER, 2);
2532 SHIFT_FUNCTION(ROL, word, u16, WORD, NEVER, 2);
2533 SHIFT_FUNCTION(ROL, long, u32, LONG, NEVER, 4);
2534 
2535 
2536 #define ROR_OPERATION(width) \
2537     data3 = data2 >> data; \
2538     data3 |= data2 << (NUMBITS_##width - data);
2539 
2540 #define ROR_FLAG_C_CHECK(width, size) \
2541     context->flag_c = data2 & (1 << (data - 1));
2542 
2543 SHIFT_FUNCTION(ROR, byte, u8,  BYTE, NEVER, 2);
2544 SHIFT_FUNCTION(ROR, word, u16, WORD, NEVER, 2);
2545 SHIFT_FUNCTION(ROR, long, u32, LONG, NEVER, 4);
2546 
2547 
2548 #define ROXL_OPERATION(width) \
2549     data3 = data2 << data; \
2550     data3 |= data2 >> ((NUMBITS_##width + 1) - data); \
2551     if (context->flag_x) { data3 |= 1 << (data - 1); }
2552 
2553 #define ROXL_FLAG_C_CHECK(width, size) \
2554     if (data2 & (HIGHBIT_##width >> (data - 1))) { \
2555 	context->flag_c = 1; }
2556 
2557 SHIFT_FUNCTION(ROXL, byte, u8,  BYTE, FLAGCOPY, 2);
2558 SHIFT_FUNCTION(ROXL, word, u16, WORD, FLAGCOPY, 2);
2559 
2560 /* Workaround for x86 masking shift count to 5 bits */
2561 #undef ROXL_OPERATION
2562 #define ROXL_OPERATION(width) \
2563     data3 = data2 << data; \
2564     if (data == 1) { data3 |= data2 >> (33 - data); } \
2565     if (data && context->flag_x) { data3 |= 1 << (data - 1); }
2566 
2567 SHIFT_FUNCTION(ROXL, long, u32, LONG, FLAGCOPY, 4);
2568 
2569 
2570 #define ROXR_OPERATION(width) \
2571     data3 = data2 >> data; \
2572     data3 |= data2 << ((NUMBITS_##width + 1) - data); \
2573     if (context->flag_x) { data3 |= (HIGHBIT_##width >> (data - 1)); }
2574 
2575 #define ROXR_FLAG_C_CHECK(width, size) \
2576     if (data) { context->flag_x = data2 & (1 << (data - 1)); } \
2577     context->flag_c = context->flag_x;
2578 
2579 SHIFT_FUNCTION(ROXR, byte, u8,  BYTE, FLAGCOPY, 2);
2580 SHIFT_FUNCTION(ROXR, word, u16, WORD, FLAGCOPY, 2);
2581 
2582 /* workaround for the x86's mod 32 shift instruction */
2583 #undef ROXR_OPERATION
2584 #define ROXR_OPERATION(width) \
2585     data3 = data2 >> data; \
2586     if (data > 1) { data3 |= data2 << (33 - data); } \
2587     if (context->flag_x && data) { data3 |= 0x80000000 >> (data - 1); }
2588 
2589 SHIFT_FUNCTION(ROXR, long, u32, LONG, FLAGCOPY, 4);
2590 
2591 
m68k_do_LSL_m(struct emu68k_context * context,u16 opword)2592 void m68k_do_LSL_m(struct emu68k_context *context, u16 opword)
2593 {
2594     u16 data;
2595     u16 data2;
2596     u16 data3;
2597     struct m68k_amode src;
2598 
2599     src = m68k_get_src_amode(opword);
2600 
2601     if (!AMODE_IS(src, AMT_DA)) {
2602 	m68k_do_unimp(context, opword);
2603 	return;
2604     }
2605 
2606     src.api->resolve(&src, context, AMS_WORD);
2607 
2608     data = 1;
2609     data2 = src.api->readword(&src);
2610     data3 = data2 << data;
2611 
2612     FLAG_NZ_word(context, data3);
2613 
2614     if (data2 & (0x8000 >> (data - 1))) {
2615 	context->flags |= 0x11;
2616     }
2617 
2618     src.api->writeword(&src, data3);
2619 
2620     src.api->after(&src);
2621 }
2622 
m68k_do_LSR_m(struct emu68k_context * context,u16 opword)2623 void m68k_do_LSR_m(struct emu68k_context *context, u16 opword)
2624 {
2625     u16 data;
2626     u16 data2;
2627     u16 data3;
2628     struct m68k_amode src;
2629 
2630     src = m68k_get_src_amode(opword);
2631 
2632     if (!AMODE_IS(src, AMT_DA)) {
2633 	m68k_do_unimp(context, opword);
2634 	return;
2635     }
2636 
2637     src.api->resolve(&src, context, AMS_WORD);
2638 
2639     data = 1;
2640     data2 = src.api->readword(&src);
2641     data3 = data2 >> data;
2642 
2643     FLAG_NZ_word(context, data3);
2644 
2645     if (data2 & (1 << (data - 1))) {
2646 	context->flags |= 0x11;
2647     }
2648 
2649     src.api->writeword(&src, data3);
2650 
2651     src.api->after(&src);
2652 }
2653 
m68k_do_ASR_m(struct emu68k_context * context,u16 opword)2654 void m68k_do_ASR_m(struct emu68k_context *context, u16 opword)
2655 {
2656     u16 data;
2657     u16 data2;
2658     u16 data3;
2659     struct m68k_amode src;
2660 
2661     src = m68k_get_src_amode(opword);
2662 
2663     if (!AMODE_IS(src, AMT_DA)) {
2664 	m68k_do_unimp(context, opword);
2665 	return;
2666     }
2667 
2668     src.api->resolve(&src, context, AMS_WORD);
2669 
2670     data = 1;
2671     data2 = src.api->readword(&src);
2672     data3 = data2 >> data;
2673 
2674     FLAG_NZ_word(context, data3);
2675 
2676     if (data2 & (1 << (data - 1))) {
2677 	context->flags |= 0x11;
2678     }
2679 
2680     src.api->writeword(&src, data3);
2681 
2682     src.api->after(&src);
2683 }
2684 
m68k_do_ROL_m(struct emu68k_context * context,u16 opword)2685 void m68k_do_ROL_m(struct emu68k_context *context, u16 opword)
2686 {
2687     u16 data;
2688     u16 data2;
2689     u16 data3;
2690     struct m68k_amode src;
2691 
2692     src = m68k_get_src_amode(opword);
2693 
2694     if (!AMODE_IS(src, AMT_DA)) {
2695 	m68k_do_unimp(context, opword);
2696 	return;
2697     }
2698 
2699     src.api->resolve(&src, context, AMS_WORD);
2700 
2701     data = 1;
2702     data2 = src.api->readword(&src);
2703     data3 = data2 << data;
2704     data3 |= data2 >> (16 - data);
2705 
2706     FLAG_NZ_word(context, data3);
2707 
2708     if (data2 & (0x8000 >> (data - 1))) {
2709 	context->flags |= 0x11;
2710     }
2711 
2712     src.api->writeword(&src, data3);
2713 
2714     src.api->after(&src);
2715 }
2716 
m68k_do_ROR_m(struct emu68k_context * context,u16 opword)2717 void m68k_do_ROR_m(struct emu68k_context *context, u16 opword)
2718 {
2719     u16 data;
2720     u16 data2;
2721     u16 data3;
2722     struct m68k_amode src;
2723 
2724     src = m68k_get_src_amode(opword);
2725 
2726     if (!AMODE_IS(src, AMT_DA)) {
2727 	m68k_do_unimp(context, opword);
2728 	return;
2729     }
2730 
2731     src.api->resolve(&src, context, AMS_WORD);
2732 
2733     data = 1;
2734     data2 = src.api->readword(&src);
2735     data3 = data2 >> data;
2736     data3 |= data2 << (16 - data);
2737 
2738     FLAG_NZ_word(context, data3);
2739 
2740     if (data2 & (1 << (data - 1))) {
2741 	context->flags |= 0x11;
2742     }
2743 
2744     src.api->writeword(&src, data3);
2745 
2746     src.api->after(&src);
2747 }
2748 
m68k_do_ROXL_m(struct emu68k_context * context,u16 opword)2749 void m68k_do_ROXL_m(struct emu68k_context *context, u16 opword)
2750 {
2751     u16 data;
2752     u16 data2;
2753     u16 data3;
2754     struct m68k_amode src;
2755 
2756     src = m68k_get_src_amode(opword);
2757 
2758     if (!AMODE_IS(src, AMT_DA)) {
2759 	m68k_do_unimp(context, opword);
2760 	return;
2761     }
2762 
2763     src.api->resolve(&src, context, AMS_WORD);
2764 
2765     data = 1;
2766     data2 = src.api->readword(&src);
2767     data3 = data2 << data;
2768     data3 |= data2 >> (15 - data);
2769     if (context->flags & 0x10) {
2770 	data3 |= 1 << (data - 1);
2771     }
2772 
2773     FLAG_NZ_word(context, data3);
2774 
2775     if (data2 & (0x8000 >> (data - 1))) {
2776 	context->flags |= 0x11;
2777     }
2778 
2779     src.api->writeword(&src, data3);
2780 
2781     src.api->after(&src);
2782 }
2783 
m68k_do_ROXR_m(struct emu68k_context * context,u16 opword)2784 void m68k_do_ROXR_m(struct emu68k_context *context, u16 opword)
2785 {
2786     u16 data;
2787     u16 data2;
2788     u16 data3;
2789     struct m68k_amode src;
2790 
2791     src = m68k_get_src_amode(opword);
2792 
2793     if (!AMODE_IS(src, AMT_DA)) {
2794 	m68k_do_unimp(context, opword);
2795 	return;
2796     }
2797 
2798     src.api->resolve(&src, context, AMS_WORD);
2799 
2800     data = 1;
2801     data2 = src.api->readword(&src);
2802     data3 = data2 >> data;
2803     data3 |= data2 << (15 - data);
2804     if (context->flags & 0x10) {
2805 	data3 |= 0x8000 >> (data - 1);
2806     }
2807 
2808     FLAG_NZ_word(context, data3);
2809 
2810     if (data2 & (1 << (data - 1))) {
2811 	context->flags |= 0x11;
2812     }
2813 
2814     src.api->writeword(&src, data3);
2815 
2816     src.api->after(&src);
2817 }
2818 
2819 /*
2820  * Decode tables
2821  */
2822 
2823 struct m68k_instr m68k_grp_0[] = {
2824     {0x0fc0, 0x0000, m68k_do_ORI_byte, "ORI.B"},
2825     {0x0fc0, 0x0040, m68k_do_ORI_word, "ORI.W"},
2826     {0x0fc0, 0x0080, m68k_do_ORI_long, "ORI.L"},
2827     {0x0fc0, 0x0200, m68k_do_ANDI_byte, "ANDI.B"},
2828     {0x0fc0, 0x0240, m68k_do_ANDI_word, "ANDI.W"},
2829     {0x0fc0, 0x0280, m68k_do_ANDI_long, "ANDI.L"},
2830     {0x0fc0, 0x0400, m68k_do_SUBI_byte, "SUBI.B"},
2831     {0x0fc0, 0x0440, m68k_do_SUBI_word, "SUBI.W"},
2832     {0x0fc0, 0x0480, m68k_do_SUBI_long, "SUBI.L"},
2833     {0x0fc0, 0x0600, m68k_do_ADDI_byte, "ADDI.B"},
2834     {0x0fc0, 0x0640, m68k_do_ADDI_word, "ADDI.W"},
2835     {0x0fc0, 0x0680, m68k_do_ADDI_long, "ADDI.L"},
2836     {0x0fc0, 0x0800, m68k_do_BTST_stat, "BTST-S"},
2837     {0x0fc0, 0x0a00, m68k_do_EORI_byte, "EORI.B"},
2838     {0x0fc0, 0x0a40, m68k_do_EORI_word, "EORI.W"},
2839     {0x0fc0, 0x0a80, m68k_do_EORI_long, "EORI.L"},
2840     {0x0fc0, 0x0c00, m68k_do_CMPI_byte, "CMPI.B"},
2841     {0x0fc0, 0x0c40, m68k_do_CMPI_word, "CMPI.W"},
2842     {0x0fc0, 0x0c80, m68k_do_CMPI_long, "CMPI.L"},
2843     {0x01c0, 0x0100, m68k_do_BTST_dyn, "BTST-D"},
2844     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2845 };
2846 
2847 struct m68k_instr m68k_grp_1[] = {
2848     {0x0000, 0x0000, m68k_do_MOVE_byte, "MOVE.B"},
2849 };
2850 
2851 struct m68k_instr m68k_grp_2[] = {
2852     {0x01c0, 0x0040, m68k_do_MOVEA_long, "MOVEA.L"},
2853     {0x0000, 0x0000, m68k_do_MOVE_long, "MOVE.L"},
2854 };
2855 
2856 struct m68k_instr m68k_grp_3[] = {
2857     {0x01c0, 0x0040, m68k_do_MOVEA_word, "MOVEA.W"},
2858     {0x0000, 0x0000, m68k_do_MOVE_word, "MOVE.W"},
2859 };
2860 
2861 struct m68k_instr m68k_grp_4[] = {
2862     {0x0fff, 0x0e70, m68k_do_RESET, "RESET"},
2863     {0x0fff, 0x0e71, m68k_do_NOP, "NOP"},
2864     {0x0fff, 0x0e73, m68k_do_RTE, "RTE"},
2865     {0x0fff, 0x0e75, m68k_do_RTS, "RTS"},
2866     {0x0ff8, 0x0e50, m68k_do_LINK, "LINK"},
2867     {0x0ff8, 0x0e58, m68k_do_UNLK, "UNLK"},
2868     {0x0ff8, 0x0e60, m68k_do_MOVE_to_USP, "MOVE to USP"},
2869 #ifdef USE_UNTESTED
2870     {0x0ff8, 0x0e68, m68k_do_MOVE_from_USP, "MOVE from USP"},
2871 #endif
2872     {0x0fc0, 0x00c0, m68k_do_MOVE_from_SR, "MOVE from SR"},
2873     {0x0fc0, 0x0200, m68k_do_CLR_byte, "CLR.B"},
2874     {0x0fc0, 0x0240, m68k_do_CLR_word, "CLR.W"},
2875     {0x0fc0, 0x0280, m68k_do_CLR_long, "CLR.L"},
2876     {0x0fc0, 0x04c0, m68k_do_MOVE_to_CCR, "MOVE to CCR"},
2877     {0x0fc0, 0x0600, m68k_do_NOT_byte, "NOT.B"},
2878     {0x0fc0, 0x0640, m68k_do_NOT_word, "NOT.W"},
2879     {0x0fc0, 0x0680, m68k_do_NOT_long, "NOT.L"},
2880     {0x0fc0, 0x06c0, m68k_do_MOVE_to_SR, "MOVE to SR"},
2881     {0x0fc0, 0x0880, m68k_do_MOVEM_RM_word, "MOVEM.W"},
2882     {0x0fc0, 0x08c0, m68k_do_MOVEM_RM_long, "MOVEM.L"},
2883     {0x0fc0, 0x0a00, m68k_do_TST_byte, "TST.B"},
2884     {0x0fc0, 0x0a40, m68k_do_TST_word, "TST.W"},
2885     {0x0fc0, 0x0a80, m68k_do_TST_long, "TST.L"},
2886 #ifdef USE_UNTESTED
2887     {0x0fc0, 0x0ac0, m68k_do_TAS, "TAS"},
2888 #endif
2889     {0x0fc0, 0x0c80, m68k_do_MOVEM_MR_word, "MOVEM.W"},
2890     {0x0fc0, 0x0cc0, m68k_do_MOVEM_MR_long, "MOVEM.L"},
2891     {0x0fc0, 0x0e80, m68k_do_JSR, "JSR"},
2892     {0x0fc0, 0x0ec0, m68k_do_JMP, "JMP"},
2893     {0x01c0, 0x01c0, m68k_do_LEA, "LEA"},
2894     {0x0ff8, 0x0840, m68k_do_SWAP, "SWAP"},
2895     {0x0fc0, 0x0840, m68k_do_PEA, "PEA"},
2896     {0x0fc0, 0x0400, m68k_do_NEG_byte, "NEG.B"},
2897     {0x0fc0, 0x0440, m68k_do_NEG_word, "NEG.W"},
2898     {0x0fc0, 0x0480, m68k_do_NEG_long, "NEG.L"},
2899     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2900 };
2901 
2902 struct m68k_instr m68k_grp_5[] = {
2903     /* FIXME: DBcc instructions come first */
2904     {0x0ff8, 0x01c8, m68k_do_DBF, "DBF"},
2905 #ifdef USE_UNTESTED
2906     {0x0fc0, 0x01c0, m68k_do_SF, "SF"},
2907 #endif
2908     {0x01c0, 0x0000, m68k_do_ADDQ_byte, "ADDQ.B"},
2909     {0x01f8, 0x0048, m68k_do_ADDQ_An, "ADDQ.W"},
2910     {0x01c0, 0x0040, m68k_do_ADDQ_word, "ADDQ.W"},
2911     {0x01f8, 0x0088, m68k_do_ADDQ_An, "ADDQ.L"},
2912     {0x01c0, 0x0080, m68k_do_ADDQ_long, "ADDQ.L"},
2913     {0x01c0, 0x0100, m68k_do_SUBQ_byte, "SUBQ.B"},
2914     {0x01f8, 0x0148, m68k_do_SUBQ_An, "SUBQ.W"},
2915     {0x01c0, 0x0140, m68k_do_SUBQ_word, "SUBQ.W"},
2916     {0x01f8, 0x0188, m68k_do_SUBQ_An, "SUBQ.L"},
2917     {0x01c0, 0x0180, m68k_do_SUBQ_long, "SUBQ.L"},
2918     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2919 };
2920 
2921 struct m68k_instr m68k_grp_6[] = {
2922     {0x0f00, 0x0000, m68k_do_BRA, "BRA"},
2923     {0x0f00, 0x0100, m68k_do_BSR, "BSR"},
2924     {0x0f00, 0x0200, m68k_do_BHI, "BHI"},
2925     {0x0f00, 0x0300, m68k_do_BLS, "BLS"},
2926     {0x0f00, 0x0400, m68k_do_BCC, "BCC"},
2927     {0x0f00, 0x0500, m68k_do_BCS, "BCS"},
2928     {0x0f00, 0x0600, m68k_do_BNE, "BNE"},
2929     {0x0f00, 0x0700, m68k_do_BEQ, "BEQ"},
2930     {0x0f00, 0x0800, m68k_do_BVC, "BVC"},
2931     {0x0f00, 0x0900, m68k_do_BVS, "BVS"},
2932     {0x0f00, 0x0a00, m68k_do_BPL, "BPL"},
2933     {0x0f00, 0x0b00, m68k_do_BMI, "BMI"},
2934     {0x0f00, 0x0c00, m68k_do_BGE, "BGE"},
2935     {0x0f00, 0x0d00, m68k_do_BLT, "BLT"},
2936     {0x0f00, 0x0e00, m68k_do_BGT, "BGT"},
2937     {0x0f00, 0x0f00, m68k_do_BLE, "BLE"},
2938     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2939 };
2940 
2941 struct m68k_instr m68k_grp_7[] = {
2942     {0x0100, 0x0000, m68k_do_MOVEQ, "MOVEQ"},
2943     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2944 };
2945 
2946 struct m68k_instr m68k_grp_8[] = {
2947     {0x01c0, 0x0000, m68k_do_OR_reg_byte, "OR.B"},
2948     {0x01c0, 0x0040, m68k_do_OR_reg_word, "OR.W"},
2949     {0x01c0, 0x0080, m68k_do_OR_reg_long, "OR.L"},
2950     {0x01c0, 0x0100, m68k_do_OR_mem_byte, "OR.B"},
2951     {0x01c0, 0x0140, m68k_do_OR_mem_word, "OR.W"},
2952     {0x01c0, 0x0180, m68k_do_OR_mem_long, "OR.L"},
2953     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2954 };
2955 
2956 struct m68k_instr m68k_grp_9[] = {
2957     {0x01c0, 0x0000, m68k_do_SUB_reg_byte, "SUB.B"},
2958     {0x01c0, 0x0040, m68k_do_SUB_reg_word, "SUB.W"},
2959     {0x01c0, 0x0080, m68k_do_SUB_reg_long, "SUB.L"},
2960     {0x01c0, 0x00c0, m68k_do_SUBA_word, "SUBA.W"},
2961     {0x01c0, 0x0100, m68k_do_SUB_mem_byte, "SUB.B"},
2962     {0x01c0, 0x0140, m68k_do_SUB_mem_word, "SUB.W"},
2963     {0x01c0, 0x0180, m68k_do_SUB_mem_long, "SUB.L"},
2964     {0x01c0, 0x01c0, m68k_do_SUBA_long, "SUBA.L"},
2965     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2966 };
2967 
2968 struct m68k_instr m68k_grp_a[] = {
2969     {0x0000, 0x0000, m68k_do_alinetrap, "A-TRAP"},
2970 };
2971 
2972 struct m68k_instr m68k_grp_b[] = {
2973     {0x01c0, 0x0000, m68k_do_CMP_reg_byte, "CMP.B"},
2974     {0x01c0, 0x0040, m68k_do_CMP_reg_word, "CMP.W"},
2975     {0x01c0, 0x0080, m68k_do_CMP_reg_long, "CMP.L"},
2976     {0x01c0, 0x0100, m68k_do_EOR_mem_byte, "EOR.B"},
2977     {0x01c0, 0x0140, m68k_do_EOR_mem_word, "EOR.W"},
2978     {0x01c0, 0x0180, m68k_do_EOR_mem_long, "EOR.L"},
2979     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2980 };
2981 
2982 struct m68k_instr m68k_grp_c[] = {
2983     {0x01c0, 0x0000, m68k_do_AND_reg_byte, "AND.B"},
2984     {0x01c0, 0x0040, m68k_do_AND_reg_word, "AND.W"},
2985     {0x01c0, 0x0080, m68k_do_AND_reg_long, "AND.L"},
2986     {0x01c0, 0x0100, m68k_do_AND_mem_byte, "AND.B"},
2987     {0x01c0, 0x0140, m68k_do_AND_mem_word, "AND.W"},
2988     {0x01c0, 0x0180, m68k_do_AND_mem_long, "AND.L"},
2989     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
2990 };
2991 
2992 struct m68k_instr m68k_grp_d[] = {
2993     {0x01c0, 0x0000, m68k_do_ADD_reg_byte, "ADD.B"},
2994     {0x01c0, 0x0040, m68k_do_ADD_reg_word, "ADD.W"},
2995     {0x01c0, 0x0080, m68k_do_ADD_reg_long, "ADD.L"},
2996     {0x01c0, 0x00c0, m68k_do_ADDA_word, "ADDA.W"},
2997     {0x01c0, 0x0100, m68k_do_ADD_mem_byte, "ADD.B"},
2998     {0x01c0, 0x0140, m68k_do_ADD_mem_word, "ADD.W"},
2999     {0x01c0, 0x0180, m68k_do_ADD_mem_long, "ADD.L"},
3000     {0x01c0, 0x01c0, m68k_do_ADDA_long, "ADDA.L"},
3001     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
3002 };
3003 
3004 struct m68k_instr m68k_grp_e[] = {
3005     {0x1d8, 0x0100, m68k_do_ASL_r_byte},
3006     {0x1d8, 0x0140, m68k_do_ASL_r_word},
3007     {0x1d8, 0x0180, m68k_do_ASL_r_long},
3008     {0x1d8, 0x0000, m68k_do_ASR_r_byte},
3009     {0x1d8, 0x0040, m68k_do_ASR_r_word},
3010     {0x1d8, 0x0080, m68k_do_ASR_r_long},
3011 #ifdef USE_UNTESTED
3012     {0xfc0, 0x00c0, m68k_do_ASR_m},
3013 #endif
3014     {0x1d8, 0x0108, m68k_do_LSL_r_byte},
3015     {0x1d8, 0x0148, m68k_do_LSL_r_word},
3016     {0x1d8, 0x0188, m68k_do_LSL_r_long},
3017 #ifdef USE_UNTESTED
3018     {0xdc0, 0x01c0, m68k_do_LSL_m},
3019 #endif
3020     {0x1d8, 0x0008, m68k_do_LSR_r_byte},
3021     {0x1d8, 0x0048, m68k_do_LSR_r_word},
3022     {0x1d8, 0x0088, m68k_do_LSR_r_long},
3023 #ifdef USE_UNTESTED
3024     {0xfc0, 0x02c0, m68k_do_LSR_m},
3025 #endif
3026     {0x1d8, 0x0010, m68k_do_ROXR_r_byte},
3027     {0x1d8, 0x0050, m68k_do_ROXR_r_word},
3028     {0x1d8, 0x0090, m68k_do_ROXR_r_long},
3029 #ifdef USE_UNTESTED
3030     {0xfc0, 0x04c0, m68k_do_ROXR_m},
3031 #endif
3032     {0x1d8, 0x0110, m68k_do_ROXL_r_byte},
3033     {0x1d8, 0x0150, m68k_do_ROXL_r_word},
3034     {0x1d8, 0x0190, m68k_do_ROXL_r_long},
3035 #ifdef USE_UNTESTED
3036     {0xfc0, 0x05c0, m68k_do_ROXL_m},
3037 #endif
3038     {0x1d8, 0x0018, m68k_do_ROR_r_byte},
3039     {0x1d8, 0x0058, m68k_do_ROR_r_word},
3040     {0x1d8, 0x0098, m68k_do_ROR_r_long},
3041 #ifdef USE_UNTESTED
3042     {0xfc0, 0x06c0, m68k_do_ROR_m},
3043 #endif
3044     {0x1d8, 0x0118, m68k_do_ROL_r_byte},
3045     {0x1d8, 0x0158, m68k_do_ROL_r_word},
3046     {0x1d8, 0x0198, m68k_do_ROL_r_long},
3047 #ifdef USE_UNTESTED
3048     {0xfc0, 0x07c0, m68k_do_ROL_m},
3049 #endif
3050     {0x0000, 0x0000, m68k_do_unimp, "<unimp>"},
3051 };
3052 
3053 struct m68k_instr m68k_grp_f[] = {
3054     {0x0000, 0x0000, m68k_do_flinetrap, "F-TRAP"},
3055 };
3056 
3057 struct m68k_instr *m68k_instrs[16] = {
3058     m68k_grp_0, m68k_grp_1, m68k_grp_2, m68k_grp_3,
3059     m68k_grp_4, m68k_grp_5, m68k_grp_6, m68k_grp_7,
3060     m68k_grp_8, m68k_grp_9, m68k_grp_a, m68k_grp_b,
3061     m68k_grp_c, m68k_grp_d, m68k_grp_e, m68k_grp_f,
3062 };
3063 
3064 /*
3065  * $Log: emu68k.c,v $
3066  * Revision 1.64  2001/03/31 19:51:57  nyef
3067  * formatting changes
3068  *
3069  * Revision 1.63  2001/03/31 17:56:23  nyef
3070  * rebuilt the Bcc wrapper functions by means of a preprocessor macro
3071  *
3072  * Revision 1.62  2001/03/31 04:27:29  nyef
3073  * fixed subtractive overflow calculations based on tests on a real '030
3074  *
3075  * Revision 1.61  2001/03/29 19:58:07  nyef
3076  * first round of shift/rotate fixes
3077  *
3078  * Revision 1.60  2001/03/28 03:26:28  nyef
3079  *     started cleaning up shift/rotate instruction flag calculation,
3080  * only to discover some problems with the test suite and my original
3081  * interpretataion of the instruction descriptions
3082  *     wrote up a comment describing the problems
3083  *
3084  * Revision 1.59  2001/03/28 00:56:31  nyef
3085  * switched from using cal_torr68k_irq() to cal_junk68k_irq() (breaks IRQs)
3086  *
3087  * Revision 1.58  2001/02/25 22:05:30  nyef
3088  * moved CAL interface code in from cal.c
3089  *
3090  * Revision 1.57  2000/12/11 18:13:17  nyef
3091  * rewrote the register and memory ALU instructions with much less code
3092  * (also, it is to be hoped, fewer bugs)
3093  *
3094  * Revision 1.56  2000/12/10 02:40:12  nyef
3095  * rewrote the 0x0xxx immediate instructions with much less code
3096  *
3097  * Revision 1.55  2000/12/10 01:33:34  nyef
3098  * rewrote the shift/rotate instructions with much less code
3099  *
3100  * Revision 1.54  2000/12/10 00:07:21  nyef
3101  * moved some code around and added a few section comments
3102  * made all control amodes use the same accessor routines
3103  *
3104  * Revision 1.53  2000/12/08 20:49:02  nyef
3105  * added dummy implementation of the RESET instruction
3106  *
3107  * Revision 1.52  2000/06/04 16:52:51  nyef
3108  * fixed and enabled all shift/rotate immediate, reg instructions
3109  *
3110  * Revision 1.51  2000/04/28 00:50:37  nyef
3111  * added SWAP and NEG instructions
3112  *
3113  * Revision 1.50  2000/04/23 18:07:46  nyef
3114  * added ADDA.L instruction
3115  *
3116  * Revision 1.49  2000/04/23 17:39:08  nyef
3117  * added PEA instruction
3118  *
3119  * Revision 1.48  2000/04/23 14:51:06  nyef
3120  * fixed immediate instructions in the 0x0xxx range (adding EORI)
3121  *
3122  * Revision 1.47  2000/04/23 03:07:25  nyef
3123  * fixed ADD instructions in the 0xdxxx range
3124  *
3125  * Revision 1.46  2000/04/23 02:43:27  nyef
3126  * fixed SUB instructions in the 0x9xxx range
3127  *
3128  * Revision 1.45  2000/04/23 01:48:48  nyef
3129  * fixed and enabled all AND and OR instructions in banks 0x8000 and 0x9000
3130  *
3131  * Revision 1.44  2000/04/22 22:52:58  nyef
3132  * added remaining conditional branch instructions
3133  *
3134  * Revision 1.43  2000/03/18 21:10:45  nyef
3135  * unified all writes to D registers behind a set of macros
3136  *
3137  * Revision 1.42  2000/03/18 19:45:00  nyef
3138  * delayed "V" flag evaluation
3139  *
3140  * Revision 1.41  2000/03/18 19:23:19  nyef
3141  * cleaned up a bit of duplication in the shift/rotate instructions
3142  *
3143  * Revision 1.40  2000/03/18 18:49:12  nyef
3144  * delayed "C" and "X" flag evaluation
3145  *
3146  * Revision 1.39  2000/03/18 18:27:13  nyef
3147  * cleaned up a "big oops" with the new flag interface
3148  *
3149  * Revision 1.38  2000/03/18 18:20:43  nyef
3150  * delayed "N" flag evaluation
3151  *
3152  * Revision 1.37  2000/03/18 18:13:25  nyef
3153  * added a new flag get/set interface
3154  * changed flag handling to use the new flag interface
3155  *
3156  * Revision 1.36  2000/03/04 22:45:23  nyef
3157  * added BHI and BLE instructions
3158  *
3159  * Revision 1.35  2000/01/14 04:39:44  nyef
3160  * added an emu68k_run() function to handle cycle-counted operation
3161  *
3162  * Revision 1.34  2000/01/14 03:56:51  nyef
3163  * fixed and enabled CMPI, ADDQ, and SUBQ instructions
3164  *
3165  * Revision 1.33  2000/01/12 03:22:59  nyef
3166  * fixed and enabled the ROXL.[BWL] ??, Dn instructions
3167  *
3168  * Revision 1.32  2000/01/09 19:41:58  nyef
3169  * fixed and enabled some more shift instructions
3170  * changed the decoding on LSL instructions to cover ASL as well
3171  *
3172  * Revision 1.31  1999/12/27 00:58:52  nyef
3173  * made it easy to re-enable all disabled instructions at once
3174  * fixed and enabled a handful more instructions
3175  *
3176  * Revision 1.30  1999/12/25 05:13:04  nyef
3177  * debugged and enabled CLR.B, CLR.W, ADDQ.W, AND.L, AND.L, ADD.L, LSR.W,
3178  *     LSR.L, and LSL.W
3179  *
3180  * Revision 1.29  1999/12/19 00:02:38  nyef
3181  * enabled BCC, BCS, CMP.W, and CMP.L
3182  *
3183  * Revision 1.28  1999/12/18 23:31:21  nyef
3184  * enabled the remaining MOVEM instructions
3185  *
3186  * Revision 1.27  1999/12/18 23:01:07  nyef
3187  * enabled LINK and UNLK instructions
3188  * fixed 16-bit write cycle cost
3189  *
3190  * Revision 1.26  1999/12/18 22:15:12  nyef
3191  * cleaned up a lot of stuff in the opcode handlers
3192  *
3193  * Revision 1.25  1999/12/18 20:31:06  nyef
3194  * fixed SUBQ.B, SUBQ.W, and SUBQ.[WL] An
3195  *
3196  * Revision 1.24  1999/12/18 18:54:55  nyef
3197  * disabled any instruction there is no test case for
3198  * added more cycle counting code
3199  * cleaned up some debug output
3200  * cleaned up an opfetch
3201  *
3202  * Revision 1.23  1999/12/18 04:24:27  nyef
3203  * cleaned up some stuff with the MOVEA instructions
3204  *
3205  * Revision 1.22  1999/12/18 04:18:44  nyef
3206  * fixed sign extension in MOVEA.W emulation
3207  *
3208  * Revision 1.21  1999/12/18 04:08:52  nyef
3209  * added SUB.B and SUB.W instruction emulation
3210  *
3211  * Revision 1.20  1999/12/18 03:05:50  nyef
3212  * added ADDA.W instruction emulation
3213  *
3214  * Revision 1.19  1999/12/18 02:43:02  nyef
3215  * changed most variable declarations to use the new type interface
3216  *
3217  * Revision 1.18  1999/12/18 01:52:30  nyef
3218  * changed ADD instructions to evaluate the X flag
3219  *
3220  * Revision 1.17  1999/12/17 02:48:20  nyef
3221  * added BPL and BMI instructions
3222  *
3223  * Revision 1.16  1999/12/17 02:21:15  nyef
3224  * added EOR instruction emulation
3225  *
3226  * Revision 1.15  1999/12/17 01:45:22  nyef
3227  * fixed a typo in m68k_do_unimp()
3228  *
3229  * Revision 1.14  1999/12/16 05:03:43  nyef
3230  * fixed cycle timing and other suchwhat in the DBF instruction
3231  *
3232  * Revision 1.13  1999/12/16 04:47:57  nyef
3233  * refactored and added cycle counts to the Bcc family of instructions
3234  *
3235  * Revision 1.12  1999/12/15 03:49:04  nyef
3236  * added implementation of the NOT instructions
3237  *
3238  * Revision 1.11  1999/12/15 03:06:25  nyef
3239  * fixed a major bug in the DBF instruction
3240  *
3241  * Revision 1.10  1999/12/15 02:32:31  nyef
3242  * fixed a bug in the stack pop long routine
3243  * added more cycle timing data
3244  *
3245  * Revision 1.9  1999/12/15 01:56:55  nyef
3246  * fixed a bug in the new 32-bit write routine
3247  *
3248  * Revision 1.8  1999/12/15 00:56:28  nyef
3249  * changed the write sequence cycle count to reflect the
3250  *   official motorola docu
3251  *
3252  * Revision 1.7  1999/12/13 03:14:38  nyef
3253  * fixed address calculation for amode 10 (PC relative indexed)
3254  * added more cycle counting code
3255  *
3256  * Revision 1.6  1999/12/12 21:49:44  nyef
3257  * created procedures to handle opword fetches
3258  * changed several opfetch operations to use the new opfetch code
3259  * added more cycle counting code
3260  *
3261  * Revision 1.5  1999/12/12 17:28:13  nyef
3262  * created procedures to handle reading and writing memory
3263  * changed a lot of memory accesses to use the new memory access code
3264  * started adding code for cycle counting
3265  *
3266  * Revision 1.4  1999/09/08 01:05:06  nyef
3267  * added numerous instructions, cleaned up numerous bugs
3268  *
3269  * Revision 1.3  1999/08/07 15:37:45  nyef
3270  * added the final amode, some debugging stuff, and one less bug
3271  *
3272  * Revision 1.2  1999/06/19 18:44:27  nyef
3273  * added preliminary implementation of amode 6 (register indirect index)
3274  *
3275  * Revision 1.1  1999/04/17 22:24:55  nyef
3276  * Initial revision
3277  *
3278  */
3279