Statistics
| Branch: | Revision:

root / target-m68k / translate.c @ 0cf5c677

History | View | Annotate | Download (80.6 kB)

1
/*
2
 *  m68k translation
3
 * 
4
 *  Copyright (c) 2005-2007 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

    
33
//#define DEBUG_DISPATCH 1
34

    
35
static inline void qemu_assert(int cond, const char *msg)
36
{
37
    if (!cond) {
38
        fprintf (stderr, "badness: %s\n", msg);
39
        abort();
40
    }
41
}
42

    
43
/* internal defines */
44
typedef struct DisasContext {
45
    CPUM68KState *env;
46
    target_ulong insn_pc; /* Start of the current instruction.  */
47
    target_ulong pc;
48
    int is_jmp;
49
    int cc_op;
50
    int user;
51
    uint32_t fpcr;
52
    struct TranslationBlock *tb;
53
    int singlestep_enabled;
54
} DisasContext;
55

    
56
#define DISAS_JUMP_NEXT 4
57

    
58
#if defined(CONFIG_USER_ONLY)
59
#define IS_USER(s) 1
60
#else
61
#define IS_USER(s) s->user
62
#endif
63

    
64
/* XXX: move that elsewhere */
65
/* ??? Fix exceptions.  */
66
static void *gen_throws_exception;
67
#define gen_last_qop NULL
68

    
69
static uint16_t *gen_opc_ptr;
70
static uint32_t *gen_opparam_ptr;
71
extern FILE *logfile;
72
extern int loglevel;
73

    
74
enum {
75
#define DEF(s, n, copy_size) INDEX_op_ ## s,
76
#include "opc.h"
77
#undef DEF
78
    NB_OPS,
79
};
80

    
81
#include "gen-op.h"
82

    
83
#if defined(CONFIG_USER_ONLY)
84
#define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val)
85
#define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr)
86
#else
87
#define gen_st(s, name, addr, val) do { \
88
    if (IS_USER(s)) \
89
        gen_op_st##name##_user(addr, val); \
90
    else \
91
        gen_op_st##name##_kernel(addr, val); \
92
    } while (0)
93
#define gen_ld(s, name, val, addr) do { \
94
    if (IS_USER(s)) \
95
        gen_op_ld##name##_user(val, addr); \
96
    else \
97
        gen_op_ld##name##_kernel(val, addr); \
98
    } while (0)
99
#endif
100

    
101
#include "op-hacks.h"
102

    
103
#define OS_BYTE 0
104
#define OS_WORD 1
105
#define OS_LONG 2
106
#define OS_SINGLE 4
107
#define OS_DOUBLE 5
108

    
109
#define DREG(insn, pos) (((insn >> pos) & 7) + QREG_D0)
110
#define AREG(insn, pos) (((insn >> pos) & 7) + QREG_A0)
111
#define FREG(insn, pos) (((insn >> pos) & 7) + QREG_F0)
112

    
113
typedef void (*disas_proc)(DisasContext *, uint16_t);
114

    
115
#ifdef DEBUG_DISPATCH
116
#define DISAS_INSN(name) \
117
  static void real_disas_##name (DisasContext *s, uint16_t insn); \
118
  static void disas_##name (DisasContext *s, uint16_t insn) { \
119
    if (logfile) fprintf(logfile, "Dispatch " #name "\n"); \
120
    real_disas_##name(s, insn); } \
121
  static void real_disas_##name (DisasContext *s, uint16_t insn)
122
#else
123
#define DISAS_INSN(name) \
124
  static void disas_##name (DisasContext *s, uint16_t insn)
125
#endif
126

    
127
/* Generate a load from the specified address.  Narrow values are
128
   sign extended to full register width.  */
129
static inline int gen_load(DisasContext * s, int opsize, int addr, int sign)
130
{
131
    int tmp;
132
    switch(opsize) {
133
    case OS_BYTE:
134
        tmp = gen_new_qreg(QMODE_I32);
135
        if (sign)
136
            gen_ld(s, 8s32, tmp, addr);
137
        else
138
            gen_ld(s, 8u32, tmp, addr);
139
        break;
140
    case OS_WORD:
141
        tmp = gen_new_qreg(QMODE_I32);
142
        if (sign)
143
            gen_ld(s, 16s32, tmp, addr);
144
        else
145
            gen_ld(s, 16u32, tmp, addr);
146
        break;
147
    case OS_LONG:
148
        tmp = gen_new_qreg(QMODE_I32);
149
        gen_ld(s, 32, tmp, addr);
150
        break;
151
    case OS_SINGLE:
152
        tmp = gen_new_qreg(QMODE_F32);
153
        gen_ld(s, f32, tmp, addr);
154
        break;
155
    case OS_DOUBLE:
156
        tmp  = gen_new_qreg(QMODE_F64);
157
        gen_ld(s, f64, tmp, addr);
158
        break;
159
    default:
160
        qemu_assert(0, "bad load size");
161
    }
162
    gen_throws_exception = gen_last_qop;
163
    return tmp;
164
}
165

    
166
/* Generate a store.  */
167
static inline void gen_store(DisasContext *s, int opsize, int addr, int val)
168
{
169
    switch(opsize) {
170
    case OS_BYTE:
171
        gen_st(s, 8, addr, val);
172
        break;
173
    case OS_WORD:
174
        gen_st(s, 16, addr, val);
175
        break;
176
    case OS_LONG:
177
        gen_st(s, 32, addr, val);
178
        break;
179
    case OS_SINGLE:
180
        gen_st(s, f32, addr, val);
181
        break;
182
    case OS_DOUBLE:
183
        gen_st(s, f64, addr, val);
184
        break;
185
    default:
186
        qemu_assert(0, "bad store size");
187
    }
188
    gen_throws_exception = gen_last_qop;
189
}
190

    
191
/* Generate an unsigned load if VAL is 0 a signed load if val is -1,
192
   otherwise generate a store.  */
193
static int gen_ldst(DisasContext *s, int opsize, int addr, int val)
194
{
195
    if (val > 0) {
196
        gen_store(s, opsize, addr, val);
197
        return 0;
198
    } else {
199
        return gen_load(s, opsize, addr, val != 0);
200
    }
201
}
202

    
203
/* Read a 32-bit immediate constant.  */
204
static inline uint32_t read_im32(DisasContext *s)
205
{
206
    uint32_t im;
207
    im = ((uint32_t)lduw_code(s->pc)) << 16;
208
    s->pc += 2;
209
    im |= lduw_code(s->pc);
210
    s->pc += 2;
211
    return im;
212
}
213

    
214
/* Calculate and address index.  */
215
static int gen_addr_index(uint16_t ext, int tmp)
216
{
217
    int add;
218
    int scale;
219

    
220
    add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
221
    if ((ext & 0x800) == 0) {
222
        gen_op_ext16s32(tmp, add);
223
        add = tmp;
224
    }
225
    scale = (ext >> 9) & 3;
226
    if (scale != 0) {
227
        gen_op_shl32(tmp, add, gen_im32(scale));
228
        add = tmp;
229
    }
230
    return add;
231
}
232

    
233
/* Handle a base + index + displacement effective addresss.  A base of
234
   -1 means pc-relative.  */
235
static int gen_lea_indexed(DisasContext *s, int opsize, int base)
236
{
237
    uint32_t offset;
238
    uint16_t ext;
239
    int add;
240
    int tmp;
241
    uint32_t bd, od;
242

    
243
    offset = s->pc;
244
    ext = lduw_code(s->pc);
245
    s->pc += 2;
246

    
247
    if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
248
        return -1;
249

    
250
    if (ext & 0x100) {
251
        /* full extension word format */
252
        if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
253
            return -1;
254

    
255
        if ((ext & 0x30) > 0x10) {
256
            /* base displacement */
257
            if ((ext & 0x30) == 0x20) {
258
                bd = (int16_t)lduw_code(s->pc);
259
                s->pc += 2;
260
            } else {
261
                bd = read_im32(s);
262
            }
263
        } else {
264
            bd = 0;
265
        }
266
        tmp = gen_new_qreg(QMODE_I32);
267
        if ((ext & 0x44) == 0) {
268
            /* pre-index */
269
            add = gen_addr_index(ext, tmp);
270
        } else {
271
            add = QREG_NULL;
272
        }
273
        if ((ext & 0x80) == 0) {
274
            /* base not suppressed */
275
            if (base == -1) {
276
                base = gen_im32(offset + bd);
277
                bd = 0;
278
            }
279
            if (add) {
280
                gen_op_add32(tmp, add, base);
281
                add = tmp;
282
            } else {
283
                add = base;
284
            }
285
        }
286
        if (add) {
287
            if (bd != 0) {
288
                gen_op_add32(tmp, add, gen_im32(bd));
289
                add = tmp;
290
            }
291
        } else {
292
            add = gen_im32(bd);
293
        }
294
        if ((ext & 3) != 0) {
295
            /* memory indirect */
296
            base = gen_load(s, OS_LONG, add, 0);
297
            if ((ext & 0x44) == 4) {
298
                add = gen_addr_index(ext, tmp);
299
                gen_op_add32(tmp, add, base);
300
                add = tmp;
301
            } else {
302
                add = base;
303
            }
304
            if ((ext & 3) > 1) {
305
                /* outer displacement */
306
                if ((ext & 3) == 2) {
307
                    od = (int16_t)lduw_code(s->pc);
308
                    s->pc += 2;
309
                } else {
310
                    od = read_im32(s);
311
                }
312
            } else {
313
                od = 0;
314
            }
315
            if (od != 0) {
316
                gen_op_add32(tmp, add, gen_im32(od));
317
                add = tmp;
318
            }
319
        }
320
    } else {
321
        /* brief extension word format */
322
        tmp = gen_new_qreg(QMODE_I32);
323
        add = gen_addr_index(ext, tmp);
324
        if (base != -1) {
325
            gen_op_add32(tmp, add, base);
326
            if ((int8_t)ext)
327
                gen_op_add32(tmp, tmp, gen_im32((int8_t)ext));
328
        } else {
329
            gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
330
        }
331
        add = tmp;
332
    }
333
    return add;
334
}
335

    
336
/* Update the CPU env CC_OP state.  */
337
static inline void gen_flush_cc_op(DisasContext *s)
338
{
339
    if (s->cc_op != CC_OP_DYNAMIC)
340
        gen_op_mov32(QREG_CC_OP, gen_im32(s->cc_op));
341
}
342

    
343
/* Evaluate all the CC flags.  */
344
static inline void gen_flush_flags(DisasContext *s)
345
{
346
    if (s->cc_op == CC_OP_FLAGS)
347
        return;
348
    gen_flush_cc_op(s);
349
    gen_op_flush_flags();
350
    s->cc_op = CC_OP_FLAGS;
351
}
352

    
353
static inline int opsize_bytes(int opsize)
354
{
355
    switch (opsize) {
356
    case OS_BYTE: return 1;
357
    case OS_WORD: return 2;
358
    case OS_LONG: return 4;
359
    case OS_SINGLE: return 4;
360
    case OS_DOUBLE: return 8;
361
    default:
362
        qemu_assert(0, "bad operand size");
363
    }
364
}
365

    
366
/* Assign value to a register.  If the width is less than the register width
367
   only the low part of the register is set.  */
368
static void gen_partset_reg(int opsize, int reg, int val)
369
{
370
    int tmp;
371
    switch (opsize) {
372
    case OS_BYTE:
373
        gen_op_and32(reg, reg, gen_im32(0xffffff00));
374
        tmp = gen_new_qreg(QMODE_I32);
375
        gen_op_and32(tmp, val, gen_im32(0xff));
376
        gen_op_or32(reg, reg, tmp);
377
        break;
378
    case OS_WORD:
379
        gen_op_and32(reg, reg, gen_im32(0xffff0000));
380
        tmp = gen_new_qreg(QMODE_I32);
381
        gen_op_and32(tmp, val, gen_im32(0xffff));
382
        gen_op_or32(reg, reg, tmp);
383
        break;
384
    case OS_LONG:
385
        gen_op_mov32(reg, val);
386
        break;
387
    case OS_SINGLE:
388
        gen_op_pack_32_f32(reg, val);
389
        break;
390
    default:
391
        qemu_assert(0, "Bad operand size");
392
        break;
393
    }
394
}
395

    
396
/* Sign or zero extend a value.  */
397
static inline int gen_extend(int val, int opsize, int sign)
398
{
399
    int tmp;
400

    
401
    switch (opsize) {
402
    case OS_BYTE:
403
        tmp = gen_new_qreg(QMODE_I32);
404
        if (sign)
405
            gen_op_ext8s32(tmp, val);
406
        else
407
            gen_op_ext8u32(tmp, val);
408
        break;
409
    case OS_WORD:
410
        tmp = gen_new_qreg(QMODE_I32);
411
        if (sign)
412
            gen_op_ext16s32(tmp, val);
413
        else
414
            gen_op_ext16u32(tmp, val);
415
        break;
416
    case OS_LONG:
417
        tmp = val;
418
        break;
419
    case OS_SINGLE:
420
        tmp = gen_new_qreg(QMODE_F32);
421
        gen_op_pack_f32_32(tmp, val);
422
        break;
423
    default:
424
        qemu_assert(0, "Bad operand size");
425
    }
426
    return tmp;
427
}
428

    
429
/* Generate code for an "effective address".  Does not adjust the base
430
   register for autoincrememnt addressing modes.  */
431
static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
432
{
433
    int reg;
434
    int tmp;
435
    uint16_t ext;
436
    uint32_t offset;
437

    
438
    reg = insn & 7;
439
    switch ((insn >> 3) & 7) {
440
    case 0: /* Data register direct.  */
441
    case 1: /* Address register direct.  */
442
        return -1;
443
    case 2: /* Indirect register */
444
    case 3: /* Indirect postincrement.  */
445
        reg += QREG_A0;
446
        return reg;
447
    case 4: /* Indirect predecrememnt.  */
448
        reg += QREG_A0;
449
        tmp = gen_new_qreg(QMODE_I32);
450
        gen_op_sub32(tmp, reg, gen_im32(opsize_bytes(opsize)));
451
        return tmp;
452
    case 5: /* Indirect displacement.  */
453
        reg += QREG_A0;
454
        tmp = gen_new_qreg(QMODE_I32);
455
        ext = lduw_code(s->pc);
456
        s->pc += 2;
457
        gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
458
        return tmp;
459
    case 6: /* Indirect index + displacement.  */
460
        reg += QREG_A0;
461
        return gen_lea_indexed(s, opsize, reg);
462
    case 7: /* Other */
463
        switch (reg) {
464
        case 0: /* Absolute short.  */
465
            offset = ldsw_code(s->pc);
466
            s->pc += 2;
467
            return gen_im32(offset);
468
        case 1: /* Absolute long.  */
469
            offset = read_im32(s);
470
            return gen_im32(offset);
471
        case 2: /* pc displacement  */
472
            tmp = gen_new_qreg(QMODE_I32);
473
            offset = s->pc;
474
            offset += ldsw_code(s->pc);
475
            s->pc += 2;
476
            return gen_im32(offset);
477
        case 3: /* pc index+displacement.  */
478
            return gen_lea_indexed(s, opsize, -1);
479
        case 4: /* Immediate.  */
480
        default:
481
            return -1;
482
        }
483
    }
484
    /* Should never happen.  */
485
    return -1;
486
}
487

    
488
/* Helper function for gen_ea. Reuse the computed address between the
489
   for read/write operands.  */
490
static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
491
                              int val, int *addrp)
