Statistics
| Branch: | Revision:

root / target-m68k / translate.c @ 0633879f

History | View | Annotate | Download (70.2 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
    target_ulong pc;
46
    int is_jmp;
47
    int cc_op;
48
    int user;
49
    uint32_t fpcr;
50
    struct TranslationBlock *tb;
51
    int singlestep_enabled;
52
} DisasContext;
53

    
54
#define DISAS_JUMP_NEXT 4
55

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

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

    
67
static uint16_t *gen_opc_ptr;
68
static uint32_t *gen_opparam_ptr;
69
extern FILE *logfile;
70
extern int loglevel;
71

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

    
79
#include "gen-op.h"
80

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

    
99
#include "op-hacks.h"
100

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

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

    
111
#define M68K_INSN_CF_A    (1 << 0)
112
#define M68K_INSN_CF_B    (1 << 1)
113
#define M68K_INSN_CF_C    (1 << 2)
114
#define M68K_INSN_CF_MAC  (1 << 3)
115
#define M68K_INSN_CF_EMAC (1 << 4)
116
#define M68K_INSN_CF_FPU  (1 << 5)
117

    
118
struct m68k_def_t {
119
    const char * name;
120
    uint32_t insns;
121
};
122

    
123
static m68k_def_t m68k_cpu_defs[] = {
124
    {"m5206", M68K_INSN_CF_A},
125
    {"cfv4e", M68K_INSN_CF_A | M68K_INSN_CF_B | M68K_INSN_CF_C
126
            | M68K_INSN_CF_MAC | M68K_INSN_CF_EMAC | M68K_INSN_CF_FPU},
127
    {NULL, 0}, 
128
};
129

    
130
typedef void (*disas_proc)(DisasContext *, uint16_t);
131

    
132
#ifdef DEBUG_DISPATCH
133
#define DISAS_INSN(name) \
134
  static void real_disas_##name (DisasContext *s, uint16_t insn); \
135
  static void disas_##name (DisasContext *s, uint16_t insn) { \
136
    if (logfile) fprintf(logfile, "Dispatch " #name "\n"); \
137
    real_disas_##name(s, insn); } \
138
  static void real_disas_##name (DisasContext *s, uint16_t insn)
139
#else
140
#define DISAS_INSN(name) \
141
  static void disas_##name (DisasContext *s, uint16_t insn)
142
#endif
143

    
144
/* Generate a load from the specified address.  Narrow values are
145
   sign extended to full register width.  */
146
static inline int gen_load(DisasContext * s, int opsize, int addr, int sign)
147
{
148
    int tmp;
149
    switch(opsize) {
150
    case OS_BYTE:
151
        tmp = gen_new_qreg(QMODE_I32);
152
        if (sign)
153
            gen_ld(s, 8s32, tmp, addr);
154
        else
155
            gen_ld(s, 8u32, tmp, addr);
156
        break;
157
    case OS_WORD:
158
        tmp = gen_new_qreg(QMODE_I32);
159
        if (sign)
160
            gen_ld(s, 16s32, tmp, addr);
161
        else
162
            gen_ld(s, 16u32, tmp, addr);
163
        break;
164
    case OS_LONG:
165
        tmp = gen_new_qreg(QMODE_I32);
166
        gen_ld(s, 32, tmp, addr);
167
        break;
168
    case OS_SINGLE:
169
        tmp = gen_new_qreg(QMODE_F32);
170
        gen_ld(s, f32, tmp, addr);
171
        break;
172
    case OS_DOUBLE:
173
        tmp  = gen_new_qreg(QMODE_F64);
174
        gen_ld(s, f64, tmp, addr);
175
        break;
176
    default:
177
        qemu_assert(0, "bad load size");
178
    }
179
    gen_throws_exception = gen_last_qop;
180
    return tmp;
181
}
182

    
183
/* Generate a store.  */
184
static inline void gen_store(DisasContext *s, int opsize, int addr, int val)
185
{
186
    switch(opsize) {
187
    case OS_BYTE:
188
        gen_st(s, 8, addr, val);
189
        break;
190
    case OS_WORD:
191
        gen_st(s, 16, addr, val);
192
        break;
193
    case OS_LONG:
194
        gen_st(s, 32, addr, val);
195
        break;
196
    case OS_SINGLE:
197
        gen_st(s, f32, addr, val);
198
        break;
199
    case OS_DOUBLE:
200
        gen_st(s, f64, addr, val);
201
        break;
202
    default:
203
        qemu_assert(0, "bad store size");
204
    }
205
    gen_throws_exception = gen_last_qop;
206
}
207

    
208
/* Generate an unsigned load if VAL is 0 a signed load if val is -1,
209
   otherwise generate a store.  */
210
static int gen_ldst(DisasContext *s, int opsize, int addr, int val)
211
{
212
    if (val > 0) {
213
        gen_store(s, opsize, addr, val);
214
        return 0;
215
    } else {
216
        return gen_load(s, opsize, addr, val != 0);
217
    }
218
}
219

    
220
/* Handle a base + index + displacement effective addresss.  A base of
221
   -1 means pc-relative.  */
222
static int gen_lea_indexed(DisasContext *s, int opsize, int base)
223
{
224
    int scale;
225
    uint32_t offset;
226
    uint16_t ext;
227
    int add;
228
    int tmp;
229

    
230
    offset = s->pc;
231
    ext = lduw_code(s->pc);
232
    s->pc += 2;
233
    tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
234
    /* ??? Check W/L bit.  */
235
    scale = (ext >> 9) & 3;
236
    if (scale == 0) {
237
        add = tmp;
238
    } else {
239
        add = gen_new_qreg(QMODE_I32);
240
        gen_op_shl32(add, tmp, gen_im32(scale));
241
    }
242
    tmp = gen_new_qreg(QMODE_I32);
243
    if (base != -1) {
244
        gen_op_add32(tmp, base, gen_im32((int8_t)ext));
245
        gen_op_add32(tmp, tmp, add);
246
    } else {
247
        gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
248
    }
249
    return tmp;
250
}
251

    
252
/* Read a 32-bit immediate constant.  */
253
static inline uint32_t read_im32(DisasContext *s)
254
{
255
    uint32_t im;
256
    im = ((uint32_t)lduw_code(s->pc)) << 16;
257
    s->pc += 2;
258
    im |= lduw_code(s->pc);
259
    s->pc += 2;
260
    return im;
261
}
262

    
263

    
264
/* Update the CPU env CC_OP state.  */
265
static inline void gen_flush_cc_op(DisasContext *s)
266
{
267
    if (s->cc_op != CC_OP_DYNAMIC)
268
        gen_op_mov32(QREG_CC_OP, gen_im32(s->cc_op));
269
}
270

    
271
/* Evaluate all the CC flags.  */
272
static inline void gen_flush_flags(DisasContext *s)
273
{
274
    if (s->cc_op == CC_OP_FLAGS)
275
        return;
276
    gen_op_flush_flags(s->cc_op);
277
    s->cc_op = CC_OP_FLAGS;
278
}
279

    
280
static inline int opsize_bytes(int opsize)
281
{
282
    switch (opsize) {
283
    case OS_BYTE: return 1;
284
    case OS_WORD: return 2;
285
    case OS_LONG: return 4;
286
    case OS_SINGLE: return 4;
287
    case OS_DOUBLE: return 8;
288
    default:
289
        qemu_assert(0, "bad operand size");
290
    }
291
}
292

    
293
/* Assign value to a register.  If the width is less than the register width
294
   only the low part of the register is set.  */
295
static void gen_partset_reg(int opsize, int reg, int val)
296
{
297
    int tmp;
298
    switch (opsize) {
299
    case OS_BYTE:
300
        gen_op_and32(reg, reg, gen_im32(0xffffff00));
301
        tmp = gen_new_qreg(QMODE_I32);
302
        gen_op_and32(tmp, val, gen_im32(0xff));
303
        gen_op_or32(reg, reg, tmp);
304
        break;
305
    case OS_WORD:
306
        gen_op_and32(reg, reg, gen_im32(0xffff0000));
307
        tmp = gen_new_qreg(QMODE_I32);
308
        gen_op_and32(tmp, val, gen_im32(0xffff));
309
        gen_op_or32(reg, reg, tmp);
310
        break;
311
    case OS_LONG:
312
        gen_op_mov32(reg, val);
313
        break;
314
    case OS_SINGLE:
315
        gen_op_pack_32_f32(reg, val);
316
        break;
317
    default:
318
        qemu_assert(0, "Bad operand size");
319
        break;
320
    }
321
}
322

    
323
/* Sign or zero extend a value.  */
324
static inline int gen_extend(int val, int opsize, int sign)
325
{
326
    int tmp;
327

    
328
    switch (opsize) {
329
    case OS_BYTE:
330
        tmp = gen_new_qreg(QMODE_I32);
331
        if (sign)
332
            gen_op_ext8s32(tmp, val);
333
        else
334
            gen_op_ext8u32(tmp, val);
335
        break;
336
    case OS_WORD:
337
        tmp = gen_new_qreg(QMODE_I32);
338
        if (sign)
339
            gen_op_ext16s32(tmp, val);
340
        else
341
            gen_op_ext16u32(tmp, val);
342
        break;
343
    case OS_LONG:
344
        tmp = val;
345
        break;
346
    case OS_SINGLE:
347
        tmp = gen_new_qreg(QMODE_F32);
348
        gen_op_pack_f32_32(tmp, val);
349
        break;
350
    default:
351
        qemu_assert(0, "Bad operand size");
352
    }
353
    return tmp;
354
}
355

    
356
/* Generate code for an "effective address".  Does not adjust the base
357
   register for autoincrememnt addressing modes.  */
358
static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
359
{
360
    int reg;
361
    int tmp;
362
    uint16_t ext;
363
    uint32_t offset;
364

    
365
    reg = insn & 7;
366
    switch ((insn >> 3) & 7) {
367
    case 0: /* Data register direct.  */
368
    case 1: /* Address register direct.  */
369
        /* ??? generate bad addressing mode fault.  */
370
        qemu_assert(0, "invalid addressing mode");
371
    case 2: /* Indirect register */
372
    case 3: /* Indirect postincrement.  */
373
        reg += QREG_A0;
374
        return reg;
375
    case 4: /* Indirect predecrememnt.  */
376
        reg += QREG_A0;
377
        tmp = gen_new_qreg(QMODE_I32);
378
        gen_op_sub32(tmp, reg, gen_im32(opsize_bytes(opsize)));
379
        return tmp;
380
    case 5: /* Indirect displacement.  */
381
        reg += QREG_A0;
382
        tmp = gen_new_qreg(QMODE_I32);
383
        ext = lduw_code(s->pc);
384
        s->pc += 2;
385
        gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
386
        return tmp;
387
    case 6: /* Indirect index + displacement.  */
388
        reg += QREG_A0;
389
        return gen_lea_indexed(s, opsize, reg);
390
    case 7: /* Other */
391
        switch (reg) {
392
        case 0: /* Absolute short.  */
393
            offset = ldsw_code(s->pc);
394
            s->pc += 2;
395
            return gen_im32(offset);
396
        case 1: /* Absolute long.  */
397
            offset = read_im32(s);
398
            return gen_im32(offset);
399
        case 2: /* pc displacement  */
400
            tmp = gen_new_qreg(QMODE_I32);
401
            offset = s->pc;
402
            offset += ldsw_code(s->pc);
403
            s->pc += 2;
404
            return gen_im32(offset);
405
        case 3: /* pc index+displacement.  */
406
            return gen_lea_indexed(s, opsize, -1);
407
        case 4: /* Immediate.  */
408
        default:
409
            /* ??? generate bad addressing mode fault.  */
410
            qemu_assert(0, "invalid addressing mode");
411
        }
412
    }
413
    /* Should never happen.  */
414
    return -1;
415
}
416

    
417
/* Helper function for gen_ea. Reuse the computed address between the
418
   for read/write operands.  */
419
static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
420
                              int val, int *addrp)
421
{
422
    int tmp;
423

    
424
    if (addrp && val > 0) {
425
        tmp = *addrp;
426
    } else {
427
        tmp = gen_lea(s, insn, opsize);
428
        if (addrp)
429
            *addrp = tmp;
430
    }
431
    return gen_ldst(s, opsize, tmp, val);
432
}
433

    
434
/* Generate code to load/store a value ito/from an EA.  If VAL > 0 this is
435
   a write otherwise it is a read (0 == sign extend, -1 == zero extend).
436
   ADDRP is non-null for readwrite operands.  */
437
static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
438
                  int *addrp)
