Statistics
| Branch: | Revision:

root / target-m68k / translate.c @ ce62e5ba

History | View | Annotate | Download (81 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
    int is_mem;
55
} DisasContext;
56

    
57
#define DISAS_JUMP_NEXT 4
58

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

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

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

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

    
82
#include "gen-op.h"
83

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

    
102
#include "op-hacks.h"
103

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

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

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

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

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

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

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

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

    
217
/* Calculate and address index.  */
218
static int gen_addr_index(uint16_t ext, int tmp)
219
{
220
    int add;
221
    int scale;
222

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

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

    
246
    offset = s->pc;
247
    ext = lduw_code(s->pc);
248
    s->pc += 2;
249

    
250
    if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
251
        return -1;
252

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
612
static void gen_logic_cc(DisasContext *s, int val)
613
{
614
    gen_op_logic_cc(val);
615
    s->cc_op = CC_OP_LOGIC;
616
}
617

    
618
static void gen_jmpcc(DisasContext *s, int cond, int l1)
619
{
620
    int tmp;
621

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

    
725
DISAS_INSN(scc)
726
{
727
    int l1;
728
    int cond;
729
    int reg;
730

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

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

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

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

    
763
static inline void gen_addr_fault(DisasContext *s)
764
{
765
    gen_exception(s, s->insn_pc, EXCP_ADDRESS);
766
}
767

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

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

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

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

    
806
DISAS_INSN(undef_mac)
807
{
808
    gen_exception(s, s->pc - 2, EXCP_LINEA);
809
}
810

    
811
DISAS_INSN(undef_fpu)
812
{
813
    gen_exception(s, s->pc - 2, EXCP_LINEF);
814
}
815

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

    
823
DISAS_INSN(mulw)
824
{
825
    int reg;
826
    int tmp;
827
    int src;
828
    int sign;
829

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

    
844
DISAS_INSN(divw)
845
{
846
    int reg;
847
    int tmp;
848
    int src;
849
    int sign;
850

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

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

    
875
DISAS_INSN(divl)
876
{
877
    int num;
878
    int den;
879
    int reg;
880
    uint16_t ext;
881

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

    
909
DISAS_INSN(addsub)
910
{
911
    int reg;
912
    int dest;
913
    int src;
914
    int tmp;
915
    int addr;
916
    int add;
917

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

    
945

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

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

    
982
DISAS_INSN(bitop_reg)
983
{
984
    int opsize;
985
    int op;
986
    int src1;
987
    int src2;
988
    int tmp;
989
    int addr;
990
    int dest;
991

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

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

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

    
1030
DISAS_INSN(sats)
1031
{
1032
    int reg;
1033
    int tmp;
1034
    int l1;
1035

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

    
1050
static void gen_push(DisasContext *s, int val)
1051
{
1052
    int tmp;
1053

    
1054
    tmp = gen_new_qreg(QMODE_I32);
1055
    gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1056
    gen_store(s, OS_LONG, tmp, val);
1057
    gen_op_mov32(QREG_SP, tmp);
1058
}
1059

    
1060
DISAS_INSN(movem)
1061
{
1062
    int addr;
1063
    int i;
1064
    uint16_t mask;
1065
    int reg;
1066
    int tmp;
1067
    int is_load;
1068

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

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

    
1108
    if ((insn & 0x38) != 0)
1109
        opsize = OS_BYTE;
1110
    else
1111
        opsize = OS_LONG;
1112
    op = (insn >> 6) & 3;
1113

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

    
1121
    SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1122

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

    
1131
    gen_op_btest(src1, gen_im32(mask));
1132
    if (op)
1133
        dest = gen_new_qreg(QMODE_I32);
1134
    else
1135
        dest = -1;
1136

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

    
1154
DISAS_INSN(arith_im)
1155
{
1156
    int op;
1157
    int src1;
1158
    int dest;
1159
    int src2;
1160
    int addr;
1161

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

    
1207
DISAS_INSN(byterev)
1208
{
1209
    int reg;
1210

    
1211
    reg = DREG(insn, 0);
1212
    gen_op_bswap32(reg, reg);
1213
}
1214

    
1215
DISAS_INSN(move)
1216
{
1217
    int src;
1218
    int dest;
1219
    int op;
1220
    int opsize;
1221

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

    
1252
DISAS_INSN(negx)
1253
{
1254
    int reg;
1255
    int dest;
1256
    int tmp;
1257

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

    
1275
DISAS_INSN(lea)
1276
{
1277
    int reg;
1278
    int tmp;
1279

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

    
1289
DISAS_INSN(clr)
1290
{
1291
    int opsize;
1292

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

    
1310
static int gen_get_ccr(DisasContext *s)
1311
{
1312
    int dest;
1313

    
1314
    gen_flush_flags(s);
1315
    dest = gen_new_qreg(QMODE_I32);
1316
    gen_op_get_xflag(dest);
1317
    gen_op_shl32(dest, dest, gen_im32(4));
1318
    gen_op_or32(dest, dest, QREG_CC_DEST);
1319
    return dest;
1320
}
1321

    
1322
DISAS_INSN(move_from_ccr)
1323
{
1324
    int reg;
1325
    int ccr;
1326

    
1327
    ccr = gen_get_ccr(s);
1328
    reg = DREG(insn, 0);
1329
    gen_partset_reg(OS_WORD, reg, ccr);
1330
}
1331

    
1332
DISAS_INSN(neg)
1333
{
1334
    int reg;
1335
    int src1;
1336

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

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

    
1356
static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
1357
{
1358
    int src1;
1359
    int reg;
1360

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

    
1386
DISAS_INSN(move_to_ccr)
1387
{
1388
    gen_set_sr(s, insn, 1);
1389
}
1390

    
1391
DISAS_INSN(not)
1392
{
1393
    int reg;
1394

    
1395
    reg = DREG(insn, 0);
1396
    gen_op_not32(reg, reg);
1397
    gen_logic_cc(s, reg);
1398
}
1399

    
1400
DISAS_INSN(swap)
1401
{
1402
    int dest;
1403
    int src1;
1404
    int src2;
1405
    int reg;
1406

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

    
1418
DISAS_INSN(pea)
1419
{
1420
    int tmp;
1421

    
1422
    tmp = gen_lea(s, insn, OS_LONG);
1423
    if (tmp == -1) {
1424
        gen_addr_fault(s);
1425
        return;
1426
    }
1427
    gen_push(s, tmp);
1428
}
1429

    
1430
DISAS_INSN(ext)
1431
{
1432
    int reg;
1433
    int op;
1434
    int tmp;
1435

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

    
1450
DISAS_INSN(tst)
1451
{
1452
    int opsize;
1453
    int tmp;
1454

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

    
1472
DISAS_INSN(pulse)
1473
{
1474
  /* Implemented as a NOP.  */
1475
}
1476

    
1477
DISAS_INSN(illegal)
1478
{
1479
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1480
}
1481

    
1482
/* ??? This should be atomic.  */
1483
DISAS_INSN(tas)
1484
{
1485
    int dest;
1486
    int src1;
1487
    int addr;
1488

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

    
1496
DISAS_INSN(mull)
1497
{
1498
    uint16_t ext;
1499
    int reg;
1500
    int src1;
1501
    int dest;
1502

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

    
1520
DISAS_INSN(link)
1521
{
1522
    int16_t offset;
1523
    int reg;
1524
    int tmp;
1525

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

    
1537
DISAS_INSN(unlk)
1538
{
1539
    int src;
1540
    int reg;
1541
    int tmp;
1542

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

    
1551
DISAS_INSN(nop)
1552
{
1553
}
1554

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

    
1559
    tmp = gen_load(s, OS_LONG, QREG_SP, 0);
1560
    gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
1561
    gen_jmp(s, tmp);
1562
}
1563

    
1564
DISAS_INSN(jump)
1565
{
1566
    int tmp;
1567

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

    
1582
DISAS_INSN(addsubq)
1583
{
1584
    int src1;
1585
    int src2;
1586
    int dest;
1587
    int val;
1588
    int addr;
1589

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

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

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

    
1670
DISAS_INSN(moveq)
1671
{
1672
    int tmp;
1673

    
1674
    tmp = gen_im32((int8_t)insn);
1675
    gen_op_mov32(DREG(insn, 9), tmp);
1676
    gen_logic_cc(s, tmp);
1677
}
1678

    
1679
DISAS_INSN(mvzs)
1680
{
1681
    int opsize;
1682
    int src;
1683
    int reg;
1684

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

    
1695
DISAS_INSN(or)
1696
{
1697
    int reg;
1698
    int dest;
1699
    int src;
1700
    int addr;
1701

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

    
1716
DISAS_INSN(suba)
1717
{
1718
    int src;
1719
    int reg;
1720

    
1721
    SRC_EA(src, OS_LONG, 0, NULL);
1722
    reg = AREG(insn, 9);
1723
    gen_op_sub32(reg, reg, src);
1724
}
1725

    
1726
DISAS_INSN(subx)
1727
{
1728
    int reg;
1729
    int src;
1730
    int dest;
1731
    int tmp;
1732

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

    
1751
DISAS_INSN(mov3q)
1752
{
1753
    int src;
1754
    int val;
1755

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

    
1764
DISAS_INSN(cmp)
1765
{
1766
    int op;
1767
    int src;
1768
    int reg;
1769
    int dest;
1770
    int opsize;
1771

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

    
1796
DISAS_INSN(cmpa)
1797
{
1798
    int opsize;
1799
    int src;
1800
    int reg;
1801
    int dest;
1802

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

    
1816
DISAS_INSN(eor)
1817
{
1818
    int src;
1819
    int reg;
1820
    int dest;
1821
    int addr;
1822

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

    
1831
DISAS_INSN(and)
1832
{
1833
    int src;
1834
    int reg;
1835
    int dest;
1836
    int addr;
1837

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

    
1852
DISAS_INSN(adda)
1853
{
1854
    int src;
1855
    int reg;
1856

    
1857
    SRC_EA(src, OS_LONG, 0, NULL);
1858
    reg = AREG(insn, 9);
1859
    gen_op_add32(reg, reg, src);
1860
}
1861

    
1862
DISAS_INSN(addx)
1863
{
1864
    int reg;
1865
    int src;
1866
    int dest;
1867
    int tmp;
1868

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

    
1887
DISAS_INSN(shift_im)
1888
{
1889
    int reg;
1890
    int tmp;
1891

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

    
1910
DISAS_INSN(shift_reg)
1911
{
1912
    int reg;
1913
    int src;
1914
    int tmp;
1915

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

    
1934
DISAS_INSN(ff1)
1935
{
1936
    int reg;
1937
    reg = DREG(insn, 0);
1938
    gen_logic_cc(s, reg);
1939
    gen_op_ff1(reg, reg);
1940
}
1941

    
1942
static int gen_get_sr(DisasContext *s)
1943
{
1944
    int ccr;
1945
    int sr;
1946

    
1947
    ccr = gen_get_ccr(s);
1948
    sr = gen_new_qreg(QMODE_I32);
1949
    gen_op_and32(sr, QREG_SR, gen_im32(0xffe0));
1950
    gen_op_or32(sr, sr, ccr);
1951
    return sr;
1952
}
1953

    
1954
DISAS_INSN(strldsr)
1955
{
1956
    uint16_t ext;
1957
    uint32_t addr;
1958

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

    
1976
DISAS_INSN(move_from_sr)
1977
{
1978
    int reg;
1979
    int sr;
1980

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

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

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

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

    
2020
DISAS_INSN(halt)
2021
{
2022
    gen_jmp(s, gen_im32(s->pc));
2023
    gen_op_halt();
2024
}
2025

    
2026
DISAS_INSN(stop)
2027
{
2028
    uint16_t ext;
2029

    
2030
    if (IS_USER(s)) {
2031
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2032
        return;
2033
    }
2034

    
2035
    ext = lduw_code(s->pc);
2036
    s->pc += 2;
2037

    
2038
    gen_set_sr_im(s, ext, 0);
2039
    gen_jmp(s, gen_im32(s->pc));
2040
    gen_op_stop();
2041
}
2042

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

    
2052
DISAS_INSN(movec)
2053
{
2054
    uint16_t ext;
2055
    int reg;
2056

    
2057
    if (IS_USER(s)) {
2058
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2059
        return;
2060
    }
2061

    
2062
    ext = lduw_code(s->pc);
2063
    s->pc += 2;
2064

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

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

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

    
2092
DISAS_INSN(wddata)
2093
{
2094
    gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2095
}
2096

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

    
2107
DISAS_INSN(trap)
2108
{
2109
    gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
2110
}
2111

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

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

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

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

    
2337
DISAS_INSN(fbcc)
2338
{
2339
    uint32_t offset;
2340
    uint32_t addr;
2341
    int flag;
2342
    int zero;
2343
    int l1;
2344

    
2345
    addr = s->pc;
2346
    offset = ldsw_code(s->pc);
2347
    s->pc += 2;
2348
    if (insn & (1 << 6)) {
2349
        offset = (offset << 16) | lduw_code(s->pc);
2350
        s->pc += 2;
2351
    }
2352

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

    
2429
DISAS_INSN(frestore)
2430
{
2431
    /* TODO: Implement frestore.  */
2432
    qemu_assert(0, "FRESTORE not implemented");
2433
}
2434

    
2435
DISAS_INSN(fsave)
2436
{
2437
    /* TODO: Implement fsave.  */
2438
    qemu_assert(0, "FSAVE not implemented");
2439
}
2440

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

    
2463
DISAS_INSN(mac)
2464
{
2465
    int rx;
2466
    int ry;
2467
    uint16_t ext;
2468
    int acc;
2469
    int l1;
2470
    int tmp;
2471
    int addr;
2472
    int loadval;
2473
    int dual;
2474
    int saved_flags = -1;
2475

    
2476
    ext = lduw_code(s->pc);
2477
    s->pc += 2;
2478

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

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

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

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

    
2535
    if (dual) {
2536
        /* Save the overflow flag from the multiply.  */
2537
        saved_flags = gen_new_qreg(QMODE_I32);
2538
        gen_op_mov32(saved_flags, QREG_MACSR);
2539
    }
2540

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

    
2549
    if (insn & 0x100)
2550
        gen_op_macsub(acc);
2551
    else
2552
        gen_op_macadd(acc);
2553

    
2554
    if (s->env->macsr & MACSR_FI)
2555
        gen_op_macsatf(acc);
2556
    else if (s->env->macsr & MACSR_SU)
2557
        gen_op_macsats(acc);
2558
    else
2559
        gen_op_macsatu(acc);
2560

    
2561
    if (l1 != -1)
2562
        gen_set_label(l1);
2563

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

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

    
2607
DISAS_INSN(from_mac)
2608
{
2609
    int rx;
2610
    int acc;
2611

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

    
2627
DISAS_INSN(move_mac)
2628
{
2629
    int src;
2630
    int dest;
2631
    src = insn & 3;
2632
    dest = (insn >> 9) & 3;
2633
    gen_op_move_mac(dest, src);
2634
    gen_op_mac_clear_flags();
2635
    gen_op_mac_set_flags(dest);
2636
}
2637

    
2638
DISAS_INSN(from_macsr)
2639
{
2640
    int reg;
2641

    
2642
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2643
    gen_op_mov32(reg, QREG_MACSR);
2644
}
2645

    
2646
DISAS_INSN(from_mask)
2647
{
2648
    int reg;
2649
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2650
    gen_op_mov32(reg, QREG_MAC_MASK);
2651
}
2652

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

    
2665
DISAS_INSN(macsr_to_ccr)
2666
{
2667
    gen_op_mov32(QREG_CC_X, gen_im32(0));
2668
    gen_op_and32(QREG_CC_DEST, QREG_MACSR, gen_im32(0xf));
2669
    s->cc_op = CC_OP_FLAGS;
2670
}
2671

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

    
2689
DISAS_INSN(to_macsr)
2690
{
2691
    int val;
2692
    SRC_EA(val, OS_LONG, 0, NULL);
2693
    gen_op_set_macsr(val);
2694
    gen_lookup_tb(s);
2695
}
2696

    
2697
DISAS_INSN(to_mask)
2698
{
2699
    int val;
2700
    SRC_EA(val, OS_LONG, 0, NULL);
2701
    gen_op_or32(QREG_MAC_MASK, val, gen_im32(0xffff0000));
2702
}
2703

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

    
2718
static disas_proc opcode_table[65536];
2719

    
2720
static void
2721
register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2722
{
2723
  int i;
2724
  int from;
2725
  int to;
2726

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

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

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

    
2832
    INSN(moveq,     7000, f100, CF_ISA_A);
2833
    INSN(mvzs,      7100, f100, CF_ISA_B);
2834
    INSN(or,        8000, f000, CF_ISA_A);
2835
    INSN(divw,      80c0, f0c0, CF_ISA_A);
2836
    INSN(addsub,    9000, f000, CF_ISA_A);
2837
    INSN(subx,      9180, f1f8, CF_ISA_A);
2838
    INSN(suba,      91c0, f1c0, CF_ISA_A);
2839

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

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

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

    
2885
    insn = lduw_code(s->pc);
2886
    s->pc += 2;
2887

    
2888
    opcode_table[insn](s, insn);
2889
}
2890

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

2898
/* Dummy op to indicate that the flags have been set.  */
2899
static void expand_op_flags_set(qOP *qop)
2900
{
2901
}
2902

2903
/* Convert the confition codes into CC_OP_FLAGS format.  */
2904
static void expand_op_flush_flags(qOP *qop)
2905
{
2906
    int cc_opreg;
2907

2908
    if (qop->args[0] == CC_OP_DYNAMIC)
2909
        cc_opreg = QREG_CC_OP;
2910
    else
2911
        cc_opreg = gen_im32(qop->args[0]);
2912
    gen_op_helper32(QREG_NULL, cc_opreg, HELPER_flush_flags);
2913
}
2914

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

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

2928
/* Update the X flag.  */
2929
static void expand_op_update_xflag(qOP *qop)
2930
{
2931
    int arg0;
2932
    int arg1;
2933

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

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

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

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

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

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

2996
static void expand_op_sar_im_cc(qOP *qop)
2997
{
2998
    expand_shift_im(qop, 1, 1);
2999
}
3000

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

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

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

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

3042
static void expand_op_sar_cc(qOP *qop)
3043
{
3044
    expand_shift_reg(qop, 1, 1);
3045
}
3046

3047
/* Set the Z flag to (arg0 & arg1) == 0.  */
3048
static void expand_op_btest(qOP *qop)
3049
{
3050
    int tmp;
3051
    int l1;
3052

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

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

3083
/* arg0 -= arg1 + CC_X */
3084
static void expand_op_subx_cc(qOP *qop)
3085
{
3086
    int arg0 = qop->args[0];
3087
    int arg1 = qop->args[1];
3088
    int l1, l2;
3089

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

3104
/* Expand target specific ops to generic qops.  */
3105
static void expand_target_qops(void)
3106
{
3107
    qOP *qop;
3108
    qOP *next;
3109
    int c;
3110

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

3141
/* ??? Implement this.  */
3142
static void
3143
optimize_flags(void)
3144
{
3145
}
3146
#endif
3147

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

    
3160
    /* generate intermediate code */
3161
    pc_start = tb->pc;
3162
       
3163
    dc->tb = tb;
3164

    
3165
    gen_opc_ptr = gen_opc_buf;
3166
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3167
    gen_opparam_ptr = gen_opparam_buf;
3168

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

    
3208
        /* Terminate the TB on memory ops if watchpoints are present.  */
3209
        /* FIXME: This should be replacd by the deterministic execution
3210
         * IRQ raising bits.  */
3211
        if (dc->is_mem && env->nb_watchpoints)
3212
            break;
3213
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3214
             !env->singlestep_enabled &&
3215
             (pc_offset) < (TARGET_PAGE_SIZE - 32));
3216

    
3217
    if (__builtin_expect(env->singlestep_enabled, 0)) {
3218
        /* Make sure the pc is updated, and raise a debug exception.  */
3219
        if (!dc->is_jmp) {
3220
            gen_flush_cc_op(dc);
3221
            gen_op_mov32(QREG_PC, gen_im32((long)dc->pc));
3222
        }
3223
        gen_op_raise_exception(EXCP_DEBUG);
3224
    } else {
3225
        switch(dc->is_jmp) {
3226
        case DISAS_NEXT:
3227
            gen_flush_cc_op(dc);
3228
            gen_jmp_tb(dc, 0, dc->pc);
3229
            break;
3230
        default:
3231
        case DISAS_JUMP:
3232
        case DISAS_UPDATE:
3233
            gen_flush_cc_op(dc);
3234
            /* indicate that the hash table must be used to find the next TB */
3235
            gen_op_mov32(QREG_T0, gen_im32(0));
3236
            gen_op_exit_tb();
3237
            break;
3238
        case DISAS_TB_JUMP:
3239
            /* nothing more to generate */
3240
            break;
3241
        }
3242
    }
3243
    *gen_opc_ptr = INDEX_op_end;
3244

    
3245
#ifdef DEBUG_DISAS
3246
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3247
        fprintf(logfile, "----------------\n");
3248
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3249
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
3250
        fprintf(logfile, "\n");
3251
        if (loglevel & (CPU_LOG_TB_OP)) {
3252
            fprintf(logfile, "OP:\n");
3253
            dump_ops(gen_opc_buf, gen_opparam_buf);
3254
            fprintf(logfile, "\n");
3255
        }
3256
    }
3257
#endif
3258
    if (search_pc) {
3259
        j = gen_opc_ptr - gen_opc_buf;
3260
        lj++;
3261
        while (lj <= j)
3262
            gen_opc_instr_start[lj++] = 0;
3263
    } else {
3264
        tb->size = dc->pc - pc_start;
3265
    }
3266

    
3267
    //optimize_flags();
3268
    //expand_target_qops();
3269
    return 0;
3270
}
3271

    
3272
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
3273
{
3274
    return gen_intermediate_code_internal(env, tb, 0);
3275
}
3276

    
3277
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
3278
{
3279
    return gen_intermediate_code_internal(env, tb, 1);
3280
}
3281

    
3282
void cpu_reset(CPUM68KState *env)
3283
{
3284
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
3285
#if !defined (CONFIG_USER_ONLY)
3286
    env->sr = 0x2700;
3287
#endif
3288
    m68k_switch_sp(env);
3289
    /* ??? FP regs should be initialized to NaN.  */
3290
    env->cc_op = CC_OP_FLAGS;
3291
    /* TODO: We should set PC from the interrupt vector.  */
3292
    env->pc = 0;
3293
    tlb_flush(env, 1);
3294
}
3295

    
3296
CPUM68KState *cpu_m68k_init(void)
3297
{
3298
    CPUM68KState *env;
3299

    
3300
    env = malloc(sizeof(CPUM68KState));
3301
    if (!env)
3302
        return NULL;
3303
    cpu_exec_init(env);
3304

    
3305
    cpu_reset(env);
3306
    return env;
3307
}
3308

    
3309
void cpu_m68k_close(CPUM68KState *env)
3310
{
3311
    free(env);
3312
}
3313

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