492
{
493
    int tmp;
494

    
495
    if (addrp && val > 0) {
496
        tmp = *addrp;
497
    } else {
498
        tmp = gen_lea(s, insn, opsize);
499
        if (tmp == -1)
500
            return -1;
501
        if (addrp)
502
            *addrp = tmp;
503
    }
504
    return gen_ldst(s, opsize, tmp, val);
505
}
506

    
507
/* Generate code to load/store a value ito/from an EA.  If VAL > 0 this is
508
   a write otherwise it is a read (0 == sign extend, -1 == zero extend).
509
   ADDRP is non-null for readwrite operands.  */
510
static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
511
                  int *addrp)
512
{
513
    int reg;
514
    int result;
515
    uint32_t offset;
516

    
517
    reg = insn & 7;
518
    switch ((insn >> 3) & 7) {
519
    case 0: /* Data register direct.  */
520
        reg += QREG_D0;
521
        if (val > 0) {
522
            gen_partset_reg(opsize, reg, val);
523
            return 0;
524
        } else {
525
            return gen_extend(reg, opsize, val);
526
        }
527
    case 1: /* Address register direct.  */
528
        reg += QREG_A0;
529
        if (val > 0) {
530
            gen_op_mov32(reg, val);
531
            return 0;
532
        } else {
533
            return gen_extend(reg, opsize, val);
534
        }
535
    case 2: /* Indirect register */
536
        reg += QREG_A0;
537
        return gen_ldst(s, opsize, reg, val);
538
    case 3: /* Indirect postincrement.  */
539
        reg += QREG_A0;
540
        result = gen_ldst(s, opsize, reg, val);
541
        /* ??? This is not exception safe.  The instruction may still
542
           fault after this point.  */
543
        if (val > 0 || !addrp)
544
            gen_op_add32(reg, reg, gen_im32(opsize_bytes(opsize)));
545
        return result;
546
    case 4: /* Indirect predecrememnt.  */
547
        {
548
            int tmp;
549
            if (addrp && val > 0) {
550
                tmp = *addrp;
551
            } else {
552
                tmp = gen_lea(s, insn, opsize);
553
                if (tmp == -1)
554
                    return -1;
555
                if (addrp)
556
                    *addrp = tmp;
557
            }
558
            result = gen_ldst(s, opsize, tmp, val);
559
            /* ??? This is not exception safe.  The instruction may still
560
               fault after this point.  */
561
            if (val > 0 || !addrp) {
562
                reg += QREG_A0;
563
                gen_op_mov32(reg, tmp);
564
            }
565
        }
566
        return result;
567
    case 5: /* Indirect displacement.  */
568
    case 6: /* Indirect index + displacement.  */
569
        return gen_ea_once(s, insn, opsize, val, addrp);
570
    case 7: /* Other */
571
        switch (reg) {
572
        case 0: /* Absolute short.  */
573
        case 1: /* Absolute long.  */
574
        case 2: /* pc displacement  */
575
        case 3: /* pc index+displacement.  */
576
            return gen_ea_once(s, insn, opsize, val, addrp);
577
        case 4: /* Immediate.  */
578
            /* Sign extend values for consistency.  */
579
            switch (opsize) {
580
            case OS_BYTE:
581
                if (val)
582
                    offset = ldsb_code(s->pc + 1);
583
                else
584
                    offset = ldub_code(s->pc + 1);
585
                s->pc += 2;
586
                break;
587
            case OS_WORD:
588
                if (val)
589
                    offset = ldsw_code(s->pc);
590
                else
591
                    offset = lduw_code(s->pc);
592
                s->pc += 2;
593
                break;
594
            case OS_LONG:
595
                offset = read_im32(s);
596
                break;
597
            default:
598
                qemu_assert(0, "Bad immediate operand");
599
            }
600
            return gen_im32(offset);
601
        default:
602
            return -1;
603
        }
604
    }
605
    /* Should never happen.  */
606
    return -1;
607
}
608

    
609
static void gen_logic_cc(DisasContext *s, int val)
610
{
611
    gen_op_logic_cc(val);
612
    s->cc_op = CC_OP_LOGIC;
613
}
614

    
615
static void gen_jmpcc(DisasContext *s, int cond, int l1)
616
{
617
    int tmp;
618

    
619
    gen_flush_flags(s);
620
    switch (cond) {
621
    case 0: /* T */
622
        gen_op_jmp(l1);
623
        break;
624
    case 1: /* F */
625
        break;
626
    case 2: /* HI (!C && !Z) */
627
        tmp = gen_new_qreg(QMODE_I32);
628
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
629
        gen_op_jmp_z32(tmp, l1);
630
        break;
631
    case 3: /* LS (C || Z) */
632
        tmp = gen_new_qreg(QMODE_I32);
633
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
634
        gen_op_jmp_nz32(tmp, l1);
635
        break;
636
    case 4: /* CC (!C) */
637
        tmp = gen_new_qreg(QMODE_I32);
638
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
639
        gen_op_jmp_z32(tmp, l1);
640
        break;
641
    case 5: /* CS (C) */
642
        tmp = gen_new_qreg(QMODE_I32);
643
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
644
        gen_op_jmp_nz32(tmp, l1);
645
        break;
646
    case 6: /* NE (!Z) */
647
        tmp = gen_new_qreg(QMODE_I32);
648
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
649
        gen_op_jmp_z32(tmp, l1);
650
        break;
651
    case 7: /* EQ (Z) */
652
        tmp = gen_new_qreg(QMODE_I32);
653
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
654
        gen_op_jmp_nz32(tmp, l1);
655
        break;
656
    case 8: /* VC (!V) */
657
        tmp = gen_new_qreg(QMODE_I32);
658
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
659
        gen_op_jmp_z32(tmp, l1);
660
        break;
661
    case 9: /* VS (V) */
662
        tmp = gen_new_qreg(QMODE_I32);
663
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
664
        gen_op_jmp_nz32(tmp, l1);
665
        break;
666
    case 10: /* PL (!N) */
667
        tmp = gen_new_qreg(QMODE_I32);
668
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
669
        gen_op_jmp_z32(tmp, l1);
670
        break;
671
    case 11: /* MI (N) */
672
        tmp = gen_new_qreg(QMODE_I32);
673
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
674
        gen_op_jmp_nz32(tmp, l1);
675
        break;
676
    case 12: /* GE (!(N ^ V)) */
677
        tmp = gen_new_qreg(QMODE_I32);
678
        gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
679
        gen_op_xor32(tmp, tmp, QREG_CC_DEST);
680
        gen_op_and32(tmp, tmp, gen_im32(CCF_V));
681
        gen_op_jmp_z32(tmp, l1);
682
        break;
683
    case 13: /* LT (N ^ V) */
684
        tmp = gen_new_qreg(QMODE_I32);
685
        gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
686
        gen_op_xor32(tmp, tmp, QREG_CC_DEST);
687
        gen_op_and32(tmp, tmp, gen_im32(CCF_V));
688
        gen_op_jmp_nz32(tmp, l1);
689
        break;
690
    case 14: /* GT (!(Z || (N ^ V))) */
691
        {
692
            int l2;
693
            l2 = gen_new_label();
694
            tmp = gen_new_qreg(QMODE_I32);
695
            gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
696
            gen_op_jmp_nz32(tmp, l2);
697
            tmp = gen_new_qreg(QMODE_I32);
698
            gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
699
            gen_op_xor32(tmp, tmp, QREG_CC_DEST);
700
            gen_op_and32(tmp, tmp, gen_im32(CCF_V));
701
            gen_op_jmp_nz32(tmp, l2);
702
            gen_op_jmp(l1);
703
            gen_set_label(l2);
704
        }
705
        break;
706
    case 15: /* LE (Z || (N ^ V)) */
707
        tmp = gen_new_qreg(QMODE_I32);
708
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
709
        gen_op_jmp_nz32(tmp, l1);
710
        tmp = gen_new_qreg(QMODE_I32);
711
        gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
712
        gen_op_xor32(tmp, tmp, QREG_CC_DEST);
713
        gen_op_and32(tmp, tmp, gen_im32(CCF_V));
714
        gen_op_jmp_nz32(tmp, l1);
715
        break;
716
    default:
717
        /* Should ever happen.  */
718
        abort();
719
    }
720
}
721

    
722
DISAS_INSN(scc)
723
{
724
    int l1;
725
    int cond;
726
    int reg;
727

    
728
    l1 = gen_new_label();
729
    cond = (insn >> 8) & 0xf;
730
    reg = DREG(insn, 0);
731
    gen_op_and32(reg, reg, gen_im32(0xffffff00));
732
    gen_jmpcc(s, cond ^ 1, l1);
733
    gen_op_or32(reg, reg, gen_im32(0xff));
734
    gen_set_label(l1);
735
}
736

    
737
/* Force a TB lookup after an instruction that changes the CPU state.  */
738
static void gen_lookup_tb(DisasContext *s)
739
{
740
    gen_flush_cc_op(s);
741
    gen_op_mov32(QREG_PC, gen_im32(s->pc));
742
    s->is_jmp = DISAS_UPDATE;
743
}
744

    
745
/* Generate a jump to to the address in qreg DEST.  */
746
static void gen_jmp(DisasContext *s, int dest)
747
{
748
    gen_flush_cc_op(s);
749
    gen_op_mov32(QREG_PC, dest);
750
    s->is_jmp = DISAS_JUMP;
751
}
752

    
753
static void gen_exception(DisasContext *s, uint32_t where, int nr)
754
{
755
    gen_flush_cc_op(s);
756
    gen_jmp(s, gen_im32(where));
757
    gen_op_raise_exception(nr);
758
}
759

    
760
static inline void gen_addr_fault(DisasContext *s)
761
{
762
    gen_exception(s, s->insn_pc, EXCP_ADDRESS);
763
}
764

    
765
#define SRC_EA(result, opsize, val, addrp) do { \
766
    result = gen_ea(s, insn, opsize, val, addrp); \
767
    if (result == -1) { \
768
        gen_addr_fault(s); \
769
        return; \
770
    } \
771
    } while (0)
772

    
773
#define DEST_EA(insn, opsize, val, addrp) do { \
774
    int ea_result = gen_ea(s, insn, opsize, val, addrp); \
775
    if (ea_result == -1) { \
776
        gen_addr_fault(s); \
777
        return; \
778
    } \
779
    } while (0)
780

    
781
/* Generate a jump to an immediate address.  */
782
static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
783
{
784
    TranslationBlock *tb;
785

    
786
    tb = s->tb;
787
    if (__builtin_expect (s->singlestep_enabled, 0)) {
788
        gen_exception(s, dest, EXCP_DEBUG);
789
    } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
790
               (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
791
        gen_op_goto_tb(0, n, (long)tb);
792
        gen_op_mov32(QREG_PC, gen_im32(dest));
793
        gen_op_mov32(QREG_T0, gen_im32((long)tb + n));
794
        gen_op_exit_tb();
795
    } else {
796
        gen_jmp(s, gen_im32(dest));
797
        gen_op_mov32(QREG_T0, gen_im32(0));
798
        gen_op_exit_tb();
799
    }
800
    s->is_jmp = DISAS_TB_JUMP;
801
}
802

    
803
DISAS_INSN(undef_mac)
804
{
805
    gen_exception(s, s->pc - 2, EXCP_LINEA);
806
}
807

    
808
DISAS_INSN(undef_fpu)
809
{
810
    gen_exception(s, s->pc - 2, EXCP_LINEF);
811
}
812

    
813
DISAS_INSN(undef)
814
{
815
    gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
816
    cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
817
              insn, s->pc - 2);
818
}
819

    
820
DISAS_INSN(mulw)
821
{
822
    int reg;
823
    int tmp;
824
    int src;
825
    int sign;
826

    
827
    sign = (insn & 0x100) != 0;
828
    reg = DREG(insn, 9);
829
    tmp = gen_new_qreg(QMODE_I32);
830
    if (sign)
831
        gen_op_ext16s32(tmp, reg);
832
    else
833
        gen_op_ext16u32(tmp, reg);
834
    SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL);
835
    gen_op_mul32(tmp, tmp, src);
836
    gen_op_mov32(reg, tmp);
837
    /* Unlike m68k, coldfire always clears the overflow bit.  */
838
    gen_logic_cc(s, tmp);
839
}
840

    
841
DISAS_INSN(divw)
842
{
843
    int reg;
844
    int tmp;
845
    int src;
846
    int sign;
847

    
848
    sign = (insn & 0x100) != 0;
849
    reg = DREG(insn, 9);
850
    if (sign) {
851
        gen_op_ext16s32(QREG_DIV1, reg);
852
    } else {
853
        gen_op_ext16u32(QREG_DIV1, reg);
854
    }
855
    SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL);
856
    gen_op_mov32(QREG_DIV2, src);
857
    if (sign) {
858
        gen_op_divs(1);
859
    } else {
860
        gen_op_divu(1);
861
    }
862

    
863
    tmp = gen_new_qreg(QMODE_I32);
864
    src = gen_new_qreg(QMODE_I32);
865
    gen_op_ext16u32(tmp, QREG_DIV1);
866
    gen_op_shl32(src, QREG_DIV2, gen_im32(16));
867
    gen_op_or32(reg, tmp, src);
868
    gen_op_flags_set();
869
    s->cc_op = CC_OP_FLAGS;