439
{
440
    int reg;
441
    int result;
442
    uint32_t offset;
443

    
444
    reg = insn & 7;
445
    switch ((insn >> 3) & 7) {
446
    case 0: /* Data register direct.  */
447
        reg += QREG_D0;
448
        if (val > 0) {
449
            gen_partset_reg(opsize, reg, val);
450
            return 0;
451
        } else {
452
            return gen_extend(reg, opsize, val);
453
        }
454
    case 1: /* Address register direct.  */
455
        reg += QREG_A0;
456
        if (val > 0) {
457
            gen_op_mov32(reg, val);
458
            return 0;
459
        } else {
460
            return gen_extend(reg, opsize, val);
461
        }
462
    case 2: /* Indirect register */
463
        reg += QREG_A0;
464
        return gen_ldst(s, opsize, reg, val);
465
    case 3: /* Indirect postincrement.  */
466
        reg += QREG_A0;
467
        result = gen_ldst(s, opsize, reg, val);
468
        /* ??? This is not exception safe.  The instruction may still
469
           fault after this point.  */
470
        if (val > 0 || !addrp)
471
            gen_op_add32(reg, reg, gen_im32(opsize_bytes(opsize)));
472
        return result;
473
    case 4: /* Indirect predecrememnt.  */
474
        {
475
            int tmp;
476
            if (addrp && val > 0) {
477
                tmp = *addrp;
478
            } else {
479
                tmp = gen_lea(s, insn, opsize);
480
                if (addrp)
481
                    *addrp = tmp;
482
            }
483
            result = gen_ldst(s, opsize, tmp, val);
484
            /* ??? This is not exception safe.  The instruction may still
485
               fault after this point.  */
486
            if (val > 0 || !addrp) {
487
                reg += QREG_A0;
488
                gen_op_mov32(reg, tmp);
489
            }
490
        }
491
        return result;
492
    case 5: /* Indirect displacement.  */
493
    case 6: /* Indirect index + displacement.  */
494
        return gen_ea_once(s, insn, opsize, val, addrp);
495
    case 7: /* Other */
496
        switch (reg) {
497
        case 0: /* Absolute short.  */
498
        case 1: /* Absolute long.  */
499
        case 2: /* pc displacement  */
500
        case 3: /* pc index+displacement.  */
501
            return gen_ea_once(s, insn, opsize, val, addrp);
502
        case 4: /* Immediate.  */
503
            /* Sign extend values for consistency.  */
504
            switch (opsize) {
505
            case OS_BYTE:
506
                if (val)
507
                    offset = ldsb_code(s->pc + 1);
508
                else
509
                    offset = ldub_code(s->pc + 1);
510
                s->pc += 2;
511
                break;
512
            case OS_WORD:
513
                if (val)
514
                    offset = ldsw_code(s->pc);
515
                else
516
                    offset = lduw_code(s->pc);
517
                s->pc += 2;
518
                break;
519
            case OS_LONG:
520
                offset = read_im32(s);
521
                break;
522
            default:
523
                qemu_assert(0, "Bad immediate operand");
524
            }
525
            return gen_im32(offset);
526
        default:
527
            qemu_assert(0, "invalid addressing mode");
528
        }
529
    }
530
    /* Should never happen.  */
531
    return -1;
532
}
533

    
534
static void gen_logic_cc(DisasContext *s, int val)
535
{
536
    gen_op_logic_cc(val);
537
    s->cc_op = CC_OP_LOGIC;
538
}
539

    
540
static void gen_jmpcc(DisasContext *s, int cond, int l1)
541
{
542
    int tmp;
543

    
544
    gen_flush_flags(s);
545
    switch (cond) {
546
    case 0: /* T */
547
        gen_op_jmp(l1);
548
        break;
549
    case 1: /* F */
550
        break;
551
    case 2: /* HI (!C && !Z) */
552
        tmp = gen_new_qreg(QMODE_I32);
553
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
554
        gen_op_jmp_z32(tmp, l1);
555
        break;
556
    case 3: /* LS (C || Z) */
557
        tmp = gen_new_qreg(QMODE_I32);
558
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
559
        gen_op_jmp_nz32(tmp, l1);
560
        break;
561
    case 4: /* CC (!C) */
562
        tmp = gen_new_qreg(QMODE_I32);
563
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
564
        gen_op_jmp_z32(tmp, l1);
565
        break;
566
    case 5: /* CS (C) */
567
        tmp = gen_new_qreg(QMODE_I32);
568
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
569
        gen_op_jmp_nz32(tmp, l1);
570
        break;
571
    case 6: /* NE (!Z) */
572
        tmp = gen_new_qreg(QMODE_I32);
573
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
574
        gen_op_jmp_z32(tmp, l1);
575
        break;
576
    case 7: /* EQ (Z) */
577
        tmp = gen_new_qreg(QMODE_I32);
578
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
579
        gen_op_jmp_nz32(tmp, l1);
580
        break;
581
    case 8: /* VC (!V) */
582
        tmp = gen_new_qreg(QMODE_I32);
583
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
584
        gen_op_jmp_z32(tmp, l1);
585
        break;
586
    case 9: /* VS (V) */
587
        tmp = gen_new_qreg(QMODE_I32);
588
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
589
        gen_op_jmp_nz32(tmp, l1);
590
        break;
591
    case 10: /* PL (!N) */
592
        tmp = gen_new_qreg(QMODE_I32);
593
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
594
        gen_op_jmp_z32(tmp, l1);
595
        break;
596
    case 11: /* MI (N) */
597
        tmp = gen_new_qreg(QMODE_I32);
598
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
599
        gen_op_jmp_nz32(tmp, l1);
600
        break;
601
    case 12: /* GE (!(N ^ V)) */
602
        tmp = gen_new_qreg(QMODE_I32);
603
        gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
604
        gen_op_xor32(tmp, tmp, QREG_CC_DEST);
605
        gen_op_and32(tmp, tmp, gen_im32(CCF_V));
606
        gen_op_jmp_z32(tmp, l1);
607
        break;
608
    case 13: /* LT (N ^ V) */
609
        tmp = gen_new_qreg(QMODE_I32);
610
        gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
611
        gen_op_xor32(tmp, tmp, QREG_CC_DEST);
612
        gen_op_and32(tmp, tmp, gen_im32(CCF_V));
613
        gen_op_jmp_nz32(tmp, l1);
614
        break;
615
    case 14: /* GT (!(Z || (N ^ V))) */
616
        {
617
            int l2;
618
            l2 = gen_new_label();
619
            tmp = gen_new_qreg(QMODE_I32);
620
            gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
621
            gen_op_jmp_nz32(tmp, l2);
622
            tmp = gen_new_qreg(QMODE_I32);
623
            gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
624
            gen_op_xor32(tmp, tmp, QREG_CC_DEST);
625
            gen_op_and32(tmp, tmp, gen_im32(CCF_V));
626
            gen_op_jmp_nz32(tmp, l2);
627
            gen_op_jmp(l1);
628
            gen_set_label(l2);
629
        }
630
        break;
631
    case 15: /* LE (Z || (N ^ V)) */
632
        tmp = gen_new_qreg(QMODE_I32);
633
        gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
634
        gen_op_jmp_nz32(tmp, l1);
635
        tmp = gen_new_qreg(QMODE_I32);
636
        gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
637
        gen_op_xor32(tmp, tmp, QREG_CC_DEST);
638
        gen_op_and32(tmp, tmp, gen_im32(CCF_V));
639
        gen_op_jmp_nz32(tmp, l1);
640
        break;
641
    default:
642
        /* Should ever happen.  */
643
        abort();
644
    }
645
}
646

    
647
DISAS_INSN(scc)
648
{
649
    int l1;
650
    int cond;
651
    int reg;
652

    
653
    l1 = gen_new_label();
654
    cond = (insn >> 8) & 0xf;
655
    reg = DREG(insn, 0);
656
    gen_op_and32(reg, reg, gen_im32(0xffffff00));
657
    gen_jmpcc(s, cond ^ 1, l1);
658
    gen_op_or32(reg, reg, gen_im32(0xff));
659
    gen_set_label(l1);
660
}
661

    
662
/* Force a TB lookup after an instruction that changes the CPU state.  */
663
static void gen_lookup_tb(DisasContext *s)
664
{
665
    gen_flush_cc_op(s);
666
    gen_op_mov32(QREG_PC, gen_im32(s->pc));
667
    s->is_jmp = DISAS_UPDATE;
668
}
669

    
670
/* Generate a jump to to the address in qreg DEST.  */
671
static void gen_jmp(DisasContext *s, int dest)
672
{
673
    gen_flush_cc_op(s);
674
    gen_op_mov32(QREG_PC, dest);
675
    s->is_jmp = DISAS_JUMP;
676
}
677

    
678
static void gen_exception(DisasContext *s, uint32_t where, int nr)
679
{
680
    gen_flush_cc_op(s);
681
    gen_jmp(s, gen_im32(where));
682
    gen_op_raise_exception(nr);
683
}
684

    
685
/* Generate a jump to an immediate address.  */
686
static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
687
{
688
    TranslationBlock *tb;
689

    
690
    tb = s->tb;
691
    if (__builtin_expect (s->singlestep_enabled, 0)) {
692
        gen_exception(s, dest, EXCP_DEBUG);
693
    } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
694
               (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
695
        gen_op_goto_tb(0, n, (long)tb);
696
        gen_op_mov32(QREG_PC, gen_im32(dest));
697
        gen_op_mov32(QREG_T0, gen_im32((long)tb + n));
698
        gen_op_exit_tb();
699
    } else {
700
        gen_jmp(s, gen_im32(dest));
701
        gen_op_mov32(QREG_T0, gen_im32(0));
702
        gen_op_exit_tb();
703
    }
704
    s->is_jmp = DISAS_TB_JUMP;
705
}
706

    
707
DISAS_INSN(undef_mac)
708
{
709
    gen_exception(s, s->pc - 2, EXCP_LINEA);
710
}
711

    
712
DISAS_INSN(undef_fpu)
713
{
714
    gen_exception(s, s->pc - 2, EXCP_LINEF);
715
}
716

    
717
DISAS_INSN(undef)
718
{
719
    gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
720
    cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
721
              insn, s->pc - 2);
