]> git.proxmox.com Git - qemu.git/blame - target-m68k/translate.c
Avoid redundant TLB flushes (Daniel Jacobowitz).
[qemu.git] / target-m68k / translate.c
CommitLineData
e6e5906b
PB
1/*
2 * m68k translation
3 *
4 * Copyright (c) 2005-2006 CodeSourcery
5 * Written by Paul Brook
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <stdarg.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <inttypes.h>
26
27#include "config.h"
28#include "cpu.h"
29#include "exec-all.h"
30#include "disas.h"
31#include "m68k-qreg.h"
32
33static inline void qemu_assert(int cond, const char *msg)
34{
35 if (!cond) {
36 fprintf (stderr, "badness: %s\n", msg);
37 abort();
38 }
39}
40
41/* internal defines */
42typedef struct DisasContext {
43 target_ulong pc;
44 int is_jmp;
45 int cc_op;
46 uint32_t fpcr;
47 struct TranslationBlock *tb;
48 int singlestep_enabled;
49} DisasContext;
50
51#define DISAS_JUMP_NEXT 4
52
53/* XXX: move that elsewhere */
54/* ??? Fix exceptions. */
55static void *gen_throws_exception;
56#define gen_last_qop NULL
57
58static uint16_t *gen_opc_ptr;
59static uint32_t *gen_opparam_ptr;
60extern FILE *logfile;
61extern int loglevel;
62
63enum {
64#define DEF(s, n, copy_size) INDEX_op_ ## s,
65#include "opc.h"
66#undef DEF
67 NB_OPS,
68};
69
70#include "gen-op.h"
71#include "op-hacks.h"
72
73#define OS_BYTE 0
74#define OS_WORD 1
75#define OS_LONG 2
76#define OS_SINGLE 4
77#define OS_DOUBLE 5
78
79#define DREG(insn, pos) (((insn >> pos) & 7) + QREG_D0)
80#define AREG(insn, pos) (((insn >> pos) & 7) + QREG_A0)
81#define FREG(insn, pos) (((insn >> pos) & 7) + QREG_F0)
82
83#define M68K_INSN_CF_A (1 << 0)
84#define M68K_INSN_CF_B (1 << 1)
85#define M68K_INSN_CF_C (1 << 2)
86#define M68K_INSN_CF_MAC (1 << 3)
87#define M68K_INSN_CF_EMAC (1 << 4)
88#define M68K_INSN_CF_FPU (1 << 5)
89
90struct m68k_def_t {
91 const char * name;
92 uint32_t insns;
93};
94
95static m68k_def_t m68k_cpu_defs[] = {
96 {"m5206", M68K_INSN_CF_A},
97 {"cfv4e", M68K_INSN_CF_A | M68K_INSN_CF_B | M68K_INSN_CF_C
98 | M68K_INSN_CF_MAC | M68K_INSN_CF_EMAC | M68K_INSN_CF_FPU},
99 {NULL, 0},
100};
101
102typedef void (*disas_proc)(DisasContext *, uint16_t);
103
104#define DISAS_INSN(name) \
105 static void disas_##name (DisasContext *s, uint16_t insn)
106
107/* Generate a load from the specified address. Narrow values are
108 sign extended to full register width. */
109static inline int gen_load(int opsize, int addr, int sign)
110{
111 int tmp;
112 switch(opsize) {
113 case OS_BYTE:
114 tmp = gen_new_qreg(QMODE_I32);
115 if (sign)
116 gen_op_ld8s32(tmp, addr);
117 else
118 gen_op_ld8u32(tmp, addr);
119 break;
120 case OS_WORD:
121 tmp = gen_new_qreg(QMODE_I32);
122 if (sign)
123 gen_op_ld16s32(tmp, addr);
124 else
125 gen_op_ld16u32(tmp, addr);
126 break;
127 case OS_LONG:
128 tmp = gen_new_qreg(QMODE_I32);
129 gen_op_ld32(tmp, addr);
130 break;
131 case OS_SINGLE:
132 tmp = gen_new_qreg(QMODE_F32);
133 gen_op_ldf32(tmp, addr);
134 break;
135 case OS_DOUBLE:
136 tmp = gen_new_qreg(QMODE_F64);
137 gen_op_ldf64(tmp, addr);
138 break;
139 default:
140 qemu_assert(0, "bad load size");
141 }
142 gen_throws_exception = gen_last_qop;
143 return tmp;
144}
145
146/* Generate a store. */
147static inline void gen_store(int opsize, int addr, int val)
148{
149 switch(opsize) {
150 case OS_BYTE:
151 gen_op_st8(addr, val);
152 break;
153 case OS_WORD:
154 gen_op_st16(addr, val);
155 break;
156 case OS_LONG:
157 gen_op_st32(addr, val);
158 break;
159 case OS_SINGLE:
160 gen_op_stf32(addr, val);
161 break;
162 case OS_DOUBLE:
163 gen_op_stf64(addr, val);
164 break;
165 default:
166 qemu_assert(0, "bad store size");
167 }
168 gen_throws_exception = gen_last_qop;
169}
170
171/* Generate an unsigned load if VAL is 0 a signed load if val is -1,
172 otherwise generate a store. */
173static int gen_ldst(int opsize, int addr, int val)
174{
175 if (val > 0) {
176 gen_store(opsize, addr, val);
177 return 0;
178 } else {
179 return gen_load(opsize, addr, val != 0);
180 }
181}
182
183/* Handle a base + index + displacement effective addresss. A base of
184 -1 means pc-relative. */
185static int gen_lea_indexed(DisasContext *s, int opsize, int base)
186{
187 int scale;
188 uint32_t offset;
189 uint16_t ext;
190 int add;
191 int tmp;
192
193 offset = s->pc;
194 ext = lduw(s->pc);
195 s->pc += 2;
196 tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
197 /* ??? Check W/L bit. */
198 scale = (ext >> 9) & 3;
199 if (scale == 0) {
200 add = tmp;
201 } else {
202 add = gen_new_qreg(QMODE_I32);
203 gen_op_shl32(add, tmp, gen_im32(scale));
204 }
205 tmp = gen_new_qreg(QMODE_I32);
206 if (base != -1) {
207 gen_op_add32(tmp, base, gen_im32((int8_t)ext));
208 gen_op_add32(tmp, tmp, add);
209 } else {
210 gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
211 }
212 return tmp;
213}
214
215/* Read a 32-bit immediate constant. */
216static inline uint32_t read_im32(DisasContext *s)
217{
218 uint32_t im;
219 im = ((uint32_t)lduw(s->pc)) << 16;
220 s->pc += 2;
221 im |= lduw(s->pc);
222 s->pc += 2;
223 return im;
224}
225
226
227/* Update the CPU env CC_OP state. */
228static inline void gen_flush_cc_op(DisasContext *s)
229{
230 if (s->cc_op != CC_OP_DYNAMIC)
231 gen_op_mov32(QREG_CC_OP, gen_im32(s->cc_op));
232}
233
234/* Evaluate all the CC flags. */
235static inline void gen_flush_flags(DisasContext *s)
236{
237 if (s->cc_op == CC_OP_FLAGS)
238 return;
239 gen_op_flush_flags(s->cc_op);
240 s->cc_op = CC_OP_FLAGS;
241}
242
243static inline int opsize_bytes(int opsize)
244{
245 switch (opsize) {
246 case OS_BYTE: return 1;
247 case OS_WORD: return 2;
248 case OS_LONG: return 4;
249 case OS_SINGLE: return 4;
250 case OS_DOUBLE: return 8;
251 default:
252 qemu_assert(0, "bad operand size");
253 }
254}
255
256/* Assign value to a register. If the width is less than the register width
257 only the low part of the register is set. */
258static void gen_partset_reg(int opsize, int reg, int val)
259{
260 int tmp;
261 switch (opsize) {
262 case OS_BYTE:
263 gen_op_and32(reg, reg, gen_im32(0xffffff00));
264 tmp = gen_new_qreg(QMODE_I32);
265 gen_op_and32(tmp, val, gen_im32(0xff));
266 gen_op_or32(reg, reg, tmp);
267 break;
268 case OS_WORD:
269 gen_op_and32(reg, reg, gen_im32(0xffff0000));
270 tmp = gen_new_qreg(QMODE_I32);
271 gen_op_and32(tmp, val, gen_im32(0xffff));
272 gen_op_or32(reg, reg, tmp);
273 break;
274 case OS_LONG:
275 gen_op_mov32(reg, val);
276 break;
277 case OS_SINGLE:
278 gen_op_pack_32_f32(reg, val);
279 break;
280 default:
281 qemu_assert(0, "Bad operand size");
282 break;
283 }
284}
285
286/* Sign or zero extend a value. */
287static inline int gen_extend(int val, int opsize, int sign)
288{
289 int tmp;
290
291 switch (opsize) {
292 case OS_BYTE:
293 tmp = gen_new_qreg(QMODE_I32);
294 if (sign)
295 gen_op_ext8s32(tmp, val);
296 else
297 gen_op_ext8u32(tmp, val);
298 break;
299 case OS_WORD:
300 tmp = gen_new_qreg(QMODE_I32);
301 if (sign)
302 gen_op_ext16s32(tmp, val);
303 else
304 gen_op_ext16u32(tmp, val);
305 break;
306 case OS_LONG:
307 tmp = val;
308 break;
309 case OS_SINGLE:
310 tmp = gen_new_qreg(QMODE_F32);
311 gen_op_pack_f32_32(tmp, val);
312 break;
313 default:
314 qemu_assert(0, "Bad operand size");
315 }
316 return tmp;
317}
318
319/* Generate code for an "effective address". Does not adjust the base
320 register for autoincrememnt addressing modes. */
321static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
322{
323 int reg;
324 int tmp;
325 uint16_t ext;
326 uint32_t offset;
327
328 reg = insn & 7;
329 switch ((insn >> 3) & 7) {
330 case 0: /* Data register direct. */
331 case 1: /* Address register direct. */
332 /* ??? generate bad addressing mode fault. */
333 qemu_assert(0, "invalid addressing mode");
334 case 2: /* Indirect register */
335 case 3: /* Indirect postincrement. */
336 reg += QREG_A0;
337 return reg;
338 case 4: /* Indirect predecrememnt. */
339 reg += QREG_A0;
340 tmp = gen_new_qreg(QMODE_I32);
341 gen_op_sub32(tmp, reg, gen_im32(opsize_bytes(opsize)));
342 return tmp;
343 case 5: /* Indirect displacement. */
344 reg += QREG_A0;
345 tmp = gen_new_qreg(QMODE_I32);
346 ext = lduw(s->pc);
347 s->pc += 2;
348 gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
349 return tmp;
350 case 6: /* Indirect index + displacement. */
351 reg += QREG_A0;
352 return gen_lea_indexed(s, opsize, reg);
353 case 7: /* Other */
354 switch (reg) {
355 case 0: /* Absolute short. */
356 offset = ldsw(s->pc);
357 s->pc += 2;
358 return gen_im32(offset);
359 case 1: /* Absolute long. */
360 offset = read_im32(s);
361 return gen_im32(offset);
362 case 2: /* pc displacement */
363 tmp = gen_new_qreg(QMODE_I32);
364 offset = s->pc;
365 offset += ldsw(s->pc);
366 s->pc += 2;
367 return gen_im32(offset);
368 case 3: /* pc index+displacement. */
369 return gen_lea_indexed(s, opsize, -1);
370 case 4: /* Immediate. */
371 default:
372 /* ??? generate bad addressing mode fault. */
373 qemu_assert(0, "invalid addressing mode");
374 }
375 }
376 /* Should never happen. */
377 return -1;
378}
379
380/* Helper function for gen_ea. Reuse the computed address between the
381 for read/write operands. */
382static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
383 int val, int *addrp)
384{
385 int tmp;
386
387 if (addrp && val > 0) {
388 tmp = *addrp;
389 } else {
390 tmp = gen_lea(s, insn, opsize);
391 if (addrp)
392 *addrp = tmp;
393 }
394 return gen_ldst(opsize, tmp, val);
395}
396
397/* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
398 a write otherwise it is a read (0 == sign extend, -1 == zero extend).
399 ADDRP is non-null for readwrite operands. */
400static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
401 int *addrp)
402{
403 int reg;
404 int result;
405 uint32_t offset;
406
407 reg = insn & 7;
408 switch ((insn >> 3) & 7) {
409 case 0: /* Data register direct. */
410 reg += QREG_D0;
411 if (val > 0) {
412 gen_partset_reg(opsize, reg, val);
413 return 0;
414 } else {
415 return gen_extend(reg, opsize, val);
416 }
417 case 1: /* Address register direct. */
418 reg += QREG_A0;
419 if (val > 0) {
420 gen_op_mov32(reg, val);
421 return 0;
422 } else {
423 return gen_extend(reg, opsize, val);
424 }
425 case 2: /* Indirect register */
426 reg += QREG_A0;
427 return gen_ldst(opsize, reg, val);
428 case 3: /* Indirect postincrement. */
429 reg += QREG_A0;
430 result = gen_ldst(opsize, reg, val);
431 /* ??? This is not exception safe. The instruction may still
432 fault after this point. */
433 if (val > 0 || !addrp)
434 gen_op_add32(reg, reg, gen_im32(opsize_bytes(opsize)));
435 return result;
436 case 4: /* Indirect predecrememnt. */
437 {
438 int tmp;
439 if (addrp && val > 0) {
440 tmp = *addrp;
441 } else {
442 tmp = gen_lea(s, insn, opsize);
443 if (addrp)
444 *addrp = tmp;
445 }
446 result = gen_ldst(opsize, tmp, val);
447 /* ??? This is not exception safe. The instruction may still
448 fault after this point. */
449 if (val > 0 || !addrp) {
450 reg += QREG_A0;
451 gen_op_mov32(reg, tmp);
452 }
453 }
454 return result;
455 case 5: /* Indirect displacement. */
456 case 6: /* Indirect index + displacement. */
457 return gen_ea_once(s, insn, opsize, val, addrp);
458 case 7: /* Other */
459 switch (reg) {
460 case 0: /* Absolute short. */
461 case 1: /* Absolute long. */
462 case 2: /* pc displacement */
463 case 3: /* pc index+displacement. */
464 return gen_ea_once(s, insn, opsize, val, addrp);
465 case 4: /* Immediate. */
466 /* Sign extend values for consistency. */
467 switch (opsize) {
468 case OS_BYTE:
469 if (val)
470 offset = ldsb(s->pc + 1);
471 else
472 offset = ldub(s->pc + 1);
473 s->pc += 2;
474 break;
475 case OS_WORD:
476 if (val)
477 offset = ldsw(s->pc);
478 else
479 offset = lduw(s->pc);
480 s->pc += 2;
481 break;
482 case OS_LONG:
483 offset = read_im32(s);
484 break;
485 default:
486 qemu_assert(0, "Bad immediate operand");
487 }
488 return gen_im32(offset);
489 default:
490 qemu_assert(0, "invalid addressing mode");
491 }
492 }
493 /* Should never happen. */
494 return -1;
495}
496
497static void gen_logic_cc(DisasContext *s, int val)
498{
499 gen_op_logic_cc(val);
500 s->cc_op = CC_OP_LOGIC;
501}
502
503static void gen_jmpcc(DisasContext *s, int cond, int l1)
504{
505 int tmp;
506
507 gen_flush_flags(s);
508 switch (cond) {
509 case 0: /* T */
510 gen_op_jmp(l1);
511 break;
512 case 1: /* F */
513 break;
514 case 2: /* HI (!C && !Z) */
515 tmp = gen_new_qreg(QMODE_I32);
516 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
517 gen_op_jmp_z32(tmp, l1);
518 break;
519 case 3: /* LS (C || Z) */
520 tmp = gen_new_qreg(QMODE_I32);
521 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
522 gen_op_jmp_nz32(tmp, l1);
523 break;
524 case 4: /* CC (!C) */
525 tmp = gen_new_qreg(QMODE_I32);
526 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
527 gen_op_jmp_z32(tmp, l1);
528 break;
529 case 5: /* CS (C) */
530 tmp = gen_new_qreg(QMODE_I32);
531 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
532 gen_op_jmp_nz32(tmp, l1);
533 break;
534 case 6: /* NE (!Z) */
535 tmp = gen_new_qreg(QMODE_I32);
536 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
537 gen_op_jmp_z32(tmp, l1);
538 break;
539 case 7: /* EQ (Z) */
540 tmp = gen_new_qreg(QMODE_I32);
541 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
542 gen_op_jmp_nz32(tmp, l1);
543 break;
544 case 8: /* VC (!V) */
545 tmp = gen_new_qreg(QMODE_I32);
546 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
547 gen_op_jmp_z32(tmp, l1);
548 break;
549 case 9: /* VS (V) */
550 tmp = gen_new_qreg(QMODE_I32);
551 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
552 gen_op_jmp_nz32(tmp, l1);
553 break;
554 case 10: /* PL (!N) */
555 tmp = gen_new_qreg(QMODE_I32);
556 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
557 gen_op_jmp_z32(tmp, l1);
558 break;
559 case 11: /* MI (N) */
560 tmp = gen_new_qreg(QMODE_I32);
561 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
562 gen_op_jmp_nz32(tmp, l1);
563 break;
564 case 12: /* GE (!(N ^ V)) */
565 tmp = gen_new_qreg(QMODE_I32);
566 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
567 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
568 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
569 gen_op_jmp_z32(tmp, l1);
570 break;
571 case 13: /* LT (N ^ V) */
572 tmp = gen_new_qreg(QMODE_I32);
573 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
574 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
575 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
576 gen_op_jmp_nz32(tmp, l1);
577 break;
578 case 14: /* GT (!(Z || (N ^ V))) */
579 {
580 int l2;
581 l2 = gen_new_label();
582 tmp = gen_new_qreg(QMODE_I32);
583 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
584 gen_op_jmp_nz32(tmp, l2);
585 tmp = gen_new_qreg(QMODE_I32);
586 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
587 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
588 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
589 gen_op_jmp_nz32(tmp, l2);
590 gen_op_jmp(l1);
591 gen_set_label(l2);
592 }
593 break;
594 case 15: /* LE (Z || (N ^ V)) */
595 tmp = gen_new_qreg(QMODE_I32);
596 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
597 gen_op_jmp_nz32(tmp, l1);
598 tmp = gen_new_qreg(QMODE_I32);
599 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
600 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
601 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
602 gen_op_jmp_nz32(tmp, l1);
603 break;
604 default:
605 /* Should ever happen. */
606 abort();
607 }
608}
609
610DISAS_INSN(scc)
611{
612 int l1;
613 int cond;
614 int reg;
615
616 l1 = gen_new_label();
617 cond = (insn >> 8) & 0xf;
618 reg = DREG(insn, 0);
619 gen_op_and32(reg, reg, gen_im32(0xffffff00));
620 gen_jmpcc(s, cond ^ 1, l1);
621 gen_op_or32(reg, reg, gen_im32(0xff));
622 gen_set_label(l1);
623}
624
625/* Generate a jump to to the address in qreg DEST. */
626static void gen_jmp(DisasContext *s, int dest)
627{
628 gen_flush_cc_op(s);
629 gen_op_mov32(QREG_PC, dest);
630 s->is_jmp = DISAS_JUMP;
631}
632
633static void gen_exception(DisasContext *s, uint32_t where, int nr)
634{
635 gen_flush_cc_op(s);
636 gen_jmp(s, gen_im32(where));
637 gen_op_raise_exception(nr);
638}
639
640/* Generate a jump to an immediate address. */
641static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
642{
643 TranslationBlock *tb;
644
645 tb = s->tb;
646 if (__builtin_expect (s->singlestep_enabled, 0)) {
647 gen_exception(s, dest, EXCP_DEBUG);
648 } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
649 (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
650 gen_op_goto_tb(0, n, (long)tb);
651 gen_op_mov32(QREG_PC, gen_im32(dest));
652 gen_op_mov32(QREG_T0, gen_im32((long)tb + n));
653 gen_op_exit_tb();
654 } else {
655 gen_jmp(s, gen_im32(dest));
656 gen_op_mov32(QREG_T0, gen_im32(0));
657 gen_op_exit_tb();
658 }
659 s->is_jmp = DISAS_TB_JUMP;
660}
661
662DISAS_INSN(undef_mac)
663{
664 gen_exception(s, s->pc - 2, EXCP_LINEA);
665}
666
667DISAS_INSN(undef_fpu)
668{
669 gen_exception(s, s->pc - 2, EXCP_LINEF);
670}
671
672DISAS_INSN(undef)
673{
674 gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
675 cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
676 insn, s->pc - 2);
677}
678
679DISAS_INSN(mulw)
680{
681 int reg;
682 int tmp;
683 int src;
684 int sign;
685
686 sign = (insn & 0x100) != 0;
687 reg = DREG(insn, 9);
688 tmp = gen_new_qreg(QMODE_I32);
689 if (sign)
690 gen_op_ext16s32(tmp, reg);
691 else
692 gen_op_ext16u32(tmp, reg);
693 src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
694 gen_op_mul32(tmp, tmp, src);
695 gen_op_mov32(reg, tmp);
696 /* Unlike m68k, coldfire always clears the overflow bit. */
697 gen_logic_cc(s, tmp);
698}
699
700DISAS_INSN(divw)
701{
702 int reg;
703 int tmp;
704 int src;
705 int sign;
706
707 sign = (insn & 0x100) != 0;
708 reg = DREG(insn, 9);
709 if (sign) {
710 gen_op_ext16s32(QREG_DIV1, reg);
711 } else {
712 gen_op_ext16u32(QREG_DIV1, reg);
713 }
714 src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
715 gen_op_mov32(QREG_DIV2, src);
716 if (sign) {
717 gen_op_divs(1);
718 } else {
719 gen_op_divu(1);
720 }
721
722 tmp = gen_new_qreg(QMODE_I32);
723 src = gen_new_qreg(QMODE_I32);
724 gen_op_ext16u32(tmp, QREG_DIV1);
725 gen_op_shl32(src, QREG_DIV2, gen_im32(16));
726 gen_op_or32(reg, tmp, src);
727 gen_op_flags_set();
728 s->cc_op = CC_OP_FLAGS;
729}
730
731DISAS_INSN(divl)
732{
733 int num;
734 int den;
735 int reg;
736 uint16_t ext;
737
738 ext = lduw(s->pc);
739 s->pc += 2;
740 if (ext & 0x87f8) {
741 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
742 return;
743 }
744 num = DREG(ext, 12);
745 reg = DREG(ext, 0);
746 gen_op_mov32(QREG_DIV1, num);
747 den = gen_ea(s, insn, OS_LONG, 0, NULL);
748 gen_op_mov32(QREG_DIV2, den);
749 if (ext & 0x0800) {
750 gen_op_divs(0);
751 } else {
752 gen_op_divu(0);
753 }
754 if (num == reg) {
755 /* div */
756 gen_op_mov32 (reg, QREG_DIV1);
757 } else {
758 /* rem */
759 gen_op_mov32 (reg, QREG_DIV2);
760 }
761 gen_op_flags_set();
762 s->cc_op = CC_OP_FLAGS;
763}
764
765DISAS_INSN(addsub)
766{
767 int reg;
768 int dest;
769 int src;
770 int tmp;
771 int addr;
772 int add;
773
774 add = (insn & 0x4000) != 0;
775 reg = DREG(insn, 9);
776 dest = gen_new_qreg(QMODE_I32);
777 if (insn & 0x100) {
778 tmp = gen_ea(s, insn, OS_LONG, 0, &addr);
779 src = reg;
780 } else {
781 tmp = reg;
782 src = gen_ea(s, insn, OS_LONG, 0, NULL);
783 }
784 if (add) {
785 gen_op_add32(dest, tmp, src);
786 gen_op_update_xflag_lt(dest, src);
787 s->cc_op = CC_OP_ADD;
788 } else {
789 gen_op_update_xflag_lt(tmp, src);
790 gen_op_sub32(dest, tmp, src);
791 s->cc_op = CC_OP_SUB;
792 }
793 gen_op_update_cc_add(dest, src);
794 if (insn & 0x100) {
795 gen_ea(s, insn, OS_LONG, dest, &addr);
796 } else {
797 gen_op_mov32(reg, dest);
798 }
799}
800
801
802/* Reverse the order of the bits in REG. */
803DISAS_INSN(bitrev)
804{
805 int val;
806 int tmp1;
807 int tmp2;
808 int reg;
809
810 val = gen_new_qreg(QMODE_I32);
811 tmp1 = gen_new_qreg(QMODE_I32);
812 tmp2 = gen_new_qreg(QMODE_I32);
813 reg = DREG(insn, 0);
814 gen_op_mov32(val, reg);
815 /* Reverse bits within each nibble. */
816 gen_op_shl32(tmp1, val, gen_im32(3));
817 gen_op_and32(tmp1, tmp1, gen_im32(0x88888888));
818 gen_op_shl32(tmp2, val, gen_im32(1));
819 gen_op_and32(tmp2, tmp2, gen_im32(0x44444444));
820 gen_op_or32(tmp1, tmp1, tmp2);
821 gen_op_shr32(tmp2, val, gen_im32(1));
822 gen_op_and32(tmp2, tmp2, gen_im32(0x22222222));
823 gen_op_or32(tmp1, tmp1, tmp2);
824 gen_op_shr32(tmp2, val, gen_im32(3));
825 gen_op_and32(tmp2, tmp2, gen_im32(0x11111111));
826 gen_op_or32(tmp1, tmp1, tmp2);
827 /* Reverse nibbles withing bytes. */
828 gen_op_shl32(val, tmp1, gen_im32(4));
829 gen_op_and32(val, val, gen_im32(0xf0f0f0f0));
830 gen_op_shr32(tmp2, tmp1, gen_im32(4));
831 gen_op_and32(tmp2, tmp2, gen_im32(0x0f0f0f0f));
832 gen_op_or32(val, val, tmp2);
833 /* Reverse bytes. */
834 gen_op_bswap32(reg, val);
835 gen_op_mov32(reg, val);
836}
837
838DISAS_INSN(bitop_reg)
839{
840 int opsize;
841 int op;
842 int src1;
843 int src2;
844 int tmp;
845 int addr;
846 int dest;
847
848 if ((insn & 0x38) != 0)
849 opsize = OS_BYTE;
850 else
851 opsize = OS_LONG;
852 op = (insn >> 6) & 3;
853 src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
854 src2 = DREG(insn, 9);
855 dest = gen_new_qreg(QMODE_I32);
856
857 gen_flush_flags(s);
858 tmp = gen_new_qreg(QMODE_I32);
859 if (opsize == OS_BYTE)
860 gen_op_and32(tmp, src2, gen_im32(7));
861 else
862 gen_op_and32(tmp, src2, gen_im32(31));
863 src2 = tmp;
864 tmp = gen_new_qreg(QMODE_I32);
865 gen_op_shl32(tmp, gen_im32(1), src2);
866
867 gen_op_btest(src1, tmp);
868 switch (op) {
869 case 1: /* bchg */
870 gen_op_xor32(dest, src1, tmp);
871 break;
872 case 2: /* bclr */
873 gen_op_not32(tmp, tmp);
874 gen_op_and32(dest, src1, tmp);
875 break;
876 case 3: /* bset */
877 gen_op_or32(dest, src1, tmp);
878 break;
879 default: /* btst */
880 break;
881 }
882 if (op)
883 gen_ea(s, insn, opsize, dest, &addr);
884}
885
886DISAS_INSN(sats)
887{
888 int reg;
889 int tmp;
890 int l1;
891
892 reg = DREG(insn, 0);
893 tmp = gen_new_qreg(QMODE_I32);
894 gen_flush_flags(s);
895 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
896 l1 = gen_new_label();
897 gen_op_jmp_z32(tmp, l1);
898 tmp = gen_new_qreg(QMODE_I32);
899 gen_op_shr32(tmp, reg, gen_im32(31));
900 gen_op_xor32(tmp, tmp, gen_im32(0x80000000));
901 gen_op_mov32(reg, tmp);
902 gen_set_label(l1);
903 gen_logic_cc(s, tmp);
904}
905
906static void gen_push(int val)
907{
908 int tmp;
909
910 tmp = gen_new_qreg(QMODE_I32);
911 gen_op_sub32(tmp, QREG_SP, gen_im32(4));
912 gen_store(OS_LONG, tmp, val);
913 gen_op_mov32(QREG_SP, tmp);
914}
915
916DISAS_INSN(movem)
917{
918 int addr;
919 int i;
920 uint16_t mask;
921 int reg;
922 int tmp;
923 int is_load;
924
925 mask = lduw(s->pc);
926 s->pc += 2;
927 tmp = gen_lea(s, insn, OS_LONG);
928 addr = gen_new_qreg(QMODE_I32);
929 gen_op_mov32(addr, tmp);
930 is_load = ((insn & 0x0400) != 0);
931 for (i = 0; i < 16; i++, mask >>= 1) {
932 if (mask & 1) {
933 if (i < 8)
934 reg = DREG(i, 0);
935 else
936 reg = AREG(i, 0);
937 if (is_load) {
938 tmp = gen_load(OS_LONG, addr, 0);
939 gen_op_mov32(reg, tmp);
940 } else {
941 gen_store(OS_LONG, addr, reg);
942 }
943 if (mask != 1)
944 gen_op_add32(addr, addr, gen_im32(4));
945 }
946 }
947}
948
949DISAS_INSN(bitop_im)
950{
951 int opsize;
952 int op;
953 int src1;
954 uint32_t mask;
955 int bitnum;
956 int tmp;
957 int addr;
958 int dest;
959
960 if ((insn & 0x38) != 0)
961 opsize = OS_BYTE;
962 else
963 opsize = OS_LONG;
964 op = (insn >> 6) & 3;
965
966 bitnum = lduw(s->pc);
967 s->pc += 2;
968 if (bitnum & 0xff00) {
969 disas_undef(s, insn);
970 return;
971 }
972
973 src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
974
975 gen_flush_flags(s);
976 tmp = gen_new_qreg(QMODE_I32);
977 if (opsize == OS_BYTE)
978 bitnum &= 7;
979 else
980 bitnum &= 31;
981 mask = 1 << bitnum;
982
983 gen_op_btest(src1, gen_im32(mask));
984 if (op)
985 dest = gen_new_qreg(QMODE_I32);
986 else
987 dest = -1;
988
989 switch (op) {
990 case 1: /* bchg */
991 gen_op_xor32(dest, src1, gen_im32(mask));
992 break;
993 case 2: /* bclr */
994 gen_op_and32(dest, src1, gen_im32(~mask));
995 break;
996 case 3: /* bset */
997 gen_op_or32(dest, src1, gen_im32(mask));
998 break;
999 default: /* btst */
1000 break;
1001 }
1002 if (op)
1003 gen_ea(s, insn, opsize, dest, &addr);
1004}
1005
1006DISAS_INSN(arith_im)
1007{
1008 int op;
1009 int src1;
1010 int dest;
1011 int src2;
1012 int addr;
1013
1014 op = (insn >> 9) & 7;
1015 src1 = gen_ea(s, insn, OS_LONG, 0, (op == 6) ? NULL : &addr);
1016 src2 = gen_im32(read_im32(s));
1017 dest = gen_new_qreg(QMODE_I32);
1018 switch (op) {
1019 case 0: /* ori */
1020 gen_op_or32(dest, src1, src2);
1021 gen_logic_cc(s, dest);
1022 break;
1023 case 1: /* andi */
1024 gen_op_and32(dest, src1, src2);
1025 gen_logic_cc(s, dest);
1026 break;
1027 case 2: /* subi */
1028 gen_op_mov32(dest, src1);
1029 gen_op_update_xflag_lt(dest, src2);
1030 gen_op_sub32(dest, dest, src2);
1031 gen_op_update_cc_add(dest, src2);
1032 s->cc_op = CC_OP_SUB;
1033 break;
1034 case 3: /* addi */
1035 gen_op_mov32(dest, src1);
1036 gen_op_add32(dest, dest, src2);
1037 gen_op_update_cc_add(dest, src2);
1038 gen_op_update_xflag_lt(dest, src2);
1039 s->cc_op = CC_OP_ADD;
1040 break;
1041 case 5: /* eori */
1042 gen_op_xor32(dest, src1, src2);
1043 gen_logic_cc(s, dest);
1044 break;
1045 case 6: /* cmpi */
1046 gen_op_mov32(dest, src1);
1047 gen_op_sub32(dest, dest, src2);
1048 gen_op_update_cc_add(dest, src2);
1049 s->cc_op = CC_OP_SUB;
1050 break;
1051 default:
1052 abort();
1053 }
1054 if (op != 6) {
1055 gen_ea(s, insn, OS_LONG, dest, &addr);
1056 }
1057}
1058
1059DISAS_INSN(byterev)
1060{
1061 int reg;
1062
1063 reg = DREG(insn, 0);
1064 gen_op_bswap32(reg, reg);
1065}
1066
1067DISAS_INSN(move)
1068{
1069 int src;
1070 int dest;
1071 int op;
1072 int opsize;
1073
1074 switch (insn >> 12) {
1075 case 1: /* move.b */
1076 opsize = OS_BYTE;
1077 break;
1078 case 2: /* move.l */
1079 opsize = OS_LONG;
1080 break;
1081 case 3: /* move.w */
1082 opsize = OS_WORD;
1083 break;
1084 default:
1085 abort();
1086 }
1087 src = gen_ea(s, insn, opsize, -1, NULL);
1088 op = (insn >> 6) & 7;
1089 if (op == 1) {
1090 /* movea */
1091 /* The value will already have been sign extended. */
1092 dest = AREG(insn, 9);
1093 gen_op_mov32(dest, src);
1094 } else {
1095 /* normal move */
1096 uint16_t dest_ea;
1097 dest_ea = ((insn >> 9) & 7) | (op << 3);
1098 gen_ea(s, dest_ea, opsize, src, NULL);
1099 /* This will be correct because loads sign extend. */
1100 gen_logic_cc(s, src);
1101 }
1102}
1103
1104DISAS_INSN(negx)
1105{
1106 int reg;
1107 int dest;
1108 int tmp;
1109
1110 gen_flush_flags(s);
1111 reg = DREG(insn, 0);
1112 dest = gen_new_qreg(QMODE_I32);
1113 gen_op_mov32 (dest, gen_im32(0));
1114 gen_op_subx_cc(dest, reg);
1115 /* !Z is sticky. */
1116 tmp = gen_new_qreg(QMODE_I32);
1117 gen_op_mov32 (tmp, QREG_CC_DEST);
1118 gen_op_update_cc_add(dest, reg);
1119 gen_op_mov32(reg, dest);
1120 s->cc_op = CC_OP_DYNAMIC;
1121 gen_flush_flags(s);
1122 gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1123 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1124 s->cc_op = CC_OP_FLAGS;
1125}
1126
1127DISAS_INSN(lea)
1128{
1129 int reg;
1130 int tmp;
1131
1132 reg = AREG(insn, 9);
1133 tmp = gen_lea(s, insn, OS_LONG);
1134 gen_op_mov32(reg, tmp);
1135}
1136
1137DISAS_INSN(clr)
1138{
1139 int opsize;
1140
1141 switch ((insn >> 6) & 3) {
1142 case 0: /* clr.b */
1143 opsize = OS_BYTE;
1144 break;
1145 case 1: /* clr.w */
1146 opsize = OS_WORD;
1147 break;
1148 case 2: /* clr.l */
1149 opsize = OS_LONG;
1150 break;
1151 default:
1152 abort();
1153 }
1154 gen_ea (s, insn, opsize, gen_im32(0), NULL);
1155 gen_logic_cc(s, gen_im32(0));
1156}
1157
1158DISAS_INSN(move_from_ccr)
1159{
1160 int reg;
1161 int dest;
1162
1163 gen_flush_flags(s);
1164 dest = gen_new_qreg(QMODE_I32);
1165 gen_op_get_xflag(dest);
1166 gen_op_shl32(dest, dest, gen_im32(4));
1167 gen_op_or32(dest, dest, QREG_CC_DEST);
1168 reg = DREG(insn, 0);
1169 gen_partset_reg(OS_WORD, reg, dest);
1170}
1171
1172DISAS_INSN(neg)
1173{
1174 int reg;
1175 int src1;
1176
1177 reg = DREG(insn, 0);
1178 src1 = gen_new_qreg(QMODE_I32);
1179 gen_op_mov32(src1, reg);
1180 gen_op_neg32(reg, src1);
1181 s->cc_op = CC_OP_SUB;
1182 gen_op_update_cc_add(reg, src1);
1183 gen_op_update_xflag_lt(gen_im32(0), src1);
1184 s->cc_op = CC_OP_SUB;
1185}
1186
1187DISAS_INSN(move_to_ccr)
1188{
1189 int src1;
1190 int reg;
1191
1192 s->cc_op = CC_OP_FLAGS;
1193 if ((insn & 0x38) == 0)
1194 {
1195 src1 = gen_new_qreg(QMODE_I32);
1196 reg = DREG(insn, 0);
1197 gen_op_and32(src1, reg, gen_im32(0xf));
1198 gen_op_logic_cc(src1);
1199 gen_op_shr32(src1, reg, gen_im32(4));
1200 gen_op_and32(src1, src1, gen_im32(1));
1201 gen_op_update_xflag_tst(src1);
1202 }
1203 else if ((insn & 0x3f) != 0x3c)
1204 {
1205 uint8_t val;
1206 val = ldsb(s->pc);
1207 s->pc += 2;
1208 gen_op_logic_cc(gen_im32(val & 0xf));
1209 gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
1210 }
1211 else
1212 disas_undef(s, insn);
1213}
1214
1215DISAS_INSN(not)
1216{
1217 int reg;
1218
1219 reg = DREG(insn, 0);
1220 gen_op_not32(reg, reg);
1221 gen_logic_cc(s, reg);
1222}
1223
1224DISAS_INSN(swap)
1225{
1226 int dest;
1227 int src1;
1228 int src2;
1229 int reg;
1230
1231 dest = gen_new_qreg(QMODE_I32);
1232 src1 = gen_new_qreg(QMODE_I32);
1233 src2 = gen_new_qreg(QMODE_I32);
1234 reg = DREG(insn, 0);
1235 gen_op_shl32(src1, reg, gen_im32(16));
1236 gen_op_shr32(src2, reg, gen_im32(16));
1237 gen_op_or32(dest, src1, src2);
1238 gen_op_mov32(reg, dest);
1239 gen_logic_cc(s, dest);
1240}
1241
1242DISAS_INSN(pea)
1243{
1244 int tmp;
1245
1246 tmp = gen_lea(s, insn, OS_LONG);
1247 gen_push(tmp);
1248}
1249
1250DISAS_INSN(ext)
1251{
1252 int reg;
1253 int op;
1254 int tmp;
1255
1256 reg = DREG(insn, 0);
1257 op = (insn >> 6) & 7;
1258 tmp = gen_new_qreg(QMODE_I32);
1259 if (op == 3)
1260 gen_op_ext16s32(tmp, reg);
1261 else
1262 gen_op_ext8s32(tmp, reg);
1263 if (op == 2)
1264 gen_partset_reg(OS_WORD, reg, tmp);
1265 else
1266 gen_op_mov32(reg, tmp);
1267 gen_logic_cc(s, tmp);
1268}
1269
1270DISAS_INSN(tst)
1271{
1272 int opsize;
1273 int tmp;
1274
1275 switch ((insn >> 6) & 3) {
1276 case 0: /* tst.b */
1277 opsize = OS_BYTE;
1278 break;
1279 case 1: /* tst.w */
1280 opsize = OS_WORD;
1281 break;
1282 case 2: /* tst.l */
1283 opsize = OS_LONG;
1284 break;
1285 default:
1286 abort();
1287 }
1288 tmp = gen_ea(s, insn, opsize, -1, NULL);
1289 gen_logic_cc(s, tmp);
1290}
1291
1292DISAS_INSN(pulse)
1293{
1294 /* Implemented as a NOP. */
1295}
1296
1297DISAS_INSN(illegal)
1298{
1299 gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1300}
1301
1302/* ??? This should be atomic. */
1303DISAS_INSN(tas)
1304{
1305 int dest;
1306 int src1;
1307 int addr;
1308
1309 dest = gen_new_qreg(QMODE_I32);
1310 src1 = gen_ea(s, insn, OS_BYTE, -1, &addr);
1311 gen_logic_cc(s, src1);
1312 gen_op_or32(dest, src1, gen_im32(0x80));
1313 gen_ea(s, insn, OS_BYTE, dest, &addr);
1314}
1315
1316DISAS_INSN(mull)
1317{
1318 uint16_t ext;
1319 int reg;
1320 int src1;
1321 int dest;
1322
1323 /* The upper 32 bits of the product are discarded, so
1324 muls.l and mulu.l are functionally equivalent. */
1325 ext = lduw(s->pc);
1326 s->pc += 2;
1327 if (ext & 0x87ff) {
1328 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
1329 return;
1330 }
1331 reg = DREG(ext, 12);
1332 src1 = gen_ea(s, insn, OS_LONG, 0, NULL);
1333 dest = gen_new_qreg(QMODE_I32);
1334 gen_op_mul32(dest, src1, reg);
1335 gen_op_mov32(reg, dest);
1336 /* Unlike m68k, coldfire always clears the overflow bit. */
1337 gen_logic_cc(s, dest);
1338}
1339
1340DISAS_INSN(link)
1341{
1342 int16_t offset;
1343 int reg;
1344 int tmp;
1345
1346 offset = ldsw(s->pc);
1347 s->pc += 2;
1348 reg = AREG(insn, 0);
1349 tmp = gen_new_qreg(QMODE_I32);
1350 gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1351 gen_store(OS_LONG, tmp, reg);
1352 if (reg != QREG_SP)
1353 gen_op_mov32(reg, tmp);
1354 gen_op_add32(QREG_SP, tmp, gen_im32(offset));
1355}
1356
1357DISAS_INSN(unlk)
1358{
1359 int src;
1360 int reg;
1361 int tmp;
1362
1363 src = gen_new_qreg(QMODE_I32);
1364 reg = AREG(insn, 0);
1365 gen_op_mov32(src, reg);
1366 tmp = gen_load(OS_LONG, src, 0);
1367 gen_op_mov32(reg, tmp);
1368 gen_op_add32(QREG_SP, src, gen_im32(4));
1369}
1370
1371DISAS_INSN(nop)
1372{
1373}
1374
1375DISAS_INSN(rts)
1376{
1377 int tmp;
1378
1379 tmp = gen_load(OS_LONG, QREG_SP, 0);
1380 gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
1381 gen_jmp(s, tmp);
1382}
1383
1384DISAS_INSN(jump)
1385{
1386 int tmp;
1387
1388 /* Load the target address first to ensure correct exception
1389 behavior. */
1390 tmp = gen_lea(s, insn, OS_LONG);
1391 if ((insn & 0x40) == 0) {
1392 /* jsr */
1393 gen_push(gen_im32(s->pc));
1394 }
1395 gen_jmp(s, tmp);
1396}
1397
1398DISAS_INSN(addsubq)
1399{
1400 int src1;
1401 int src2;
1402 int dest;
1403 int val;
1404 int addr;
1405
1406 src1 = gen_ea(s, insn, OS_LONG, 0, &addr);
1407 val = (insn >> 9) & 7;
1408 if (val == 0)
1409 val = 8;
1410 src2 = gen_im32(val);
1411 dest = gen_new_qreg(QMODE_I32);
1412 gen_op_mov32(dest, src1);
1413 if ((insn & 0x38) == 0x08) {
1414 /* Don't update condition codes if the destination is an
1415 address register. */
1416 if (insn & 0x0100) {
1417 gen_op_sub32(dest, dest, src2);
1418 } else {
1419 gen_op_add32(dest, dest, src2);
1420 }
1421 } else {
1422 if (insn & 0x0100) {
1423 gen_op_update_xflag_lt(dest, src2);
1424 gen_op_sub32(dest, dest, src2);
1425 s->cc_op = CC_OP_SUB;
1426 } else {
1427 gen_op_add32(dest, dest, src2);
1428 gen_op_update_xflag_lt(dest, src2);
1429 s->cc_op = CC_OP_ADD;
1430 }
1431 gen_op_update_cc_add(dest, src2);
1432 }
1433 gen_ea(s, insn, OS_LONG, dest, &addr);
1434}
1435
1436DISAS_INSN(tpf)
1437{
1438 switch (insn & 7) {
1439 case 2: /* One extension word. */
1440 s->pc += 2;
1441 break;
1442 case 3: /* Two extension words. */
1443 s->pc += 4;
1444 break;
1445 case 4: /* No extension words. */
1446 break;
1447 default:
1448 disas_undef(s, insn);
1449 }
1450}
1451
1452DISAS_INSN(branch)
1453{
1454 int32_t offset;
1455 uint32_t base;
1456 int op;
1457 int l1;
1458
1459 base = s->pc;
1460 op = (insn >> 8) & 0xf;
1461 offset = (int8_t)insn;
1462 if (offset == 0) {
1463 offset = ldsw(s->pc);
1464 s->pc += 2;
1465 } else if (offset == -1) {
1466 offset = read_im32(s);
1467 }
1468 if (op == 1) {
1469 /* bsr */
1470 gen_push(gen_im32(s->pc));
1471 }
1472 gen_flush_cc_op(s);
1473 if (op > 1) {
1474 /* Bcc */
1475 l1 = gen_new_label();
1476 gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
1477 gen_jmp_tb(s, 1, base + offset);
1478 gen_set_label(l1);
1479 gen_jmp_tb(s, 0, s->pc);
1480 } else {
1481 /* Unconditional branch. */
1482 gen_jmp_tb(s, 0, base + offset);
1483 }
1484}
1485
1486DISAS_INSN(moveq)
1487{
1488 int tmp;
1489
1490 tmp = gen_im32((int8_t)insn);
1491 gen_op_mov32(DREG(insn, 9), tmp);
1492 gen_logic_cc(s, tmp);
1493}
1494
1495DISAS_INSN(mvzs)
1496{
1497 int opsize;
1498 int src;
1499 int reg;
1500
1501 if (insn & 0x40)
1502 opsize = OS_WORD;
1503 else
1504 opsize = OS_BYTE;
1505 src = gen_ea(s, insn, opsize, (insn & 0x80) ? 0 : -1, NULL);
1506 reg = DREG(insn, 9);
1507 gen_op_mov32(reg, src);
1508 gen_logic_cc(s, src);
1509}
1510
1511DISAS_INSN(or)
1512{
1513 int reg;
1514 int dest;
1515 int src;
1516 int addr;
1517
1518 reg = DREG(insn, 9);
1519 dest = gen_new_qreg(QMODE_I32);
1520 if (insn & 0x100) {
1521 src = gen_ea(s, insn, OS_LONG, 0, &addr);
1522 gen_op_or32(dest, src, reg);
1523 gen_ea(s, insn, OS_LONG, dest, &addr);
1524 } else {
1525 src = gen_ea(s, insn, OS_LONG, 0, NULL);
1526 gen_op_or32(dest, src, reg);
1527 gen_op_mov32(reg, dest);
1528 }
1529 gen_logic_cc(s, dest);
1530}
1531
1532DISAS_INSN(suba)
1533{
1534 int src;
1535 int reg;
1536
1537 src = gen_ea(s, insn, OS_LONG, 0, NULL);
1538 reg = AREG(insn, 9);
1539 gen_op_sub32(reg, reg, src);
1540}
1541
1542DISAS_INSN(subx)
1543{
1544 int reg;
1545 int src;
1546 int dest;
1547 int tmp;
1548
1549 gen_flush_flags(s);
1550 reg = DREG(insn, 9);
1551 src = DREG(insn, 0);
1552 dest = gen_new_qreg(QMODE_I32);
1553 gen_op_mov32 (dest, reg);
1554 gen_op_subx_cc(dest, src);
1555 /* !Z is sticky. */
1556 tmp = gen_new_qreg(QMODE_I32);
1557 gen_op_mov32 (tmp, QREG_CC_DEST);
1558 gen_op_update_cc_add(dest, src);
1559 gen_op_mov32(reg, dest);
1560 s->cc_op = CC_OP_DYNAMIC;
1561 gen_flush_flags(s);
1562 gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1563 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1564 s->cc_op = CC_OP_FLAGS;
1565}
1566
1567DISAS_INSN(mov3q)
1568{
1569 int src;
1570 int val;
1571
1572 val = (insn >> 9) & 7;
1573 if (val == 0)
1574 val = -1;
1575 src = gen_im32(val);
1576 gen_logic_cc(s, src);
1577 gen_ea(s, insn, OS_LONG, src, NULL);
1578}
1579
1580DISAS_INSN(cmp)
1581{
1582 int op;
1583 int src;
1584 int reg;
1585 int dest;
1586 int opsize;
1587
1588 op = (insn >> 6) & 3;
1589 switch (op) {
1590 case 0: /* cmp.b */
1591 opsize = OS_BYTE;
1592 s->cc_op = CC_OP_CMPB;
1593 break;
1594 case 1: /* cmp.w */
1595 opsize = OS_WORD;
1596 s->cc_op = CC_OP_CMPW;
1597 break;
1598 case 2: /* cmp.l */
1599 opsize = OS_LONG;
1600 s->cc_op = CC_OP_SUB;
1601 break;
1602 default:
1603 abort();
1604 }
1605 src = gen_ea(s, insn, opsize, -1, NULL);
1606 reg = DREG(insn, 9);
1607 dest = gen_new_qreg(QMODE_I32);
1608 gen_op_sub32(dest, reg, src);
1609 gen_op_update_cc_add(dest, src);
1610}
1611
1612DISAS_INSN(cmpa)
1613{
1614 int opsize;
1615 int src;
1616 int reg;
1617 int dest;
1618
1619 if (insn & 0x100) {
1620 opsize = OS_LONG;
1621 } else {
1622 opsize = OS_WORD;
1623 }
1624 src = gen_ea(s, insn, opsize, -1, NULL);
1625 reg = AREG(insn, 9);
1626 dest = gen_new_qreg(QMODE_I32);
1627 gen_op_sub32(dest, reg, src);
1628 gen_op_update_cc_add(dest, src);
1629 s->cc_op = CC_OP_SUB;
1630}
1631
1632DISAS_INSN(eor)
1633{
1634 int src;
1635 int reg;
1636 int dest;
1637 int addr;
1638
1639 src = gen_ea(s, insn, OS_LONG, 0, &addr);
1640 reg = DREG(insn, 9);
1641 dest = gen_new_qreg(QMODE_I32);
1642 gen_op_xor32(dest, src, reg);
1643 gen_logic_cc(s, dest);
1644 gen_ea(s, insn, OS_LONG, dest, &addr);
1645}
1646
1647DISAS_INSN(and)
1648{
1649 int src;
1650 int reg;
1651 int dest;
1652 int addr;
1653
1654 reg = DREG(insn, 9);
1655 dest = gen_new_qreg(QMODE_I32);
1656 if (insn & 0x100) {
1657 src = gen_ea(s, insn, OS_LONG, 0, &addr);
1658 gen_op_and32(dest, src, reg);
1659 gen_ea(s, insn, OS_LONG, dest, &addr);
1660 } else {
1661 src = gen_ea(s, insn, OS_LONG, 0, NULL);
1662 gen_op_and32(dest, src, reg);
1663 gen_op_mov32(reg, dest);
1664 }
1665 gen_logic_cc(s, dest);
1666}
1667
1668DISAS_INSN(adda)
1669{
1670 int src;
1671 int reg;
1672
1673 src = gen_ea(s, insn, OS_LONG, 0, NULL);
1674 reg = AREG(insn, 9);
1675 gen_op_add32(reg, reg, src);
1676}
1677
1678DISAS_INSN(addx)
1679{
1680 int reg;
1681 int src;
1682 int dest;
1683 int tmp;
1684
1685 gen_flush_flags(s);
1686 reg = DREG(insn, 9);
1687 src = DREG(insn, 0);
1688 dest = gen_new_qreg(QMODE_I32);
1689 gen_op_mov32 (dest, reg);
1690 gen_op_addx_cc(dest, src);
1691 /* !Z is sticky. */
1692 tmp = gen_new_qreg(QMODE_I32);
1693 gen_op_mov32 (tmp, QREG_CC_DEST);
1694 gen_op_update_cc_add(dest, src);
1695 gen_op_mov32(reg, dest);
1696 s->cc_op = CC_OP_DYNAMIC;
1697 gen_flush_flags(s);
1698 gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1699 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1700 s->cc_op = CC_OP_FLAGS;
1701}
1702
1703DISAS_INSN(shift_im)
1704{
1705 int reg;
1706 int tmp;
1707
1708 reg = DREG(insn, 0);
1709 tmp = (insn >> 9) & 7;
1710 if (tmp == 0)
1711 tmp = 8;
1712 if (insn & 0x100) {
1713 gen_op_shl_im_cc(reg, tmp);
1714 s->cc_op = CC_OP_SHL;
1715 } else {
1716 if (insn & 8) {
1717 gen_op_shr_im_cc(reg, tmp);
1718 s->cc_op = CC_OP_SHR;
1719 } else {
1720 gen_op_sar_im_cc(reg, tmp);
1721 s->cc_op = CC_OP_SAR;
1722 }
1723 }
1724}
1725
1726DISAS_INSN(shift_reg)
1727{
1728 int reg;
1729 int src;
1730 int tmp;
1731
1732 reg = DREG(insn, 0);
1733 src = DREG(insn, 9);
1734 tmp = gen_new_qreg(QMODE_I32);
1735 gen_op_and32(tmp, src, gen_im32(63));
1736 if (insn & 0x100) {
1737 gen_op_shl_cc(reg, tmp);
1738 s->cc_op = CC_OP_SHL;
1739 } else {
1740 if (insn & 8) {
1741 gen_op_shr_cc(reg, tmp);
1742 s->cc_op = CC_OP_SHR;
1743 } else {
1744 gen_op_sar_cc(reg, tmp);
1745 s->cc_op = CC_OP_SAR;
1746 }
1747 }
1748}
1749
1750DISAS_INSN(ff1)
1751{
1752 cpu_abort(NULL, "Unimplemented insn: ff1");
1753}
1754
1755DISAS_INSN(strldsr)
1756{
1757 uint16_t ext;
1758 uint32_t addr;
1759
1760 addr = s->pc - 2;
1761 ext = lduw(s->pc);
1762 s->pc += 2;
1763 if (ext != 0x46FC)
1764 gen_exception(s, addr, EXCP_UNSUPPORTED);
1765 else
1766 gen_exception(s, addr, EXCP_PRIVILEGE);
1767}
1768
1769DISAS_INSN(move_from_sr)
1770{
1771 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1772}
1773
1774DISAS_INSN(move_to_sr)
1775{
1776 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1777}
1778
1779DISAS_INSN(move_from_usp)
1780{
1781 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1782}
1783
1784DISAS_INSN(move_to_usp)
1785{
1786 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1787}
1788
1789DISAS_INSN(halt)
1790{
1791 gen_exception(s, s->pc, EXCP_HLT);
1792}
1793
1794DISAS_INSN(stop)
1795{
1796 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1797}
1798
1799DISAS_INSN(rte)
1800{
1801 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1802}
1803
1804DISAS_INSN(movec)
1805{
1806 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1807}
1808
1809DISAS_INSN(intouch)
1810{
1811 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1812}
1813
1814DISAS_INSN(cpushl)
1815{
1816 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1817}
1818
1819DISAS_INSN(wddata)
1820{
1821 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1822}
1823
1824DISAS_INSN(wdebug)
1825{
1826 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1827}
1828
1829DISAS_INSN(trap)
1830{
1831 gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
1832}
1833
1834/* ??? FP exceptions are not implemented. Most exceptions are deferred until
1835 immediately before the next FP instruction is executed. */
1836DISAS_INSN(fpu)
1837{
1838 uint16_t ext;
1839 int opmode;
1840 int src;
1841 int dest;
1842 int res;
1843 int round;
1844 int opsize;
1845
1846 ext = lduw(s->pc);
1847 s->pc += 2;
1848 opmode = ext & 0x7f;
1849 switch ((ext >> 13) & 7) {
1850 case 0: case 2:
1851 break;
1852 case 1:
1853 goto undef;
1854 case 3: /* fmove out */
1855 src = FREG(ext, 7);
1856 /* fmove */
1857 /* ??? TODO: Proper behavior on overflow. */
1858 switch ((ext >> 10) & 7) {
1859 case 0:
1860 opsize = OS_LONG;
1861 res = gen_new_qreg(QMODE_I32);
1862 gen_op_f64_to_i32(res, src);
1863 break;
1864 case 1:
1865 opsize = OS_SINGLE;
1866 res = gen_new_qreg(QMODE_F32);
1867 gen_op_f64_to_f32(res, src);
1868 break;
1869 case 4:
1870 opsize = OS_WORD;
1871 res = gen_new_qreg(QMODE_I32);
1872 gen_op_f64_to_i32(res, src);
1873 break;
1874 case 5:
1875 opsize = OS_DOUBLE;
1876 res = src;
1877 break;
1878 case 6:
1879 opsize = OS_BYTE;
1880 res = gen_new_qreg(QMODE_I32);
1881 gen_op_f64_to_i32(res, src);
1882 break;
1883 default:
1884 goto undef;
1885 }
1886 gen_ea(s, insn, opsize, res, NULL);
1887 return;
1888 case 4: /* fmove to control register. */
1889 switch ((ext >> 10) & 7) {
1890 case 4: /* FPCR */
1891 /* Not implemented. Ignore writes. */
1892 break;
1893 case 1: /* FPIAR */
1894 case 2: /* FPSR */
1895 default:
1896 cpu_abort(NULL, "Unimplemented: fmove to control %d",
1897 (ext >> 10) & 7);
1898 }
1899 break;
1900 case 5: /* fmove from control register. */
1901 switch ((ext >> 10) & 7) {
1902 case 4: /* FPCR */
1903 /* Not implemented. Always return zero. */
1904 res = gen_im32(0);
1905 break;
1906 case 1: /* FPIAR */
1907 case 2: /* FPSR */
1908 default:
1909 cpu_abort(NULL, "Unimplemented: fmove from control %d",
1910 (ext >> 10) & 7);
1911 goto undef;
1912 }
1913 gen_ea(s, insn, OS_LONG, res, NULL);
1914 break;
1915 case 6: /* fmovem */
1916 case 7:
1917 {
1918 int addr;
1919 uint16_t mask;
1920 if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
1921 goto undef;
1922 src = gen_lea(s, insn, OS_LONG);
1923 addr = gen_new_qreg(QMODE_I32);
1924 gen_op_mov32(addr, src);
1925 mask = 0x80;
1926 dest = QREG_F0;
1927 while (mask) {
1928 if (ext & mask) {
1929 if (ext & (1 << 13)) {
1930 /* store */
1931 gen_op_stf64(addr, dest);
1932 } else {
1933 /* load */
1934 gen_op_ldf64(dest, addr);
1935 }
1936 if (ext & (mask - 1))
1937 gen_op_add32(addr, addr, gen_im32(8));
1938 }
1939 mask >>= 1;
1940 dest++;
1941 }
1942 }
1943 return;
1944 }
1945 if (ext & (1 << 14)) {
1946 int tmp;
1947
1948 /* Source effective address. */
1949 switch ((ext >> 10) & 7) {
1950 case 0: opsize = OS_LONG; break;
1951 case 1: opsize = OS_SINGLE; break;
1952 case 4: opsize = OS_WORD; break;
1953 case 5: opsize = OS_DOUBLE; break;
1954 case 6: opsize = OS_BYTE; break;
1955 default:
1956 goto undef;
1957 }
1958 tmp = gen_ea(s, insn, opsize, -1, NULL);
1959 if (opsize == OS_DOUBLE) {
1960 src = tmp;
1961 } else {
1962 src = gen_new_qreg(QMODE_F64);
1963 switch (opsize) {
1964 case OS_LONG:
1965 case OS_WORD:
1966 case OS_BYTE:
1967 gen_op_i32_to_f64(src, tmp);
1968 break;
1969 case OS_SINGLE:
1970 gen_op_f32_to_f64(src, tmp);
1971 break;
1972 }
1973 }
1974 } else {
1975 /* Source register. */
1976 src = FREG(ext, 10);
1977 }
1978 dest = FREG(ext, 7);
1979 res = gen_new_qreg(QMODE_F64);
1980 if (opmode != 0x3a)
1981 gen_op_movf64(res, dest);
1982 round = 1;
1983 switch (opmode) {
1984 case 0: case 0x40: case 0x44: /* fmove */
1985 gen_op_movf64(res, src);
1986 break;
1987 case 1: /* fint */
1988 gen_op_iround_f64(res, src);
1989 round = 0;
1990 break;
1991 case 3: /* fintrz */
1992 gen_op_itrunc_f64(res, src);
1993 round = 0;
1994 break;
1995 case 4: case 0x41: case 0x45: /* fsqrt */
1996 gen_op_sqrtf64(res, src);
1997 break;
1998 case 0x18: case 0x58: case 0x5c: /* fabs */
1999 gen_op_absf64(res, src);
2000 break;
2001 case 0x1a: case 0x5a: case 0x5e: /* fneg */
2002 gen_op_chsf64(res, src);
2003 break;
2004 case 0x20: case 0x60: case 0x64: /* fdiv */
2005 gen_op_divf64(res, res, src);
2006 break;
2007 case 0x22: case 0x62: case 0x66: /* fadd */
2008 gen_op_addf64(res, res, src);
2009 break;
2010 case 0x23: case 0x63: case 0x67: /* fmul */
2011 gen_op_mulf64(res, res, src);
2012 break;
2013 case 0x28: case 0x68: case 0x6c: /* fsub */
2014 gen_op_subf64(res, res, src);
2015 break;
2016 case 0x38: /* fcmp */
2017 gen_op_sub_cmpf64(res, res, src);
2018 dest = 0;
2019 round = 0;
2020 break;
2021 case 0x3a: /* ftst */
2022 gen_op_movf64(res, src);
2023 dest = 0;
2024 round = 0;
2025 break;
2026 default:
2027 goto undef;
2028 }
2029 if (round) {
2030 if (opmode & 0x40) {
2031 if ((opmode & 0x4) != 0)
2032 round = 0;
2033 } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
2034 round = 0;
2035 }
2036 }
2037 if (round) {
2038 int tmp;
2039
2040 tmp = gen_new_qreg(QMODE_F32);
2041 gen_op_f64_to_f32(tmp, res);
2042 gen_op_f32_to_f64(res, tmp);
2043 }
2044 gen_op_fp_result(res);
2045 if (dest) {
2046 gen_op_movf64(dest, res);
2047 }
2048 return;
2049undef:
2050 s->pc -= 2;
2051 disas_undef_fpu(s, insn);
2052}
2053
2054DISAS_INSN(fbcc)
2055{
2056 uint32_t offset;
2057 uint32_t addr;
2058 int flag;
2059 int zero;
2060 int l1;
2061
2062 addr = s->pc;
2063 offset = ldsw(s->pc);
2064 s->pc += 2;
2065 if (insn & (1 << 6)) {
2066 offset = (offset << 16) | lduw(s->pc);
2067 s->pc += 2;
2068 }
2069
2070 l1 = gen_new_label();
2071 /* TODO: Raise BSUN exception. */
2072 flag = gen_new_qreg(QMODE_I32);
2073 zero = gen_new_qreg(QMODE_F64);
2074 gen_op_zerof64(zero);
2075 gen_op_compare_quietf64(flag, QREG_FP_RESULT, zero);
2076 /* Jump to l1 if condition is true. */
2077 switch (insn & 0xf) {
2078 case 0: /* f */
2079 break;
2080 case 1: /* eq (=0) */
2081 gen_op_jmp_z32(flag, l1);
2082 break;
2083 case 2: /* ogt (=1) */
2084 gen_op_sub32(flag, flag, gen_im32(1));
2085 gen_op_jmp_z32(flag, l1);
2086 break;
2087 case 3: /* oge (=0 or =1) */
2088 gen_op_jmp_z32(flag, l1);
2089 gen_op_sub32(flag, flag, gen_im32(1));
2090 gen_op_jmp_z32(flag, l1);
2091 break;
2092 case 4: /* olt (=-1) */
2093 gen_op_jmp_s32(flag, l1);
2094 break;
2095 case 5: /* ole (=-1 or =0) */
2096 gen_op_jmp_s32(flag, l1);
2097 gen_op_jmp_z32(flag, l1);
2098 break;
2099 case 6: /* ogl (=-1 or =1) */
2100 gen_op_jmp_s32(flag, l1);
2101 gen_op_sub32(flag, flag, gen_im32(1));
2102 gen_op_jmp_z32(flag, l1);
2103 break;
2104 case 7: /* or (=2) */
2105 gen_op_sub32(flag, flag, gen_im32(2));
2106 gen_op_jmp_z32(flag, l1);
2107 break;
2108 case 8: /* un (<2) */
2109 gen_op_sub32(flag, flag, gen_im32(2));
2110 gen_op_jmp_s32(flag, l1);
2111 break;
2112 case 9: /* ueq (=0 or =2) */
2113 gen_op_jmp_z32(flag, l1);
2114 gen_op_sub32(flag, flag, gen_im32(2));
2115 gen_op_jmp_z32(flag, l1);
2116 break;
2117 case 10: /* ugt (>0) */
2118 /* ??? Add jmp_gtu. */
2119 gen_op_sub32(flag, flag, gen_im32(1));
2120 gen_op_jmp_ns32(flag, l1);
2121 break;
2122 case 11: /* uge (>=0) */
2123 gen_op_jmp_ns32(flag, l1);
2124 break;
2125 case 12: /* ult (=-1 or =2) */
2126 gen_op_jmp_s32(flag, l1);
2127 gen_op_sub32(flag, flag, gen_im32(2));
2128 gen_op_jmp_z32(flag, l1);
2129 break;
2130 case 13: /* ule (!=1) */
2131 gen_op_sub32(flag, flag, gen_im32(1));
2132 gen_op_jmp_nz32(flag, l1);
2133 break;
2134 case 14: /* ne (!=0) */
2135 gen_op_jmp_nz32(flag, l1);
2136 break;
2137 case 15: /* t */
2138 gen_op_mov32(flag, gen_im32(1));
2139 break;
2140 }
2141 gen_jmp_tb(s, 0, s->pc);
2142 gen_set_label(l1);
2143 gen_jmp_tb(s, 1, addr + offset);
2144}
2145
2146static disas_proc opcode_table[65536];
2147
2148static void
2149register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2150{
2151 int i;
2152 int from;
2153 int to;
2154
2155 /* Sanity check. All set bits must be included in the mask. */
2156 if (opcode & ~mask)
2157 abort();
2158 /* This could probably be cleverer. For now just optimize the case where
2159 the top bits are known. */
2160 /* Find the first zero bit in the mask. */
2161 i = 0x8000;
2162 while ((i & mask) != 0)
2163 i >>= 1;
2164 /* Iterate over all combinations of this and lower bits. */
2165 if (i == 0)
2166 i = 1;
2167 else
2168 i <<= 1;
2169 from = opcode & ~(i - 1);
2170 to = from + i;
2171 for (i = from; i < to; i++)
2172 {
2173 if ((i & mask) == opcode)
2174 opcode_table[i] = proc;
2175 }
2176}
2177
2178/* Register m68k opcode handlers. Order is important.
2179 Later insn override earlier ones. */
2180static void
2181register_m68k_insns (m68k_def_t *def)
2182{
2183 uint32_t iflags;
2184
2185 iflags = def->insns;
2186#define INSN(name, opcode, mask, isa) \
2187 if (iflags & M68K_INSN_##isa) \
2188 register_opcode(disas_##name, 0x##opcode, 0x##mask)
2189 INSN(undef, 0000, 0000, CF_A);
2190 INSN(arith_im, 0080, fff8, CF_A);
2191 INSN(bitrev, 00c0, fff8, CF_C);
2192 INSN(bitop_reg, 0100, f1c0, CF_A);
2193 INSN(bitop_reg, 0140, f1c0, CF_A);
2194 INSN(bitop_reg, 0180, f1c0, CF_A);
2195 INSN(bitop_reg, 01c0, f1c0, CF_A);
2196 INSN(arith_im, 0280, fff8, CF_A);
2197 INSN(byterev, 02c0, fff8, CF_A);
2198 INSN(arith_im, 0480, fff8, CF_A);
2199 INSN(ff1, 04c0, fff8, CF_C);
2200 INSN(arith_im, 0680, fff8, CF_A);
2201 INSN(bitop_im, 0800, ffc0, CF_A);
2202 INSN(bitop_im, 0840, ffc0, CF_A);
2203 INSN(bitop_im, 0880, ffc0, CF_A);
2204 INSN(bitop_im, 08c0, ffc0, CF_A);
2205 INSN(arith_im, 0a80, fff8, CF_A);
2206 INSN(arith_im, 0c00, ff38, CF_A);
2207 INSN(move, 1000, f000, CF_A);
2208 INSN(move, 2000, f000, CF_A);
2209 INSN(move, 3000, f000, CF_A);
2210 INSN(strldsr, 40e7, ffff, CF_A);
2211 INSN(negx, 4080, fff8, CF_A);
2212 INSN(move_from_sr, 40c0, fff8, CF_A);
2213 INSN(lea, 41c0, f1c0, CF_A);
2214 INSN(clr, 4200, ff00, CF_A);
2215 INSN(undef, 42c0, ffc0, CF_A);
2216 INSN(move_from_ccr, 42c0, fff8, CF_A);
2217 INSN(neg, 4480, fff8, CF_A);
2218 INSN(move_to_ccr, 44c0, ffc0, CF_A);
2219 INSN(not, 4680, fff8, CF_A);
2220 INSN(move_to_sr, 46c0, ffc0, CF_A);
2221 INSN(pea, 4840, ffc0, CF_A);
2222 INSN(swap, 4840, fff8, CF_A);
2223 INSN(movem, 48c0, fbc0, CF_A);
2224 INSN(ext, 4880, fff8, CF_A);
2225 INSN(ext, 48c0, fff8, CF_A);
2226 INSN(ext, 49c0, fff8, CF_A);
2227 INSN(tst, 4a00, ff00, CF_A);
2228 INSN(tas, 4ac0, ffc0, CF_B);
2229 INSN(halt, 4ac8, ffff, CF_A);
2230 INSN(pulse, 4acc, ffff, CF_A);
2231 INSN(illegal, 4afc, ffff, CF_A);
2232 INSN(mull, 4c00, ffc0, CF_A);
2233 INSN(divl, 4c40, ffc0, CF_A);
2234 INSN(sats, 4c80, fff8, CF_B);
2235 INSN(trap, 4e40, fff0, CF_A);
2236 INSN(link, 4e50, fff8, CF_A);
2237 INSN(unlk, 4e58, fff8, CF_A);
2238 INSN(move_to_usp, 4e60, fff8, CF_B);
2239 INSN(move_from_usp, 4e68, fff8, CF_B);
2240 INSN(nop, 4e71, ffff, CF_A);
2241 INSN(stop, 4e72, ffff, CF_A);
2242 INSN(rte, 4e73, ffff, CF_A);
2243 INSN(rts, 4e75, ffff, CF_A);
2244 INSN(movec, 4e7b, ffff, CF_A);
2245 INSN(jump, 4e80, ffc0, CF_A);
2246 INSN(jump, 4ec0, ffc0, CF_A);
2247 INSN(addsubq, 5180, f1c0, CF_A);
2248 INSN(scc, 50c0, f0f8, CF_A);
2249 INSN(addsubq, 5080, f1c0, CF_A);
2250 INSN(tpf, 51f8, fff8, CF_A);
2251 INSN(branch, 6000, f000, CF_A);
2252 INSN(moveq, 7000, f100, CF_A);
2253 INSN(mvzs, 7100, f100, CF_B);
2254 INSN(or, 8000, f000, CF_A);
2255 INSN(divw, 80c0, f0c0, CF_A);
2256 INSN(addsub, 9000, f000, CF_A);
2257 INSN(subx, 9180, f1f8, CF_A);
2258 INSN(suba, 91c0, f1c0, CF_A);
2259 INSN(undef_mac, a000, f000, CF_A);
2260 INSN(mov3q, a140, f1c0, CF_B);
2261 INSN(cmp, b000, f1c0, CF_B); /* cmp.b */
2262 INSN(cmp, b040, f1c0, CF_B); /* cmp.w */
2263 INSN(cmpa, b0c0, f1c0, CF_B); /* cmpa.w */
2264 INSN(cmp, b080, f1c0, CF_A);
2265 INSN(cmpa, b1c0, f1c0, CF_A);
2266 INSN(eor, b180, f1c0, CF_A);
2267 INSN(and, c000, f000, CF_A);
2268 INSN(mulw, c0c0, f0c0, CF_A);
2269 INSN(addsub, d000, f000, CF_A);
2270 INSN(addx, d180, f1f8, CF_A);
2271 INSN(adda, d1c0, f1c0, CF_A);
2272 INSN(shift_im, e080, f0f0, CF_A);
2273 INSN(shift_reg, e0a0, f0f0, CF_A);
2274 INSN(undef_fpu, f000, f000, CF_A);
2275 INSN(fpu, f200, ffc0, CF_FPU);
2276 INSN(fbcc, f280, ffc0, CF_FPU);
2277 INSN(intouch, f340, ffc0, CF_A);
2278 INSN(cpushl, f428, ff38, CF_A);
2279 INSN(wddata, fb00, ff00, CF_A);
2280 INSN(wdebug, fbc0, ffc0, CF_A);
2281#undef INSN
2282}
2283
2284/* ??? Some of this implementation is not exception safe. We should always
2285 write back the result to memory before setting the condition codes. */
2286static void disas_m68k_insn(CPUState * env, DisasContext *s)
2287{
2288 uint16_t insn;
2289
2290 insn = lduw(s->pc);
2291 s->pc += 2;
2292
2293 opcode_table[insn](s, insn);
2294}
2295
2296#if 0
2297/* Save the result of a floating point operation. */
2298static void expand_op_fp_result(qOP *qop)
2299{
2300 gen_op_movf64(QREG_FP_RESULT, qop->args[0]);
2301}
2302
2303/* Dummy op to indicate that the flags have been set. */
2304static void expand_op_flags_set(qOP *qop)
2305{
2306}
2307
2308/* Convert the confition codes into CC_OP_FLAGS format. */
2309static void expand_op_flush_flags(qOP *qop)
2310{
2311 int cc_opreg;
2312
2313 if (qop->args[0] == CC_OP_DYNAMIC)
2314 cc_opreg = QREG_CC_OP;
2315 else
2316 cc_opreg = gen_im32(qop->args[0]);
2317 gen_op_helper32(QREG_NULL, cc_opreg, HELPER_flush_flags);
2318}
2319
2320/* Set CC_DEST after a logical or direct flag setting operation. */
2321static void expand_op_logic_cc(qOP *qop)
2322{
2323 gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2324}
2325
2326/* Set CC_SRC and CC_DEST after an arithmetic operation. */
2327static void expand_op_update_cc_add(qOP *qop)
2328{
2329 gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2330 gen_op_mov32(QREG_CC_SRC, qop->args[1]);
2331}
2332
2333/* Update the X flag. */
2334static void expand_op_update_xflag(qOP *qop)
2335{
2336 int arg0;
2337 int arg1;
2338
2339 arg0 = qop->args[0];
2340 arg1 = qop->args[1];
2341 if (arg1 == QREG_NULL) {
2342 /* CC_X = arg0. */
2343 gen_op_mov32(QREG_CC_X, arg0);
2344 } else {
2345 /* CC_X = arg0 < (unsigned)arg1. */
2346 gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2347 }
2348}
2349
2350/* Set arg0 to the contents of the X flag. */
2351static void expand_op_get_xflag(qOP *qop)
2352{
2353 gen_op_mov32(qop->args[0], QREG_CC_X);
2354}
2355
2356/* Expand a shift by immediate. The ISA only allows shifts by 1-8, so we
2357 already know the shift is within range. */
2358static inline void expand_shift_im(qOP *qop, int right, int arith)
2359{
2360 int val;
2361 int reg;
2362 int tmp;
2363 int im;
2364
2365 reg = qop->args[0];
2366 im = qop->args[1];
2367 tmp = gen_im32(im);
2368 val = gen_new_qreg(QMODE_I32);
2369 gen_op_mov32(val, reg);
2370 gen_op_mov32(QREG_CC_DEST, val);
2371 gen_op_mov32(QREG_CC_SRC, tmp);
2372 if (right) {
2373 if (arith) {
2374 gen_op_sar32(reg, val, tmp);
2375 } else {
2376 gen_op_shr32(reg, val, tmp);
2377 }
2378 if (im == 1)
2379 tmp = QREG_NULL;
2380 else
2381 tmp = gen_im32(im - 1);
2382 } else {
2383 gen_op_shl32(reg, val, tmp);
2384 tmp = gen_im32(32 - im);
2385 }
2386 if (tmp != QREG_NULL)
2387 gen_op_shr32(val, val, tmp);
2388 gen_op_and32(QREG_CC_X, val, gen_im32(1));
2389}
2390
2391static void expand_op_shl_im_cc(qOP *qop)
2392{
2393 expand_shift_im(qop, 0, 0);
2394}
2395
2396static void expand_op_shr_im_cc(qOP *qop)
2397{
2398 expand_shift_im(qop, 1, 0);
2399}
2400
2401static void expand_op_sar_im_cc(qOP *qop)
2402{
2403 expand_shift_im(qop, 1, 1);
2404}
2405
2406/* Expand a shift by register. */
2407/* ??? This gives incorrect answers for shifts by 0 or >= 32 */
2408static inline void expand_shift_reg(qOP *qop, int right, int arith)
2409{
2410 int val;
2411 int reg;
2412 int shift;
2413 int tmp;
2414
2415 reg = qop->args[0];
2416 shift = qop->args[1];
2417 val = gen_new_qreg(QMODE_I32);
2418 gen_op_mov32(val, reg);
2419 gen_op_mov32(QREG_CC_DEST, val);
2420 gen_op_mov32(QREG_CC_SRC, shift);
2421 tmp = gen_new_qreg(QMODE_I32);
2422 if (right) {
2423 if (arith) {
2424 gen_op_sar32(reg, val, shift);
2425 } else {
2426 gen_op_shr32(reg, val, shift);
2427 }
2428 gen_op_sub32(tmp, shift, gen_im32(1));
2429 } else {
2430 gen_op_shl32(reg, val, shift);
2431 gen_op_sub32(tmp, gen_im32(31), shift);
2432 }
2433 gen_op_shl32(val, val, tmp);
2434 gen_op_and32(QREG_CC_X, val, gen_im32(1));
2435}
2436
2437static void expand_op_shl_cc(qOP *qop)
2438{
2439 expand_shift_reg(qop, 0, 0);
2440}
2441
2442static void expand_op_shr_cc(qOP *qop)
2443{
2444 expand_shift_reg(qop, 1, 0);
2445}
2446
2447static void expand_op_sar_cc(qOP *qop)
2448{
2449 expand_shift_reg(qop, 1, 1);
2450}
2451
2452/* Set the Z flag to (arg0 & arg1) == 0. */
2453static void expand_op_btest(qOP *qop)
2454{
2455 int tmp;
2456 int l1;
2457
2458 l1 = gen_new_label();
2459 tmp = gen_new_qreg(QMODE_I32);
2460 gen_op_and32(tmp, qop->args[0], qop->args[1]);
2461 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(~(uint32_t)CCF_Z));
2462 gen_op_jmp_nz32(tmp, l1);
2463 gen_op_or32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(CCF_Z));
2464 gen_op_label(l1);
2465}
2466
2467/* arg0 += arg1 + CC_X */
2468static void expand_op_addx_cc(qOP *qop)
2469{
2470 int arg0 = qop->args[0];
2471 int arg1 = qop->args[1];
2472 int l1, l2;
2473
2474 gen_op_add32 (arg0, arg0, arg1);
2475 l1 = gen_new_label();
2476 l2 = gen_new_label();
2477 gen_op_jmp_z32(QREG_CC_X, l1);
2478 gen_op_add32(arg0, arg0, gen_im32(1));
2479 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
2480 gen_op_set_leu32(QREG_CC_X, arg0, arg1);
2481 gen_op_jmp(l2);
2482 gen_set_label(l1);
2483 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
2484 gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2485 gen_set_label(l2);
2486}
2487
2488/* arg0 -= arg1 + CC_X */
2489static void expand_op_subx_cc(qOP *qop)
2490{
2491 int arg0 = qop->args[0];
2492 int arg1 = qop->args[1];
2493 int l1, l2;
2494
2495 l1 = gen_new_label();
2496 l2 = gen_new_label();
2497 gen_op_jmp_z32(QREG_CC_X, l1);
2498 gen_op_set_leu32(QREG_CC_X, arg0, arg1);
2499 gen_op_sub32(arg0, arg0, gen_im32(1));
2500 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
2501 gen_op_jmp(l2);
2502 gen_set_label(l1);
2503 gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2504 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
2505 gen_set_label(l2);
2506 gen_op_sub32 (arg0, arg0, arg1);
2507}
2508
2509/* Expand target specific ops to generic qops. */
2510static void expand_target_qops(void)
2511{
2512 qOP *qop;
2513 qOP *next;
2514 int c;
2515
2516 /* Copy the list of qops, expanding target specific ops as we go. */
2517 qop = gen_first_qop;
2518 gen_first_qop = NULL;
2519 gen_last_qop = NULL;
2520 for (; qop; qop = next) {
2521 c = qop->opcode;
2522 next = qop->next;
2523 if (c < FIRST_TARGET_OP) {
2524 qop->prev = gen_last_qop;
2525 qop->next = NULL;
2526 if (gen_last_qop)
2527 gen_last_qop->next = qop;
2528 else
2529 gen_first_qop = qop;
2530 gen_last_qop = qop;
2531 continue;
2532 }
2533 switch (c) {
2534#define DEF(name, nargs, barrier) \
2535 case INDEX_op_##name: \
2536 expand_op_##name(qop); \
2537 break;
2538#include "qop-target.def"
2539#undef DEF
2540 default:
2541 cpu_abort(NULL, "Unexpanded target qop");
2542 }
2543 }
2544}
2545
2546/* ??? Implement this. */
2547static void
2548optimize_flags(void)
2549{
2550}
2551#endif
2552
2553/* generate intermediate code for basic block 'tb'. */
2554int gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2555 int search_pc)
2556{
2557 DisasContext dc1, *dc = &dc1;
2558 uint16_t *gen_opc_end;
2559 int j, lj;
2560 target_ulong pc_start;
2561 int pc_offset;
2562 int last_cc_op;
2563
2564 /* generate intermediate code */
2565 pc_start = tb->pc;
2566
2567 dc->tb = tb;
2568
2569 gen_opc_ptr = gen_opc_buf;
2570 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2571 gen_opparam_ptr = gen_opparam_buf;
2572
2573 dc->is_jmp = DISAS_NEXT;
2574 dc->pc = pc_start;
2575 dc->cc_op = CC_OP_DYNAMIC;
2576 dc->singlestep_enabled = env->singlestep_enabled;
2577 dc->fpcr = env->fpcr;
2578 nb_gen_labels = 0;
2579 lj = -1;
2580 do {
2581 free_qreg = 0;
2582 pc_offset = dc->pc - pc_start;
2583 gen_throws_exception = NULL;
2584 if (env->nb_breakpoints > 0) {
2585 for(j = 0; j < env->nb_breakpoints; j++) {
2586 if (env->breakpoints[j] == dc->pc) {
2587 gen_exception(dc, dc->pc, EXCP_DEBUG);
2588 dc->is_jmp = DISAS_JUMP;
2589 break;
2590 }
2591 }
2592 if (dc->is_jmp)
2593 break;
2594 }
2595 if (search_pc) {
2596 j = gen_opc_ptr - gen_opc_buf;
2597 if (lj < j) {
2598 lj++;
2599 while (lj < j)
2600 gen_opc_instr_start[lj++] = 0;
2601 }
2602 gen_opc_pc[lj] = dc->pc;
2603 gen_opc_instr_start[lj] = 1;
2604 }
2605 last_cc_op = dc->cc_op;
2606 disas_m68k_insn(env, dc);
2607 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2608 !env->singlestep_enabled &&
2609 (pc_offset) < (TARGET_PAGE_SIZE - 32));
2610
2611 if (__builtin_expect(env->singlestep_enabled, 0)) {
2612 /* Make sure the pc is updated, and raise a debug exception. */
2613 if (!dc->is_jmp) {
2614 gen_flush_cc_op(dc);
2615 gen_op_mov32(QREG_PC, gen_im32((long)dc->pc));
2616 }
2617 gen_op_raise_exception(EXCP_DEBUG);
2618 } else {
2619 switch(dc->is_jmp) {
2620 case DISAS_NEXT:
2621 gen_flush_cc_op(dc);
2622 gen_jmp_tb(dc, 0, dc->pc);
2623 break;
2624 default:
2625 case DISAS_JUMP:
2626 case DISAS_UPDATE:
2627 gen_flush_cc_op(dc);
2628 /* indicate that the hash table must be used to find the next TB */
2629 gen_op_mov32(QREG_T0, gen_im32(0));
2630 gen_op_exit_tb();
2631 break;
2632 case DISAS_TB_JUMP:
2633 /* nothing more to generate */
2634 break;
2635 }
2636 }
2637 *gen_opc_ptr = INDEX_op_end;
2638
2639#ifdef DEBUG_DISAS
2640 if (loglevel & CPU_LOG_TB_IN_ASM) {
2641 fprintf(logfile, "----------------\n");
2642 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2643 target_disas(logfile, pc_start, dc->pc - pc_start, 0);
2644 fprintf(logfile, "\n");
2645 if (loglevel & (CPU_LOG_TB_OP)) {
2646 fprintf(logfile, "OP:\n");
2647 dump_ops(gen_opc_buf, gen_opparam_buf);
2648 fprintf(logfile, "\n");
2649 }
2650 }
2651#endif
2652 if (search_pc) {
2653 j = gen_opc_ptr - gen_opc_buf;
2654 lj++;
2655 while (lj <= j)
2656 gen_opc_instr_start[lj++] = 0;
2657 tb->size = 0;
2658 } else {
2659 tb->size = dc->pc - pc_start;
2660 }
2661
2662 //optimize_flags();
2663 //expand_target_qops();
2664 return 0;
2665}
2666
2667int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2668{
2669 return gen_intermediate_code_internal(env, tb, 0);
2670}
2671
2672int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2673{
2674 return gen_intermediate_code_internal(env, tb, 1);
2675}
2676
2677CPUM68KState *cpu_m68k_init(void)
2678{
2679 CPUM68KState *env;
2680
2681 env = malloc(sizeof(CPUM68KState));
2682 if (!env)
2683 return NULL;
2684 cpu_exec_init(env);
2685
2686 memset(env, 0, sizeof(CPUM68KState));
2687 /* ??? FP regs should be initialized to NaN. */
2688 cpu_single_env = env;
2689 env->cc_op = CC_OP_FLAGS;
2690 return env;
2691}
2692
2693void cpu_m68k_close(CPUM68KState *env)
2694{
2695 free(env);
2696}
2697
2698m68k_def_t *m68k_find_by_name(const char *name)
2699{
2700 m68k_def_t *def;
2701
2702 def = m68k_cpu_defs;
2703 while (def->name)
2704 {
2705 if (strcmp(def->name, name) == 0)
2706 return def;
2707 def++;
2708 }
2709 return NULL;
2710}
2711
2712void cpu_m68k_register(CPUM68KState *env, m68k_def_t *def)
2713{
2714 register_m68k_insns(def);
2715}
2716
2717void cpu_dump_state(CPUState *env, FILE *f,
2718 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2719 int flags)
2720{
2721 int i;
2722 uint16_t sr;
2723 CPU_DoubleU u;
2724 for (i = 0; i < 8; i++)
2725 {
2726 u.d = env->fregs[i];
2727 cpu_fprintf (f, "D%d = %08x A%d = %08x F%d = %08x%08x (%12g)\n",
2728 i, env->dregs[i], i, env->aregs[i],
2729 i, u.l.upper, u.l.lower, u.d);
2730 }
2731 cpu_fprintf (f, "PC = %08x ", env->pc);
2732 sr = env->sr;
2733 cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
2734 (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
2735 (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
2736 cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result);
2737}
2738
2739/* ??? */
2740target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2741{
2742 return addr;
2743}
2744
2745#if defined(CONFIG_USER_ONLY)
2746
2747int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2748 int is_user, int is_softmmu)
2749{
2750 env->exception_index = EXCP_ACCESS;
2751 env->mmu.ar = address;
2752 return 1;
2753}
2754
2755#else
2756
2757#error not implemented
2758
2759#endif