870
}
871

    
872
DISAS_INSN(divl)
873
{
874
    int num;
875
    int den;
876
    int reg;
877
    uint16_t ext;
878

    
879
    ext = lduw_code(s->pc);
880
    s->pc += 2;
881
    if (ext & 0x87f8) {
882
        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
883
        return;
884
    }
885
    num = DREG(ext, 12);
886
    reg = DREG(ext, 0);
887
    gen_op_mov32(QREG_DIV1, num);
888
    SRC_EA(den, OS_LONG, 0, NULL);
889
    gen_op_mov32(QREG_DIV2, den);
890
    if (ext & 0x0800) {
891
        gen_op_divs(2);
892
    } else {
893
        gen_op_divu(2);
894
    }
895
    if (num == reg) {
896
        /* div */
897
        gen_op_mov32 (reg, QREG_DIV1);
898
    } else {
899
        /* rem */
900
        gen_op_mov32 (reg, QREG_DIV2);
901
    }
902
    gen_op_flags_set();
903
    s->cc_op = CC_OP_FLAGS;
904
}
905

    
906
DISAS_INSN(addsub)
907
{
908
    int reg;
909
    int dest;
910
    int src;
911
    int tmp;
912
    int addr;
913
    int add;
914

    
915
    add = (insn & 0x4000) != 0;
916
    reg = DREG(insn, 9);
917
    dest = gen_new_qreg(QMODE_I32);
918
    if (insn & 0x100) {
919
        SRC_EA(tmp, OS_LONG, 0, &addr);
920
        src = reg;
921
    } else {
922
        tmp = reg;
923
        SRC_EA(src, OS_LONG, 0, NULL);
924
    }
925
    if (add) {
926
        gen_op_add32(dest, tmp, src);
927
        gen_op_update_xflag_lt(dest, src);
928
        s->cc_op = CC_OP_ADD;
929
    } else {
930
        gen_op_update_xflag_lt(tmp, src);
931
        gen_op_sub32(dest, tmp, src);
932
        s->cc_op = CC_OP_SUB;
933
    }
934
    gen_op_update_cc_add(dest, src);
935
    if (insn & 0x100) {
936
        DEST_EA(insn, OS_LONG, dest, &addr);
937
    } else {
938
        gen_op_mov32(reg, dest);
939
    }
940
}
941

    
942

    
943
/* Reverse the order of the bits in REG.  */
944
DISAS_INSN(bitrev)
945
{
946
    int val;
947
    int tmp1;
948
    int tmp2;
949
    int reg;
950

    
951
    val = gen_new_qreg(QMODE_I32);
952
    tmp1 = gen_new_qreg(QMODE_I32);
953
    tmp2 = gen_new_qreg(QMODE_I32);
954
    reg = DREG(insn, 0);
955
    gen_op_mov32(val, reg);
956
    /* Reverse bits within each nibble.  */
957
    gen_op_shl32(tmp1, val, gen_im32(3));
958
    gen_op_and32(tmp1, tmp1, gen_im32(0x88888888));
959
    gen_op_shl32(tmp2, val, gen_im32(1));
960
    gen_op_and32(tmp2, tmp2, gen_im32(0x44444444));
961
    gen_op_or32(tmp1, tmp1, tmp2);
962
    gen_op_shr32(tmp2, val, gen_im32(1));
963
    gen_op_and32(tmp2, tmp2, gen_im32(0x22222222));
964
    gen_op_or32(tmp1, tmp1, tmp2);
965
    gen_op_shr32(tmp2, val, gen_im32(3));
966
    gen_op_and32(tmp2, tmp2, gen_im32(0x11111111));
967
    gen_op_or32(tmp1, tmp1, tmp2);
968
    /* Reverse nibbles withing bytes.  */
969
    gen_op_shl32(val, tmp1, gen_im32(4));
970
    gen_op_and32(val, val, gen_im32(0xf0f0f0f0));
971
    gen_op_shr32(tmp2, tmp1, gen_im32(4));
972
    gen_op_and32(tmp2, tmp2, gen_im32(0x0f0f0f0f));
973
    gen_op_or32(val, val, tmp2);
974
    /* Reverse bytes.  */
975
    gen_op_bswap32(reg, val);
976
    gen_op_mov32(reg, val);
977
}
978

    
979
DISAS_INSN(bitop_reg)
980
{
981
    int opsize;
982
    int op;
983
    int src1;
984
    int src2;
985
    int tmp;
986
    int addr;
987
    int dest;
988

    
989
    if ((insn & 0x38) != 0)
990
        opsize = OS_BYTE;
991
    else
992
        opsize = OS_LONG;
993
    op = (insn >> 6) & 3;
994
    SRC_EA(src1, opsize, 0, op ? &addr: NULL);
995
    src2 = DREG(insn, 9);
996
    dest = gen_new_qreg(QMODE_I32);
997

    
998
    gen_flush_flags(s);
999
    tmp = gen_new_qreg(QMODE_I32);
1000
    if (opsize == OS_BYTE)
1001
        gen_op_and32(tmp, src2, gen_im32(7));
1002
    else
1003
        gen_op_and32(tmp, src2, gen_im32(31));
1004
    src2 = tmp;
1005
    tmp = gen_new_qreg(QMODE_I32);
1006
    gen_op_shl32(tmp, gen_im32(1), src2);
1007

    
1008
    gen_op_btest(src1, tmp);
1009
    switch (op) {
1010
    case 1: /* bchg */
1011
        gen_op_xor32(dest, src1, tmp);
1012
        break;
1013
    case 2: /* bclr */
1014
        gen_op_not32(tmp, tmp);
1015
        gen_op_and32(dest, src1, tmp);
1016
        break;
1017
    case 3: /* bset */
1018
        gen_op_or32(dest, src1, tmp);
1019
        break;
1020
    default: /* btst */
1021
        break;
1022
    }
1023
    if (op)
1024
        DEST_EA(insn, opsize, dest, &addr);
1025
}
1026

    
1027
DISAS_INSN(sats)
1028
{
1029
    int reg;
1030
    int tmp;
1031
    int l1;
1032

    
1033
    reg = DREG(insn, 0);
1034
    tmp = gen_new_qreg(QMODE_I32);
1035
    gen_flush_flags(s);
1036
    gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
1037
    l1 = gen_new_label();
1038
    gen_op_jmp_z32(tmp, l1);
1039
    tmp = gen_new_qreg(QMODE_I32);
1040
    gen_op_shr32(tmp, reg, gen_im32(31));
1041
    gen_op_xor32(tmp, tmp, gen_im32(0x80000000));
1042
    gen_op_mov32(reg, tmp);
1043
    gen_set_label(l1);
1044
    gen_logic_cc(s, tmp);
1045
}
1046

    
1047
static void gen_push(DisasContext *s, int val)
1048
{
1049
    int tmp;
1050

    
1051
    tmp = gen_new_qreg(QMODE_I32);
1052
    gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1053
    gen_store(s, OS_LONG, tmp, val);
1054
    gen_op_mov32(QREG_SP, tmp);
1055
}
1056

    
1057
DISAS_INSN(movem)
1058
{
1059
    int addr;
1060
    int i;
1061
    uint16_t mask;
1062
    int reg;
1063
    int tmp;
1064
    int is_load;
1065

    
1066
    mask = lduw_code(s->pc);
1067
    s->pc += 2;
1068
    tmp = gen_lea(s, insn, OS_LONG);
1069
    if (tmp == -1) {
1070
        gen_addr_fault(s);
1071
        return;
1072
    }
1073
    addr = gen_new_qreg(QMODE_I32);
1074
    gen_op_mov32(addr, tmp);
1075
    is_load = ((insn & 0x0400) != 0);
1076
    for (i = 0; i < 16; i++, mask >>= 1) {
1077
        if (mask & 1) {
1078
            if (i < 8)
1079
                reg = DREG(i, 0);
1080
            else
1081
                reg = AREG(i, 0);
1082
            if (is_load) {
1083
                tmp = gen_load(s, OS_LONG, addr, 0);
1084
                gen_op_mov32(reg, tmp);
1085
            } else {
1086
                gen_store(s, OS_LONG, addr, reg);
1087
            }
1088
            if (mask != 1)
1089
                gen_op_add32(addr, addr, gen_im32(4));
1090
        }
1091
    }
1092
}
1093

    
1094
DISAS_INSN(bitop_im)
1095
{
1096
    int opsize;
1097
    int op;
1098
    int src1;
1099
    uint32_t mask;
1100
    int bitnum;
1101
    int tmp;
1102
    int addr;
1103
    int dest;
1104

    
1105
    if ((insn & 0x38) != 0)
1106
        opsize = OS_BYTE;
1107
    else
1108
        opsize = OS_LONG;
1109
    op = (insn >> 6) & 3;
1110

    
1111
    bitnum = lduw_code(s->pc);
1112
    s->pc += 2;
1113
    if (bitnum & 0xff00) {
1114
        disas_undef(s, insn);
1115
        return;
1116
    }
1117

    
1118
    SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1119

    
1120
    gen_flush_flags(s);
1121
    tmp = gen_new_qreg(QMODE_I32);
1122
    if (opsize == OS_BYTE)
1123
        bitnum &= 7;
1124
    else
1125
        bitnum &= 31;
1126
    mask = 1 << bitnum;
1127

    
1128
    gen_op_btest(src1, gen_im32(mask));
1129
    if (op)
1130
        dest = gen_new_qreg(QMODE_I32);
1131
    else
1132
        dest = -1;
1133

    
1134
    switch (op) {
1135
    case 1: /* bchg */
1136
        gen_op_xor32(dest, src1, gen_im32(mask));
1137
        break;
1138
    case 2: /* bclr */
1139
        gen_op_and32(dest, src1, gen_im32(~mask));
1140
        break;
1141
    case 3: /* bset */
1142
        gen_op_or32(dest, src1, gen_im32(mask));
1143
        break;
1144
    default: /* btst */
1145
        break;
1146
    }
1147
    if (op)
1148
        DEST_EA(insn, opsize, dest, &addr);
1149
}
1150

    
1151
DISAS_INSN(arith_im)
1152
{
1153
    int op;
1154
    int src1;
1155
    int dest;
1156
    int src2;
1157
    int addr;
1158

    
1159
    op = (insn >> 9) & 7;
1160
    SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
1161
    src2 = gen_im32(read_im32(s));
1162
    dest = gen_new_qreg(QMODE_I32);
1163
    switch (op) {
1164
    case 0: /* ori */
1165
        gen_op_or32(dest, src1, src2);
1166
        gen_logic_cc(s, dest);
1167
        break;
1168
    case 1: /* andi */
1169
        gen_op_and32(dest, src1, src2);
1170
        gen_logic_cc(s, dest);
1171
        break;
1172
    case 2: /* subi */
1173
        gen_op_mov32(dest, src1);
1174
        gen_op_update_xflag_lt(dest, src2);
1175
        gen_op_sub32(dest, dest, src2);
1176
        gen_op_update_cc_add(dest, src2);
1177
        s->cc_op = CC_OP_SUB;
1178
        break;
1179
    case 3: /* addi */
1180
        gen_op_mov32(dest, src1);
1181
        gen_op_add32(dest, dest, src2);
1182
        gen_op_update_cc_add(dest, src2);
1183
        gen_op_update_xflag_lt(dest, src2);
1184
        s->cc_op = CC_OP_ADD;
1185
        break;
1186
    case 5: /* eori */
1187
        gen_op_xor32(dest, src1, src2);
1188
        gen_logic_cc(s, dest);
1189
        break;
1190
    case 6: /* cmpi */
1191
        gen_op_mov32(dest, src1);
1192
        gen_op_sub32(dest, dest, src2);
1193
        gen_op_update_cc_add(dest, src2);
1194
        s->cc_op = CC_OP_SUB;
1195
        break;
1196
    default:
1197
        abort();
1198
    }
1199
    if (op != 6) {
1200
        DEST_EA(insn, OS_LONG, dest, &addr);
1201
    }
1202
}
1203

    
1204
DISAS_INSN(byterev)
1205
{
1206
    int reg;
1207

    
1208
    reg = DREG(insn, 0);
1209
    gen_op_bswap32(reg, reg);
1210
}
1211

    
1212
DISAS_INSN(move)
1213
{
1214
    int src;
1215
    int dest;
1216
    int op;
1217
    int opsize;
1218

    
1219
    switch (insn >> 12) {
1220
    case 1: /* move.b */
1221
        opsize = OS_BYTE;
1222
        break;
1223
    case 2: /* move.l */
1224
        opsize = OS_LONG;
1225
        break;
1226
    case 3: /* move.w */
1227
        opsize = OS_WORD;
1228
        break;
1229
    default:
1230
        abort();
1231
    }
1232
    SRC_EA(src, opsize, -1, NULL);
1233
    op = (insn >> 6) & 7;
1234
    if (op == 1) {
1235
        /* movea */
1236
        /* The value will already have been sign extended.  */
1237
        dest = AREG(insn, 9);
1238
        gen_op_mov32(dest, src);
1239
    } else {
1240
        /* normal move */
1241
        uint16_t dest_ea;
1242
        dest_ea = ((insn >> 9) & 7) | (op << 3);
1243
        DEST_EA(dest_ea, opsize, src, NULL);
1244
        /* This will be correct because loads sign extend.  */
1245
        gen_logic_cc(s, src);
1246
    }
1247
}
1248

    
1249
DISAS_INSN(negx)
1250
{
1251
    int reg;
1252
    int dest;
1253
    int tmp;
1254

    
1255
    gen_flush_flags(s);
1256
    reg = DREG(insn, 0);
1257
    dest = gen_new_qreg(QMODE_I32);
1258
    gen_op_mov32 (dest, gen_im32(0));
1259
    gen_op_subx_cc(dest, reg);
1260
    /* !Z is sticky.  */
1261
    tmp = gen_new_qreg(QMODE_I32);
1262
    gen_op_mov32 (tmp, QREG_CC_DEST);
1263
    gen_op_update_cc_add(dest, reg);
1264
    gen_op_mov32(reg, dest);
1265
    s->cc_op = CC_OP_DYNAMIC;
1266
    gen_flush_flags(s);
1267
    gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1268
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1269
    s->cc_op = CC_OP_FLAGS;
1270
}
1271

    
1272
DISAS_INSN(lea)
1273
{
1274
    int reg;
1275
    int tmp;
1276

    
1277
    reg = AREG(insn, 9);
1278
    tmp = gen_lea(s, insn, OS_LONG);
1279
    if (tmp == -1) {
1280
        gen_addr_fault(s);
1281
        return;
1282
    }
1283
    gen_op_mov32(reg, tmp);
1284
}
1285

    
1286
DISAS_INSN(clr)
1287
{
1288
    int opsize;
1289

    
1290
    switch ((insn >> 6) & 3) {
1291
    case 0: /* clr.b */
1292
        opsize = OS_BYTE;
1293
        break;
1294
    case 1: /* clr.w */
1295
        opsize = OS_WORD;
1296
        break;
1297
    case 2: /* clr.l */
1298
        opsize = OS_LONG;
1299
        break;
1300
    default:
1301
        abort();
1302
    }
1303
    DEST_EA(insn, opsize, gen_im32(0), NULL);
1304
    gen_logic_cc(s, gen_im32(0));
1305
}
1306

    
1307
static int gen_get_ccr(DisasContext *s)
1308
{
1309
    int dest;
1310

    
1311
    gen_flush_flags(s);
1312
    dest = gen_new_qreg(QMODE_I32);
1313
    gen_op_get_xflag(dest);
1314
    gen_op_shl32(dest, dest, gen_im32(4));
1315
    gen_op_or32(dest, dest, QREG_CC_DEST);
1316
    return dest;
1317
}
1318

    
1319
DISAS_INSN(move_from_ccr)
1320
{
1321
    int reg;
1322
    int ccr;
1323

    
1324
    ccr = gen_get_ccr(s);
1325
    reg = DREG(insn, 0);
1326
    gen_partset_reg(OS_WORD, reg, ccr);
1327
}
1328

    
1329
DISAS_INSN(neg)
1330
{
1331
    int reg;
1332
    int src1;
1333

    
1334
    reg = DREG(insn, 0);
1335
    src1 = gen_new_qreg(QMODE_I32);
1336
    gen_op_mov32(src1, reg);
1337
    gen_op_neg32(reg, src1);
1338
    s->cc_op = CC_OP_SUB;
1339
    gen_op_update_cc_add(reg, src1);
1340
    gen_op_update_xflag_lt(gen_im32(0), src1);
1341
    s->cc_op = CC_OP_SUB;
1342
}
1343

    
1344
static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
1345
{
1346
    gen_op_logic_cc(gen_im32(val & 0xf));
1347
    gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
1348
    if (!ccr_only) {
1349
        gen_op_set_sr(gen_im32(val & 0xff00));
1350
    }
1351
}
1352

    
1353
static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
1354
{
1355
    int src1;
1356
    int reg;
1357

    
1358
    s->cc_op = CC_OP_FLAGS;
1359
    if ((insn & 0x38) == 0)
1360
      {
1361
        src1 = gen_new_qreg(QMODE_I32);
1362
        reg = DREG(insn, 0);
1363
        gen_op_and32(src1, reg, gen_im32(0xf));
1364
        gen_op_logic_cc(src1);
1365
        gen_op_shr32(src1, reg, gen_im32(4));
1366
        gen_op_and32(src1, src1, gen_im32(1));
1367
        gen_op_update_xflag_tst(src1);
1368
        if (!ccr_only) {
1369
            gen_op_set_sr(reg);
1370
        }
1371
      }
1372
    else if ((insn & 0x3f) == 0x3c)
1373
      {
1374
        uint16_t val;
1375
        val = lduw_code(s->pc);
1376
        s->pc += 2;
1377
        gen_set_sr_im(s, val, ccr_only);
1378
      }
1379
    else
1380
        disas_undef(s, insn);
1381
}
1382

    
1383
DISAS_INSN(move_to_ccr)
1384
{
1385
    gen_set_sr(s, insn, 1);
1386
}
1387

    
1388
DISAS_INSN(not)
1389
{
1390
    int reg;
1391

    
1392
    reg = DREG(insn, 0);
1393
    gen_op_not32(reg, reg);
1394
    gen_logic_cc(s, reg);
1395
}
1396

    
1397
DISAS_INSN(swap)
1398
{
1399
    int dest;
1400
    int src1;
1401
    int src2;
1402
    int reg;
1403

    
1404
    dest = gen_new_qreg(QMODE_I32);
1405
    src1 = gen_new_qreg(QMODE_I32);
1406
    src2 = gen_new_qreg(QMODE_I32);
1407
    reg = DREG(insn, 0);
1408
    gen_op_shl32(src1, reg, gen_im32(16));
1409
    gen_op_shr32(src2, reg, gen_im32(16));
1410
    gen_op_or32(dest, src1, src2);
1411
    gen_op_mov32(reg, dest);
1412
    gen_logic_cc(s, dest);
1413
}
1414

    
1415
DISAS_INSN(pea)
1416
{
1417
    int tmp;
1418

    
1419
    tmp = gen_lea(s, insn, OS_LONG);
1420
    if (tmp == -1) {
1421
        gen_addr_fault(s);
1422
        return;
1423
    }
1424
    gen_push(s, tmp);
1425
}
1426

    
1427
DISAS_INSN(ext)
1428
{
1429
    int reg;
1430
    int op;
1431
    int tmp;
1432

    
1433
    reg = DREG(insn, 0);
1434
    op = (insn >> 6) & 7;
1435
    tmp = gen_new_qreg(QMODE_I32);
1436
    if (op == 3)
1437
        gen_op_ext16s32(tmp, reg);
1438
    else
1439
        gen_op_ext8s32(tmp, reg);
1440
    if (op == 2)
1441
        gen_partset_reg(OS_WORD, reg, tmp);
1442
    else
1443
      gen_op_mov32(reg, tmp);
1444
    gen_logic_cc(s, tmp);
1445
}
1446

    
1447
DISAS_INSN(tst)
1448
{
1449
    int opsize;
1450
    int tmp;
1451

    
1452
    switch ((insn >> 6) & 3) {
1453
    case 0: /* tst.b */
1454
        opsize = OS_BYTE;
1455
        break;
1456
    case 1: /* tst.w */
1457
        opsize = OS_WORD;
1458
        break;
1459
    case 2: /* tst.l */
1460
        opsize = OS_LONG;
1461
        break;
1462
    default:
1463
        abort();
1464
    }
1465
    SRC_EA(tmp, opsize, -1, NULL);
1466
    gen_logic_cc(s, tmp);
1467
}
1468

    
1469
DISAS_INSN(pulse)
1470
{
1471
  /* Implemented as a NOP.  */
1472
}
1473

    
1474
DISAS_INSN(illegal)
1475
{
1476
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1477
}
1478

    
1479
/* ??? This should be atomic.  */
1480
DISAS_INSN(tas)
1481
{
1482
    int dest;
1483
    int src1;
1484
    int addr;
1485

    
1486
    dest = gen_new_qreg(QMODE_I32);
1487
    SRC_EA(src1, OS_BYTE, -1, &addr);
1488
    gen_logic_cc(s, src1);
1489
    gen_op_or32(dest, src1, gen_im32(0x80));
1490
    DEST_EA(insn, OS_BYTE, dest, &addr);
1491
}
1492

    
1493
DISAS_INSN(mull)
1494
{
1495
    uint16_t ext;
1496
    int reg;
1497
    int src1;
1498
    int dest;
1499

    
1500
    /* The upper 32 bits of the product are discarded, so
1501
       muls.l and mulu.l are functionally equivalent.  */
1502
    ext = lduw_code(s->pc);
1503
    s->pc += 2;
1504
    if (ext & 0x87ff) {
1505
        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
1506
        return;
1507
    }
1508
    reg = DREG(ext, 12);
1509
    SRC_EA(src1, OS_LONG, 0, NULL);
1510
    dest = gen_new_qreg(QMODE_I32);
1511
    gen_op_mul32(dest, src1, reg);
1512
    gen_op_mov32(reg, dest);
1513
    /* Unlike m68k, coldfire always clears the overflow bit.  */
1514
    gen_logic_cc(s, dest);
1515
}
1516

    
1517
DISAS_INSN(link)
1518
{
1519
    int16_t offset;
1520
    int reg;
1521
    int tmp;
1522

    
1523
    offset = ldsw_code(s->pc);
1524
    s->pc += 2;
1525
    reg = AREG(insn, 0);
1526
    tmp = gen_new_qreg(QMODE_I32);
1527
    gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1528
    gen_store(s, OS_LONG, tmp, reg);
1529
    if (reg != QREG_SP)
1530
        gen_op_mov32(reg, tmp);
1531
    gen_op_add32(QREG_SP, tmp, gen_im32(offset));
1532
}
1533

    
1534
DISAS_INSN(unlk)
1535
{
1536
    int src;
1537
    int reg;
1538
    int tmp;
1539

    
1540
    src = gen_new_qreg(QMODE_I32);
1541
    reg = AREG(insn, 0);
1542
    gen_op_mov32(src, reg);
1543
    tmp = gen_load(s, OS_LONG, src, 0);
1544
    gen_op_mov32(reg, tmp);
1545
    gen_op_add32(QREG_SP, src, gen_im32(4));
1546
}
1547

    
1548
DISAS_INSN(nop)
1549
{
1550
}
1551

    
1552
DISAS_INSN(rts)
1553
{
1554
    int tmp;
1555

    
1556
    tmp = gen_load(s, OS_LONG, QREG_SP, 0);
1557
    gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
1558
    gen_jmp(s, tmp);
1559
}
1560

    
1561
DISAS_INSN(jump)
1562
{
1563
    int tmp;
1564

    
1565
    /* Load the target address first to ensure correct exception
1566
       behavior.  */
1567
    tmp = gen_lea(s, insn, OS_LONG);
1568
    if (tmp == -1) {
1569
        gen_addr_fault(s);
1570
        return;
1571
    }
1572
    if ((insn & 0x40) == 0) {
1573
        /* jsr */
1574
        gen_push(s, gen_im32(s->pc));
1575
    }
1576
    gen_jmp(s, tmp);
1577
}
1578

    
1579
DISAS_INSN(addsubq)
1580
{
1581
    int src1;
1582
    int src2;
1583
    int dest;
1584
    int val;
1585
    int addr;
1586

    
1587
    SRC_EA(src1, OS_LONG, 0, &addr);
1588
    val = (insn >> 9) & 7;
1589
    if (val == 0)
1590
        val = 8;
1591
    src2 = gen_im32(val);
1592
    dest = gen_new_qreg(QMODE_I32);
1593
    gen_op_mov32(dest, src1);
1594
    if ((insn & 0x38) == 0x08) {
1595
        /* Don't update condition codes if the destination is an
1596
           address register.  */
1597
        if (insn & 0x0100) {
1598
            gen_op_sub32(dest, dest, src2);
1599
        } else {
1600
            gen_op_add32(dest, dest, src2);
1601
        }
1602
    } else {
1603
        if (insn & 0x0100) {
1604
            gen_op_update_xflag_lt(dest, src2);
1605
            gen_op_sub32(dest, dest, src2);
1606
            s->cc_op = CC_OP_SUB;
1607
        } else {
1608
            gen_op_add32(dest, dest, src2);
1609
            gen_op_update_xflag_lt(dest, src2);
1610
            s->cc_op = CC_OP_ADD;
1611
        }
1612
        gen_op_update_cc_add(dest, src2);
1613
    }
1614
    DEST_EA(insn, OS_LONG, dest, &addr);
1615
}
1616

    
1617
DISAS_INSN(tpf)
1618
{
1619
    switch (insn & 7) {
1620
    case 2: /* One extension word.  */
1621
        s->pc += 2;
1622
        break;
1623
    case 3: /* Two extension words.  */
1624
        s->pc += 4;
1625
        break;
1626
    case 4: /* No extension words.  */
1627
        break;
1628
    default:
1629
        disas_undef(s, insn);
1630
    }
1631
}
1632

    
1633
DISAS_INSN(branch)
1634
{
1635
    int32_t offset;
1636
    uint32_t base;
1637
    int op;
1638
    int l1;
1639
    
1640
    base = s->pc;
1641
    op = (insn >> 8) & 0xf;
1642
    offset = (int8_t)insn;
1643
    if (offset == 0) {
1644
        offset = ldsw_code(s->pc);
1645
        s->pc += 2;
1646
    } else if (offset == -1) {
1647
        offset = read_im32(s);
1648
    }
1649
    if (op == 1) {
1650
        /* bsr */
1651
        gen_push(s, gen_im32(s->pc));
1652
    }
1653
    gen_flush_cc_op(s);
1654
    if (op > 1) {
1655
        /* Bcc */
1656
        l1 = gen_new_label();
1657
        gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
1658
        gen_jmp_tb(s, 1, base + offset);
1659
        gen_set_label(l1);
1660
        gen_jmp_tb(s, 0, s->pc);
1661
    } else {
1662
        /* Unconditional branch.  */
1663
        gen_jmp_tb(s, 0, base + offset);
1664
    }
1665
}
1666

    
1667
DISAS_INSN(moveq)
1668
{
1669
    int tmp;
1670

    
1671
    tmp = gen_im32((int8_t)insn);
1672
    gen_op_mov32(DREG(insn, 9), tmp);
1673
    gen_logic_cc(s, tmp);
1674
}
1675

    
1676
DISAS_INSN(mvzs)
1677
{
1678
    int opsize;
1679
    int src;
1680
    int reg;
1681

    
1682
    if (insn & 0x40)
1683
        opsize = OS_WORD;
1684
    else
1685
        opsize = OS_BYTE;
1686
    SRC_EA(src, opsize, (insn & 0x80) ? 0 : -1, NULL);
1687
    reg = DREG(insn, 9);
1688
    gen_op_mov32(reg, src);
1689
    gen_logic_cc(s, src);
1690
}
1691

    
1692
DISAS_INSN(or)
1693
{
1694
    int reg;
1695
    int dest;
1696
    int src;
1697
    int addr;
1698

    
1699
    reg = DREG(insn, 9);
1700
    dest = gen_new_qreg(QMODE_I32);
1701
    if (insn & 0x100) {
1702
        SRC_EA(src, OS_LONG, 0, &addr);
1703
        gen_op_or32(dest, src, reg);
1704
        DEST_EA(insn, OS_LONG, dest, &addr);
1705
    } else {
1706
        SRC_EA(src, OS_LONG, 0, NULL);
1707
        gen_op_or32(dest, src, reg);
1708
        gen_op_mov32(reg, dest);
1709
    }
1710
    gen_logic_cc(s, dest);
1711
}
1712

    
1713
DISAS_INSN(suba)
1714
{
1715
    int src;
1716
    int reg;
1717

    
1718
    SRC_EA(src, OS_LONG, 0, NULL);
1719
    reg = AREG(insn, 9);
1720
    gen_op_sub32(reg, reg, src);
1721
}
1722

    
1723
DISAS_INSN(subx)
1724
{
1725
    int reg;
1726
    int src;
1727
    int dest;
1728
    int tmp;
1729

    
1730
    gen_flush_flags(s);
1731
    reg = DREG(insn, 9);
1732
    src = DREG(insn, 0);
1733
    dest = gen_new_qreg(QMODE_I32);
1734
    gen_op_mov32 (dest, reg);
1735
    gen_op_subx_cc(dest, src);
1736
    /* !Z is sticky.  */
1737
    tmp = gen_new_qreg(QMODE_I32);
1738
    gen_op_mov32 (tmp, QREG_CC_DEST);
1739
    gen_op_update_cc_add(dest, src);
1740
    gen_op_mov32(reg, dest);
1741
    s->cc_op = CC_OP_DYNAMIC;
1742
    gen_flush_flags(s);
1743
    gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1744
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1745
    s->cc_op = CC_OP_FLAGS;
1746
}
1747

    
1748
DISAS_INSN(mov3q)
1749
{
1750
    int src;
1751
    int val;
1752

    
1753
    val = (insn >> 9) & 7;
1754
    if (val == 0)
1755
        val = -1;
1756
    src = gen_im32(val);
1757
    gen_logic_cc(s, src);
1758
    DEST_EA(insn, OS_LONG, src, NULL);
1759
}
1760

    
1761
DISAS_INSN(cmp)
1762
{
1763
    int op;
1764
    int src;
1765
    int reg;
1766
    int dest;
1767
    int opsize;
1768

    
1769
    op = (insn >> 6) & 3;
1770
    switch (op) {
1771
    case 0: /* cmp.b */
1772
        opsize = OS_BYTE;
1773
        s->cc_op = CC_OP_CMPB;
1774
        break;
1775
    case 1: /* cmp.w */
1776
        opsize = OS_WORD;
1777
        s->cc_op = CC_OP_CMPW;
1778
        break;
1779
    case 2: /* cmp.l */
1780
        opsize = OS_LONG;
1781
        s->cc_op = CC_OP_SUB;
1782
        break;
1783
    default:
1784
        abort();
1785
    }
1786
    SRC_EA(src, opsize, -1, NULL);
1787
    reg = DREG(insn, 9);
1788
    dest = gen_new_qreg(QMODE_I32);
1789
    gen_op_sub32(dest, reg, src);
1790
    gen_op_update_cc_add(dest, src);
1791
}
1792

    
1793
DISAS_INSN(cmpa)
1794
{
1795
    int opsize;
1796
    int src;
1797
    int reg;
1798
    int dest;
1799

    
1800
    if (insn & 0x100) {
1801
        opsize = OS_LONG;
1802
    } else {
1803
        opsize = OS_WORD;
1804
    }
1805
    SRC_EA(src, opsize, -1, NULL);
1806
    reg = AREG(insn, 9);
1807
    dest = gen_new_qreg(QMODE_I32);
1808
    gen_op_sub32(dest, reg, src);
1809
    gen_op_update_cc_add(dest, src);
1810
    s->cc_op = CC_OP_SUB;
1811
}
1812

    
1813
DISAS_INSN(eor)
1814
{
1815
    int src;
1816
    int reg;
1817
    int dest;
1818
    int addr;
1819

    
1820
    SRC_EA(src, OS_LONG, 0, &addr);
1821
    reg = DREG(insn, 9);
1822
    dest = gen_new_qreg(QMODE_I32);
1823
    gen_op_xor32(dest, src, reg);
1824
    gen_logic_cc(s, dest);
1825
    DEST_EA(insn, OS_LONG, dest, &addr);
1826
}
1827

    
1828
DISAS_INSN(and)
1829
{
1830
    int src;
1831
    int reg;
1832
    int dest;
1833
    int addr;
1834

    
1835
    reg = DREG(insn, 9);
1836
    dest = gen_new_qreg(QMODE_I32);
1837
    if (insn & 0x100) {
1838
        SRC_EA(src, OS_LONG, 0, &addr);
1839
        gen_op_and32(dest, src, reg);
1840
        DEST_EA(insn, OS_LONG, dest, &addr);
1841
    } else {
1842
        SRC_EA(src, OS_LONG, 0, NULL);
1843
        gen_op_and32(dest, src, reg);
1844
        gen_op_mov32(reg, dest);
1845
    }
1846
    gen_logic_cc(s, dest);
1847
}
1848

    
1849
DISAS_INSN(adda)
1850
{
1851
    int src;
1852
    int reg;
1853

    
1854
    SRC_EA(src, OS_LONG, 0, NULL);
1855
    reg = AREG(insn, 9);
1856
    gen_op_add32(reg, reg, src);
1857
}
1858

    
1859
DISAS_INSN(addx)
1860
{
1861
    int reg;
1862
    int src;
1863
    int dest;
1864
    int tmp;
1865

    
1866
    gen_flush_flags(s);
1867
    reg = DREG(insn, 9);
1868
    src = DREG(insn, 0);
1869
    dest = gen_new_qreg(QMODE_I32);
1870
    gen_op_mov32 (dest, reg);
1871
    gen_op_addx_cc(dest, src);
1872
    /* !Z is sticky.  */
1873
    tmp = gen_new_qreg(QMODE_I32);
1874
    gen_op_mov32 (tmp, QREG_CC_DEST);
1875
    gen_op_update_cc_add(dest, src);
1876
    gen_op_mov32(reg, dest);
1877
    s->cc_op = CC_OP_DYNAMIC;
1878
    gen_flush_flags(s);
1879
    gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1880
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1881
    s->cc_op = CC_OP_FLAGS;
1882
}
1883

    
1884
DISAS_INSN(shift_im)
1885
{
1886
    int reg;
1887
    int tmp;
1888

    
1889
    reg = DREG(insn, 0);
1890
    tmp = (insn >> 9) & 7;
1891
    if (tmp == 0)
1892
      tmp = 8;
1893
    if (insn & 0x100) {
1894
        gen_op_shl_im_cc(reg, tmp);
1895
        s->cc_op = CC_OP_SHL;
1896
    } else {
1897
        if (insn & 8) {
1898
            gen_op_shr_im_cc(reg, tmp);
1899
            s->cc_op = CC_OP_SHR;
1900
        } else {
1901
            gen_op_sar_im_cc(reg, tmp);
1902
            s->cc_op = CC_OP_SAR;
1903
        }
1904
    }
1905
}
1906

    
1907
DISAS_INSN(shift_reg)
1908
{
1909
    int reg;
1910
    int src;
1911
    int tmp;
1912

    
1913
    reg = DREG(insn, 0);
1914
    src = DREG(insn, 9);
1915
    tmp = gen_new_qreg(QMODE_I32);
1916
    gen_op_and32(tmp, src, gen_im32(63));
1917
    if (insn & 0x100) {
1918
        gen_op_shl_cc(reg, tmp);
1919
        s->cc_op = CC_OP_SHL;
1920
    } else {
1921
        if (insn & 8) {
1922
            gen_op_shr_cc(reg, tmp);
1923
            s->cc_op = CC_OP_SHR;
1924
        } else {
1925
            gen_op_sar_cc(reg, tmp);
1926
            s->cc_op = CC_OP_SAR;
1927
        }
1928
    }
1929
}
1930

    
1931
DISAS_INSN(ff1)
1932
{
1933
    int reg;
1934
    reg = DREG(insn, 0);
1935
    gen_logic_cc(s, reg);
1936
    gen_op_ff1(reg, reg);
1937
}
1938

    
1939
static int gen_get_sr(DisasContext *s)
1940
{
1941
    int ccr;
1942
    int sr;
1943

    
1944
    ccr = gen_get_ccr(s);
1945
    sr = gen_new_qreg(QMODE_I32);
1946
    gen_op_and32(sr, QREG_SR, gen_im32(0xffe0));
1947
    gen_op_or32(sr, sr, ccr);
1948
    return sr;
1949
}
1950

    
1951
DISAS_INSN(strldsr)
1952
{
1953
    uint16_t ext;
1954
    uint32_t addr;
1955

    
1956
    addr = s->pc - 2;
1957
    ext = lduw_code(s->pc);
1958
    s->pc += 2;
1959
    if (ext != 0x46FC) {
1960
        gen_exception(s, addr, EXCP_UNSUPPORTED);
1961
        return;
1962
    }
1963
    ext = lduw_code(s->pc);
1964
    s->pc += 2;
1965
    if (IS_USER(s) || (ext & SR_S) == 0) {
1966
        gen_exception(s, addr, EXCP_PRIVILEGE);
1967
        return;
1968
    }
1969
    gen_push(s, gen_get_sr(s));
1970
    gen_set_sr_im(s, ext, 0);
1971
}
1972

    
1973
DISAS_INSN(move_from_sr)
1974
{
1975
    int reg;
1976
    int sr;
1977

    
1978
    if (IS_USER(s)) {
1979
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1980
        return;
1981
    }
1982
    sr = gen_get_sr(s);
1983
    reg = DREG(insn, 0);
1984
    gen_partset_reg(OS_WORD, reg, sr);
1985
}
1986

    
1987
DISAS_INSN(move_to_sr)
1988
{
1989
    if (IS_USER(s)) {
1990
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1991
        return;
1992
    }
1993
    gen_set_sr(s, insn, 0);
1994
    gen_lookup_tb(s);
1995
}
1996

    
1997
DISAS_INSN(move_from_usp)
1998
{
1999
    if (IS_USER(s)) {
2000
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2001
        return;
2002
    }
2003
    /* TODO: Implement USP.  */
2004
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
2005
}
2006

    
2007
DISAS_INSN(move_to_usp)
2008
{
2009
    if (IS_USER(s)) {
2010
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2011
        return;
2012
    }
2013
    /* TODO: Implement USP.  */
2014
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
2015
}
2016

    
2017
DISAS_INSN(halt)
2018
{
2019
    gen_jmp(s, gen_im32(s->pc));
2020
    gen_op_halt();
2021
}
2022

    
2023
DISAS_INSN(stop)
2024
{
2025
    uint16_t ext;
2026

    
2027
    if (IS_USER(s)) {
2028
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2029
        return;
2030
    }
2031

    
2032
    ext = lduw_code(s->pc);
2033
    s->pc += 2;
2034

    
2035
    gen_set_sr_im(s, ext, 0);
2036
    gen_jmp(s, gen_im32(s->pc));
2037
    gen_op_stop();
2038
}
2039

    
2040
DISAS_INSN(rte)
2041
{
2042
    if (IS_USER(s)) {
2043
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2044
        return;
2045
    }
2046
    gen_exception(s, s->pc - 2, EXCP_RTE);
2047
}
2048

    
2049
DISAS_INSN(movec)
2050
{
2051
    uint16_t ext;
2052
    int reg;
2053

    
2054
    if (IS_USER(s)) {
2055
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2056
        return;
2057
    }
2058

    
2059
    ext = lduw_code(s->pc);
2060
    s->pc += 2;
2061

    
2062
    if (ext & 0x8000) {
2063
        reg = AREG(ext, 12);
2064
    } else {
2065
        reg = DREG(ext, 12);
2066
    }
2067
    gen_op_movec(gen_im32(ext & 0xfff), reg);
2068
    gen_lookup_tb(s);
2069
}
2070

    
2071
DISAS_INSN(intouch)
2072
{
2073
    if (IS_USER(s)) {
2074
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2075
        return;
2076
    }
2077
    /* ICache fetch.  Implement as no-op.  */
2078
}
2079

    
2080
DISAS_INSN(cpushl)
2081
{
2082
    if (IS_USER(s)) {
2083
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2084
        return;
2085
    }
2086
    /* Cache push/invalidate.  Implement as no-op.  */
2087
}
2088

    
2089
DISAS_INSN(wddata)
2090
{
2091
    gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2092
}
2093

    
2094
DISAS_INSN(wdebug)
2095
{
2096
    if (IS_USER(s)) {
2097
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2098
        return;
2099
    }
2100
    /* TODO: Implement wdebug.  */
2101
    qemu_assert(0, "WDEBUG not implemented");
2102
}
2103

    
2104
DISAS_INSN(trap)
2105
{
2106
    gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
2107
}
2108

    
2109
/* ??? FP exceptions are not implemented.  Most exceptions are deferred until
2110
   immediately before the next FP instruction is executed.  */