722
}
723

    
724
DISAS_INSN(mulw)
725
{
726
    int reg;
727
    int tmp;
728
    int src;
729
    int sign;
730

    
731
    sign = (insn & 0x100) != 0;
732
    reg = DREG(insn, 9);
733
    tmp = gen_new_qreg(QMODE_I32);
734
    if (sign)
735
        gen_op_ext16s32(tmp, reg);
736
    else
737
        gen_op_ext16u32(tmp, reg);
738
    src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
739
    gen_op_mul32(tmp, tmp, src);
740
    gen_op_mov32(reg, tmp);
741
    /* Unlike m68k, coldfire always clears the overflow bit.  */
742
    gen_logic_cc(s, tmp);
743
}
744

    
745
DISAS_INSN(divw)
746
{
747
    int reg;
748
    int tmp;
749
    int src;
750
    int sign;
751

    
752
    sign = (insn & 0x100) != 0;
753
    reg = DREG(insn, 9);
754
    if (sign) {
755
        gen_op_ext16s32(QREG_DIV1, reg);
756
    } else {
757
        gen_op_ext16u32(QREG_DIV1, reg);
758
    }
759
    src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
760
    gen_op_mov32(QREG_DIV2, src);
761
    if (sign) {
762
        gen_op_divs(1);
763
    } else {
764
        gen_op_divu(1);
765
    }
766

    
767
    tmp = gen_new_qreg(QMODE_I32);
768
    src = gen_new_qreg(QMODE_I32);
769
    gen_op_ext16u32(tmp, QREG_DIV1);
770
    gen_op_shl32(src, QREG_DIV2, gen_im32(16));
771
    gen_op_or32(reg, tmp, src);
772
    gen_op_flags_set();
773
    s->cc_op = CC_OP_FLAGS;
774
}
775

    
776
DISAS_INSN(divl)
777
{
778
    int num;
779
    int den;
780
    int reg;
781
    uint16_t ext;
782

    
783
    ext = lduw_code(s->pc);
784
    s->pc += 2;
785
    if (ext & 0x87f8) {
786
        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
787
        return;
788
    }
789
    num = DREG(ext, 12);
790
    reg = DREG(ext, 0);
791
    gen_op_mov32(QREG_DIV1, num);
792
    den = gen_ea(s, insn, OS_LONG, 0, NULL);
793
    gen_op_mov32(QREG_DIV2, den);
794
    if (ext & 0x0800) {
795
        gen_op_divs(2);
796
    } else {
797
        gen_op_divu(2);
798
    }
799
    if (num == reg) {
800
        /* div */
801
        gen_op_mov32 (reg, QREG_DIV1);
802
    } else {
803
        /* rem */
804
        gen_op_mov32 (reg, QREG_DIV2);
805
    }
806
    gen_op_flags_set();
807
    s->cc_op = CC_OP_FLAGS;
808
}
809

    
810
DISAS_INSN(addsub)
811
{
812
    int reg;
813
    int dest;
814
    int src;
815
    int tmp;
816
    int addr;
817
    int add;
818

    
819
    add = (insn & 0x4000) != 0;
820
    reg = DREG(insn, 9);
821
    dest = gen_new_qreg(QMODE_I32);
822
    if (insn & 0x100) {
823
        tmp = gen_ea(s, insn, OS_LONG, 0, &addr);
824
        src = reg;
825
    } else {
826
        tmp = reg;
827
        src = gen_ea(s, insn, OS_LONG, 0, NULL);
828
    }
829
    if (add) {
830
        gen_op_add32(dest, tmp, src);
831
        gen_op_update_xflag_lt(dest, src);
832
        s->cc_op = CC_OP_ADD;
833
    } else {
834
        gen_op_update_xflag_lt(tmp, src);
835
        gen_op_sub32(dest, tmp, src);
836
        s->cc_op = CC_OP_SUB;
837
    }
838
    gen_op_update_cc_add(dest, src);
839
    if (insn & 0x100) {
840
        gen_ea(s, insn, OS_LONG, dest, &addr);
841
    } else {
842
        gen_op_mov32(reg, dest);
843
    }
844
}
845

    
846

    
847
/* Reverse the order of the bits in REG.  */
848
DISAS_INSN(bitrev)
849
{
850
    int val;
851
    int tmp1;
852
    int tmp2;
853
    int reg;
854

    
855
    val = gen_new_qreg(QMODE_I32);
856
    tmp1 = gen_new_qreg(QMODE_I32);
857
    tmp2 = gen_new_qreg(QMODE_I32);
858
    reg = DREG(insn, 0);
859
    gen_op_mov32(val, reg);
860
    /* Reverse bits within each nibble.  */
861
    gen_op_shl32(tmp1, val, gen_im32(3));
862
    gen_op_and32(tmp1, tmp1, gen_im32(0x88888888));
863
    gen_op_shl32(tmp2, val, gen_im32(1));
864
    gen_op_and32(tmp2, tmp2, gen_im32(0x44444444));
865
    gen_op_or32(tmp1, tmp1, tmp2);
866
    gen_op_shr32(tmp2, val, gen_im32(1));
867
    gen_op_and32(tmp2, tmp2, gen_im32(0x22222222));
868
    gen_op_or32(tmp1, tmp1, tmp2);
869
    gen_op_shr32(tmp2, val, gen_im32(3));
870
    gen_op_and32(tmp2, tmp2, gen_im32(0x11111111));
871
    gen_op_or32(tmp1, tmp1, tmp2);
872
    /* Reverse nibbles withing bytes.  */
873
    gen_op_shl32(val, tmp1, gen_im32(4));
874
    gen_op_and32(val, val, gen_im32(0xf0f0f0f0));
875
    gen_op_shr32(tmp2, tmp1, gen_im32(4));
876
    gen_op_and32(tmp2, tmp2, gen_im32(0x0f0f0f0f));
877
    gen_op_or32(val, val, tmp2);
878
    /* Reverse bytes.  */
879
    gen_op_bswap32(reg, val);
880
    gen_op_mov32(reg, val);
881
}
882

    
883
DISAS_INSN(bitop_reg)
884
{
885
    int opsize;
886
    int op;
887
    int src1;
888
    int src2;
889
    int tmp;
890
    int addr;
891
    int dest;
892

    
893
    if ((insn & 0x38) != 0)
894
        opsize = OS_BYTE;
895
    else
896
        opsize = OS_LONG;
897
    op = (insn >> 6) & 3;
898
    src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
899
    src2 = DREG(insn, 9);
900
    dest = gen_new_qreg(QMODE_I32);
901

    
902
    gen_flush_flags(s);
903
    tmp = gen_new_qreg(QMODE_I32);
904
    if (opsize == OS_BYTE)
905
        gen_op_and32(tmp, src2, gen_im32(7));
906
    else
907
        gen_op_and32(tmp, src2, gen_im32(31));
908
    src2 = tmp;
909
    tmp = gen_new_qreg(QMODE_I32);
910
    gen_op_shl32(tmp, gen_im32(1), src2);
911

    
912
    gen_op_btest(src1, tmp);
913
    switch (op) {
914
    case 1: /* bchg */
915
        gen_op_xor32(dest, src1, tmp);
916
        break;
917
    case 2: /* bclr */
918
        gen_op_not32(tmp, tmp);
919
        gen_op_and32(dest, src1, tmp);
920
        break;
921
    case 3: /* bset */
922
        gen_op_or32(dest, src1, tmp);
923
        break;
924
    default: /* btst */
925
        break;
926
    }
927
    if (op)
928
        gen_ea(s, insn, opsize, dest, &addr);
929
}
930

    
931
DISAS_INSN(sats)
932
{
933
    int reg;
934
    int tmp;
935
    int l1;
936

    
937
    reg = DREG(insn, 0);
938
    tmp = gen_new_qreg(QMODE_I32);
939
    gen_flush_flags(s);
940
    gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
941
    l1 = gen_new_label();
942
    gen_op_jmp_z32(tmp, l1);
943
    tmp = gen_new_qreg(QMODE_I32);
944
    gen_op_shr32(tmp, reg, gen_im32(31));
945
    gen_op_xor32(tmp, tmp, gen_im32(0x80000000));
946
    gen_op_mov32(reg, tmp);
947
    gen_set_label(l1);
948
    gen_logic_cc(s, tmp);
949
}
950

    
951
static void gen_push(DisasContext *s, int val)
952
{
953
    int tmp;
954

    
955
    tmp = gen_new_qreg(QMODE_I32);
956
    gen_op_sub32(tmp, QREG_SP, gen_im32(4));
957
    gen_store(s, OS_LONG, tmp, val);
958
    gen_op_mov32(QREG_SP, tmp);
959
}
960

    
961
DISAS_INSN(movem)
962
{
963
    int addr;
964
    int i;
965
    uint16_t mask;
966
    int reg;
967
    int tmp;
968
    int is_load;
969

    
970
    mask = lduw_code(s->pc);
971
    s->pc += 2;
972
    tmp = gen_lea(s, insn, OS_LONG);
973
    addr = gen_new_qreg(QMODE_I32);
974
    gen_op_mov32(addr, tmp);
975
    is_load = ((insn & 0x0400) != 0);
976
    for (i = 0; i < 16; i++, mask >>= 1) {
977
        if (mask & 1) {
978
            if (i < 8)
979
                reg = DREG(i, 0);
980
            else
981
                reg = AREG(i, 0);
982
            if (is_load) {
983
                tmp = gen_load(s, OS_LONG, addr, 0);
984
                gen_op_mov32(reg, tmp);
985
            } else {
986
                gen_store(s, OS_LONG, addr, reg);
987
            }
988
            if (mask != 1)
989
                gen_op_add32(addr, addr, gen_im32(4));
990
        }
991
    }
992
}
993

    
994
DISAS_INSN(bitop_im)
995
{
996
    int opsize;
997
    int op;
998
    int src1;
999
    uint32_t mask;
1000
    int bitnum;
1001
    int tmp;
1002
    int addr;
1003
    int dest;
1004

    
1005
    if ((insn & 0x38) != 0)
1006
        opsize = OS_BYTE;
1007
    else
1008
        opsize = OS_LONG;
1009
    op = (insn >> 6) & 3;
1010

    
1011
    bitnum = lduw_code(s->pc);
1012
    s->pc += 2;
1013
    if (bitnum & 0xff00) {
1014
        disas_undef(s, insn);
1015
        return;
1016
    }
1017

    
1018
    src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
1019

    
1020
    gen_flush_flags(s);
1021
    tmp = gen_new_qreg(QMODE_I32);
1022
    if (opsize == OS_BYTE)
1023
        bitnum &= 7;
1024
    else
1025
        bitnum &= 31;
1026
    mask = 1 << bitnum;
1027

    
1028
    gen_op_btest(src1, gen_im32(mask));
1029
    if (op)
1030
        dest = gen_new_qreg(QMODE_I32);
1031
    else
1032
        dest = -1;
1033

    
1034
    switch (op) {
1035
    case 1: /* bchg */
1036
        gen_op_xor32(dest, src1, gen_im32(mask));
1037
        break;
1038
    case 2: /* bclr */
1039
        gen_op_and32(dest, src1, gen_im32(~mask));
1040
        break;
1041
    case 3: /* bset */
1042
        gen_op_or32(dest, src1, gen_im32(mask));
1043
        break;
1044
    default: /* btst */
1045
        break;
1046
    }
1047
    if (op)
1048
        gen_ea(s, insn, opsize, dest, &addr);
1049
}
1050

    
1051
DISAS_INSN(arith_im)
1052
{
1053
    int op;
1054
    int src1;
1055
    int dest;
1056
    int src2;
1057
    int addr;
1058

    
1059
    op = (insn >> 9) & 7;
1060
    src1 = gen_ea(s, insn, OS_LONG, 0, (op == 6) ? NULL : &addr);
1061
    src2 = gen_im32(read_im32(s));
1062
    dest = gen_new_qreg(QMODE_I32);
1063
    switch (op) {
1064
    case 0: /* ori */
1065
        gen_op_or32(dest, src1, src2);
1066
        gen_logic_cc(s, dest);
1067
        break;
1068
    case 1: /* andi */
1069
        gen_op_and32(dest, src1, src2);
1070
        gen_logic_cc(s, dest);
1071
        break;
1072
    case 2: /* subi */
1073
        gen_op_mov32(dest, src1);
1074
        gen_op_update_xflag_lt(dest, src2);
1075
        gen_op_sub32(dest, dest, src2);
1076
        gen_op_update_cc_add(dest, src2);
1077
        s->cc_op = CC_OP_SUB;
1078
        break;
1079
    case 3: /* addi */
1080
        gen_op_mov32(dest, src1);
1081
        gen_op_add32(dest, dest, src2);
1082
        gen_op_update_cc_add(dest, src2);
1083
        gen_op_update_xflag_lt(dest, src2);
1084
        s->cc_op = CC_OP_ADD;
1085
        break;
1086
    case 5: /* eori */
1087
        gen_op_xor32(dest, src1, src2);
1088
        gen_logic_cc(s, dest);
1089
        break;
1090
    case 6: /* cmpi */
1091
        gen_op_mov32(dest, src1);
1092
        gen_op_sub32(dest, dest, src2);
1093
        gen_op_update_cc_add(dest, src2);
1094
        s->cc_op = CC_OP_SUB;
1095
        break;
1096
    default:
1097
        abort();
1098
    }
1099
    if (op != 6) {
1100
        gen_ea(s, insn, OS_LONG, dest, &addr);
1101
    }
1102
}
1103

    
1104
DISAS_INSN(byterev)
1105
{
1106
    int reg;
1107

    
1108
    reg = DREG(insn, 0);
1109
    gen_op_bswap32(reg, reg);
1110
}
1111

    
1112
DISAS_INSN(move)
1113
{
1114
    int src;
1115
    int dest;
1116
    int op;
1117
    int opsize;
1118

    
1119
    switch (insn >> 12) {
1120
    case 1: /* move.b */
1121
        opsize = OS_BYTE;
1122
        break;
1123
    case 2: /* move.l */
1124
        opsize = OS_LONG;
1125
        break;
1126
    case 3: /* move.w */
1127
        opsize = OS_WORD;
1128
        break;
1129
    default:
1130
        abort();
1131
    }
1132
    src = gen_ea(s, insn, opsize, -1, NULL);
1133
    op = (insn >> 6) & 7;
1134
    if (op == 1) {
1135
        /* movea */
1136
        /* The value will already have been sign extended.  */
1137
        dest = AREG(insn, 9);
1138
        gen_op_mov32(dest, src);
1139
    } else {
1140
        /* normal move */
1141
        uint16_t dest_ea;
1142
        dest_ea = ((insn >> 9) & 7) | (op << 3);
1143
        gen_ea(s, dest_ea, opsize, src, NULL);
1144
        /* This will be correct because loads sign extend.  */
1145
        gen_logic_cc(s, src);
1146
    }
1147
}
1148

    
1149
DISAS_INSN(negx)
1150
{
1151
    int reg;
1152
    int dest;
1153
    int tmp;
1154

    
1155
    gen_flush_flags(s);
1156
    reg = DREG(insn, 0);
1157
    dest = gen_new_qreg(QMODE_I32);
1158
    gen_op_mov32 (dest, gen_im32(0));
1159
    gen_op_subx_cc(dest, reg);
1160
    /* !Z is sticky.  */
1161
    tmp = gen_new_qreg(QMODE_I32);
1162
    gen_op_mov32 (tmp, QREG_CC_DEST);
1163
    gen_op_update_cc_add(dest, reg);
1164
    gen_op_mov32(reg, dest);
1165
    s->cc_op = CC_OP_DYNAMIC;
1166
    gen_flush_flags(s);
1167
    gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1168
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1169
    s->cc_op = CC_OP_FLAGS;
1170
}
1171

    
1172
DISAS_INSN(lea)
1173
{
1174
    int reg;
1175
    int tmp;
1176

    
1177
    reg = AREG(insn, 9);
1178
    tmp = gen_lea(s, insn, OS_LONG);
1179
    gen_op_mov32(reg, tmp);
1180
}
1181

    
1182
DISAS_INSN(clr)
1183
{
1184
    int opsize;
1185

    
1186
    switch ((insn >> 6) & 3) {
1187
    case 0: /* clr.b */
1188
        opsize = OS_BYTE;
1189
        break;
1190
    case 1: /* clr.w */
1191
        opsize = OS_WORD;
1192
        break;
1193
    case 2: /* clr.l */
1194
        opsize = OS_LONG;
1195
        break;
1196
    default:
1197
        abort();
1198
    }
1199
    gen_ea (s, insn, opsize, gen_im32(0), NULL);
1200
    gen_logic_cc(s, gen_im32(0));
1201
}
1202

    
1203
static int gen_get_ccr(DisasContext *s)
1204
{
1205
    int dest;
1206

    
1207
    gen_flush_flags(s);
1208
    dest = gen_new_qreg(QMODE_I32);
1209
    gen_op_get_xflag(dest);
1210
    gen_op_shl32(dest, dest, gen_im32(4));
1211
    gen_op_or32(dest, dest, QREG_CC_DEST);
1212
    return dest;
1213
}
1214

    
1215
DISAS_INSN(move_from_ccr)
1216
{
1217
    int reg;
1218
    int ccr;
1219

    
1220
    ccr = gen_get_ccr(s);
1221
    reg = DREG(insn, 0);
1222
    gen_partset_reg(OS_WORD, reg, ccr);
1223
}
1224

    
1225
DISAS_INSN(neg)
1226
{
1227
    int reg;
1228
    int src1;
1229

    
1230
    reg = DREG(insn, 0);
1231
    src1 = gen_new_qreg(QMODE_I32);
1232
    gen_op_mov32(src1, reg);
1233
    gen_op_neg32(reg, src1);
1234
    s->cc_op = CC_OP_SUB;
1235
    gen_op_update_cc_add(reg, src1);
1236
    gen_op_update_xflag_lt(gen_im32(0), src1);
1237
    s->cc_op = CC_OP_SUB;
1238
}
1239

    
1240
static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
1241
{
1242
    gen_op_logic_cc(gen_im32(val & 0xf));
1243
    gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
1244
    if (!ccr_only) {
1245
        gen_op_mov32(QREG_SR, gen_im32(val & 0xff00));
1246
    }
1247
}
1248

    
1249
static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
1250
{
1251
    int src1;
1252
    int reg;
1253

    
1254
    s->cc_op = CC_OP_FLAGS;
1255
    if ((insn & 0x38) == 0)
1256
      {
1257
        src1 = gen_new_qreg(QMODE_I32);
1258
        reg = DREG(insn, 0);
1259
        gen_op_and32(src1, reg, gen_im32(0xf));
1260
        gen_op_logic_cc(src1);
1261
        gen_op_shr32(src1, reg, gen_im32(4));
1262
        gen_op_and32(src1, src1, gen_im32(1));
1263
        gen_op_update_xflag_tst(src1);
1264
        if (!ccr_only) {
1265
            gen_op_and32(QREG_SR, reg, gen_im32(0xff00));
1266
        }
1267
      }
1268
    else if ((insn & 0x3f) == 0x3c)
1269
      {
1270
        uint16_t val;
1271
        val = lduw_code(s->pc);
1272
        s->pc += 2;
1273
        gen_set_sr_im(s, val, ccr_only);
1274
      }
1275
    else
1276
        disas_undef(s, insn);
1277
}
1278

    
1279
DISAS_INSN(move_to_ccr)
1280
{
1281
    gen_set_sr(s, insn, 1);
1282
}
1283

    
1284
DISAS_INSN(not)
1285
{
1286
    int reg;
1287

    
1288
    reg = DREG(insn, 0);
1289
    gen_op_not32(reg, reg);
1290
    gen_logic_cc(s, reg);
1291
}
1292

    
1293
DISAS_INSN(swap)
1294
{
1295
    int dest;
1296
    int src1;
1297
    int src2;
1298
    int reg;
1299

    
1300
    dest = gen_new_qreg(QMODE_I32);
1301
    src1 = gen_new_qreg(QMODE_I32);
1302
    src2 = gen_new_qreg(QMODE_I32);
1303
    reg = DREG(insn, 0);
1304
    gen_op_shl32(src1, reg, gen_im32(16));
1305
    gen_op_shr32(src2, reg, gen_im32(16));
1306
    gen_op_or32(dest, src1, src2);
1307
    gen_op_mov32(reg, dest);
1308
    gen_logic_cc(s, dest);
1309
}
1310

    
1311
DISAS_INSN(pea)
1312
{
1313
    int tmp;
1314

    
1315
    tmp = gen_lea(s, insn, OS_LONG);
1316
    gen_push(s, tmp);
1317
}
1318

    
1319
DISAS_INSN(ext)
1320
{
1321
    int reg;
1322
    int op;
1323
    int tmp;
1324

    
1325
    reg = DREG(insn, 0);
1326
    op = (insn >> 6) & 7;
1327
    tmp = gen_new_qreg(QMODE_I32);
1328
    if (op == 3)
1329
        gen_op_ext16s32(tmp, reg);
1330
    else
1331
        gen_op_ext8s32(tmp, reg);
1332
    if (op == 2)
1333
        gen_partset_reg(OS_WORD, reg, tmp);
1334
    else
1335
      gen_op_mov32(reg, tmp);
1336
    gen_logic_cc(s, tmp);
1337
}
1338

    
1339
DISAS_INSN(tst)
1340
{
1341
    int opsize;
1342
    int tmp;
1343

    
1344
    switch ((insn >> 6) & 3) {
1345
    case 0: /* tst.b */
1346
        opsize = OS_BYTE;
1347
        break;
1348
    case 1: /* tst.w */
1349
        opsize = OS_WORD;
1350
        break;
1351
    case 2: /* tst.l */
1352
        opsize = OS_LONG;
1353
        break;
1354
    default:
1355
        abort();
1356
    }
1357
    tmp = gen_ea(s, insn, opsize, -1, NULL);
1358
    gen_logic_cc(s, tmp);
1359
}
1360

    
1361
DISAS_INSN(pulse)
1362
{
1363
  /* Implemented as a NOP.  */
1364
}
1365

    
1366
DISAS_INSN(illegal)
1367
{
1368
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1369
}
1370

    
1371
/* ??? This should be atomic.  */
1372
DISAS_INSN(tas)
1373
{
1374
    int dest;
1375
    int src1;
1376
    int addr;
1377

    
1378
    dest = gen_new_qreg(QMODE_I32);
1379
    src1 = gen_ea(s, insn, OS_BYTE, -1, &addr);
1380
    gen_logic_cc(s, src1);
1381
    gen_op_or32(dest, src1, gen_im32(0x80));
1382
    gen_ea(s, insn, OS_BYTE, dest, &addr);
1383
}
1384

    
1385
DISAS_INSN(mull)
1386
{
1387
    uint16_t ext;
1388
    int reg;
1389
    int src1;
1390
    int dest;
1391

    
1392
    /* The upper 32 bits of the product are discarded, so
1393
       muls.l and mulu.l are functionally equivalent.  */
1394
    ext = lduw_code(s->pc);
1395
    s->pc += 2;
1396
    if (ext & 0x87ff) {
1397
        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
1398
        return;
1399
    }
1400
    reg = DREG(ext, 12);
1401
    src1 = gen_ea(s, insn, OS_LONG, 0, NULL);
1402
    dest = gen_new_qreg(QMODE_I32);
1403
    gen_op_mul32(dest, src1, reg);
1404
    gen_op_mov32(reg, dest);
1405
    /* Unlike m68k, coldfire always clears the overflow bit.  */
1406
    gen_logic_cc(s, dest);
1407
}
1408

    
1409
DISAS_INSN(link)
1410
{
1411
    int16_t offset;
1412
    int reg;
1413
    int tmp;
1414

    
1415
    offset = ldsw_code(s->pc);
1416
    s->pc += 2;
1417
    reg = AREG(insn, 0);
1418
    tmp = gen_new_qreg(QMODE_I32);
1419
    gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1420
    gen_store(s, OS_LONG, tmp, reg);
1421
    if (reg != QREG_SP)
1422
        gen_op_mov32(reg, tmp);
1423
    gen_op_add32(QREG_SP, tmp, gen_im32(offset));
1424
}
1425

    
1426
DISAS_INSN(unlk)
1427
{
1428
    int src;
1429
    int reg;
1430
    int tmp;
1431

    
1432
    src = gen_new_qreg(QMODE_I32);
1433
    reg = AREG(insn, 0);
1434
    gen_op_mov32(src, reg);
1435
    tmp = gen_load(s, OS_LONG, src, 0);
1436
    gen_op_mov32(reg, tmp);
1437
    gen_op_add32(QREG_SP, src, gen_im32(4));
1438
}
1439

    
1440
DISAS_INSN(nop)
1441
{
1442
}
1443

    
1444
DISAS_INSN(rts)
1445
{
1446
    int tmp;
1447

    
1448
    tmp = gen_load(s, OS_LONG, QREG_SP, 0);
1449
    gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
1450
    gen_jmp(s, tmp);
1451
}
1452

    
1453
DISAS_INSN(jump)
1454
{
1455
    int tmp;
1456

    
1457
    /* Load the target address first to ensure correct exception
1458
       behavior.  */
1459
    tmp = gen_lea(s, insn, OS_LONG);
1460
    if ((insn & 0x40) == 0) {
1461
        /* jsr */
1462
        gen_push(s, gen_im32(s->pc));
1463
    }
1464
    gen_jmp(s, tmp);
1465
}
1466

    
1467
DISAS_INSN(addsubq)
1468
{
1469
    int src1;
1470
    int src2;
1471
    int dest;
1472
    int val;
1473
    int addr;
1474

    
1475
    src1 = gen_ea(s, insn, OS_LONG, 0, &addr);
1476
    val = (insn >> 9) & 7;
1477
    if (val == 0)
1478
        val = 8;
1479
    src2 = gen_im32(val);
1480
    dest = gen_new_qreg(QMODE_I32);
1481
    gen_op_mov32(dest, src1);
1482
    if ((insn & 0x38) == 0x08) {
1483
        /* Don't update condition codes if the destination is an
1484
           address register.  */
1485
        if (insn & 0x0100) {
1486
            gen_op_sub32(dest, dest, src2);
1487
        } else {
1488
            gen_op_add32(dest, dest, src2);
1489
        }
1490
    } else {
1491
        if (insn & 0x0100) {
1492
            gen_op_update_xflag_lt(dest, src2);
1493
            gen_op_sub32(dest, dest, src2);
1494
            s->cc_op = CC_OP_SUB;
1495
        } else {
1496
            gen_op_add32(dest, dest, src2);
1497
            gen_op_update_xflag_lt(dest, src2);
1498
            s->cc_op = CC_OP_ADD;
1499
        }
1500
        gen_op_update_cc_add(dest, src2);
1501
    }
1502
    gen_ea(s, insn, OS_LONG, dest, &addr);
1503
}
1504

    
1505
DISAS_INSN(tpf)
1506
{
1507
    switch (insn & 7) {
1508
    case 2: /* One extension word.  */
1509
        s->pc += 2;
1510
        break;
1511
    case 3: /* Two extension words.  */
1512
        s->pc += 4;
1513
        break;
1514
    case 4: /* No extension words.  */
1515
        break;
1516
    default:
1517
        disas_undef(s, insn);
1518
    }
1519
}
1520

    
1521
DISAS_INSN(branch)
1522
{
1523
    int32_t offset;
1524
    uint32_t base;
1525
    int op;
1526
    int l1;
1527
    
1528
    base = s->pc;
1529
    op = (insn >> 8) & 0xf;
1530
    offset = (int8_t)insn;
1531
    if (offset == 0) {
1532
        offset = ldsw_code(s->pc);
1533
        s->pc += 2;
1534
    } else if (offset == -1) {
1535
        offset = read_im32(s);
1536
    }
1537
    if (op == 1) {
1538
        /* bsr */
1539
        gen_push(s, gen_im32(s->pc));
1540
    }
1541
    gen_flush_cc_op(s);
1542
    if (op > 1) {
1543
        /* Bcc */
1544
        l1 = gen_new_label();
1545
        gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
1546
        gen_jmp_tb(s, 1, base + offset);
1547
        gen_set_label(l1);
1548
        gen_jmp_tb(s, 0, s->pc);
1549
    } else {
1550
        /* Unconditional branch.  */
1551
        gen_jmp_tb(s, 0, base + offset);
1552
    }
1553
}
1554

    
1555
DISAS_INSN(moveq)
1556
{
1557
    int tmp;
1558

    
1559
    tmp = gen_im32((int8_t)insn);
1560
    gen_op_mov32(DREG(insn, 9), tmp);
1561
    gen_logic_cc(s, tmp);
1562
}
1563

    
1564
DISAS_INSN(mvzs)
1565
{
1566
    int opsize;
1567
    int src;
1568
    int reg;
1569

    
1570
    if (insn & 0x40)
1571
        opsize = OS_WORD;
1572
    else
1573
        opsize = OS_BYTE;
1574
    src = gen_ea(s, insn, opsize, (insn & 0x80) ? 0 : -1, NULL);
1575
    reg = DREG(insn, 9);
1576
    gen_op_mov32(reg, src);
1577
    gen_logic_cc(s, src);
1578
}
1579

    
1580
DISAS_INSN(or)
1581
{
1582
    int reg;
1583
    int dest;
1584
    int src;
1585
    int addr;
1586

    
1587
    reg = DREG(insn, 9);
1588
    dest = gen_new_qreg(QMODE_I32);
1589
    if (insn & 0x100) {
1590
        src = gen_ea(s, insn, OS_LONG, 0, &addr);
1591
        gen_op_or32(dest, src, reg);
1592
        gen_ea(s, insn, OS_LONG, dest, &addr);
1593
    } else {
1594
        src = gen_ea(s, insn, OS_LONG, 0, NULL);
1595
        gen_op_or32(dest, src, reg);
1596
        gen_op_mov32(reg, dest);
1597
    }
1598
    gen_logic_cc(s, dest);
1599
}
1600

    
1601
DISAS_INSN(suba)
1602
{
1603
    int src;
1604
    int reg;
1605

    
1606
    src = gen_ea(s, insn, OS_LONG, 0, NULL);
1607
    reg = AREG(insn, 9);
1608
    gen_op_sub32(reg, reg, src);
1609
}
1610

    
1611
DISAS_INSN(subx)
1612
{
1613
    int reg;
1614
    int src;
1615
    int dest;
1616
    int tmp;
1617

    
1618
    gen_flush_flags(s);
1619
    reg = DREG(insn, 9);
1620
    src = DREG(insn, 0);
1621
    dest = gen_new_qreg(QMODE_I32);
1622
    gen_op_mov32 (dest, reg);
1623
    gen_op_subx_cc(dest, src);
1624
    /* !Z is sticky.  */
1625
    tmp = gen_new_qreg(QMODE_I32);
1626
    gen_op_mov32 (tmp, QREG_CC_DEST);
1627
    gen_op_update_cc_add(dest, src);
1628
    gen_op_mov32(reg, dest);
1629
    s->cc_op = CC_OP_DYNAMIC;
1630
    gen_flush_flags(s);
1631
    gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1632
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1633
    s->cc_op = CC_OP_FLAGS;
1634
}
1635

    
1636
DISAS_INSN(mov3q)
1637
{
1638
    int src;
1639
    int val;
1640

    
1641
    val = (insn >> 9) & 7;
1642
    if (val == 0)
1643
        val = -1;
1644
    src = gen_im32(val);
1645
    gen_logic_cc(s, src);
1646
    gen_ea(s, insn, OS_LONG, src, NULL);
1647
}
1648

    
1649
DISAS_INSN(cmp)
1650
{
1651
    int op;
1652
    int src;
1653
    int reg;
1654
    int dest;
1655
    int opsize;
1656

    
1657
    op = (insn >> 6) & 3;
1658
    switch (op) {
1659
    case 0: /* cmp.b */
1660
        opsize = OS_BYTE;
1661
        s->cc_op = CC_OP_CMPB;
1662
        break;
1663
    case 1: /* cmp.w */
1664
        opsize = OS_WORD;
1665
        s->cc_op = CC_OP_CMPW;
1666
        break;
1667
    case 2: /* cmp.l */
1668
        opsize = OS_LONG;
1669
        s->cc_op = CC_OP_SUB;
1670
        break;
1671
    default:
1672
        abort();
1673
    }
1674
    src = gen_ea(s, insn, opsize, -1, NULL);
1675
    reg = DREG(insn, 9);
1676
    dest = gen_new_qreg(QMODE_I32);
1677
    gen_op_sub32(dest, reg, src);
1678
    gen_op_update_cc_add(dest, src);
1679
}
1680

    
1681
DISAS_INSN(cmpa)
1682
{
1683
    int opsize;
1684
    int src;
1685
    int reg;
1686
    int dest;
1687

    
1688
    if (insn & 0x100) {
1689
        opsize = OS_LONG;
1690
    } else {
1691
        opsize = OS_WORD;
1692
    }
1693
    src = gen_ea(s, insn, opsize, -1, NULL);
1694
    reg = AREG(insn, 9);
1695
    dest = gen_new_qreg(QMODE_I32);
1696
    gen_op_sub32(dest, reg, src);
1697
    gen_op_update_cc_add(dest, src);
1698
    s->cc_op = CC_OP_SUB;
1699
}
1700

    
1701
DISAS_INSN(eor)
1702
{
1703
    int src;
1704
    int reg;
1705
    int dest;
1706
    int addr;
1707

    
1708
    src = gen_ea(s, insn, OS_LONG, 0, &addr);
1709
    reg = DREG(insn, 9);
1710
    dest = gen_new_qreg(QMODE_I32);
1711
    gen_op_xor32(dest, src, reg);
1712
    gen_logic_cc(s, dest);
1713
    gen_ea(s, insn, OS_LONG, dest, &addr);
1714
}
1715

    
1716
DISAS_INSN(and)
1717
{
1718
    int src;
1719
    int reg;
1720
    int dest;
1721
    int addr;
1722

    
1723
    reg = DREG(insn, 9);
1724
    dest = gen_new_qreg(QMODE_I32);
1725
    if (insn & 0x100) {
1726
        src = gen_ea(s, insn, OS_LONG, 0, &addr);
1727
        gen_op_and32(dest, src, reg);
1728
        gen_ea(s, insn, OS_LONG, dest, &addr);
1729
    } else {
1730
        src = gen_ea(s, insn, OS_LONG, 0, NULL);
1731
        gen_op_and32(dest, src, reg);
1732
        gen_op_mov32(reg, dest);
1733
    }
1734
    gen_logic_cc(s, dest);
1735
}
1736

    
1737
DISAS_INSN(adda)
1738
{
1739
    int src;
1740
    int reg;
1741

    
1742
    src = gen_ea(s, insn, OS_LONG, 0, NULL);
1743
    reg = AREG(insn, 9);
1744
    gen_op_add32(reg, reg, src);
1745
}
1746

    
1747
DISAS_INSN(addx)
1748
{
1749
    int reg;
1750
    int src;
1751
    int dest;
1752
    int tmp;
1753

    
1754
    gen_flush_flags(s);
1755
    reg = DREG(insn, 9);
1756
    src = DREG(insn, 0);
1757
    dest = gen_new_qreg(QMODE_I32);
1758
    gen_op_mov32 (dest, reg);
1759
    gen_op_addx_cc(dest, src);
1760
    /* !Z is sticky.  */
1761
    tmp = gen_new_qreg(QMODE_I32);
1762
    gen_op_mov32 (tmp, QREG_CC_DEST);
1763
    gen_op_update_cc_add(dest, src);
1764
    gen_op_mov32(reg, dest);
1765
    s->cc_op = CC_OP_DYNAMIC;
1766
    gen_flush_flags(s);
1767
    gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1768
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1769
    s->cc_op = CC_OP_FLAGS;
1770
}
1771

    
1772
DISAS_INSN(shift_im)
1773
{
1774
    int reg;
1775
    int tmp;
1776

    
1777
    reg = DREG(insn, 0);
1778
    tmp = (insn >> 9) & 7;
1779
    if (tmp == 0)
1780
      tmp = 8;
1781
    if (insn & 0x100) {
1782
        gen_op_shl_im_cc(reg, tmp);
1783
        s->cc_op = CC_OP_SHL;
1784
    } else {
1785
        if (insn & 8) {
1786
            gen_op_shr_im_cc(reg, tmp);
1787
            s->cc_op = CC_OP_SHR;
1788
        } else {
1789
            gen_op_sar_im_cc(reg, tmp);
1790
            s->cc_op = CC_OP_SAR;
1791
        }
1792
    }
1793
}
1794

    
1795
DISAS_INSN(shift_reg)
1796
{
1797
    int reg;
1798
    int src;
1799
    int tmp;
1800

    
1801
    reg = DREG(insn, 0);
1802
    src = DREG(insn, 9);
1803
    tmp = gen_new_qreg(QMODE_I32);
1804
    gen_op_and32(tmp, src, gen_im32(63));
1805
    if (insn & 0x100) {
1806
        gen_op_shl_cc(reg, tmp);
1807
        s->cc_op = CC_OP_SHL;
1808
    } else {
1809
        if (insn & 8) {
1810
            gen_op_shr_cc(reg, tmp);
1811
            s->cc_op = CC_OP_SHR;
1812
        } else {
1813
            gen_op_sar_cc(reg, tmp);
1814
            s->cc_op = CC_OP_SAR;
1815
        }
1816
    }
1817
}
1818

    
1819
DISAS_INSN(ff1)
1820
{
1821
    cpu_abort(NULL, "Unimplemented insn: ff1");
1822
}
1823

    
1824
static int gen_get_sr(DisasContext *s)
1825
{
1826
    int ccr;
1827
    int sr;
1828

    
1829
    ccr = gen_get_ccr(s);
1830
    sr = gen_new_qreg(QMODE_I32);
1831
    gen_op_and32(sr, QREG_SR, gen_im32(0xffe0));
1832
    gen_op_or32(sr, sr, ccr);
1833
    return sr;
1834
}
1835

    
1836
DISAS_INSN(strldsr)
1837
{
1838
    uint16_t ext;
1839
    uint32_t addr;
1840

    
1841
    addr = s->pc - 2;
1842
    ext = lduw_code(s->pc);
1843
    s->pc += 2;
1844
    if (ext != 0x46FC) {
1845
        gen_exception(s, addr, EXCP_UNSUPPORTED);
1846
        return;
1847
    }
1848
    ext = lduw_code(s->pc);
1849
    s->pc += 2;
1850
    if (IS_USER(s) || (ext & SR_S) == 0) {
1851
        gen_exception(s, addr, EXCP_PRIVILEGE);
1852
        return;
1853
    }
1854
    gen_push(s, gen_get_sr(s));
1855
    gen_set_sr_im(s, ext, 0);
1856
}
1857

    
1858
DISAS_INSN(move_from_sr)
1859
{
1860
    int reg;
1861
    int sr;
1862

    
1863
    if (IS_USER(s)) {
1864
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1865
        return;
1866
    }
1867
    sr = gen_get_sr(s);
1868
    reg = DREG(insn, 0);
1869
    gen_partset_reg(OS_WORD, reg, sr);
1870
}
1871

    
1872
DISAS_INSN(move_to_sr)
1873
{
1874
    if (IS_USER(s)) {
1875
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1876
        return;
1877
    }
1878
    gen_set_sr(s, insn, 0);
1879
    gen_lookup_tb(s);
1880
}
1881

    
1882
DISAS_INSN(move_from_usp)
1883
{
1884
    if (IS_USER(s)) {
1885
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1886
        return;
1887
    }
1888
    /* TODO: Implement USP.  */
1889
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1890
}
1891

    
1892
DISAS_INSN(move_to_usp)
1893
{
1894
    if (IS_USER(s)) {
1895
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1896
        return;
1897
    }
1898
    /* TODO: Implement USP.  */
1899
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1900
}
1901

    
1902
DISAS_INSN(halt)
1903
{
1904
    gen_flush_cc_op(s);
1905
    gen_jmp(s, gen_im32(s->pc));
1906
    gen_op_halt();
1907
}
1908

    
1909
DISAS_INSN(stop)
1910
{
1911
    uint16_t ext;
1912

    
1913
    if (IS_USER(s)) {
1914
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1915
        return;
1916
    }
1917

    
1918
    ext = lduw_code(s->pc);
1919
    s->pc += 2;
1920

    
1921
    gen_set_sr_im(s, ext, 0);
1922
    disas_halt(s, insn);
1923
}
1924

    
1925
DISAS_INSN(rte)
1926
{
1927
    if (IS_USER(s)) {
1928
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1929
        return;
1930
    }
1931
    gen_exception(s, s->pc - 2, EXCP_RTE);
1932
}
1933

    
1934
DISAS_INSN(movec)
1935
{
1936
    uint16_t ext;
1937
    int reg;
1938

    
1939
    if (IS_USER(s)) {
1940
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1941
        return;
1942
    }
1943

    
1944
    ext = lduw_code(s->pc);
1945
    s->pc += 2;
1946

    
1947
    if (ext & 0x8000) {
1948
        reg = AREG(ext, 12);
1949
    } else {
1950
        reg = DREG(ext, 12);
1951
    }
1952
    gen_op_movec(gen_im32(ext & 0xfff), reg);
1953
    gen_lookup_tb(s);
1954
}
1955

    
1956
DISAS_INSN(intouch)
1957
{
1958
    if (IS_USER(s)) {
1959
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1960
        return;
1961
    }
1962
    /* ICache fetch.  Implement as no-op.  */
1963
}
1964

    
1965
DISAS_INSN(cpushl)
1966
{
1967
    if (IS_USER(s)) {
1968
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1969
        return;
1970
    }
1971
    /* Cache push/invalidate.  Implement as no-op.  */
1972
}
1973

    
1974
DISAS_INSN(wddata)
1975
{
1976
    gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1977
}
1978

    
1979
DISAS_INSN(wdebug)
1980
{
1981
    if (IS_USER(s)) {
1982
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1983
        return;
1984
    }
1985
    /* TODO: Implement wdebug.  */
1986
    qemu_assert(0, "WDEBUG not implemented");
1987
}
1988

    
1989
DISAS_INSN(trap)
1990
{
1991
    gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
1992
}
1993

    
1994
/* ??? FP exceptions are not implemented.  Most exceptions are deferred until
1995
   immediately before the next FP instruction is executed.  */
