Statistics
| Branch: | Revision:

root / target-m68k / translate.c @ d315c888

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_op_flush_flags(s->cc_op);
349
    s->cc_op = CC_OP_FLAGS;
350
}
351

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
941

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1547
DISAS_INSN(nop)
1548
{
1549
}
1550

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2713
static disas_proc opcode_table[65536];
2714

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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