2111
DISAS_INSN(fpu)
2112
{
2113
    uint16_t ext;
2114
    int opmode;
2115
    int src;
2116
    int dest;
2117
    int res;
2118
    int round;
2119
    int opsize;
2120

    
2121
    ext = lduw_code(s->pc);
2122
    s->pc += 2;
2123
    opmode = ext & 0x7f;
2124
    switch ((ext >> 13) & 7) {
2125
    case 0: case 2:
2126
        break;
2127
    case 1:
2128
        goto undef;
2129
    case 3: /* fmove out */
2130
        src = FREG(ext, 7);
2131
        /* fmove */
2132
        /* ??? TODO: Proper behavior on overflow.  */
2133
        switch ((ext >> 10) & 7) {
2134
        case 0:
2135
            opsize = OS_LONG;
2136
            res = gen_new_qreg(QMODE_I32);
2137
            gen_op_f64_to_i32(res, src);
2138
            break;
2139
        case 1:
2140
            opsize = OS_SINGLE;
2141
            res = gen_new_qreg(QMODE_F32);
2142
            gen_op_f64_to_f32(res, src);
2143
            break;
2144
        case 4:
2145
            opsize = OS_WORD;
2146
            res = gen_new_qreg(QMODE_I32);
2147
            gen_op_f64_to_i32(res, src);
2148
            break;
2149
        case 5:
2150
            opsize = OS_DOUBLE;
2151
            res = src;
2152
            break;
2153
        case 6:
2154
            opsize = OS_BYTE;
2155
            res = gen_new_qreg(QMODE_I32);
2156
            gen_op_f64_to_i32(res, src);
2157
            break;
2158
        default:
2159
            goto undef;
2160
        }
2161
        DEST_EA(insn, opsize, res, NULL);
2162
        return;
2163
    case 4: /* fmove to control register.  */
2164
        switch ((ext >> 10) & 7) {
2165
        case 4: /* FPCR */
2166
            /* Not implemented.  Ignore writes.  */
2167
            break;
2168
        case 1: /* FPIAR */
2169
        case 2: /* FPSR */
2170
        default:
2171
            cpu_abort(NULL, "Unimplemented: fmove to control %d",
2172
                      (ext >> 10) & 7);
2173
        }
2174
        break;
2175
    case 5: /* fmove from control register.  */
2176
        switch ((ext >> 10) & 7) {
2177
        case 4: /* FPCR */
2178
            /* Not implemented.  Always return zero.  */
2179
            res = gen_im32(0);
2180
            break;
2181
        case 1: /* FPIAR */
2182
        case 2: /* FPSR */
2183
        default:
2184
            cpu_abort(NULL, "Unimplemented: fmove from control %d",
2185
                      (ext >> 10) & 7);
2186
            goto undef;
2187
        }
2188
        DEST_EA(insn, OS_LONG, res, NULL);
2189
        break;
2190
    case 6: /* fmovem */ 
2191
    case 7:
2192
        {
2193
        int addr;
2194
        uint16_t mask;
2195
        if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
2196
            goto undef;
2197
        src = gen_lea(s, insn, OS_LONG);
2198
        if (src == -1) {
2199
            gen_addr_fault(s);
2200
            return;
2201
        }
2202
        addr = gen_new_qreg(QMODE_I32);
2203
        gen_op_mov32(addr, src);
2204
        mask = 0x80;
2205
        dest = QREG_F0;
2206
        while (mask) {
2207
            if (ext & mask) {
2208
                if (ext & (1 << 13)) {
2209
                    /* store */
2210
                    gen_st(s, f64, addr, dest);
2211
                } else {
2212
                    /* load */
2213
                    gen_ld(s, f64, dest, addr);
2214
                }
2215
                if (ext & (mask - 1))
2216
                    gen_op_add32(addr, addr, gen_im32(8));
2217
            }
2218
            mask >>= 1;
2219
            dest++;
2220
        }
2221
        }
2222
        return;
2223
    }
2224
    if (ext & (1 << 14)) {
2225
        int tmp;
2226

    
2227
        /* Source effective address.  */
2228
        switch ((ext >> 10) & 7) {
2229
        case 0: opsize = OS_LONG; break;
2230
        case 1: opsize = OS_SINGLE; break;
2231
        case 4: opsize = OS_WORD; break;
2232
        case 5: opsize = OS_DOUBLE; break;
2233
        case 6: opsize = OS_BYTE; break;
2234
        default:
2235
            goto undef;
2236
        }
2237
        SRC_EA(tmp, opsize, -1, NULL);
2238
        if (opsize == OS_DOUBLE) {
2239
            src = tmp;
2240
        } else {
2241
            src = gen_new_qreg(QMODE_F64);
2242
            switch (opsize) {
2243
            case OS_LONG:
2244
            case OS_WORD:
2245
            case OS_BYTE:
2246
                gen_op_i32_to_f64(src, tmp);
2247
                break;
2248
            case OS_SINGLE:
2249
                gen_op_f32_to_f64(src, tmp);
2250
                break;
2251
            }
2252
        }
2253
    } else {
2254
        /* Source register.  */
2255
        src = FREG(ext, 10);
2256
    }
2257
    dest = FREG(ext, 7);
2258
    res = gen_new_qreg(QMODE_F64);
2259
    if (opmode != 0x3a)
2260
        gen_op_movf64(res, dest);
2261
    round = 1;
2262
    switch (opmode) {
2263
    case 0: case 0x40: case 0x44: /* fmove */
2264
        gen_op_movf64(res, src);
2265
        break;
2266
    case 1: /* fint */
2267
        gen_op_iround_f64(res, src);
2268
        round = 0;
2269
        break;
2270
    case 3: /* fintrz */
2271
        gen_op_itrunc_f64(res, src);
2272
        round = 0;
2273
        break;
2274
    case 4: case 0x41: case 0x45: /* fsqrt */
2275
        gen_op_sqrtf64(res, src);
2276
        break;
2277
    case 0x18: case 0x58: case 0x5c: /* fabs */
2278
        gen_op_absf64(res, src);
2279
        break;
2280
    case 0x1a: case 0x5a: case 0x5e: /* fneg */
2281
        gen_op_chsf64(res, src);
2282
        break;
2283
    case 0x20: case 0x60: case 0x64: /* fdiv */
2284
        gen_op_divf64(res, res, src);
2285
        break;
2286
    case 0x22: case 0x62: case 0x66: /* fadd */
2287
        gen_op_addf64(res, res, src);
2288
        break;
2289
    case 0x23: case 0x63: case 0x67: /* fmul */
2290
        gen_op_mulf64(res, res, src);
2291
        break;
2292
    case 0x28: case 0x68: case 0x6c: /* fsub */
2293
        gen_op_subf64(res, res, src);
2294
        break;
2295
    case 0x38: /* fcmp */
2296
        gen_op_sub_cmpf64(res, res, src);
2297
        dest = 0;
2298
        round = 0;
2299
        break;
2300
    case 0x3a: /* ftst */
2301
        gen_op_movf64(res, src);
2302
        dest = 0;
2303
        round = 0;
2304
        break;
2305
    default:
2306
        goto undef;
2307
    }
2308
    if (round) {
2309
        if (opmode & 0x40) {
2310
            if ((opmode & 0x4) != 0)
2311
                round = 0;
2312
        } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
2313
            round = 0;
2314
        }
2315
    }