1996
DISAS_INSN(fpu)
1997
{
1998
    uint16_t ext;
1999
    int opmode;
2000
    int src;
2001
    int dest;
2002
    int res;
2003
    int round;
2004
    int opsize;
2005

    
2006
    ext = lduw_code(s->pc);
2007
    s->pc += 2;
2008
    opmode = ext & 0x7f;
2009
    switch ((ext >> 13) & 7) {
2010
    case 0: case 2:
2011
        break;
2012
    case 1:
2013
        goto undef;
2014
    case 3: /* fmove out */
2015
        src = FREG(ext, 7);
2016
        /* fmove */
2017
        /* ??? TODO: Proper behavior on overflow.  */
2018
        switch ((ext >> 10) & 7) {
2019
        case 0:
2020
            opsize = OS_LONG;
2021
            res = gen_new_qreg(QMODE_I32);
2022
            gen_op_f64_to_i32(res, src);
2023
            break;
2024
        case 1:
2025
            opsize = OS_SINGLE;
2026
            res = gen_new_qreg(QMODE_F32);
2027
            gen_op_f64_to_f32(res, src);
2028
            break;
2029
        case 4:
2030
            opsize = OS_WORD;
2031
            res = gen_new_qreg(QMODE_I32);
2032
            gen_op_f64_to_i32(res, src);
2033
            break;
2034
        case 5:
2035
            opsize = OS_DOUBLE;
2036
            res = src;
2037
            break;
2038
        case 6:
2039
            opsize = OS_BYTE;
2040
            res = gen_new_qreg(QMODE_I32);
2041
            gen_op_f64_to_i32(res, src);
2042
            break;
2043
        default:
2044
            goto undef;
2045
        }
2046
        gen_ea(s, insn, opsize, res, NULL);
2047
        return;
2048
    case 4: /* fmove to control register.  */
2049
        switch ((ext >> 10) & 7) {
2050
        case 4: /* FPCR */
2051
            /* Not implemented.  Ignore writes.  */
2052
            break;
2053
        case 1: /* FPIAR */
2054
        case 2: /* FPSR */
2055
        default:
2056
            cpu_abort(NULL, "Unimplemented: fmove to control %d",
2057
                      (ext >> 10) & 7);
2058
        }
2059
        break;
2060
    case 5: /* fmove from control register.  */
2061
        switch ((ext >> 10) & 7) {
2062
        case 4: /* FPCR */
2063
            /* Not implemented.  Always return zero.  */
2064
            res = gen_im32(0);
2065
            break;
2066
        case 1: /* FPIAR */
2067
        case 2: /* FPSR */
2068
        default:
2069
            cpu_abort(NULL, "Unimplemented: fmove from control %d",
2070
                      (ext >> 10) & 7);
2071
            goto undef;
2072
        }
2073
        gen_ea(s, insn, OS_LONG, res, NULL);
2074
        break;
2075
    case 6: /* fmovem */ 
2076
    case 7:
2077
        {
2078
        int addr;
2079
        uint16_t mask;
2080
        if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
2081
            goto undef;
2082
        src = gen_lea(s, insn, OS_LONG);
2083
        addr = gen_new_qreg(QMODE_I32);
2084
        gen_op_mov32(addr, src);
2085
        mask = 0x80;
2086
        dest = QREG_F0;
2087
        while (mask) {
2088
            if (ext & mask) {
2089
                if (ext & (1 << 13)) {
2090
                    /* store */
2091
                    gen_st(s, f64, addr, dest);
2092
                } else {
2093
                    /* load */
2094
                    gen_ld(s, f64, dest, addr);
2095
                }
2096
                if (ext & (mask - 1))
2097
                    gen_op_add32(addr, addr, gen_im32(8));
2098
            }
2099
            mask >>= 1;
2100
            dest++;
2101
        }
2102
        }
2103
        return;
2104
    }
2105
    if (ext & (1 << 14)) {
2106
        int tmp;
2107

    
2108
        /* Source effective address.  */
2109
        switch ((ext >> 10) & 7) {
2110
        case 0: opsize = OS_LONG; break;
2111
        case 1: opsize = OS_SINGLE; break;
2112
        case 4: opsize = OS_WORD; break;
2113
        case 5: opsize = OS_DOUBLE; break;
2114
        case 6: opsize = OS_BYTE; break;
2115
        default:
2116
            goto undef;
2117
        }
2118
        tmp = gen_ea(s, insn, opsize, -1, NULL);
2119
        if (opsize == OS_DOUBLE) {
2120
            src = tmp;
2121
        } else {
2122
            src = gen_new_qreg(QMODE_F64);
2123
            switch (opsize) {
2124
            case OS_LONG:
2125
            case OS_WORD:
2126
            case OS_BYTE:
2127
                gen_op_i32_to_f64(src, tmp);
2128
                break;
2129
            case OS_SINGLE:
2130
                gen_op_f32_to_f64(src, tmp);
2131
                break;
2132
            }
2133
        }
2134
    } else {
2135
        /* Source register.  */
2136
        src = FREG(ext, 10);
2137
    }
2138
    dest = FREG(ext, 7);
2139
    res = gen_new_qreg(QMODE_F64);
2140
    if (opmode != 0x3a)
2141
        gen_op_movf64(res, dest);
2142
    round = 1;
2143
    switch (opmode) {
2144
    case 0: case 0x40: case 0x44: /* fmove */
2145
        gen_op_movf64(res, src);
2146
        break;
2147
    case 1: /* fint */
2148
        gen_op_iround_f64(res, src);
2149
        round = 0;
2150
        break;
2151
    case 3: /* fintrz */
2152
        gen_op_itrunc_f64(res, src);
2153
        round = 0;
2154
        break;
2155
    case 4: case 0x41: case 0x45: /* fsqrt */
2156
        gen_op_sqrtf64(res, src);
2157
        break;
2158
    case 0x18: case 0x58: case 0x5c: /* fabs */
2159
        gen_op_absf64(res, src);
2160
        break;
2161
    case 0x1a: case 0x5a: case 0x5e: /* fneg */
2162
        gen_op_chsf64(res, src);
2163
        break;
2164
    case 0x20: case 0x60: case 0x64: /* fdiv */
2165
        gen_op_divf64(res, res, src);
2166
        break;
2167
    case 0x22: case 0x62: case 0x66: /* fadd */
2168
        gen_op_addf64(res, res, src);
2169
        break;
2170
    case 0x23: case 0x63: case 0x67: /* fmul */
2171
        gen_op_mulf64(res, res, src);
2172
        break;
2173
    case 0x28: case 0x68: case 0x6c: /* fsub */
2174
        gen_op_subf64(res, res, src);
2175
        break;
2176
    case 0x38: /* fcmp */
2177
        gen_op_sub_cmpf64(res, res, src);
2178
        dest = 0;
2179
        round = 0;
2180
        break;
2181
    case 0x3a: /* ftst */
2182
        gen_op_movf64(res, src);
2183
        dest = 0;
2184
        round = 0;
2185
        break;
2186
    default:
2187
        goto undef;
2188
    }
2189
    if (round) {
2190
        if (opmode & 0x40) {
2191
            if ((opmode & 0x4) != 0)
2192
                round = 0;
2193
        } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
2194
            round = 0;
2195
        }
2196
    }
