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