2316
    if (round) {
2317
        int tmp;
2318

    
2319
        tmp = gen_new_qreg(QMODE_F32);
2320
        gen_op_f64_to_f32(tmp, res);
2321
        gen_op_f32_to_f64(res, tmp);
2322
    } 
2323
    gen_op_fp_result(res);
2324
    if (dest) {
2325
        gen_op_movf64(dest, res);
2326
    }
2327
    return;
2328
undef:
2329
    s->pc -= 2;
2330
    disas_undef_fpu(s, insn);
2331
}
2332

    
2333
DISAS_INSN(fbcc)
2334
{
2335
    uint32_t offset;
2336
    uint32_t addr;
2337
    int flag;
2338
    int zero;
2339
    int l1;
2340

    
2341
    addr = s->pc;
2342
    offset = ldsw_code(s->pc);
2343
    s->pc += 2;
2344
    if (insn & (1 << 6)) {
2345
        offset = (offset << 16) | lduw_code(s->pc);
2346
        s->pc += 2;
2347
    }
2348

    
2349
    l1 = gen_new_label();
2350
    /* TODO: Raise BSUN exception.  */
2351
    flag = gen_new_qreg(QMODE_I32);
2352
    zero = gen_new_qreg(QMODE_F64);
2353
    gen_op_zerof64(zero);
2354
    gen_op_compare_quietf64(flag, QREG_FP_RESULT, zero);
2355
    /* Jump to l1 if condition is true.  */
2356
    switch (insn & 0xf) {
2357
    case 0: /* f */
2358
        break;
2359
    case 1: /* eq (=0) */
2360
        gen_op_jmp_z32(flag, l1);
2361
        break;
2362
    case 2: /* ogt (=1) */
2363
        gen_op_sub32(flag, flag, gen_im32(1));
2364
        gen_op_jmp_z32(flag, l1);
2365
        break;
2366
    case 3: /* oge (=0 or =1) */
2367
        gen_op_jmp_z32(flag, l1);
2368
        gen_op_sub32(flag, flag, gen_im32(1));
2369
        gen_op_jmp_z32(flag, l1);
2370
        break;
2371
    case 4: /* olt (=-1) */
2372
        gen_op_jmp_s32(flag, l1);
2373
        break;
2374
    case 5: /* ole (=-1 or =0) */
2375
        gen_op_jmp_s32(flag, l1);
2376
        gen_op_jmp_z32(flag, l1);
2377
        break;
2378
    case 6: /* ogl (=-1 or =1) */
2379
        gen_op_jmp_s32(flag, l1);
2380
        gen_op_sub32(flag, flag, gen_im32(1));
2381
        gen_op_jmp_z32(flag, l1);
2382
        break;
2383
    case 7: /* or (=2) */
2384
        gen_op_sub32(flag, flag, gen_im32(2));
2385
        gen_op_jmp_z32(flag, l1);
2386
        break;
2387
    case 8: /* un (<2) */
2388
        gen_op_sub32(flag, flag, gen_im32(2));
2389
        gen_op_jmp_s32(flag, l1);
2390
        break;
2391
    case 9: /* ueq (=0 or =2) */
2392
        gen_op_jmp_z32(flag, l1);
2393
        gen_op_sub32(flag, flag, gen_im32(2));
2394
        gen_op_jmp_z32(flag, l1);
2395
        break;
2396
    case 10: /* ugt (>0) */
2397
        /* ??? Add jmp_gtu.  */
2398
        gen_op_sub32(flag, flag, gen_im32(1));
2399
        gen_op_jmp_ns32(flag, l1);
2400
        break;
2401
    case 11: /* uge (>=0) */
2402
        gen_op_jmp_ns32(flag, l1);
2403
        break;
2404
    case 12: /* ult (=-1 or =2) */
2405
        gen_op_jmp_s32(flag, l1);
2406
        gen_op_sub32(flag, flag, gen_im32(2));
2407
        gen_op_jmp_z32(flag, l1);
2408
        break;
2409
    case 13: /* ule (!=1) */
2410
        gen_op_sub32(flag, flag, gen_im32(1));
2411
        gen_op_jmp_nz32(flag, l1);
2412
        break;
2413
    case 14: /* ne (!=0) */
2414
        gen_op_jmp_nz32(flag, l1);
2415
        break;
2416
    case 15: /* t */
2417
        gen_op_mov32(flag, gen_im32(1));
2418
        break;
2419
    }
2420
    gen_jmp_tb(s, 0, s->pc);
2421
    gen_set_label(l1);
2422
    gen_jmp_tb(s, 1, addr + offset);
2423
}
2424

    
2425
DISAS_INSN(frestore)
2426
{
2427
    /* TODO: Implement frestore.  */
2428
    qemu_assert(0, "FRESTORE not implemented");
2429
}
2430

    
2431
DISAS_INSN(fsave)
2432
{
2433
    /* TODO: Implement fsave.  */
2434
    qemu_assert(0, "FSAVE not implemented");
2435
}
2436

    
2437
static inline int gen_mac_extract_word(DisasContext *s, int val, int upper)
2438
{
2439
    int tmp = gen_new_qreg(QMODE_I32);
2440
    if (s->env->macsr & MACSR_FI) {
2441
        if (upper)
2442
            gen_op_and32(tmp, val, gen_im32(0xffff0000));
2443
        else
2444
            gen_op_shl32(tmp, val, gen_im32(16));
2445
    } else if (s->env->macsr & MACSR_SU) {
2446
        if (upper)
2447
            gen_op_sar32(tmp, val, gen_im32(16));
2448
        else
2449
            gen_op_ext16s32(tmp, val);
2450
    } else {
2451
        if (upper)
2452
            gen_op_shr32(tmp, val, gen_im32(16));
2453
        else
2454
            gen_op_ext16u32(tmp, val);
2455
    }
2456
    return tmp;
2457
}
2458

    
2459
DISAS_INSN(mac)
2460
{
2461
    int rx;
2462
    int ry;
2463
    uint16_t ext;
2464
    int acc;
2465
    int l1;
2466
    int tmp;
2467
    int addr;
2468
    int loadval;
2469
    int dual;
2470
    int saved_flags = -1;
2471

    
2472
    ext = lduw_code(s->pc);
2473
    s->pc += 2;
2474

    
2475
    acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
2476
    dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
2477
    if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
2478
        disas_undef(s, insn);
2479
        return;
2480
    }