2197
    if (round) {
2198
        int tmp;
2199

    
2200
        tmp = gen_new_qreg(QMODE_F32);
2201
        gen_op_f64_to_f32(tmp, res);
2202
        gen_op_f32_to_f64(res, tmp);
2203
    } 
2204
    gen_op_fp_result(res);
2205
    if (dest) {
2206
        gen_op_movf64(dest, res);
2207
    }
2208
    return;
2209
undef:
2210
    s->pc -= 2;
2211
    disas_undef_fpu(s, insn);
2212
}
2213

    
2214
DISAS_INSN(fbcc)
2215
{
2216
    uint32_t offset;
2217
    uint32_t addr;
2218
    int flag;
2219
    int zero;
2220
    int l1;
2221

    
2222
    addr = s->pc;
2223
    offset = ldsw_code(s->pc);
2224
    s->pc += 2;
2225
    if (insn & (1 << 6)) {
2226
        offset = (offset << 16) | lduw_code(s->pc);
2227
        s->pc += 2;
2228
    }
2229

    
2230
    l1 = gen_new_label();
2231
    /* TODO: Raise BSUN exception.  */
2232
    flag = gen_new_qreg(QMODE_I32);
2233
    zero = gen_new_qreg(QMODE_F64);
2234
    gen_op_zerof64(zero);
2235
    gen_op_compare_quietf64(flag, QREG_FP_RESULT, zero);
2236
    /* Jump to l1 if condition is true.  */
2237
    switch (insn & 0xf) {
2238
    case 0: /* f */
2239
        break;
2240
    case 1: /* eq (=0) */
2241
        gen_op_jmp_z32(flag, l1);
2242
        break;
2243
    case 2: /* ogt (=1) */
2244
        gen_op_sub32(flag, flag, gen_im32(1));
2245
        gen_op_jmp_z32(flag, l1);
2246
        break;
2247
    case 3: /* oge (=0 or =1) */
2248
        gen_op_jmp_z32(flag, l1);
2249
        gen_op_sub32(flag, flag, gen_im32(1));
2250
        gen_op_jmp_z32(flag, l1);
2251
        break;
2252
    case 4: /* olt (=-1) */
2253
        gen_op_jmp_s32(flag, l1);
2254
        break;
2255
    case 5: /* ole (=-1 or =0) */
2256
        gen_op_jmp_s32(flag, l1);
2257
        gen_op_jmp_z32(flag, l1);
2258
        break;
2259
    case 6: /* ogl (=-1 or =1) */
2260
        gen_op_jmp_s32(flag, l1);
2261
        gen_op_sub32(flag, flag, gen_im32(1));
2262
        gen_op_jmp_z32(flag, l1);
2263
        break;
2264
    case 7: /* or (=2) */
2265
        gen_op_sub32(flag, flag, gen_im32(2));
2266
        gen_op_jmp_z32(flag, l1);
2267
        break;
2268
    case 8: /* un (<2) */
2269
        gen_op_sub32(flag, flag, gen_im32(2));
2270
        gen_op_jmp_s32(flag, l1);
2271
        break;
2272
    case 9: /* ueq (=0 or =2) */
2273
        gen_op_jmp_z32(flag, l1);
2274
        gen_op_sub32(flag, flag, gen_im32(2));
2275
        gen_op_jmp_z32(flag, l1);
2276
        break;
2277
    case 10: /* ugt (>0) */
2278
        /* ??? Add jmp_gtu.  */
2279
        gen_op_sub32(flag, flag, gen_im32(1));
2280
        gen_op_jmp_ns32(flag, l1);
2281
        break;
2282
    case 11: /* uge (>=0) */
2283
        gen_op_jmp_ns32(flag, l1);
2284
        break;
2285
    case 12: /* ult (=-1 or =2) */
2286
        gen_op_jmp_s32(flag, l1);
2287
        gen_op_sub32(flag, flag, gen_im32(2));
2288
        gen_op_jmp_z32(flag, l1);
2289
        break;
2290
    case 13: /* ule (!=1) */
2291
        gen_op_sub32(flag, flag, gen_im32(1));
2292
        gen_op_jmp_nz32(flag, l1);
2293
        break;
2294
    case 14: /* ne (!=0) */
2295
        gen_op_jmp_nz32(flag, l1);
2296
        break;
2297
    case 15: /* t */
2298
        gen_op_mov32(flag, gen_im32(1));
2299
        break;
2300
    }
2301
    gen_jmp_tb(s, 0, s->pc);
2302
    gen_set_label(l1);
2303
    gen_jmp_tb(s, 1, addr + offset);
2304
}
2305

    
2306
DISAS_INSN(frestore)
2307
{
2308
    /* TODO: Implement frestore.  */
2309
    qemu_assert(0, "FRESTORE not implemented");
2310
}
2311

    
2312
DISAS_INSN(fsave)
2313
{
2314
    /* TODO: Implement fsave.  */
2315
    qemu_assert(0, "FSAVE not implemented");
2316
}
2317

    
2318
static disas_proc opcode_table[65536];
2319

    
2320
static void
2321
register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2322
{
2323
  int i;
2324
  int from;
2325
  int to;
2326

    
2327
  /* Sanity check.  All set bits must be included in the mask.  */
2328
  if (opcode & ~mask)
2329
      abort();
2330
  /* This could probably be cleverer.  For now just optimize the case where
2331
     the top bits are known.  */
2332
  /* Find the first zero bit in the mask.  */
2333
  i = 0x8000;
2334
  while ((i & mask) != 0)
2335
      i >>= 1;
2336
  /* Iterate over all combinations of this and lower bits.  */
2337
  if (i == 0)
2338
      i = 1;
2339
  else
2340
      i <<= 1;
2341
  from = opcode & ~(i - 1);
2342
  to = from + i;
2343
  for (i = from; i < to; i++) {
2344
      if ((i & mask) == opcode)
2345
          opcode_table[i] = proc;
2346
  }
2347
}
2348

    
2349
/* Register m68k opcode handlers.  Order is important.
2350
   Later insn override earlier ones.  */
2351
static void
2352
register_m68k_insns (m68k_def_t *def)
2353
{
2354
    uint32_t iflags;
2355

    
2356
    iflags = def->insns;
2357
#define INSN(name, opcode, mask, isa) \
2358
    if (iflags & M68K_INSN_##isa) \
2359
        register_opcode(disas_##name, 0x##opcode, 0x##mask)
2360
    INSN(undef,     0000, 0000, CF_A);
2361
    INSN(arith_im,  0080, fff8, CF_A);
2362
    INSN(bitrev,    00c0, fff8, CF_C);
2363
    INSN(bitop_reg, 0100, f1c0, CF_A);
2364
    INSN(bitop_reg, 0140, f1c0, CF_A);
2365
    INSN(bitop_reg, 0180, f1c0, CF_A);
2366
    INSN(bitop_reg, 01c0, f1c0, CF_A);
2367
    INSN(arith_im,  0280, fff8, CF_A);
2368
    INSN(byterev,   02c0, fff8, CF_A);
2369
    INSN(arith_im,  0480, fff8, CF_A);
2370
    INSN(ff1,       04c0, fff8, CF_C);
2371
    INSN(arith_im,  0680, fff8, CF_A);
2372
    INSN(bitop_im,  0800, ffc0, CF_A);
2373
    INSN(bitop_im,  0840, ffc0, CF_A);
2374
    INSN(bitop_im,  0880, ffc0, CF_A);
2375
    INSN(bitop_im,  08c0, ffc0, CF_A);
2376
    INSN(arith_im,  0a80, fff8, CF_A);
2377
    INSN(arith_im,  0c00, ff38, CF_A);
2378
    INSN(move,      1000, f000, CF_A);
2379
    INSN(move,      2000, f000, CF_A);
2380
    INSN(move,      3000, f000, CF_A);
2381
    INSN(strldsr,   40e7, ffff, CF_A);
2382
    INSN(negx,      4080, fff8, CF_A);
2383
    INSN(move_from_sr, 40c0, fff8, CF_A);
2384
    INSN(lea,       41c0, f1c0, CF_A);
2385
    INSN(clr,       4200, ff00, CF_A);
2386
    INSN(undef,     42c0, ffc0, CF_A);
2387
    INSN(move_from_ccr, 42c0, fff8, CF_A);
2388
    INSN(neg,       4480, fff8, CF_A);
2389
    INSN(move_to_ccr, 44c0, ffc0, CF_A);
2390
    INSN(not,       4680, fff8, CF_A);
2391
    INSN(move_to_sr, 46c0, ffc0, CF_A);
2392
    INSN(pea,       4840, ffc0, CF_A);
2393
    INSN(swap,      4840, fff8, CF_A);
2394
    INSN(movem,     48c0, fbc0, CF_A);
2395
    INSN(ext,       4880, fff8, CF_A);
2396
    INSN(ext,       48c0, fff8, CF_A);
2397
    INSN(ext,       49c0, fff8, CF_A);
2398
    INSN(tst,       4a00, ff00, CF_A);
2399
    INSN(tas,       4ac0, ffc0, CF_B);
2400
    INSN(halt,      4ac8, ffff, CF_A);
2401
    INSN(pulse,     4acc, ffff, CF_A);
2402
    INSN(illegal,   4afc, ffff, CF_A);
2403
    INSN(mull,      4c00, ffc0, CF_A);
2404
    INSN(divl,      4c40, ffc0, CF_A);
2405
    INSN(sats,      4c80, fff8, CF_B);
2406
    INSN(trap,      4e40, fff0, CF_A);
2407
    INSN(link,      4e50, fff8, CF_A);
2408
    INSN(unlk,      4e58, fff8, CF_A);
2409
    INSN(move_to_usp, 4e60, fff8, CF_B);
2410
    INSN(move_from_usp, 4e68, fff8, CF_B);
2411
    INSN(nop,       4e71, ffff, CF_A);
2412
    INSN(stop,      4e72, ffff, CF_A);
2413
    INSN(rte,       4e73, ffff, CF_A);
2414
    INSN(rts,       4e75, ffff, CF_A);
2415
    INSN(movec,     4e7b, ffff, CF_A);
2416
    INSN(jump,      4e80, ffc0, CF_A);
2417
    INSN(jump,      4ec0, ffc0, CF_A);
2418
    INSN(addsubq,   5180, f1c0, CF_A);
2419
    INSN(scc,       50c0, f0f8, CF_A);
2420
    INSN(addsubq,   5080, f1c0, CF_A);
2421
    INSN(tpf,       51f8, fff8, CF_A);
2422
    INSN(branch,    6000, f000, CF_A);
2423
    INSN(moveq,     7000, f100, CF_A);
2424
    INSN(mvzs,      7100, f100, CF_B);
2425
    INSN(or,        8000, f000, CF_A);
2426
    INSN(divw,      80c0, f0c0, CF_A);
2427
    INSN(addsub,    9000, f000, CF_A);
2428
    INSN(subx,      9180, f1f8, CF_A);
2429
    INSN(suba,      91c0, f1c0, CF_A);
2430
    INSN(undef_mac, a000, f000, CF_A);
2431
    INSN(mov3q,     a140, f1c0, CF_B);
2432
    INSN(cmp,       b000, f1c0, CF_B); /* cmp.b */
2433
    INSN(cmp,       b040, f1c0, CF_B); /* cmp.w */
2434
    INSN(cmpa,      b0c0, f1c0, CF_B); /* cmpa.w */
2435
    INSN(cmp,       b080, f1c0, CF_A);
2436
    INSN(cmpa,      b1c0, f1c0, CF_A);
2437
    INSN(eor,       b180, f1c0, CF_A);
2438
    INSN(and,       c000, f000, CF_A);
2439
    INSN(mulw,      c0c0, f0c0, CF_A);
2440
    INSN(addsub,    d000, f000, CF_A);
2441
    INSN(addx,      d180, f1f8, CF_A);
2442
    INSN(adda,      d1c0, f1c0, CF_A);
2443
    INSN(shift_im,  e080, f0f0, CF_A);
2444
    INSN(shift_reg, e0a0, f0f0, CF_A);
2445
    INSN(undef_fpu, f000, f000, CF_A);
2446
    INSN(fpu,       f200, ffc0, CF_FPU);
2447
    INSN(fbcc,      f280, ffc0, CF_FPU);
2448
    INSN(frestore,  f340, ffc0, CF_FPU);
2449
    INSN(fsave,     f340, ffc0, CF_FPU);
2450
    INSN(intouch,   f340, ffc0, CF_A);
2451
    INSN(cpushl,    f428, ff38, CF_A);
2452
    INSN(wddata,    fb00, ff00, CF_A);
2453
    INSN(wdebug,    fbc0, ffc0, CF_A);
2454
#undef INSN
2455
}
2456

    
2457
/* ??? Some of this implementation is not exception safe.  We should always
2458
   write back the result to memory before setting the condition codes.  */
2459
static void disas_m68k_insn(CPUState * env, DisasContext *s)
2460
{
2461
    uint16_t insn;
2462

    
2463
    insn = lduw_code(s->pc);
2464
    s->pc += 2;
2465

    
2466
    opcode_table[insn](s, insn);
2467
}
2468

    
2469
#if 0
2470
/* Save the result of a floating point operation.  */
2471
static void expand_op_fp_result(qOP *qop)
2472
{
2473
    gen_op_movf64(QREG_FP_RESULT, qop->args[0]);
2474
}
2475

2476
/* Dummy op to indicate that the flags have been set.  */
2477
static void expand_op_flags_set(qOP *qop)
2478
{
2479
}
2480

2481
/* Convert the confition codes into CC_OP_FLAGS format.  */
2482
static void expand_op_flush_flags(qOP *qop)
2483
{
2484
    int cc_opreg;
2485

2486
    if (qop->args[0] == CC_OP_DYNAMIC)
2487
        cc_opreg = QREG_CC_OP;
2488
    else
2489
        cc_opreg = gen_im32(qop->args[0]);
2490
    gen_op_helper32(QREG_NULL, cc_opreg, HELPER_flush_flags);
2491
}
2492

2493
/* Set CC_DEST after a logical or direct flag setting operation.  */
2494
static void expand_op_logic_cc(qOP *qop)
2495
{
2496
    gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2497
}
2498

2499
/* Set CC_SRC and CC_DEST after an arithmetic operation.  */
2500
static void expand_op_update_cc_add(qOP *qop)
2501
{
2502
    gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2503
    gen_op_mov32(QREG_CC_SRC, qop->args[1]);
2504
}
2505

2506
/* Update the X flag.  */
2507
static void expand_op_update_xflag(qOP *qop)
2508
{
2509
    int arg0;
2510
    int arg1;
2511

2512
    arg0 = qop->args[0];
2513
    arg1 = qop->args[1];
2514
    if (arg1 == QREG_NULL) {
2515
        /* CC_X = arg0.  */
2516
        gen_op_mov32(QREG_CC_X, arg0);
2517
    } else {
2518
        /* CC_X = arg0 < (unsigned)arg1.  */
2519
        gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2520
    }
2521
}
2522

2523
/* Set arg0 to the contents of the X flag.  */
2524
static void expand_op_get_xflag(qOP *qop)
2525
{
2526
    gen_op_mov32(qop->args[0], QREG_CC_X);
2527
}
2528

2529
/* Expand a shift by immediate.  The ISA only allows shifts by 1-8, so we
2530
   already know the shift is within range.  */
2531
static inline void expand_shift_im(qOP *qop, int right, int arith)
2532
{
2533
    int val;
2534
    int reg;
2535
    int tmp;
2536
    int im;
2537

2538
    reg = qop->args[0];
2539
    im = qop->args[1];
2540
    tmp = gen_im32(im);
2541
    val = gen_new_qreg(QMODE_I32);
2542
    gen_op_mov32(val, reg);
2543
    gen_op_mov32(QREG_CC_DEST, val);
2544
    gen_op_mov32(QREG_CC_SRC, tmp);
2545
    if (right) {
2546
        if (arith) {
2547
            gen_op_sar32(reg, val, tmp);
2548
        } else {
2549
            gen_op_shr32(reg, val, tmp);
2550
        }
2551
        if (im == 1)
2552
            tmp = QREG_NULL;
2553
        else
2554
            tmp = gen_im32(im - 1);
2555
    } else {
2556
        gen_op_shl32(reg, val, tmp);
2557
        tmp = gen_im32(32 - im);
2558
    }
2559
    if (tmp != QREG_NULL)
2560
        gen_op_shr32(val, val, tmp);
2561
    gen_op_and32(QREG_CC_X, val, gen_im32(1));
2562
}
2563

2564
static void expand_op_shl_im_cc(qOP *qop)
2565
{
2566
    expand_shift_im(qop, 0, 0);
2567
}
2568

2569
static void expand_op_shr_im_cc(qOP *qop)
2570
{
2571
    expand_shift_im(qop, 1, 0);
2572
}
2573

2574
static void expand_op_sar_im_cc(qOP *qop)
2575
{
2576
    expand_shift_im(qop, 1, 1);
2577
}
2578

2579
/* Expand a shift by register.  */
2580
/* ??? This gives incorrect answers for shifts by 0 or >= 32 */
2581
static inline void expand_shift_reg(qOP *qop, int right, int arith)
2582
{
2583
    int val;
2584
    int reg;
2585
    int shift;
2586
    int tmp;
2587

2588
    reg = qop->args[0];
2589
    shift = qop->args[1];
2590
    val = gen_new_qreg(QMODE_I32);
2591
    gen_op_mov32(val, reg);
2592
    gen_op_mov32(QREG_CC_DEST, val);
2593
    gen_op_mov32(QREG_CC_SRC, shift);
2594
    tmp = gen_new_qreg(QMODE_I32);
2595
    if (right) {
2596
        if (arith) {
2597
            gen_op_sar32(reg, val, shift);
2598
        } else {
2599
            gen_op_shr32(reg, val, shift);
2600
        }
2601
        gen_op_sub32(tmp, shift, gen_im32(1));
2602
    } else {
2603
        gen_op_shl32(reg, val, shift);
2604
        gen_op_sub32(tmp, gen_im32(31), shift);
2605
    }
2606
    gen_op_shl32(val, val, tmp);
2607
    gen_op_and32(QREG_CC_X, val, gen_im32(1));
2608
}
2609

2610
static void expand_op_shl_cc(qOP *qop)
2611
{
2612
    expand_shift_reg(qop, 0, 0);
2613
}
2614

2615
static void expand_op_shr_cc(qOP *qop)
2616
{
2617
    expand_shift_reg(qop, 1, 0);
2618
}
2619

2620
static void expand_op_sar_cc(qOP *qop)
2621
{
2622
    expand_shift_reg(qop, 1, 1);
2623
}
2624

2625
/* Set the Z flag to (arg0 & arg1) == 0.  */
2626
static void expand_op_btest(qOP *qop)
2627
{
2628
    int tmp;
2629
    int l1;
2630

2631
    l1 = gen_new_label();
2632
    tmp = gen_new_qreg(QMODE_I32);
2633
    gen_op_and32(tmp, qop->args[0], qop->args[1]);
2634
    gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(~(uint32_t)CCF_Z));
2635
    gen_op_jmp_nz32(tmp, l1);
2636
    gen_op_or32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(CCF_Z));
2637
    gen_op_label(l1);
2638
}
2639