2481
    if (insn & 0x30) {
2482
        /* MAC with load.  */
2483
        tmp = gen_lea(s, insn, OS_LONG);
2484
        addr = gen_new_qreg(QMODE_I32);
2485
        gen_op_and32(addr, tmp, QREG_MAC_MASK);
2486
        /* Load the value now to ensure correct exception behavior.
2487
           Perform writeback after reading the MAC inputs.  */
2488
        loadval = gen_load(s, OS_LONG, addr, 0);
2489

    
2490
        acc ^= 1;
2491
        rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12);
2492
        ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0);
2493
    } else {
2494
        loadval = addr = -1;
2495
        rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
2496
        ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2497
    }
2498

    
2499
    gen_op_mac_clear_flags();
2500
    l1 = -1;
2501
    if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
2502
        /* Skip the multiply if we know we will ignore it.  */
2503
        l1 = gen_new_label();
2504
        tmp = gen_new_qreg(QMODE_I32);
2505
        gen_op_and32(tmp, QREG_MACSR, gen_im32(1 << (acc + 8)));
2506
        gen_op_jmp_nz32(tmp, l1);
2507
    }
2508

    
2509
    if ((ext & 0x0800) == 0) {
2510
        /* Word.  */
2511
        rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0);
2512
        ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0);
2513
    }
2514
    if (s->env->macsr & MACSR_FI) {
2515
        gen_op_macmulf(rx, ry);
2516
    } else {
2517
        if (s->env->macsr & MACSR_SU)
2518
            gen_op_macmuls(rx, ry);
2519
        else
2520
            gen_op_macmulu(rx, ry);
2521
        switch ((ext >> 9) & 3) {
2522
        case 1:
2523
            gen_op_macshl();
2524
            break;
2525
        case 3:
2526
            gen_op_macshr();
2527
            break;
2528
        }
2529
    }
2530

    
2531
    if (dual) {
2532
        /* Save the overflow flag from the multiply.  */
2533
        saved_flags = gen_new_qreg(QMODE_I32);
2534
        gen_op_mov32(saved_flags, QREG_MACSR);
2535
    }
2536

    
2537
    if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
2538
        /* Skip the accumulate if the value is already saturated.  */
2539
        l1 = gen_new_label();
2540
        tmp = gen_new_qreg(QMODE_I32);
2541
        gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
2542
        gen_op_jmp_nz32(tmp, l1);
2543
    }
2544

    
2545
    if (insn & 0x100)
2546
        gen_op_macsub(acc);
2547
    else
2548
        gen_op_macadd(acc);
2549

    
2550
    if (s->env->macsr & MACSR_FI)
2551
        gen_op_macsatf(acc);
2552
    else if (s->env->macsr & MACSR_SU)
2553
        gen_op_macsats(acc);
2554
    else
2555
        gen_op_macsatu(acc);
2556

    
2557
    if (l1 != -1)
2558
        gen_set_label(l1);
2559

    
2560
    if (dual) {
2561
        /* Dual accumulate variant.  */
2562
        acc = (ext >> 2) & 3;
2563
        /* Restore the overflow flag from the multiplier.  */
2564
        gen_op_mov32(QREG_MACSR, saved_flags);
2565
        if ((s->env->macsr & MACSR_OMC) != 0) {
2566
            /* Skip the accumulate if the value is already saturated.  */
2567
            l1 = gen_new_label();
2568
            tmp = gen_new_qreg(QMODE_I32);
2569
            gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
2570
            gen_op_jmp_nz32(tmp, l1);
2571
        }
2572
        if (ext & 2)
2573
            gen_op_macsub(acc);
2574
        else
2575
            gen_op_macadd(acc);
2576
        if (s->env->macsr & MACSR_FI)
2577
            gen_op_macsatf(acc);
2578
        else if (s->env->macsr & MACSR_SU)
2579
            gen_op_macsats(acc);
2580
        else
2581
            gen_op_macsatu(acc);
2582
        if (l1 != -1)
2583
            gen_set_label(l1);
2584
    }
2585
    gen_op_mac_set_flags(acc);