2640
/* arg0 += arg1 + CC_X */
2641
static void expand_op_addx_cc(qOP *qop)
2642
{
2643
    int arg0 = qop->args[0];
2644
    int arg1 = qop->args[1];
2645
    int l1, l2;
2646
    
2647
    gen_op_add32 (arg0, arg0, arg1);
2648
    l1 = gen_new_label();
2649
    l2 = gen_new_label();
2650
    gen_op_jmp_z32(QREG_CC_X, l1);
2651
    gen_op_add32(arg0, arg0, gen_im32(1));
2652
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
2653
    gen_op_set_leu32(QREG_CC_X, arg0, arg1);
2654
    gen_op_jmp(l2);
2655
    gen_set_label(l1);
2656
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
2657
    gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2658
    gen_set_label(l2);
2659
}
2660

2661
/* arg0 -= arg1 + CC_X */
2662
static void expand_op_subx_cc(qOP *qop)
2663
{
2664
    int arg0 = qop->args[0];
2665
    int arg1 = qop->args[1];
2666
    int l1, l2;
2667

2668
    l1 = gen_new_label();
2669
    l2 = gen_new_label();
2670
    gen_op_jmp_z32(QREG_CC_X, l1);
2671
    gen_op_set_leu32(QREG_CC_X, arg0, arg1);
2672
    gen_op_sub32(arg0, arg0, gen_im32(1));
2673
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
2674
    gen_op_jmp(l2);
2675
    gen_set_label(l1);
2676
    gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2677
    gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
2678
    gen_set_label(l2);
2679
    gen_op_sub32 (arg0, arg0, arg1);
2680
}
2681