2586

    
2587
    if (insn & 0x30) {
2588
        int rw;
2589
        rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
2590
        gen_op_mov32(rw, loadval);
2591
        /* FIXME: Should address writeback happen with the masked or
2592
           unmasked value?  */
2593
        switch ((insn >> 3) & 7) {
2594
        case 3: /* Post-increment.  */
2595
            gen_op_add32(AREG(insn, 0), addr, gen_im32(4));
2596
            break;
2597
        case 4: /* Pre-decrement.  */
2598
            gen_op_mov32(AREG(insn, 0), addr);
2599
        }
2600
    }
2601
}
2602

    
2603
DISAS_INSN(from_mac)
2604
{
2605
    int rx;
2606
    int acc;
2607

    
2608
    rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2609
    acc = (insn >> 9) & 3;
2610
    if (s->env->macsr & MACSR_FI) {
2611
        gen_op_get_macf(rx, acc);
2612
    } else if ((s->env->macsr & MACSR_OMC) == 0) {
2613
        gen_op_get_maci(rx, acc);
2614
    } else if (s->env->macsr & MACSR_SU) {
2615
        gen_op_get_macs(rx, acc);
2616
    } else {
2617
        gen_op_get_macu(rx, acc);
2618
    }
2619
    if (insn & 0x40)
2620
        gen_op_clear_mac(acc);
2621
}
2622

    
2623
DISAS_INSN(move_mac)
2624
{
2625
    int src;
2626
    int dest;
2627
    src = insn & 3;
2628
    dest = (insn >> 9) & 3;
2629
    gen_op_move_mac(dest, src);
2630
    gen_op_mac_clear_flags();
2631
    gen_op_mac_set_flags(dest);
2632
}
2633

    
2634
DISAS_INSN(from_macsr)
2635
{
2636
    int reg;
2637

    
2638
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2639
    gen_op_mov32(reg, QREG_MACSR);
2640
}
2641

    
2642
DISAS_INSN(from_mask)
2643
{
2644
    int reg;
2645
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2646
    gen_op_mov32(reg, QREG_MAC_MASK);
2647
}
2648

    
2649
DISAS_INSN(from_mext)
2650
{
2651
    int reg;
2652
    int acc;
2653
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2654
    acc = (insn & 0x400) ? 2 : 0;
2655
    if (s->env->macsr & MACSR_FI)
2656
        gen_op_get_mac_extf(reg, acc);
2657
    else
2658
        gen_op_get_mac_exti(reg, acc);
2659
}
2660

    
2661
DISAS_INSN(macsr_to_ccr)
2662
{
2663
    gen_op_mov32(QREG_CC_X, gen_im32(0));
2664
    gen_op_and32(QREG_CC_DEST, QREG_MACSR, gen_im32(0xf));
2665
    s->cc_op = CC_OP_FLAGS;
2666
}
2667

    
2668
DISAS_INSN(to_mac)
2669
{
2670
    int acc;
2671
    int val;
2672
    acc = (insn >>9) & 3;
2673
    SRC_EA(val, OS_LONG, 0, NULL);
2674
    if (s->env->macsr & MACSR_FI) {
2675
        gen_op_set_macf(val, acc);
2676
    } else if (s->env->macsr & MACSR_SU) {
2677
        gen_op_set_macs(val, acc);
2678
    } else {
2679
        gen_op_set_macu(val, acc);
2680
    }
2681
    gen_op_mac_clear_flags();
2682
    gen_op_mac_set_flags(acc);
2683
}
2684

    
2685
DISAS_INSN(to_macsr)
2686
{
2687
    int val;
2688
    SRC_EA(val, OS_LONG, 0, NULL);
2689
    gen_op_set_macsr(val);
2690
    gen_lookup_tb(s);
2691
}
2692

    
2693
DISAS_INSN(to_mask)
2694
{
2695
    int val;
2696
    SRC_EA(val, OS_LONG, 0, NULL);
2697
    gen_op_or32(QREG_MAC_MASK, val, gen_im32(0xffff0000));
2698
}
2699

    
2700
DISAS_INSN(to_mext)
2701
{
2702
    int val;
2703
    int acc;
2704
    SRC_EA(val, OS_LONG, 0, NULL);
2705
    acc = (insn & 0x400) ? 2 : 0;
2706
    if (s->env->macsr & MACSR_FI)
2707
        gen_op_set_mac_extf(val, acc);
2708
    else if (s->env->macsr & MACSR_SU)
2709
        gen_op_set_mac_exts(val, acc);
2710
    else
2711
        gen_op_set_mac_extu(val, acc);
2712
}
2713

    
2714
static disas_proc opcode_table[65536];
2715

    
2716
static void
2717
register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2718
{
2719
  int i;
2720
  int from;
2721
  int to;
2722

    
2723
  /* Sanity check.  All set bits must be included in the mask.  */
2724
  if (opcode & ~mask) {
2725
      fprintf(stderr,
2726
              "qemu internal error: bogus opcode definition %04x/%04x\n",
2727
              opcode, mask);
2728
      abort();
2729
  }
2730
  /* This could probably be cleverer.  For now just optimize the case where
2731
     the top bits are known.  */
2732
  /* Find the first zero bit in the mask.  */
2733
  i = 0x8000;
2734
  while ((i & mask) != 0)
2735
      i >>= 1;
2736
  /* Iterate over all combinations of this and lower bits.  */
2737
  if (i == 0)
2738
      i = 1;
2739
  else
2740
      i <<= 1;
2741
  from = opcode & ~(i - 1);
2742
  to = from + i;
2743
  for (i = from; i < to; i++) {
2744
      if ((i & mask) == opcode)
2745
          opcode_table[i] = proc;
2746
  }
2747
}
2748

    
2749
/* Register m68k opcode handlers.  Order is important.
2750
   Later insn override earlier ones.  */
2751
void register_m68k_insns (CPUM68KState *env)
2752
{
2753
#define INSN(name, opcode, mask, feature) do { \
2754
    if (m68k_feature(env, M68K_FEATURE_##feature)) \
2755
        register_opcode(disas_##name, 0x##opcode, 0x##mask); \
2756
    } while(0)
2757
    INSN(undef,     0000, 0000, CF_ISA_A);
2758
    INSN(arith_im,  0080, fff8, CF_ISA_A);
2759
    INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
2760
    INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
2761
    INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
2762
    INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
2763
    INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
2764
    INSN(arith_im,  0280, fff8, CF_ISA_A);
2765
    INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
2766
    INSN(arith_im,  0480, fff8, CF_ISA_A);
2767
    INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
2768
    INSN(arith_im,  0680, fff8, CF_ISA_A);
2769
    INSN(bitop_im,  0800, ffc0, CF_ISA_A);
2770
    INSN(bitop_im,  0840, ffc0, CF_ISA_A);
2771
    INSN(bitop_im,  0880, ffc0, CF_ISA_A);
2772
    INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
2773
    INSN(arith_im,  0a80, fff8, CF_ISA_A);
2774
    INSN(arith_im,  0c00, ff38, CF_ISA_A);
2775
    INSN(move,      1000, f000, CF_ISA_A);
2776
    INSN(move,      2000, f000, CF_ISA_A);
2777
    INSN(move,      3000, f000, CF_ISA_A);
2778
    INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
2779
    INSN(negx,      4080, fff8, CF_ISA_A);
2780
    INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
2781
    INSN(lea,       41c0, f1c0, CF_ISA_A);
2782
    INSN(clr,       4200, ff00, CF_ISA_A);
2783
    INSN(undef,     42c0, ffc0, CF_ISA_A);
2784
    INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
2785
    INSN(neg,       4480, fff8, CF_ISA_A);
2786
    INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
2787
    INSN(not,       4680, fff8, CF_ISA_A);
2788
    INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
2789
    INSN(pea,       4840, ffc0, CF_ISA_A);
2790
    INSN(swap,      4840, fff8, CF_ISA_A);
2791
    INSN(movem,     48c0, fbc0, CF_ISA_A);
2792
    INSN(ext,       4880, fff8, CF_ISA_A);
2793
    INSN(ext,       48c0, fff8, CF_ISA_A);
2794
    INSN(ext,       49c0, fff8, CF_ISA_A);
2795
    INSN(tst,       4a00, ff00, CF_ISA_A);
2796
    INSN(tas,       4ac0, ffc0, CF_ISA_B);
2797
    INSN(halt,      4ac8, ffff, CF_ISA_A);
2798
    INSN(pulse,     4acc, ffff, CF_ISA_A);
2799
    INSN(illegal,   4afc, ffff, CF_ISA_A);
2800
    INSN(mull,      4c00, ffc0, CF_ISA_A);
2801
    INSN(divl,      4c40, ffc0, CF_ISA_A);
2802
    INSN(sats,      4c80, fff8, CF_ISA_B);
2803
    INSN(trap,      4e40, fff0, CF_ISA_A);
2804
    INSN(link,      4e50, fff8, CF_ISA_A);
2805
    INSN(unlk,      4e58, fff8, CF_ISA_A);
2806
    INSN(move_to_usp, 4e60, fff8, USP);
2807
    INSN(move_from_usp, 4e68, fff8, USP);
2808
    INSN(nop,       4e71, ffff, CF_ISA_A);
2809
    INSN(stop,      4e72, ffff, CF_ISA_A);
2810
    INSN(rte,       4e73, ffff, CF_ISA_A);
2811
    INSN(rts,       4e75, ffff, CF_ISA_A);
2812
    INSN(movec,     4e7b, ffff, CF_ISA_A);
2813
    INSN(jump,      4e80, ffc0, CF_ISA_A);
2814
    INSN(jump,      4ec0, ffc0, CF_ISA_A);
2815
    INSN(addsubq,   5180, f1c0, CF_ISA_A);
2816
    INSN(scc,       50c0, f0f8, CF_ISA_A);
2817
    INSN(addsubq,   5080, f1c0, CF_ISA_A);
2818
    INSN(tpf,       51f8, fff8, CF_ISA_A);
2819

    
2820
    /* Branch instructions.  */
2821
    INSN(branch,    6000, f000, CF_ISA_A);
2822
    /* Disable long branch instructions, then add back the ones we want.  */
2823
    INSN(undef,     60ff, f0ff, CF_ISA_A); /* All long branches.  */
2824
    INSN(branch,    60ff, f0ff, CF_ISA_B);
2825
    INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
2826
    INSN(branch,    60ff, ffff, BRAL);
2827

    
2828
    INSN(moveq,     7000, f100, CF_ISA_A);
2829
    INSN(mvzs,      7100, f100, CF_ISA_B);
2830
    INSN(or,        8000, f000, CF_ISA_A);
2831
    INSN(divw,      80c0, f0c0, CF_ISA_A);
2832
    INSN(addsub,    9000, f000, CF_ISA_A);
2833
    INSN(subx,      9180, f1f8, CF_ISA_A);
2834
    INSN(suba,      91c0, f1c0, CF_ISA_A);
2835

    
2836
    INSN(undef_mac, a000, f000, CF_ISA_A);
2837
    INSN(mac,       a000, f100, CF_EMAC);
2838
    INSN(from_mac,  a180, f9b0, CF_EMAC);
2839
    INSN(move_mac,  a110, f9fc, CF_EMAC);
2840
    INSN(from_macsr,a980, f9f0, CF_EMAC);
2841
    INSN(from_mask, ad80, fff0, CF_EMAC);
2842
    INSN(from_mext, ab80, fbf0, CF_EMAC);
2843
    INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC);
2844
    INSN(to_mac,    a100, f9c0, CF_EMAC);
2845
    INSN(to_macsr,  a900, ffc0, CF_EMAC);
2846
    INSN(to_mext,   ab00, fbc0, CF_EMAC);
2847
    INSN(to_mask,   ad00, ffc0, CF_EMAC);
2848

    
2849
    INSN(mov3q,     a140, f1c0, CF_ISA_B);
2850
    INSN(cmp,       b000, f1c0, CF_ISA_B); /* cmp.b */
2851
    INSN(cmp,       b040, f1c0, CF_ISA_B); /* cmp.w */
2852
    INSN(cmpa,      b0c0, f1c0, CF_ISA_B); /* cmpa.w */
2853
    INSN(cmp,       b080, f1c0, CF_ISA_A);
2854
    INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
2855
    INSN(eor,       b180, f1c0, CF_ISA_A);
2856
    INSN(and,       c000, f000, CF_ISA_A);
2857
    INSN(mulw,      c0c0, f0c0, CF_ISA_A);
2858
    INSN(addsub,    d000, f000, CF_ISA_A);
2859
    INSN(addx,      d180, f1f8, CF_ISA_A);
2860
    INSN(adda,      d1c0, f1c0, CF_ISA_A);
2861
    INSN(shift_im,  e080, f0f0, CF_ISA_A);
2862
    INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
2863
    INSN(undef_fpu, f000, f000, CF_ISA_A);
2864
    INSN(fpu,       f200, ffc0, CF_FPU);
2865
    INSN(fbcc,      f280, ffc0, CF_FPU);
2866
    INSN(frestore,  f340, ffc0, CF_FPU);
2867
    INSN(fsave,     f340, ffc0, CF_FPU);
2868
    INSN(intouch,   f340, ffc0, CF_ISA_A);
2869
    INSN(cpushl,    f428, ff38, CF_ISA_A);
2870
    INSN(wddata,    fb00, ff00, CF_ISA_A);
2871
    INSN(wdebug,    fbc0, ffc0, CF_ISA_A);
2872
#undef INSN
2873
}
2874

    
2875
/* ??? Some of this implementation is not exception safe.  We should always
2876
   write back the result to memory before setting the condition codes.  */
2877
static void disas_m68k_insn(CPUState * env, DisasContext *s)
2878
{
2879
    uint16_t insn;
2880

    
2881
    insn = lduw_code(s->pc);
2882
    s->pc += 2;
2883

    
2884
    opcode_table[insn](s, insn);
2885
}
2886

    
2887
#if 0
2888
/* Save the result of a floating point operation.  */
2889
static void expand_op_fp_result(qOP *qop)
2890
{
2891
    gen_op_movf64(QREG_FP_RESULT, qop->args[0]);
2892
}
2893

2894
/* Dummy op to indicate that the flags have been set.  */
2895
static void expand_op_flags_set(qOP *qop)
2896
{
2897
}
2898

2899
/* Convert the confition codes into CC_OP_FLAGS format.  */
2900
static void expand_op_flush_flags(qOP *qop)
2901
{
2902
    int cc_opreg;
2903

2904
    if (qop->args[0] == CC_OP_DYNAMIC)
2905
        cc_opreg = QREG_CC_OP;
2906
    else
2907
        cc_opreg = gen_im32(qop->args[0]);
2908
    gen_op_helper32(QREG_NULL, cc_opreg, HELPER_flush_flags);
2909
}
2910

2911
/* Set CC_DEST after a logical or direct flag setting operation.  */
2912
static void expand_op_logic_cc(qOP *qop)
2913
{
2914
    gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2915
}
2916

2917
/* Set CC_SRC and CC_DEST after an arithmetic operation.  */
2918
static void expand_op_update_cc_add(qOP *qop)
2919
{
2920
    gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2921
    gen_op_mov32(QREG_CC_SRC, qop->args[1]);
2922
}
2923

2924
/* Update the X flag.  */
2925
static void expand_op_update_xflag(qOP *qop)
2926
{
2927
    int arg0;
2928
    int arg1;
2929

2930
    arg0 = qop->args[0];
2931
    arg1 = qop->args[1];
2932
    if (arg1 == QREG_NULL) {
2933
        /* CC_X = arg0.  */
2934
        gen_op_mov32(QREG_CC_X, arg0);
2935
    } else {
2936
        /* CC_X = arg0 < (unsigned)arg1.  */
2937
        gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2938
    }
2939
}
2940

2941
/* Set arg0 to the contents of the X flag.  */
2942
static void expand_op_get_xflag(qOP *qop)
2943
{
2944
    gen_op_mov32(qop->args[0], QREG_CC_X);
2945
}
2946

2947
/* Expand a shift by immediate.  The ISA only allows shifts by 1-8, so we
2948
   already know the shift is within range.  */
2949
static inline void expand_shift_im(qOP *qop, int right, int arith)
2950
{
2951
    int val;
2952
    int reg;
2953
    int tmp;
2954
    int im;
2955

2956
    reg = qop->args[0];
2957
    im = qop->args[1];
2958
    tmp = gen_im32(im);
2959
    val = gen_new_qreg(QMODE_I32);
2960
    gen_op_mov32(val, reg);
2961
    gen_op_mov32(QREG_CC_DEST, val);
2962
    gen_op_mov32(QREG_CC_SRC, tmp);
2963
    if (right) {
2964
        if (arith) {
2965
            gen_op_sar32(reg, val, tmp);
2966
        } else {
2967
            gen_op_shr32(reg, val, tmp);
2968
        }
2969
        if (im == 1)
2970
            tmp = QREG_NULL;
2971
        else
2972
            tmp = gen_im32(im - 1);
2973
    } else {
2974
        gen_op_shl32(reg, val, tmp);
2975
        tmp = gen_im32(32 - im);
2976
    }
2977
    if (tmp != QREG_NULL)
2978
        gen_op_shr32(val, val, tmp);
2979
    gen_op_and32(QREG_CC_X, val, gen_im32(1));
2980
}
2981

2982
static void expand_op_shl_im_cc(qOP *qop)
2983
{
2984
    expand_shift_im(qop, 0, 0);
2985
}
2986

2987
static void expand_op_shr_im_cc(qOP *qop)
2988
{
2989
    expand_shift_im(qop, 1, 0);
2990
}
2991

2992
static void expand_op_sar_im_cc(qOP *qop)
2993
{
2994
    expand_shift_im(qop, 1, 1);
2995
}
2996

2997
/* Expand a shift by register.  */
2998
/* ??? This gives incorrect answers for shifts by 0 or >= 32 */
2999
static inline void expand_shift_reg(qOP *qop, int right, int arith)
3000
{
3001
    int val;
3002
    int reg;
3003
    int shift;
3004
    int tmp;
3005

3006
    reg = qop->args[0];
3007
    shift = qop->args[1];
3008
    val = gen_new_qreg(QMODE_I32);
3009
    gen_op_mov32(val, reg);
3010
    gen_op_mov32(QREG_CC_DEST, val);
3011
    gen_op_mov32(QREG_CC_SRC, shift);
3012
    tmp = gen_new_qreg(QMODE_I32);
3013
    if (right) {
3014
        if (arith) {
3015
            gen_op_sar32(reg, val, shift);
3016
        } else {
3017
            gen_op_shr32(reg, val, shift);
3018
        }
3019
        gen_op_sub32(tmp, shift, gen_im32(1));
3020
    } else {
3021
        gen_op_shl32(reg, val, shift);
3022
        gen_op_sub32(tmp, gen_im32(31), shift);
3023
    }
3024
    gen_op_shl32(val, val, tmp);
3025
    gen_op_and32(QREG_CC_X, val, gen_im32(1));
3026
}
3027

3028
static void expand_op_shl_cc(qOP *qop)
3029
{
3030
    expand_shift_reg(qop, 0, 0);
3031
}
3032

3033
static void expand_op_shr_cc(qOP *qop)
3034
{
3035
    expand_shift_reg(qop, 1, 0);
3036
}
3037

3038
static void expand_op_sar_cc(qOP *qop)
3039
{
3040
    expand_shift_reg(qop, 1, 1);
3041
}
3042

3043
/* Set the Z flag to (arg0 & arg1) == 0.  */
3044
static void expand_op_btest(qOP *qop)
3045
{
3046
    int tmp;
3047
    int l1;
3048

3049
    l1 = gen_new_label();
3050
    tmp = gen_new_qreg(QMODE_I32);
3051
    gen_op_and32(tmp, qop->args[0], qop->args[1]);
3052
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(~(uint32_t)CCF_Z));
3053
    gen_op_jmp_nz32(tmp, l1);
3054
    gen_op_or32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(CCF_Z));
3055
    gen_op_label(l1);
3056
}
3057

3058
/* arg0 += arg1 + CC_X */
3059
static void expand_op_addx_cc(qOP *qop)
3060
{
3061
    int arg0 = qop->args[0];
3062
    int arg1 = qop->args[1];
3063
    int l1, l2;
3064
    
3065
    gen_op_add32 (arg0, arg0, arg1);
3066
    l1 = gen_new_label();
3067
    l2 = gen_new_label();
3068
    gen_op_jmp_z32(QREG_CC_X, l1);
3069
    gen_op_add32(arg0, arg0, gen_im32(1));
3070
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
3071
    gen_op_set_leu32(QREG_CC_X, arg0, arg1);
3072
    gen_op_jmp(l2);
3073
    gen_set_label(l1);
3074
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
3075
    gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
3076
    gen_set_label(l2);
3077
}
3078

3079
/* arg0 -= arg1 + CC_X */
3080
static void expand_op_subx_cc(qOP *qop)
3081
{
3082
    int arg0 = qop->args[0];
3083
    int arg1 = qop->args[1];
3084
    int l1, l2;
3085

3086
    l1 = gen_new_label();
3087
    l2 = gen_new_label();
3088
    gen_op_jmp_z32(QREG_CC_X, l1);
3089
    gen_op_set_leu32(QREG_CC_X, arg0, arg1);
3090
    gen_op_sub32(arg0, arg0, gen_im32(1));
3091
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
3092
    gen_op_jmp(l2);
3093
    gen_set_label(l1);
3094
    gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
3095
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
3096
    gen_set_label(l2);
3097
    gen_op_sub32 (arg0, arg0, arg1);
3098
}
3099

3100
/* Expand target specific ops to generic qops.  */
3101
static void expand_target_qops(void)
3102
{
3103
    qOP *qop;
3104
    qOP *next;
3105
    int c;
3106

3107
    /* Copy the list of qops, expanding target specific ops as we go.  */
3108
    qop = gen_first_qop;
3109
    gen_first_qop = NULL;
3110
    gen_last_qop = NULL;
3111
    for (; qop; qop = next) {
3112
        c = qop->opcode;
3113
        next = qop->next;
3114
        if (c < FIRST_TARGET_OP) {
3115
            qop->prev = gen_last_qop;
3116
            qop->next = NULL;
3117
            if (gen_last_qop)
3118
                gen_last_qop->next = qop;
3119
            else
3120
                gen_first_qop = qop;
3121
            gen_last_qop = qop;
3122
            continue;
3123
        }
3124
        switch (c) {
3125
#define DEF(name, nargs, barrier) \
3126
        case INDEX_op_##name: \
3127
            expand_op_##name(qop); \
3128
            break;
3129
#include "qop-target.def"
3130
#undef DEF
3131
        default:
3132
            cpu_abort(NULL, "Unexpanded target qop");
3133
        }
3134
    }
3135
}
3136

3137
/* ??? Implement this.  */
3138
static void
3139
optimize_flags(void)
3140
{
3141
}
3142
#endif
3143

    
3144
/* generate intermediate code for basic block 'tb'.  */
3145
static inline int
3146
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
3147
                               int search_pc)
3148
{
3149
    DisasContext dc1, *dc = &dc1;
3150
    uint16_t *gen_opc_end;
3151
    int j, lj;
3152
    target_ulong pc_start;
3153
    int pc_offset;
3154
    int last_cc_op;
3155

    
3156
    /* generate intermediate code */
3157
    pc_start = tb->pc;
3158
       
3159
    dc->tb = tb;
3160

    
3161
    gen_opc_ptr = gen_opc_buf;
3162
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3163
    gen_opparam_ptr = gen_opparam_buf;
3164

    
3165
    dc->env = env;
3166
    dc->is_jmp = DISAS_NEXT;
3167
    dc->pc = pc_start;
3168
    dc->cc_op = CC_OP_DYNAMIC;
3169
    dc->singlestep_enabled = env->singlestep_enabled;
3170
    dc->fpcr = env->fpcr;
3171
    dc->user = (env->sr & SR_S) == 0;
3172
    nb_gen_labels = 0;
3173
    lj = -1;
3174
    do {
3175
        free_qreg = 0;
3176
        pc_offset = dc->pc - pc_start;
3177
        gen_throws_exception = NULL;
3178
        if (env->nb_breakpoints > 0) {
3179
            for(j = 0; j < env->nb_breakpoints; j++) {
3180
                if (env->breakpoints[j] == dc->pc) {
3181
                    gen_exception(dc, dc->pc, EXCP_DEBUG);
3182
                    dc->is_jmp = DISAS_JUMP;
3183
                    break;
3184
                }
3185
            }
3186
            if (dc->is_jmp)
3187
                break;
3188
        }
3189
        if (search_pc) {
3190
            j = gen_opc_ptr - gen_opc_buf;
3191
            if (lj < j) {
3192
                lj++;
3193
                while (lj < j)
3194
                    gen_opc_instr_start[lj++] = 0;
3195
            }
3196
            gen_opc_pc[lj] = dc->pc;
3197
            gen_opc_instr_start[lj] = 1;
3198
        }
3199
        last_cc_op = dc->cc_op;
3200
        dc->insn_pc = dc->pc;
3201
        disas_m68k_insn(env, dc);
3202
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3203
             !env->singlestep_enabled &&
3204
             (pc_offset) < (TARGET_PAGE_SIZE - 32));
3205

    
3206
    if (__builtin_expect(env->singlestep_enabled, 0)) {
3207
        /* Make sure the pc is updated, and raise a debug exception.  */
3208
        if (!dc->is_jmp) {
3209
            gen_flush_cc_op(dc);
3210
            gen_op_mov32(QREG_PC, gen_im32((long)dc->pc));
3211
        }
3212
        gen_op_raise_exception(EXCP_DEBUG);
3213
    } else {
3214
        switch(dc->is_jmp) {
3215
        case DISAS_NEXT:
3216
            gen_flush_cc_op(dc);
3217
            gen_jmp_tb(dc, 0, dc->pc);
3218
            break;
3219
        default:
3220
        case DISAS_JUMP:
3221
        case DISAS_UPDATE:
3222
            gen_flush_cc_op(dc);
3223
            /* indicate that the hash table must be used to find the next TB */
3224
            gen_op_mov32(QREG_T0, gen_im32(0));
3225
            gen_op_exit_tb();
3226
            break;
3227
        case DISAS_TB_JUMP:
3228
            /* nothing more to generate */
3229
            break;
3230
        }
3231
    }
3232
    *gen_opc_ptr = INDEX_op_end;
3233

    
3234
#ifdef DEBUG_DISAS
3235
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3236
        fprintf(logfile, "----------------\n");
3237
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3238
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
3239
        fprintf(logfile, "\n");
3240
        if (loglevel & (CPU_LOG_TB_OP)) {
3241
            fprintf(logfile, "OP:\n");
3242
            dump_ops(gen_opc_buf, gen_opparam_buf);
3243
            fprintf(logfile, "\n");
3244
        }
3245
    }
3246
#endif
3247
    if (search_pc) {
3248
        j = gen_opc_ptr - gen_opc_buf;
3249
        lj++;
3250
        while (lj <= j)
3251
            gen_opc_instr_start[lj++] = 0;
3252
        tb->size = 0;
3253
    } else {
3254
        tb->size = dc->pc - pc_start;
3255
    }
3256

    
3257
    //optimize_flags();
3258
    //expand_target_qops();
3259
    return 0;
3260
}
3261

    
3262
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
3263
{
3264
    return gen_intermediate_code_internal(env, tb, 0);
3265
}
3266

    
3267
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
3268
{
3269
    return gen_intermediate_code_internal(env, tb, 1);
3270
}
3271

    
3272
void cpu_reset(CPUM68KState *env)
3273
{
3274
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
3275
#if !defined (CONFIG_USER_ONLY)
3276
    env->sr = 0x2700;
3277
#endif
3278
    m68k_switch_sp(env);
3279
    /* ??? FP regs should be initialized to NaN.  */
3280
    env->cc_op = CC_OP_FLAGS;
3281
    /* TODO: We should set PC from the interrupt vector.  */
3282
    env->pc = 0;
3283
    tlb_flush(env, 1);
3284
}
3285

    
3286
CPUM68KState *cpu_m68k_init(void)
3287
{
3288
    CPUM68KState *env;
3289

    
3290
    env = malloc(sizeof(CPUM68KState));
3291
    if (!env)
3292
        return NULL;
3293
    cpu_exec_init(env);
3294

    
3295
    cpu_reset(env);
3296
    return env;
3297
}
3298

    
3299
void cpu_m68k_close(CPUM68KState *env)
3300
{
3301
    free(env);
3302
}
3303

    
3304
void cpu_dump_state(CPUState *env, FILE *f, 
3305
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3306
                    int flags)
3307
{
3308
    int i;
3309
    uint16_t sr;
3310
    CPU_DoubleU u;
3311
    for (i = 0; i < 8; i++)
3312
      {
3313
        u.d = env->fregs[i];
3314
        cpu_fprintf (f, "D%d = %08x   A%d = %08x   F%d = %08x%08x (%12g)\n",
3315
                     i, env->dregs[i], i, env->aregs[i],
3316
                     i, u.l.upper, u.l.lower, u.d);
3317
      }
3318
    cpu_fprintf (f, "PC = %08x   ", env->pc);
3319
    sr = env->sr;
3320
    cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
3321
                 (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
3322
                 (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
3323
    cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result);
3324
}
3325