2682
/* Expand target specific ops to generic qops.  */
2683
static void expand_target_qops(void)
2684
{
2685
    qOP *qop;
2686
    qOP *next;
2687
    int c;
2688

2689
    /* Copy the list of qops, expanding target specific ops as we go.  */
2690
    qop = gen_first_qop;
2691
    gen_first_qop = NULL;
2692
    gen_last_qop = NULL;
2693
    for (; qop; qop = next) {
2694
        c = qop->opcode;
2695
        next = qop->next;
2696
        if (c < FIRST_TARGET_OP) {
2697
            qop->prev = gen_last_qop;
2698
            qop->next = NULL;
2699
            if (gen_last_qop)
2700
                gen_last_qop->next = qop;
2701
            else
2702
                gen_first_qop = qop;
2703
            gen_last_qop = qop;
2704
            continue;
2705
        }
2706
        switch (c) {
2707
#define DEF(name, nargs, barrier) \
2708
        case INDEX_op_##name: \
2709
            expand_op_##name(qop); \
2710
            break;
2711
#include "qop-target.def"
2712
#undef DEF
2713
        default:
2714
            cpu_abort(NULL, "Unexpanded target qop");
2715
        }
2716
    }
2717
}
2718

2719
/* ??? Implement this.  */
2720
static void
2721
optimize_flags(void)
2722
{
2723
}
2724
#endif
2725

    
2726
/* generate intermediate code for basic block 'tb'.  */
2727
static inline int
2728
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2729
                               int search_pc)
2730
{
2731
    DisasContext dc1, *dc = &dc1;
2732
    uint16_t *gen_opc_end;
2733
    int j, lj;
2734
    target_ulong pc_start;
2735
    int pc_offset;
2736
    int last_cc_op;
2737

    
2738
    /* generate intermediate code */
2739
    pc_start = tb->pc;
2740
       
2741
    dc->tb = tb;
2742

    
2743
    gen_opc_ptr = gen_opc_buf;
2744
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2745
    gen_opparam_ptr = gen_opparam_buf;
2746

    
2747
    dc->is_jmp = DISAS_NEXT;
2748
    dc->pc = pc_start;
2749
    dc->cc_op = CC_OP_DYNAMIC;
2750
    dc->singlestep_enabled = env->singlestep_enabled;
2751
    dc->fpcr = env->fpcr;
2752
    dc->user = (env->sr & SR_S) == 0;
2753
    nb_gen_labels = 0;
2754
    lj = -1;
2755
    do {
2756
        free_qreg = 0;
2757
        pc_offset = dc->pc - pc_start;
2758
        gen_throws_exception = NULL;
2759
        if (env->nb_breakpoints > 0) {
2760
            for(j = 0; j < env->nb_breakpoints; j++) {
2761
                if (env->breakpoints[j] == dc->pc) {
2762
                    gen_exception(dc, dc->pc, EXCP_DEBUG);
2763
                    dc->is_jmp = DISAS_JUMP;
2764
                    break;
2765
                }
2766
            }
2767
            if (dc->is_jmp)
2768
                break;
2769
        }
2770
        if (search_pc) {
2771
            j = gen_opc_ptr - gen_opc_buf;
2772
            if (lj < j) {
2773
                lj++;
2774
                while (lj < j)
2775
                    gen_opc_instr_start[lj++] = 0;
2776
            }
2777
            gen_opc_pc[lj] = dc->pc;
2778
            gen_opc_instr_start[lj] = 1;
2779
        }
2780
        last_cc_op = dc->cc_op;
2781
        disas_m68k_insn(env, dc);
2782
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2783
             !env->singlestep_enabled &&
2784
             (pc_offset) < (TARGET_PAGE_SIZE - 32));
2785

    
2786
    if (__builtin_expect(env->singlestep_enabled, 0)) {
2787
        /* Make sure the pc is updated, and raise a debug exception.  */
2788
        if (!dc->is_jmp) {
2789
            gen_flush_cc_op(dc);
2790
            gen_op_mov32(QREG_PC, gen_im32((long)dc->pc));
2791
        }
2792
        gen_op_raise_exception(EXCP_DEBUG);
2793
    } else {
2794
        switch(dc->is_jmp) {
2795
        case DISAS_NEXT:
2796
            gen_flush_cc_op(dc);
2797
            gen_jmp_tb(dc, 0, dc->pc);
2798
            break;
2799
        default:
2800
        case DISAS_JUMP:
2801
        case DISAS_UPDATE:
2802
            gen_flush_cc_op(dc);
2803
            /* indicate that the hash table must be used to find the next TB */
2804
            gen_op_mov32(QREG_T0, gen_im32(0));
2805
            gen_op_exit_tb();
2806
            break;
2807
        case DISAS_TB_JUMP:
2808
            /* nothing more to generate */
2809
            break;
2810
        }
2811
    }
2812
    *gen_opc_ptr = INDEX_op_end;
2813

    
2814
#ifdef DEBUG_DISAS
2815
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2816
        fprintf(logfile, "----------------\n");
2817
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2818
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
2819
        fprintf(logfile, "\n");
2820
        if (loglevel & (CPU_LOG_TB_OP)) {
2821
            fprintf(logfile, "OP:\n");
2822
            dump_ops(gen_opc_buf, gen_opparam_buf);
2823
            fprintf(logfile, "\n");
2824
        }
2825
    }
2826
#endif
2827
    if (search_pc) {
2828
        j = gen_opc_ptr - gen_opc_buf;
2829
        lj++;
2830
        while (lj <= j)
2831
            gen_opc_instr_start[lj++] = 0;
2832
        tb->size = 0;
2833
    } else {
2834
        tb->size = dc->pc - pc_start;
2835
    }
2836

    
2837
    //optimize_flags();
2838
    //expand_target_qops();
2839
    return 0;
2840
}
2841

    
2842
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2843
{
2844
    return gen_intermediate_code_internal(env, tb, 0);
2845
}
2846

    
2847
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2848
{
2849
    return gen_intermediate_code_internal(env, tb, 1);
2850
}
2851

    
2852
void cpu_reset(CPUM68KState *env)
2853
{
2854
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
2855
#if !defined (CONFIG_USER_ONLY)
2856
    env->sr = 0x2700;
2857
#endif
2858
    /* ??? FP regs should be initialized to NaN.  */
2859
    env->cc_op = CC_OP_FLAGS;
2860
    /* TODO: We should set PC from the interrupt vector.  */
2861
    env->pc = 0;
2862
    tlb_flush(env, 1);
2863
}
2864

    
2865
CPUM68KState *cpu_m68k_init(void)
2866
{
2867
    CPUM68KState *env;
2868

    
2869
    env = malloc(sizeof(CPUM68KState));
2870
    if (!env)
2871
        return NULL;
2872
    cpu_exec_init(env);
2873

    
2874
    cpu_reset(env);
2875
    return env;
2876
}
2877

    
2878
void cpu_m68k_close(CPUM68KState *env)
2879
{
2880
    free(env);
2881
}
2882

    
2883
int cpu_m68k_set_model(CPUM68KState *env, const char * name)
2884
{
2885
    m68k_def_t *def;
2886

    
2887
    for (def = m68k_cpu_defs; def->name; def++) {
2888
        if (strcmp(def->name, name) == 0)
2889
            break;
2890
    }
2891
    if (!def->name)
2892
        return 1;
2893

    
2894
    register_m68k_insns(def);
2895

    
2896
    return 0;
2897
}
2898

    
2899
void cpu_dump_state(CPUState *env, FILE *f, 
2900
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2901
                    int flags)
2902
{
2903
    int i;
2904
    uint16_t sr;
2905
    CPU_DoubleU u;
2906
    for (i = 0; i < 8; i++)
2907
      {
2908
        u.d = env->fregs[i];
2909
        cpu_fprintf (f, "D%d = %08x   A%d = %08x   F%d = %08x%08x (%12g)\n",
2910
                     i, env->dregs[i], i, env->aregs[i],
2911
                     i, u.l.upper, u.l.lower, u.d);
2912
      }
2913
    cpu_fprintf (f, "PC = %08x   ", env->pc);
2914
    sr = env->sr;
2915
    cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
2916
                 (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
2917
                 (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
2918
    cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result);
2919
}
2920