Statistics
| Branch: | Revision:

root / target-m68k / translate.c @ 57c83dac

History | View | Annotate | Download (78.9 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, see <http://www.gnu.org/licenses/>.
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25

    
26
#include "config.h"
27
#include "cpu.h"
28
#include "disas.h"
29
#include "tcg-op.h"
30
#include "qemu-log.h"
31

    
32
#include "helpers.h"
33
#define GEN_HELPER 1
34
#include "helpers.h"
35

    
36
//#define DEBUG_DISPATCH 1
37

    
38
/* Fake floating point.  */
39
#define tcg_gen_mov_f64 tcg_gen_mov_i64
40
#define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64
41
#define tcg_gen_qemu_stf64 tcg_gen_qemu_st64
42

    
43
#define DEFO32(name, offset) static TCGv QREG_##name;
44
#define DEFO64(name, offset) static TCGv_i64 QREG_##name;
45
#define DEFF64(name, offset) static TCGv_i64 QREG_##name;
46
#include "qregs.def"
47
#undef DEFO32
48
#undef DEFO64
49
#undef DEFF64
50

    
51
static TCGv_ptr cpu_env;
52

    
53
static char cpu_reg_names[3*8*3 + 5*4];
54
static TCGv cpu_dregs[8];
55
static TCGv cpu_aregs[8];
56
static TCGv_i64 cpu_fregs[8];
57
static TCGv_i64 cpu_macc[4];
58

    
59
#define DREG(insn, pos) cpu_dregs[((insn) >> (pos)) & 7]
60
#define AREG(insn, pos) cpu_aregs[((insn) >> (pos)) & 7]
61
#define FREG(insn, pos) cpu_fregs[((insn) >> (pos)) & 7]
62
#define MACREG(acc) cpu_macc[acc]
63
#define QREG_SP cpu_aregs[7]
64

    
65
static TCGv NULL_QREG;
66
#define IS_NULL_QREG(t) (TCGV_EQUAL(t, NULL_QREG))
67
/* Used to distinguish stores from bad addressing modes.  */
68
static TCGv store_dummy;
69

    
70
#include "gen-icount.h"
71

    
72
void m68k_tcg_init(void)
73
{
74
    char *p;
75
    int i;
76

    
77
#define DEFO32(name,  offset) QREG_##name = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, offset), #name);
78
#define DEFO64(name,  offset) QREG_##name = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, offset), #name);
79
#define DEFF64(name,  offset) DEFO64(name, offset)
80
#include "qregs.def"
81
#undef DEFO32
82
#undef DEFO64
83
#undef DEFF64
84

    
85
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
86

    
87
    p = cpu_reg_names;
88
    for (i = 0; i < 8; i++) {
89
        sprintf(p, "D%d", i);
90
        cpu_dregs[i] = tcg_global_mem_new(TCG_AREG0,
91
                                          offsetof(CPUM68KState, dregs[i]), p);
92
        p += 3;
93
        sprintf(p, "A%d", i);
94
        cpu_aregs[i] = tcg_global_mem_new(TCG_AREG0,
95
                                          offsetof(CPUM68KState, aregs[i]), p);
96
        p += 3;
97
        sprintf(p, "F%d", i);
98
        cpu_fregs[i] = tcg_global_mem_new_i64(TCG_AREG0,
99
                                          offsetof(CPUM68KState, fregs[i]), p);
100
        p += 3;
101
    }
102
    for (i = 0; i < 4; i++) {
103
        sprintf(p, "ACC%d", i);
104
        cpu_macc[i] = tcg_global_mem_new_i64(TCG_AREG0,
105
                                         offsetof(CPUM68KState, macc[i]), p);
106
        p += 5;
107
    }
108

    
109
    NULL_QREG = tcg_global_mem_new(TCG_AREG0, -4, "NULL");
110
    store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");
111

    
112
#define GEN_HELPER 2
113
#include "helpers.h"
114
}
115

    
116
static inline void qemu_assert(int cond, const char *msg)
117
{
118
    if (!cond) {
119
        fprintf (stderr, "badness: %s\n", msg);
120
        abort();
121
    }
122
}
123

    
124
/* internal defines */
125
typedef struct DisasContext {
126
    CPUM68KState *env;
127
    target_ulong insn_pc; /* Start of the current instruction.  */
128
    target_ulong pc;
129
    int is_jmp;
130
    int cc_op;
131
    int user;
132
    uint32_t fpcr;
133
    struct TranslationBlock *tb;
134
    int singlestep_enabled;
135
    int is_mem;
136
    TCGv_i64 mactmp;
137
    int done_mac;
138
} DisasContext;
139

    
140
#define DISAS_JUMP_NEXT 4
141

    
142
#if defined(CONFIG_USER_ONLY)
143
#define IS_USER(s) 1
144
#else
145
#define IS_USER(s) s->user
146
#endif
147

    
148
/* XXX: move that elsewhere */
149
/* ??? Fix exceptions.  */
150
static void *gen_throws_exception;
151
#define gen_last_qop NULL
152

    
153
#define OS_BYTE 0
154
#define OS_WORD 1
155
#define OS_LONG 2
156
#define OS_SINGLE 4
157
#define OS_DOUBLE 5
158

    
159
typedef void (*disas_proc)(DisasContext *, uint16_t);
160

    
161
#ifdef DEBUG_DISPATCH
162
#define DISAS_INSN(name) \
163
  static void real_disas_##name (DisasContext *s, uint16_t insn); \
164
  static void disas_##name (DisasContext *s, uint16_t insn) { \
165
    qemu_log("Dispatch " #name "\n"); \
166
    real_disas_##name(s, insn); } \
167
  static void real_disas_##name (DisasContext *s, uint16_t insn)
168
#else
169
#define DISAS_INSN(name) \
170
  static void disas_##name (DisasContext *s, uint16_t insn)
171
#endif
172

    
173
/* Generate a load from the specified address.  Narrow values are
174
   sign extended to full register width.  */
175
static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
176
{
177
    TCGv tmp;
178
    int index = IS_USER(s);
179
    s->is_mem = 1;
180
    tmp = tcg_temp_new_i32();
181
    switch(opsize) {
182
    case OS_BYTE:
183
        if (sign)
184
            tcg_gen_qemu_ld8s(tmp, addr, index);
185
        else
186
            tcg_gen_qemu_ld8u(tmp, addr, index);
187
        break;
188
    case OS_WORD:
189
        if (sign)
190
            tcg_gen_qemu_ld16s(tmp, addr, index);
191
        else
192
            tcg_gen_qemu_ld16u(tmp, addr, index);
193
        break;
194
    case OS_LONG:
195
    case OS_SINGLE:
196
        tcg_gen_qemu_ld32u(tmp, addr, index);
197
        break;
198
    default:
199
        qemu_assert(0, "bad load size");
200
    }
201
    gen_throws_exception = gen_last_qop;
202
    return tmp;
203
}
204

    
205
static inline TCGv_i64 gen_load64(DisasContext * s, TCGv addr)
206
{
207
    TCGv_i64 tmp;
208
    int index = IS_USER(s);
209
    s->is_mem = 1;
210
    tmp = tcg_temp_new_i64();
211
    tcg_gen_qemu_ldf64(tmp, addr, index);
212
    gen_throws_exception = gen_last_qop;
213
    return tmp;
214
}
215

    
216
/* Generate a store.  */
217
static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
218
{
219
    int index = IS_USER(s);
220
    s->is_mem = 1;
221
    switch(opsize) {
222
    case OS_BYTE:
223
        tcg_gen_qemu_st8(val, addr, index);
224
        break;
225
    case OS_WORD:
226
        tcg_gen_qemu_st16(val, addr, index);
227
        break;
228
    case OS_LONG:
229
    case OS_SINGLE:
230
        tcg_gen_qemu_st32(val, addr, index);
231
        break;
232
    default:
233
        qemu_assert(0, "bad store size");
234
    }
235
    gen_throws_exception = gen_last_qop;
236
}
237

    
238
static inline void gen_store64(DisasContext *s, TCGv addr, TCGv_i64 val)
239
{
240
    int index = IS_USER(s);
241
    s->is_mem = 1;
242
    tcg_gen_qemu_stf64(val, addr, index);
243
    gen_throws_exception = gen_last_qop;
244
}
245

    
246
typedef enum {
247
    EA_STORE,
248
    EA_LOADU,
249
    EA_LOADS
250
} ea_what;
251

    
252
/* Generate an unsigned load if VAL is 0 a signed load if val is -1,
253
   otherwise generate a store.  */
254
static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
255
                     ea_what what)
256
{
257
    if (what == EA_STORE) {
258
        gen_store(s, opsize, addr, val);
259
        return store_dummy;
260
    } else {
261
        return gen_load(s, opsize, addr, what == EA_LOADS);
262
    }
263
}
264

    
265
/* Read a 32-bit immediate constant.  */
266
static inline uint32_t read_im32(DisasContext *s)
267
{
268
    uint32_t im;
269
    im = ((uint32_t)lduw_code(s->pc)) << 16;
270
    s->pc += 2;
271
    im |= lduw_code(s->pc);
272
    s->pc += 2;
273
    return im;
274
}
275

    
276
/* Calculate and address index.  */
277
static TCGv gen_addr_index(uint16_t ext, TCGv tmp)
278
{
279
    TCGv add;
280
    int scale;
281

    
282
    add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
283
    if ((ext & 0x800) == 0) {
284
        tcg_gen_ext16s_i32(tmp, add);
285
        add = tmp;
286
    }
287
    scale = (ext >> 9) & 3;
288
    if (scale != 0) {
289
        tcg_gen_shli_i32(tmp, add, scale);
290
        add = tmp;
291
    }
292
    return add;
293
}
294

    
295
/* Handle a base + index + displacement effective addresss.
296
   A NULL_QREG base means pc-relative.  */
297
static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
298
{
299
    uint32_t offset;
300
    uint16_t ext;
301
    TCGv add;
302
    TCGv tmp;
303
    uint32_t bd, od;
304

    
305
    offset = s->pc;
306
    ext = lduw_code(s->pc);
307
    s->pc += 2;
308

    
309
    if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
310
        return NULL_QREG;
311

    
312
    if (ext & 0x100) {
313
        /* full extension word format */
314
        if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
315
            return NULL_QREG;
316

    
317
        if ((ext & 0x30) > 0x10) {
318
            /* base displacement */
319
            if ((ext & 0x30) == 0x20) {
320
                bd = (int16_t)lduw_code(s->pc);
321
                s->pc += 2;
322
            } else {
323
                bd = read_im32(s);
324
            }
325
        } else {
326
            bd = 0;
327
        }
328
        tmp = tcg_temp_new();
329
        if ((ext & 0x44) == 0) {
330
            /* pre-index */
331
            add = gen_addr_index(ext, tmp);
332
        } else {
333
            add = NULL_QREG;
334
        }
335
        if ((ext & 0x80) == 0) {
336
            /* base not suppressed */
337
            if (IS_NULL_QREG(base)) {
338
                base = tcg_const_i32(offset + bd);
339
                bd = 0;
340
            }
341
            if (!IS_NULL_QREG(add)) {
342
                tcg_gen_add_i32(tmp, add, base);
343
                add = tmp;
344
            } else {
345
                add = base;
346
            }
347
        }
348
        if (!IS_NULL_QREG(add)) {
349
            if (bd != 0) {
350
                tcg_gen_addi_i32(tmp, add, bd);
351
                add = tmp;
352
            }
353
        } else {
354
            add = tcg_const_i32(bd);
355
        }
356
        if ((ext & 3) != 0) {
357
            /* memory indirect */
358
            base = gen_load(s, OS_LONG, add, 0);
359
            if ((ext & 0x44) == 4) {
360
                add = gen_addr_index(ext, tmp);
361
                tcg_gen_add_i32(tmp, add, base);
362
                add = tmp;
363
            } else {
364
                add = base;
365
            }
366
            if ((ext & 3) > 1) {
367
                /* outer displacement */
368
                if ((ext & 3) == 2) {
369
                    od = (int16_t)lduw_code(s->pc);
370
                    s->pc += 2;
371
                } else {
372
                    od = read_im32(s);
373
                }
374
            } else {
375
                od = 0;
376
            }
377
            if (od != 0) {
378
                tcg_gen_addi_i32(tmp, add, od);
379
                add = tmp;
380
            }
381
        }
382
    } else {
383
        /* brief extension word format */
384
        tmp = tcg_temp_new();
385
        add = gen_addr_index(ext, tmp);
386
        if (!IS_NULL_QREG(base)) {
387
            tcg_gen_add_i32(tmp, add, base);
388
            if ((int8_t)ext)
389
                tcg_gen_addi_i32(tmp, tmp, (int8_t)ext);
390
        } else {
391
            tcg_gen_addi_i32(tmp, add, offset + (int8_t)ext);
392
        }
393
        add = tmp;
394
    }
395
    return add;
396
}
397

    
398
/* Update the CPU env CC_OP state.  */
399
static inline void gen_flush_cc_op(DisasContext *s)
400
{
401
    if (s->cc_op != CC_OP_DYNAMIC)
402
        tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
403
}
404

    
405
/* Evaluate all the CC flags.  */
406
static inline void gen_flush_flags(DisasContext *s)
407
{
408
    if (s->cc_op == CC_OP_FLAGS)
409
        return;
410
    gen_flush_cc_op(s);
411
    gen_helper_flush_flags(cpu_env, QREG_CC_OP);
412
    s->cc_op = CC_OP_FLAGS;
413
}
414

    
415
static void gen_logic_cc(DisasContext *s, TCGv val)
416
{
417
    tcg_gen_mov_i32(QREG_CC_DEST, val);
418
    s->cc_op = CC_OP_LOGIC;
419
}
420

    
421
static void gen_update_cc_add(TCGv dest, TCGv src)
422
{
423
    tcg_gen_mov_i32(QREG_CC_DEST, dest);
424
    tcg_gen_mov_i32(QREG_CC_SRC, src);
425
}
426

    
427
static inline int opsize_bytes(int opsize)
428
{
429
    switch (opsize) {
430
    case OS_BYTE: return 1;
431
    case OS_WORD: return 2;
432
    case OS_LONG: return 4;
433
    case OS_SINGLE: return 4;
434
    case OS_DOUBLE: return 8;
435
    default:
436
        qemu_assert(0, "bad operand size");
437
        return 0;
438
    }
439
}
440

    
441
/* Assign value to a register.  If the width is less than the register width
442
   only the low part of the register is set.  */
443
static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
444
{
445
    TCGv tmp;
446
    switch (opsize) {
447
    case OS_BYTE:
448
        tcg_gen_andi_i32(reg, reg, 0xffffff00);
449
        tmp = tcg_temp_new();
450
        tcg_gen_ext8u_i32(tmp, val);
451
        tcg_gen_or_i32(reg, reg, tmp);
452
        break;
453
    case OS_WORD:
454
        tcg_gen_andi_i32(reg, reg, 0xffff0000);
455
        tmp = tcg_temp_new();
456
        tcg_gen_ext16u_i32(tmp, val);
457
        tcg_gen_or_i32(reg, reg, tmp);
458
        break;
459
    case OS_LONG:
460
    case OS_SINGLE:
461
        tcg_gen_mov_i32(reg, val);
462
        break;
463
    default:
464
        qemu_assert(0, "Bad operand size");
465
        break;
466
    }
467
}
468

    
469
/* Sign or zero extend a value.  */
470
static inline TCGv gen_extend(TCGv val, int opsize, int sign)
471
{
472
    TCGv tmp;
473

    
474
    switch (opsize) {
475
    case OS_BYTE:
476
        tmp = tcg_temp_new();
477
        if (sign)
478
            tcg_gen_ext8s_i32(tmp, val);
479
        else
480
            tcg_gen_ext8u_i32(tmp, val);
481
        break;
482
    case OS_WORD:
483
        tmp = tcg_temp_new();
484
        if (sign)
485
            tcg_gen_ext16s_i32(tmp, val);
486
        else
487
            tcg_gen_ext16u_i32(tmp, val);
488
        break;
489
    case OS_LONG:
490
    case OS_SINGLE:
491
        tmp = val;
492
        break;
493
    default:
494
        qemu_assert(0, "Bad operand size");
495
    }
496
    return tmp;
497
}
498

    
499
/* Generate code for an "effective address".  Does not adjust the base
500
   register for autoincrement addressing modes.  */
501
static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
502
{
503
    TCGv reg;
504
    TCGv tmp;
505
    uint16_t ext;
506
    uint32_t offset;
507

    
508
    switch ((insn >> 3) & 7) {
509
    case 0: /* Data register direct.  */
510
    case 1: /* Address register direct.  */
511
        return NULL_QREG;
512
    case 2: /* Indirect register */
513
    case 3: /* Indirect postincrement.  */
514
        return AREG(insn, 0);
515
    case 4: /* Indirect predecrememnt.  */
516
        reg = AREG(insn, 0);
517
        tmp = tcg_temp_new();
518
        tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
519
        return tmp;
520
    case 5: /* Indirect displacement.  */
521
        reg = AREG(insn, 0);
522
        tmp = tcg_temp_new();
523
        ext = lduw_code(s->pc);
524
        s->pc += 2;
525
        tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
526
        return tmp;
527
    case 6: /* Indirect index + displacement.  */
528
        reg = AREG(insn, 0);
529
        return gen_lea_indexed(s, opsize, reg);
530
    case 7: /* Other */
531
        switch (insn & 7) {
532
        case 0: /* Absolute short.  */
533
            offset = ldsw_code(s->pc);
534
            s->pc += 2;
535
            return tcg_const_i32(offset);
536
        case 1: /* Absolute long.  */
537
            offset = read_im32(s);
538
            return tcg_const_i32(offset);
539
        case 2: /* pc displacement  */
540
            offset = s->pc;
541
            offset += ldsw_code(s->pc);
542
            s->pc += 2;
543
            return tcg_const_i32(offset);
544
        case 3: /* pc index+displacement.  */
545
            return gen_lea_indexed(s, opsize, NULL_QREG);
546
        case 4: /* Immediate.  */
547
        default:
548
            return NULL_QREG;
549
        }
550
    }
551
    /* Should never happen.  */
552
    return NULL_QREG;
553
}
554

    
555
/* Helper function for gen_ea. Reuse the computed address between the
556
   for read/write operands.  */
557
static inline TCGv gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
558
                              TCGv val, TCGv *addrp, ea_what what)
559
{
560
    TCGv tmp;
561

    
562
    if (addrp && what == EA_STORE) {
563
        tmp = *addrp;
564
    } else {
565
        tmp = gen_lea(s, insn, opsize);
566
        if (IS_NULL_QREG(tmp))
567
            return tmp;
568
        if (addrp)
569
            *addrp = tmp;
570
    }
571
    return gen_ldst(s, opsize, tmp, val, what);
572
}
573

    
574
/* Generate code to load/store a value ito/from an EA.  If VAL > 0 this is
575
   a write otherwise it is a read (0 == sign extend, -1 == zero extend).
576
   ADDRP is non-null for readwrite operands.  */
577
static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
578
                   TCGv *addrp, ea_what what)
579
{
580
    TCGv reg;
581
    TCGv result;
582
    uint32_t offset;
583

    
584
    switch ((insn >> 3) & 7) {
585
    case 0: /* Data register direct.  */
586
        reg = DREG(insn, 0);
587
        if (what == EA_STORE) {
588
            gen_partset_reg(opsize, reg, val);
589
            return store_dummy;
590
        } else {
591
            return gen_extend(reg, opsize, what == EA_LOADS);
592
        }
593
    case 1: /* Address register direct.  */
594
        reg = AREG(insn, 0);
595
        if (what == EA_STORE) {
596
            tcg_gen_mov_i32(reg, val);
597
            return store_dummy;
598
        } else {
599
            return gen_extend(reg, opsize, what == EA_LOADS);
600
        }
601
    case 2: /* Indirect register */
602
        reg = AREG(insn, 0);
603
        return gen_ldst(s, opsize, reg, val, what);
604
    case 3: /* Indirect postincrement.  */
605
        reg = AREG(insn, 0);
606
        result = gen_ldst(s, opsize, reg, val, what);
607
        /* ??? This is not exception safe.  The instruction may still
608
           fault after this point.  */
609
        if (what == EA_STORE || !addrp)
610
            tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
611
        return result;
612
    case 4: /* Indirect predecrememnt.  */
613
        {
614
            TCGv tmp;
615
            if (addrp && what == EA_STORE) {
616
                tmp = *addrp;
617
            } else {
618
                tmp = gen_lea(s, insn, opsize);
619
                if (IS_NULL_QREG(tmp))
620
                    return tmp;
621
                if (addrp)
622
                    *addrp = tmp;
623
            }
624
            result = gen_ldst(s, opsize, tmp, val, what);
625
            /* ??? This is not exception safe.  The instruction may still
626
               fault after this point.  */
627
            if (what == EA_STORE || !addrp) {
628
                reg = AREG(insn, 0);
629
                tcg_gen_mov_i32(reg, tmp);
630
            }
631
        }
632
        return result;
633
    case 5: /* Indirect displacement.  */
634
    case 6: /* Indirect index + displacement.  */
635
        return gen_ea_once(s, insn, opsize, val, addrp, what);
636
    case 7: /* Other */
637
        switch (insn & 7) {
638
        case 0: /* Absolute short.  */
639
        case 1: /* Absolute long.  */
640
        case 2: /* pc displacement  */
641
        case 3: /* pc index+displacement.  */
642
            return gen_ea_once(s, insn, opsize, val, addrp, what);
643
        case 4: /* Immediate.  */
644
            /* Sign extend values for consistency.  */
645
            switch (opsize) {
646
            case OS_BYTE:
647
                if (what == EA_LOADS)
648
                    offset = ldsb_code(s->pc + 1);
649
                else
650
                    offset = ldub_code(s->pc + 1);
651
                s->pc += 2;
652
                break;
653
            case OS_WORD:
654
                if (what == EA_LOADS)
655
                    offset = ldsw_code(s->pc);
656
                else
657
                    offset = lduw_code(s->pc);
658
                s->pc += 2;
659
                break;
660
            case OS_LONG:
661
                offset = read_im32(s);
662
                break;
663
            default:
664
                qemu_assert(0, "Bad immediate operand");
665
            }
666
            return tcg_const_i32(offset);
667
        default:
668
            return NULL_QREG;
669
        }
670
    }
671
    /* Should never happen.  */
672
    return NULL_QREG;
673
}
674

    
675
/* This generates a conditional branch, clobbering all temporaries.  */
676
static void gen_jmpcc(DisasContext *s, int cond, int l1)
677
{
678
    TCGv tmp;
679

    
680
    /* TODO: Optimize compare/branch pairs rather than always flushing
681
       flag state to CC_OP_FLAGS.  */
682
    gen_flush_flags(s);
683
    switch (cond) {
684
    case 0: /* T */
685
        tcg_gen_br(l1);
686
        break;
687
    case 1: /* F */
688
        break;
689
    case 2: /* HI (!C && !Z) */
690
        tmp = tcg_temp_new();
691
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
692
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
693
        break;
694
    case 3: /* LS (C || Z) */
695
        tmp = tcg_temp_new();
696
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
697
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
698
        break;
699
    case 4: /* CC (!C) */
700
        tmp = tcg_temp_new();
701
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
702
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
703
        break;
704
    case 5: /* CS (C) */
705
        tmp = tcg_temp_new();
706
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
707
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
708
        break;
709
    case 6: /* NE (!Z) */
710
        tmp = tcg_temp_new();
711
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
712
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
713
        break;
714
    case 7: /* EQ (Z) */
715
        tmp = tcg_temp_new();
716
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
717
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
718
        break;
719
    case 8: /* VC (!V) */
720
        tmp = tcg_temp_new();
721
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
722
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
723
        break;
724
    case 9: /* VS (V) */
725
        tmp = tcg_temp_new();
726
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
727
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
728
        break;
729
    case 10: /* PL (!N) */
730
        tmp = tcg_temp_new();
731
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
732
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
733
        break;
734
    case 11: /* MI (N) */
735
        tmp = tcg_temp_new();
736
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
737
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
738
        break;
739
    case 12: /* GE (!(N ^ V)) */
740
        tmp = tcg_temp_new();
741
        assert(CCF_V == (CCF_N >> 2));
742
        tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
743
        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
744
        tcg_gen_andi_i32(tmp, tmp, CCF_V);
745
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
746
        break;
747
    case 13: /* LT (N ^ V) */
748
        tmp = tcg_temp_new();
749
        assert(CCF_V == (CCF_N >> 2));
750
        tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
751
        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
752
        tcg_gen_andi_i32(tmp, tmp, CCF_V);
753
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
754
        break;
755
    case 14: /* GT (!(Z || (N ^ V))) */
756
        tmp = tcg_temp_new();
757
        assert(CCF_V == (CCF_N >> 2));
758
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
759
        tcg_gen_shri_i32(tmp, tmp, 2);
760
        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
761
        tcg_gen_andi_i32(tmp, tmp, CCF_V | CCF_Z);
762
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
763
        break;
764
    case 15: /* LE (Z || (N ^ V)) */
765
        tmp = tcg_temp_new();
766
        assert(CCF_V == (CCF_N >> 2));
767
        tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
768
        tcg_gen_shri_i32(tmp, tmp, 2);
769
        tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
770
        tcg_gen_andi_i32(tmp, tmp, CCF_V | CCF_Z);
771
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
772
        break;
773
    default:
774
        /* Should ever happen.  */
775
        abort();
776
    }
777
}
778

    
779
DISAS_INSN(scc)
780
{
781
    int l1;
782
    int cond;
783
    TCGv reg;
784

    
785
    l1 = gen_new_label();
786
    cond = (insn >> 8) & 0xf;
787
    reg = DREG(insn, 0);
788
    tcg_gen_andi_i32(reg, reg, 0xffffff00);
789
    /* This is safe because we modify the reg directly, with no other values
790
       live.  */
791
    gen_jmpcc(s, cond ^ 1, l1);
792
    tcg_gen_ori_i32(reg, reg, 0xff);
793
    gen_set_label(l1);
794
}
795

    
796
/* Force a TB lookup after an instruction that changes the CPU state.  */
797
static void gen_lookup_tb(DisasContext *s)
798
{
799
    gen_flush_cc_op(s);
800
    tcg_gen_movi_i32(QREG_PC, s->pc);
801
    s->is_jmp = DISAS_UPDATE;
802
}
803

    
804
/* Generate a jump to an immediate address.  */
805
static void gen_jmp_im(DisasContext *s, uint32_t dest)
806
{
807
    gen_flush_cc_op(s);
808
    tcg_gen_movi_i32(QREG_PC, dest);
809
    s->is_jmp = DISAS_JUMP;
810
}
811

    
812
/* Generate a jump to the address in qreg DEST.  */
813
static void gen_jmp(DisasContext *s, TCGv dest)
814
{
815
    gen_flush_cc_op(s);
816
    tcg_gen_mov_i32(QREG_PC, dest);
817
    s->is_jmp = DISAS_JUMP;
818
}
819

    
820
static void gen_exception(DisasContext *s, uint32_t where, int nr)
821
{
822
    gen_flush_cc_op(s);
823
    gen_jmp_im(s, where);
824
    gen_helper_raise_exception(tcg_const_i32(nr));
825
}
826

    
827
static inline void gen_addr_fault(DisasContext *s)
828
{
829
    gen_exception(s, s->insn_pc, EXCP_ADDRESS);
830
}
831

    
832
#define SRC_EA(result, opsize, op_sign, addrp) do { \
833
    result = gen_ea(s, insn, opsize, NULL_QREG, addrp, op_sign ? EA_LOADS : EA_LOADU); \
834
    if (IS_NULL_QREG(result)) { \
835
        gen_addr_fault(s); \
836
        return; \
837
    } \
838
    } while (0)
839

    
840
#define DEST_EA(insn, opsize, val, addrp) do { \
841
    TCGv ea_result = gen_ea(s, insn, opsize, val, addrp, EA_STORE); \
842
    if (IS_NULL_QREG(ea_result)) { \
843
        gen_addr_fault(s); \
844
        return; \
845
    } \
846
    } while (0)
847

    
848
/* Generate a jump to an immediate address.  */
849
static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
850
{
851
    TranslationBlock *tb;
852

    
853
    tb = s->tb;
854
    if (unlikely(s->singlestep_enabled)) {
855
        gen_exception(s, dest, EXCP_DEBUG);
856
    } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
857
               (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
858
        tcg_gen_goto_tb(n);
859
        tcg_gen_movi_i32(QREG_PC, dest);
860
        tcg_gen_exit_tb((tcg_target_long)tb + n);
861
    } else {
862
        gen_jmp_im(s, dest);
863
        tcg_gen_exit_tb(0);
864
    }
865
    s->is_jmp = DISAS_TB_JUMP;
866
}
867

    
868
DISAS_INSN(undef_mac)
869
{
870
    gen_exception(s, s->pc - 2, EXCP_LINEA);
871
}
872

    
873
DISAS_INSN(undef_fpu)
874
{
875
    gen_exception(s, s->pc - 2, EXCP_LINEF);
876
}
877

    
878
DISAS_INSN(undef)
879
{
880
    gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
881
    cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
882
              insn, s->pc - 2);
883
}
884

    
885
DISAS_INSN(mulw)
886
{
887
    TCGv reg;
888
    TCGv tmp;
889
    TCGv src;
890
    int sign;
891

    
892
    sign = (insn & 0x100) != 0;
893
    reg = DREG(insn, 9);
894
    tmp = tcg_temp_new();
895
    if (sign)
896
        tcg_gen_ext16s_i32(tmp, reg);
897
    else
898
        tcg_gen_ext16u_i32(tmp, reg);
899
    SRC_EA(src, OS_WORD, sign, NULL);
900
    tcg_gen_mul_i32(tmp, tmp, src);
901
    tcg_gen_mov_i32(reg, tmp);
902
    /* Unlike m68k, coldfire always clears the overflow bit.  */
903
    gen_logic_cc(s, tmp);
904
}
905

    
906
DISAS_INSN(divw)
907
{
908
    TCGv reg;
909
    TCGv tmp;
910
    TCGv src;
911
    int sign;
912

    
913
    sign = (insn & 0x100) != 0;
914
    reg = DREG(insn, 9);
915
    if (sign) {
916
        tcg_gen_ext16s_i32(QREG_DIV1, reg);
917
    } else {
918
        tcg_gen_ext16u_i32(QREG_DIV1, reg);
919
    }
920
    SRC_EA(src, OS_WORD, sign, NULL);
921
    tcg_gen_mov_i32(QREG_DIV2, src);
922
    if (sign) {
923
        gen_helper_divs(cpu_env, tcg_const_i32(1));
924
    } else {
925
        gen_helper_divu(cpu_env, tcg_const_i32(1));
926
    }
927

    
928
    tmp = tcg_temp_new();
929
    src = tcg_temp_new();
930
    tcg_gen_ext16u_i32(tmp, QREG_DIV1);
931
    tcg_gen_shli_i32(src, QREG_DIV2, 16);
932
    tcg_gen_or_i32(reg, tmp, src);
933
    s->cc_op = CC_OP_FLAGS;
934
}
935

    
936
DISAS_INSN(divl)
937
{
938
    TCGv num;
939
    TCGv den;
940
    TCGv reg;
941
    uint16_t ext;
942

    
943
    ext = lduw_code(s->pc);
944
    s->pc += 2;
945
    if (ext & 0x87f8) {
946
        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
947
        return;
948
    }
949
    num = DREG(ext, 12);
950
    reg = DREG(ext, 0);
951
    tcg_gen_mov_i32(QREG_DIV1, num);
952
    SRC_EA(den, OS_LONG, 0, NULL);
953
    tcg_gen_mov_i32(QREG_DIV2, den);
954
    if (ext & 0x0800) {
955
        gen_helper_divs(cpu_env, tcg_const_i32(0));
956
    } else {
957
        gen_helper_divu(cpu_env, tcg_const_i32(0));
958
    }
959
    if ((ext & 7) == ((ext >> 12) & 7)) {
960
        /* div */
961
        tcg_gen_mov_i32 (reg, QREG_DIV1);
962
    } else {
963
        /* rem */
964
        tcg_gen_mov_i32 (reg, QREG_DIV2);
965
    }
966
    s->cc_op = CC_OP_FLAGS;
967
}
968

    
969
DISAS_INSN(addsub)
970
{
971
    TCGv reg;
972
    TCGv dest;
973
    TCGv src;
974
    TCGv tmp;
975
    TCGv addr;
976
    int add;
977

    
978
    add = (insn & 0x4000) != 0;
979
    reg = DREG(insn, 9);
980
    dest = tcg_temp_new();
981
    if (insn & 0x100) {
982
        SRC_EA(tmp, OS_LONG, 0, &addr);
983
        src = reg;
984
    } else {
985
        tmp = reg;
986
        SRC_EA(src, OS_LONG, 0, NULL);
987
    }
988
    if (add) {
989
        tcg_gen_add_i32(dest, tmp, src);
990
        gen_helper_xflag_lt(QREG_CC_X, dest, src);
991
        s->cc_op = CC_OP_ADD;
992
    } else {
993
        gen_helper_xflag_lt(QREG_CC_X, tmp, src);
994
        tcg_gen_sub_i32(dest, tmp, src);
995
        s->cc_op = CC_OP_SUB;
996
    }
997
    gen_update_cc_add(dest, src);
998
    if (insn & 0x100) {
999
        DEST_EA(insn, OS_LONG, dest, &addr);
1000
    } else {
1001
        tcg_gen_mov_i32(reg, dest);
1002
    }
1003
}
1004

    
1005

    
1006
/* Reverse the order of the bits in REG.  */
1007
DISAS_INSN(bitrev)
1008
{
1009
    TCGv reg;
1010
    reg = DREG(insn, 0);
1011
    gen_helper_bitrev(reg, reg);
1012
}
1013

    
1014
DISAS_INSN(bitop_reg)
1015
{
1016
    int opsize;
1017
    int op;
1018
    TCGv src1;
1019
    TCGv src2;
1020
    TCGv tmp;
1021
    TCGv addr;
1022
    TCGv dest;
1023

    
1024
    if ((insn & 0x38) != 0)
1025
        opsize = OS_BYTE;
1026
    else
1027
        opsize = OS_LONG;
1028
    op = (insn >> 6) & 3;
1029
    SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1030
    src2 = DREG(insn, 9);
1031
    dest = tcg_temp_new();
1032

    
1033
    gen_flush_flags(s);
1034
    tmp = tcg_temp_new();
1035
    if (opsize == OS_BYTE)
1036
        tcg_gen_andi_i32(tmp, src2, 7);
1037
    else
1038
        tcg_gen_andi_i32(tmp, src2, 31);
1039
    src2 = tmp;
1040
    tmp = tcg_temp_new();
1041
    tcg_gen_shr_i32(tmp, src1, src2);
1042
    tcg_gen_andi_i32(tmp, tmp, 1);
1043
    tcg_gen_shli_i32(tmp, tmp, 2);
1044
    /* Clear CCF_Z if bit set.  */
1045
    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
1046
    tcg_gen_xor_i32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1047

    
1048
    tcg_gen_shl_i32(tmp, tcg_const_i32(1), src2);
1049
    switch (op) {
1050
    case 1: /* bchg */
1051
        tcg_gen_xor_i32(dest, src1, tmp);
1052
        break;
1053
    case 2: /* bclr */
1054
        tcg_gen_not_i32(tmp, tmp);
1055
        tcg_gen_and_i32(dest, src1, tmp);
1056
        break;
1057
    case 3: /* bset */
1058
        tcg_gen_or_i32(dest, src1, tmp);
1059
        break;
1060
    default: /* btst */
1061
        break;
1062
    }
1063
    if (op)
1064
        DEST_EA(insn, opsize, dest, &addr);
1065
}
1066

    
1067
DISAS_INSN(sats)
1068
{
1069
    TCGv reg;
1070
    reg = DREG(insn, 0);
1071
    gen_flush_flags(s);
1072
    gen_helper_sats(reg, reg, QREG_CC_DEST);
1073
    gen_logic_cc(s, reg);
1074
}
1075

    
1076
static void gen_push(DisasContext *s, TCGv val)
1077
{
1078
    TCGv tmp;
1079

    
1080
    tmp = tcg_temp_new();
1081
    tcg_gen_subi_i32(tmp, QREG_SP, 4);
1082
    gen_store(s, OS_LONG, tmp, val);
1083
    tcg_gen_mov_i32(QREG_SP, tmp);
1084
}
1085

    
1086
DISAS_INSN(movem)
1087
{
1088
    TCGv addr;
1089
    int i;
1090
    uint16_t mask;
1091
    TCGv reg;
1092
    TCGv tmp;
1093
    int is_load;
1094

    
1095
    mask = lduw_code(s->pc);
1096
    s->pc += 2;
1097
    tmp = gen_lea(s, insn, OS_LONG);
1098
    if (IS_NULL_QREG(tmp)) {
1099
        gen_addr_fault(s);
1100
        return;
1101
    }
1102
    addr = tcg_temp_new();
1103
    tcg_gen_mov_i32(addr, tmp);
1104
    is_load = ((insn & 0x0400) != 0);
1105
    for (i = 0; i < 16; i++, mask >>= 1) {
1106
        if (mask & 1) {
1107
            if (i < 8)
1108
                reg = DREG(i, 0);
1109
            else
1110
                reg = AREG(i, 0);
1111
            if (is_load) {
1112
                tmp = gen_load(s, OS_LONG, addr, 0);
1113
                tcg_gen_mov_i32(reg, tmp);
1114
            } else {
1115
                gen_store(s, OS_LONG, addr, reg);
1116
            }
1117
            if (mask != 1)
1118
                tcg_gen_addi_i32(addr, addr, 4);
1119
        }
1120
    }
1121
}
1122

    
1123
DISAS_INSN(bitop_im)
1124
{
1125
    int opsize;
1126
    int op;
1127
    TCGv src1;
1128
    uint32_t mask;
1129
    int bitnum;
1130
    TCGv tmp;
1131
    TCGv addr;
1132

    
1133
    if ((insn & 0x38) != 0)
1134
        opsize = OS_BYTE;
1135
    else
1136
        opsize = OS_LONG;
1137
    op = (insn >> 6) & 3;
1138

    
1139
    bitnum = lduw_code(s->pc);
1140
    s->pc += 2;
1141
    if (bitnum & 0xff00) {
1142
        disas_undef(s, insn);
1143
        return;
1144
    }
1145

    
1146
    SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1147

    
1148
    gen_flush_flags(s);
1149
    if (opsize == OS_BYTE)
1150
        bitnum &= 7;
1151
    else
1152
        bitnum &= 31;
1153
    mask = 1 << bitnum;
1154

    
1155
    tmp = tcg_temp_new();
1156
    assert (CCF_Z == (1 << 2));
1157
    if (bitnum > 2)
1158
        tcg_gen_shri_i32(tmp, src1, bitnum - 2);
1159
    else if (bitnum < 2)
1160
        tcg_gen_shli_i32(tmp, src1, 2 - bitnum);
1161
    else
1162
        tcg_gen_mov_i32(tmp, src1);
1163
    tcg_gen_andi_i32(tmp, tmp, CCF_Z);
1164
    /* Clear CCF_Z if bit set.  */
1165
    tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
1166
    tcg_gen_xor_i32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1167
    if (op) {
1168
        switch (op) {
1169
        case 1: /* bchg */
1170
            tcg_gen_xori_i32(tmp, src1, mask);
1171
            break;
1172
        case 2: /* bclr */
1173
            tcg_gen_andi_i32(tmp, src1, ~mask);
1174
            break;
1175
        case 3: /* bset */
1176
            tcg_gen_ori_i32(tmp, src1, mask);
1177
            break;
1178
        default: /* btst */
1179
            break;
1180
        }
1181
        DEST_EA(insn, opsize, tmp, &addr);
1182
    }
1183
}
1184

    
1185
DISAS_INSN(arith_im)
1186
{
1187
    int op;
1188
    uint32_t im;
1189
    TCGv src1;
1190
    TCGv dest;
1191
    TCGv addr;
1192

    
1193
    op = (insn >> 9) & 7;
1194
    SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
1195
    im = read_im32(s);
1196
    dest = tcg_temp_new();
1197
    switch (op) {
1198
    case 0: /* ori */
1199
        tcg_gen_ori_i32(dest, src1, im);
1200
        gen_logic_cc(s, dest);
1201
        break;
1202
    case 1: /* andi */
1203
        tcg_gen_andi_i32(dest, src1, im);
1204
        gen_logic_cc(s, dest);
1205
        break;
1206
    case 2: /* subi */
1207
        tcg_gen_mov_i32(dest, src1);
1208
        gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
1209
        tcg_gen_subi_i32(dest, dest, im);
1210
        gen_update_cc_add(dest, tcg_const_i32(im));
1211
        s->cc_op = CC_OP_SUB;
1212
        break;
1213
    case 3: /* addi */
1214
        tcg_gen_mov_i32(dest, src1);
1215
        tcg_gen_addi_i32(dest, dest, im);
1216
        gen_update_cc_add(dest, tcg_const_i32(im));
1217
        gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
1218
        s->cc_op = CC_OP_ADD;
1219
        break;
1220
    case 5: /* eori */
1221
        tcg_gen_xori_i32(dest, src1, im);
1222
        gen_logic_cc(s, dest);
1223
        break;
1224
    case 6: /* cmpi */
1225
        tcg_gen_mov_i32(dest, src1);
1226
        tcg_gen_subi_i32(dest, dest, im);
1227
        gen_update_cc_add(dest, tcg_const_i32(im));
1228
        s->cc_op = CC_OP_SUB;
1229
        break;
1230
    default:
1231
        abort();
1232
    }
1233
    if (op != 6) {
1234
        DEST_EA(insn, OS_LONG, dest, &addr);
1235
    }
1236
}
1237

    
1238
DISAS_INSN(byterev)
1239
{
1240
    TCGv reg;
1241

    
1242
    reg = DREG(insn, 0);
1243
    tcg_gen_bswap32_i32(reg, reg);
1244
}
1245

    
1246
DISAS_INSN(move)
1247
{
1248
    TCGv src;
1249
    TCGv dest;
1250
    int op;
1251
    int opsize;
1252

    
1253
    switch (insn >> 12) {
1254
    case 1: /* move.b */
1255
        opsize = OS_BYTE;
1256
        break;
1257
    case 2: /* move.l */
1258
        opsize = OS_LONG;
1259
        break;
1260
    case 3: /* move.w */
1261
        opsize = OS_WORD;
1262
        break;
1263
    default:
1264
        abort();
1265
    }
1266
    SRC_EA(src, opsize, 1, NULL);
1267
    op = (insn >> 6) & 7;
1268
    if (op == 1) {
1269
        /* movea */
1270
        /* The value will already have been sign extended.  */
1271
        dest = AREG(insn, 9);
1272
        tcg_gen_mov_i32(dest, src);
1273
    } else {
1274
        /* normal move */
1275
        uint16_t dest_ea;
1276
        dest_ea = ((insn >> 9) & 7) | (op << 3);
1277
        DEST_EA(dest_ea, opsize, src, NULL);
1278
        /* This will be correct because loads sign extend.  */
1279
        gen_logic_cc(s, src);
1280
    }
1281
}
1282

    
1283
DISAS_INSN(negx)
1284
{
1285
    TCGv reg;
1286

    
1287
    gen_flush_flags(s);
1288
    reg = DREG(insn, 0);
1289
    gen_helper_subx_cc(reg, cpu_env, tcg_const_i32(0), reg);
1290
}
1291

    
1292
DISAS_INSN(lea)
1293
{
1294
    TCGv reg;
1295
    TCGv tmp;
1296

    
1297
    reg = AREG(insn, 9);
1298
    tmp = gen_lea(s, insn, OS_LONG);
1299
    if (IS_NULL_QREG(tmp)) {
1300
        gen_addr_fault(s);
1301
        return;
1302
    }
1303
    tcg_gen_mov_i32(reg, tmp);
1304
}
1305

    
1306
DISAS_INSN(clr)
1307
{
1308
    int opsize;
1309

    
1310
    switch ((insn >> 6) & 3) {
1311
    case 0: /* clr.b */
1312
        opsize = OS_BYTE;
1313
        break;
1314
    case 1: /* clr.w */
1315
        opsize = OS_WORD;
1316
        break;
1317
    case 2: /* clr.l */
1318
        opsize = OS_LONG;
1319
        break;
1320
    default:
1321
        abort();
1322
    }
1323
    DEST_EA(insn, opsize, tcg_const_i32(0), NULL);
1324
    gen_logic_cc(s, tcg_const_i32(0));
1325
}
1326

    
1327
static TCGv gen_get_ccr(DisasContext *s)
1328
{
1329
    TCGv dest;
1330

    
1331
    gen_flush_flags(s);
1332
    dest = tcg_temp_new();
1333
    tcg_gen_shli_i32(dest, QREG_CC_X, 4);
1334
    tcg_gen_or_i32(dest, dest, QREG_CC_DEST);
1335
    return dest;
1336
}
1337

    
1338
DISAS_INSN(move_from_ccr)
1339
{
1340
    TCGv reg;
1341
    TCGv ccr;
1342

    
1343
    ccr = gen_get_ccr(s);
1344
    reg = DREG(insn, 0);
1345
    gen_partset_reg(OS_WORD, reg, ccr);
1346
}
1347

    
1348
DISAS_INSN(neg)
1349
{
1350
    TCGv reg;
1351
    TCGv src1;
1352

    
1353
    reg = DREG(insn, 0);
1354
    src1 = tcg_temp_new();
1355
    tcg_gen_mov_i32(src1, reg);
1356
    tcg_gen_neg_i32(reg, src1);
1357
    s->cc_op = CC_OP_SUB;
1358
    gen_update_cc_add(reg, src1);
1359
    gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1);
1360
    s->cc_op = CC_OP_SUB;
1361
}
1362

    
1363
static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
1364
{
1365
    tcg_gen_movi_i32(QREG_CC_DEST, val & 0xf);
1366
    tcg_gen_movi_i32(QREG_CC_X, (val & 0x10) >> 4);
1367
    if (!ccr_only) {
1368
        gen_helper_set_sr(cpu_env, tcg_const_i32(val & 0xff00));
1369
    }
1370
}
1371

    
1372
static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
1373
{
1374
    TCGv tmp;
1375
    TCGv reg;
1376

    
1377
    s->cc_op = CC_OP_FLAGS;
1378
    if ((insn & 0x38) == 0)
1379
      {
1380
        tmp = tcg_temp_new();
1381
        reg = DREG(insn, 0);
1382
        tcg_gen_andi_i32(QREG_CC_DEST, reg, 0xf);
1383
        tcg_gen_shri_i32(tmp, reg, 4);
1384
        tcg_gen_andi_i32(QREG_CC_X, tmp, 1);
1385
        if (!ccr_only) {
1386
            gen_helper_set_sr(cpu_env, reg);
1387
        }
1388
      }
1389
    else if ((insn & 0x3f) == 0x3c)
1390
      {
1391
        uint16_t val;
1392
        val = lduw_code(s->pc);
1393
        s->pc += 2;
1394
        gen_set_sr_im(s, val, ccr_only);
1395
      }
1396
    else
1397
        disas_undef(s, insn);
1398
}
1399

    
1400
DISAS_INSN(move_to_ccr)
1401
{
1402
    gen_set_sr(s, insn, 1);
1403
}
1404

    
1405
DISAS_INSN(not)
1406
{
1407
    TCGv reg;
1408

    
1409
    reg = DREG(insn, 0);
1410
    tcg_gen_not_i32(reg, reg);
1411
    gen_logic_cc(s, reg);
1412
}
1413

    
1414
DISAS_INSN(swap)
1415
{
1416
    TCGv src1;
1417
    TCGv src2;
1418
    TCGv reg;
1419

    
1420
    src1 = tcg_temp_new();
1421
    src2 = tcg_temp_new();
1422
    reg = DREG(insn, 0);
1423
    tcg_gen_shli_i32(src1, reg, 16);
1424
    tcg_gen_shri_i32(src2, reg, 16);
1425
    tcg_gen_or_i32(reg, src1, src2);
1426
    gen_logic_cc(s, reg);
1427
}
1428

    
1429
DISAS_INSN(pea)
1430
{
1431
    TCGv tmp;
1432

    
1433
    tmp = gen_lea(s, insn, OS_LONG);
1434
    if (IS_NULL_QREG(tmp)) {
1435
        gen_addr_fault(s);
1436
        return;
1437
    }
1438
    gen_push(s, tmp);
1439
}
1440

    
1441
DISAS_INSN(ext)
1442
{
1443
    int op;
1444
    TCGv reg;
1445
    TCGv tmp;
1446

    
1447
    reg = DREG(insn, 0);
1448
    op = (insn >> 6) & 7;
1449
    tmp = tcg_temp_new();
1450
    if (op == 3)
1451
        tcg_gen_ext16s_i32(tmp, reg);
1452
    else
1453
        tcg_gen_ext8s_i32(tmp, reg);
1454
    if (op == 2)
1455
        gen_partset_reg(OS_WORD, reg, tmp);
1456
    else
1457
        tcg_gen_mov_i32(reg, tmp);
1458
    gen_logic_cc(s, tmp);
1459
}
1460

    
1461
DISAS_INSN(tst)
1462
{
1463
    int opsize;
1464
    TCGv tmp;
1465

    
1466
    switch ((insn >> 6) & 3) {
1467
    case 0: /* tst.b */
1468
        opsize = OS_BYTE;
1469
        break;
1470
    case 1: /* tst.w */
1471
        opsize = OS_WORD;
1472
        break;
1473
    case 2: /* tst.l */
1474
        opsize = OS_LONG;
1475
        break;
1476
    default:
1477
        abort();
1478
    }
1479
    SRC_EA(tmp, opsize, 1, NULL);
1480
    gen_logic_cc(s, tmp);
1481
}
1482

    
1483
DISAS_INSN(pulse)
1484
{
1485
  /* Implemented as a NOP.  */
1486
}
1487

    
1488
DISAS_INSN(illegal)
1489
{
1490
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1491
}
1492

    
1493
/* ??? This should be atomic.  */
1494
DISAS_INSN(tas)
1495
{
1496
    TCGv dest;
1497
    TCGv src1;
1498
    TCGv addr;
1499

    
1500
    dest = tcg_temp_new();
1501
    SRC_EA(src1, OS_BYTE, 1, &addr);
1502
    gen_logic_cc(s, src1);
1503
    tcg_gen_ori_i32(dest, src1, 0x80);
1504
    DEST_EA(insn, OS_BYTE, dest, &addr);
1505
}
1506

    
1507
DISAS_INSN(mull)
1508
{
1509
    uint16_t ext;
1510
    TCGv reg;
1511
    TCGv src1;
1512
    TCGv dest;
1513

    
1514
    /* The upper 32 bits of the product are discarded, so
1515
       muls.l and mulu.l are functionally equivalent.  */
1516
    ext = lduw_code(s->pc);
1517
    s->pc += 2;
1518
    if (ext & 0x87ff) {
1519
        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
1520
        return;
1521
    }
1522
    reg = DREG(ext, 12);
1523
    SRC_EA(src1, OS_LONG, 0, NULL);
1524
    dest = tcg_temp_new();
1525
    tcg_gen_mul_i32(dest, src1, reg);
1526
    tcg_gen_mov_i32(reg, dest);
1527
    /* Unlike m68k, coldfire always clears the overflow bit.  */
1528
    gen_logic_cc(s, dest);
1529
}
1530

    
1531
DISAS_INSN(link)
1532
{
1533
    int16_t offset;
1534
    TCGv reg;
1535
    TCGv tmp;
1536

    
1537
    offset = ldsw_code(s->pc);
1538
    s->pc += 2;
1539
    reg = AREG(insn, 0);
1540
    tmp = tcg_temp_new();
1541
    tcg_gen_subi_i32(tmp, QREG_SP, 4);
1542
    gen_store(s, OS_LONG, tmp, reg);
1543
    if ((insn & 7) != 7)
1544
        tcg_gen_mov_i32(reg, tmp);
1545
    tcg_gen_addi_i32(QREG_SP, tmp, offset);
1546
}
1547

    
1548
DISAS_INSN(unlk)
1549
{
1550
    TCGv src;
1551
    TCGv reg;
1552
    TCGv tmp;
1553

    
1554
    src = tcg_temp_new();
1555
    reg = AREG(insn, 0);
1556
    tcg_gen_mov_i32(src, reg);
1557
    tmp = gen_load(s, OS_LONG, src, 0);
1558
    tcg_gen_mov_i32(reg, tmp);
1559
    tcg_gen_addi_i32(QREG_SP, src, 4);
1560
}
1561

    
1562
DISAS_INSN(nop)
1563
{
1564
}
1565

    
1566
DISAS_INSN(rts)
1567
{
1568
    TCGv tmp;
1569

    
1570
    tmp = gen_load(s, OS_LONG, QREG_SP, 0);
1571
    tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
1572
    gen_jmp(s, tmp);
1573
}
1574

    
1575
DISAS_INSN(jump)
1576
{
1577
    TCGv tmp;
1578

    
1579
    /* Load the target address first to ensure correct exception
1580
       behavior.  */
1581
    tmp = gen_lea(s, insn, OS_LONG);
1582
    if (IS_NULL_QREG(tmp)) {
1583
        gen_addr_fault(s);
1584
        return;
1585
    }
1586
    if ((insn & 0x40) == 0) {
1587
        /* jsr */
1588
        gen_push(s, tcg_const_i32(s->pc));
1589
    }
1590
    gen_jmp(s, tmp);
1591
}
1592

    
1593
DISAS_INSN(addsubq)
1594
{
1595
    TCGv src1;
1596
    TCGv src2;
1597
    TCGv dest;
1598
    int val;
1599
    TCGv addr;
1600

    
1601
    SRC_EA(src1, OS_LONG, 0, &addr);
1602
    val = (insn >> 9) & 7;
1603
    if (val == 0)
1604
        val = 8;
1605
    dest = tcg_temp_new();
1606
    tcg_gen_mov_i32(dest, src1);
1607
    if ((insn & 0x38) == 0x08) {
1608
        /* Don't update condition codes if the destination is an
1609
           address register.  */
1610
        if (insn & 0x0100) {
1611
            tcg_gen_subi_i32(dest, dest, val);
1612
        } else {
1613
            tcg_gen_addi_i32(dest, dest, val);
1614
        }
1615
    } else {
1616
        src2 = tcg_const_i32(val);
1617
        if (insn & 0x0100) {
1618
            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
1619
            tcg_gen_subi_i32(dest, dest, val);
1620
            s->cc_op = CC_OP_SUB;
1621
        } else {
1622
            tcg_gen_addi_i32(dest, dest, val);
1623
            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
1624
            s->cc_op = CC_OP_ADD;
1625
        }
1626
        gen_update_cc_add(dest, src2);
1627
    }
1628
    DEST_EA(insn, OS_LONG, dest, &addr);
1629
}
1630

    
1631
DISAS_INSN(tpf)
1632
{
1633
    switch (insn & 7) {
1634
    case 2: /* One extension word.  */
1635
        s->pc += 2;
1636
        break;
1637
    case 3: /* Two extension words.  */
1638
        s->pc += 4;
1639
        break;
1640
    case 4: /* No extension words.  */
1641
        break;
1642
    default:
1643
        disas_undef(s, insn);
1644
    }
1645
}
1646

    
1647
DISAS_INSN(branch)
1648
{
1649
    int32_t offset;
1650
    uint32_t base;
1651
    int op;
1652
    int l1;
1653

    
1654
    base = s->pc;
1655
    op = (insn >> 8) & 0xf;
1656
    offset = (int8_t)insn;
1657
    if (offset == 0) {
1658
        offset = ldsw_code(s->pc);
1659
        s->pc += 2;
1660
    } else if (offset == -1) {
1661
        offset = read_im32(s);
1662
    }
1663
    if (op == 1) {
1664
        /* bsr */
1665
        gen_push(s, tcg_const_i32(s->pc));
1666
    }
1667
    gen_flush_cc_op(s);
1668
    if (op > 1) {
1669
        /* Bcc */
1670
        l1 = gen_new_label();
1671
        gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
1672
        gen_jmp_tb(s, 1, base + offset);
1673
        gen_set_label(l1);
1674
        gen_jmp_tb(s, 0, s->pc);
1675
    } else {
1676
        /* Unconditional branch.  */
1677
        gen_jmp_tb(s, 0, base + offset);
1678
    }
1679
}
1680

    
1681
DISAS_INSN(moveq)
1682
{
1683
    uint32_t val;
1684

    
1685
    val = (int8_t)insn;
1686
    tcg_gen_movi_i32(DREG(insn, 9), val);
1687
    gen_logic_cc(s, tcg_const_i32(val));
1688
}
1689

    
1690
DISAS_INSN(mvzs)
1691
{
1692
    int opsize;
1693
    TCGv src;
1694
    TCGv reg;
1695

    
1696
    if (insn & 0x40)
1697
        opsize = OS_WORD;
1698
    else
1699
        opsize = OS_BYTE;
1700
    SRC_EA(src, opsize, (insn & 0x80) == 0, NULL);
1701
    reg = DREG(insn, 9);
1702
    tcg_gen_mov_i32(reg, src);
1703
    gen_logic_cc(s, src);
1704
}
1705

    
1706
DISAS_INSN(or)
1707
{
1708
    TCGv reg;
1709
    TCGv dest;
1710
    TCGv src;
1711
    TCGv addr;
1712

    
1713
    reg = DREG(insn, 9);
1714
    dest = tcg_temp_new();
1715
    if (insn & 0x100) {
1716
        SRC_EA(src, OS_LONG, 0, &addr);
1717
        tcg_gen_or_i32(dest, src, reg);
1718
        DEST_EA(insn, OS_LONG, dest, &addr);
1719
    } else {
1720
        SRC_EA(src, OS_LONG, 0, NULL);
1721
        tcg_gen_or_i32(dest, src, reg);
1722
        tcg_gen_mov_i32(reg, dest);
1723
    }
1724
    gen_logic_cc(s, dest);
1725
}
1726

    
1727
DISAS_INSN(suba)
1728
{
1729
    TCGv src;
1730
    TCGv reg;
1731

    
1732
    SRC_EA(src, OS_LONG, 0, NULL);
1733
    reg = AREG(insn, 9);
1734
    tcg_gen_sub_i32(reg, reg, src);
1735
}
1736

    
1737
DISAS_INSN(subx)
1738
{
1739
    TCGv reg;
1740
    TCGv src;
1741

    
1742
    gen_flush_flags(s);
1743
    reg = DREG(insn, 9);
1744
    src = DREG(insn, 0);
1745
    gen_helper_subx_cc(reg, cpu_env, reg, src);
1746
}
1747

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

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

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

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

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

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

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

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

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

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

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

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

    
1859
DISAS_INSN(addx)
1860
{
1861
    TCGv reg;
1862
    TCGv src;
1863

    
1864
    gen_flush_flags(s);
1865
    reg = DREG(insn, 9);
1866
    src = DREG(insn, 0);
1867
    gen_helper_addx_cc(reg, cpu_env, reg, src);
1868
    s->cc_op = CC_OP_FLAGS;
1869
}
1870

    
1871
/* TODO: This could be implemented without helper functions.  */
1872
DISAS_INSN(shift_im)
1873
{
1874
    TCGv reg;
1875
    int tmp;
1876
    TCGv shift;
1877

    
1878
    reg = DREG(insn, 0);
1879
    tmp = (insn >> 9) & 7;
1880
    if (tmp == 0)
1881
        tmp = 8;
1882
    shift = tcg_const_i32(tmp);
1883
    /* No need to flush flags becuse we know we will set C flag.  */
1884
    if (insn & 0x100) {
1885
        gen_helper_shl_cc(reg, cpu_env, reg, shift);
1886
    } else {
1887
        if (insn & 8) {
1888
            gen_helper_shr_cc(reg, cpu_env, reg, shift);
1889
        } else {
1890
            gen_helper_sar_cc(reg, cpu_env, reg, shift);
1891
        }
1892
    }
1893
    s->cc_op = CC_OP_SHIFT;
1894
}
1895

    
1896
DISAS_INSN(shift_reg)
1897
{
1898
    TCGv reg;
1899
    TCGv shift;
1900

    
1901
    reg = DREG(insn, 0);
1902
    shift = DREG(insn, 9);
1903
    /* Shift by zero leaves C flag unmodified.   */
1904
    gen_flush_flags(s);
1905
    if (insn & 0x100) {
1906
        gen_helper_shl_cc(reg, cpu_env, reg, shift);
1907
    } else {
1908
        if (insn & 8) {
1909
            gen_helper_shr_cc(reg, cpu_env, reg, shift);
1910
        } else {
1911
            gen_helper_sar_cc(reg, cpu_env, reg, shift);
1912
        }
1913
    }
1914
    s->cc_op = CC_OP_SHIFT;
1915
}
1916

    
1917
DISAS_INSN(ff1)
1918
{
1919
    TCGv reg;
1920
    reg = DREG(insn, 0);
1921
    gen_logic_cc(s, reg);
1922
    gen_helper_ff1(reg, reg);
1923
}
1924

    
1925
static TCGv gen_get_sr(DisasContext *s)
1926
{
1927
    TCGv ccr;
1928
    TCGv sr;
1929

    
1930
    ccr = gen_get_ccr(s);
1931
    sr = tcg_temp_new();
1932
    tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
1933
    tcg_gen_or_i32(sr, sr, ccr);
1934
    return sr;
1935
}
1936

    
1937
DISAS_INSN(strldsr)
1938
{
1939
    uint16_t ext;
1940
    uint32_t addr;
1941

    
1942
    addr = s->pc - 2;
1943
    ext = lduw_code(s->pc);
1944
    s->pc += 2;
1945
    if (ext != 0x46FC) {
1946
        gen_exception(s, addr, EXCP_UNSUPPORTED);
1947
        return;
1948
    }
1949
    ext = lduw_code(s->pc);
1950
    s->pc += 2;
1951
    if (IS_USER(s) || (ext & SR_S) == 0) {
1952
        gen_exception(s, addr, EXCP_PRIVILEGE);
1953
        return;
1954
    }
1955
    gen_push(s, gen_get_sr(s));
1956
    gen_set_sr_im(s, ext, 0);
1957
}
1958

    
1959
DISAS_INSN(move_from_sr)
1960
{
1961
    TCGv reg;
1962
    TCGv sr;
1963

    
1964
    if (IS_USER(s)) {
1965
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1966
        return;
1967
    }
1968
    sr = gen_get_sr(s);
1969
    reg = DREG(insn, 0);
1970
    gen_partset_reg(OS_WORD, reg, sr);
1971
}
1972

    
1973
DISAS_INSN(move_to_sr)
1974
{
1975
    if (IS_USER(s)) {
1976
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1977
        return;
1978
    }
1979
    gen_set_sr(s, insn, 0);
1980
    gen_lookup_tb(s);
1981
}
1982

    
1983
DISAS_INSN(move_from_usp)
1984
{
1985
    if (IS_USER(s)) {
1986
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1987
        return;
1988
    }
1989
    /* TODO: Implement USP.  */
1990
    gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1991
}
1992

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

    
2003
DISAS_INSN(halt)
2004
{
2005
    gen_exception(s, s->pc, EXCP_HALT_INSN);
2006
}
2007

    
2008
DISAS_INSN(stop)
2009
{
2010
    uint16_t ext;
2011

    
2012
    if (IS_USER(s)) {
2013
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2014
        return;
2015
    }
2016

    
2017
    ext = lduw_code(s->pc);
2018
    s->pc += 2;
2019

    
2020
    gen_set_sr_im(s, ext, 0);
2021
    tcg_gen_movi_i32(QREG_HALTED, 1);
2022
    gen_exception(s, s->pc, EXCP_HLT);
2023
}
2024

    
2025
DISAS_INSN(rte)
2026
{
2027
    if (IS_USER(s)) {
2028
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2029
        return;
2030
    }
2031
    gen_exception(s, s->pc - 2, EXCP_RTE);
2032
}
2033

    
2034
DISAS_INSN(movec)
2035
{
2036
    uint16_t ext;
2037
    TCGv reg;
2038

    
2039
    if (IS_USER(s)) {
2040
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2041
        return;
2042
    }
2043

    
2044
    ext = lduw_code(s->pc);
2045
    s->pc += 2;
2046

    
2047
    if (ext & 0x8000) {
2048
        reg = AREG(ext, 12);
2049
    } else {
2050
        reg = DREG(ext, 12);
2051
    }
2052
    gen_helper_movec(cpu_env, tcg_const_i32(ext & 0xfff), reg);
2053
    gen_lookup_tb(s);
2054
}
2055

    
2056
DISAS_INSN(intouch)
2057
{
2058
    if (IS_USER(s)) {
2059
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2060
        return;
2061
    }
2062
    /* ICache fetch.  Implement as no-op.  */
2063
}
2064

    
2065
DISAS_INSN(cpushl)
2066
{
2067
    if (IS_USER(s)) {
2068
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2069
        return;
2070
    }
2071
    /* Cache push/invalidate.  Implement as no-op.  */
2072
}
2073

    
2074
DISAS_INSN(wddata)
2075
{
2076
    gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2077
}
2078

    
2079
DISAS_INSN(wdebug)
2080
{
2081
    if (IS_USER(s)) {
2082
        gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2083
        return;
2084
    }
2085
    /* TODO: Implement wdebug.  */
2086
    qemu_assert(0, "WDEBUG not implemented");
2087
}
2088

    
2089
DISAS_INSN(trap)
2090
{
2091
    gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
2092
}
2093

    
2094
/* ??? FP exceptions are not implemented.  Most exceptions are deferred until
2095
   immediately before the next FP instruction is executed.  */
2096
DISAS_INSN(fpu)
2097
{
2098
    uint16_t ext;
2099
    int32_t offset;
2100
    int opmode;
2101
    TCGv_i64 src;
2102
    TCGv_i64 dest;
2103
    TCGv_i64 res;
2104
    TCGv tmp32;
2105
    int round;
2106
    int set_dest;
2107
    int opsize;
2108

    
2109
    ext = lduw_code(s->pc);
2110
    s->pc += 2;
2111
    opmode = ext & 0x7f;
2112
    switch ((ext >> 13) & 7) {
2113
    case 0: case 2:
2114
        break;
2115
    case 1:
2116
        goto undef;
2117
    case 3: /* fmove out */
2118
        src = FREG(ext, 7);
2119
        tmp32 = tcg_temp_new_i32();
2120
        /* fmove */
2121
        /* ??? TODO: Proper behavior on overflow.  */
2122
        switch ((ext >> 10) & 7) {
2123
        case 0:
2124
            opsize = OS_LONG;
2125
            gen_helper_f64_to_i32(tmp32, cpu_env, src);
2126
            break;
2127
        case 1:
2128
            opsize = OS_SINGLE;
2129
            gen_helper_f64_to_f32(tmp32, cpu_env, src);
2130
            break;
2131
        case 4:
2132
            opsize = OS_WORD;
2133
            gen_helper_f64_to_i32(tmp32, cpu_env, src);
2134
            break;
2135
        case 5: /* OS_DOUBLE */
2136
            tcg_gen_mov_i32(tmp32, AREG(insn, 0));
2137
            switch ((insn >> 3) & 7) {
2138
            case 2:
2139
            case 3:
2140
                break;
2141
            case 4:
2142
                tcg_gen_addi_i32(tmp32, tmp32, -8);
2143
                break;
2144
            case 5:
2145
                offset = ldsw_code(s->pc);
2146
                s->pc += 2;
2147
                tcg_gen_addi_i32(tmp32, tmp32, offset);
2148
                break;
2149
            default:
2150
                goto undef;
2151
            }
2152
            gen_store64(s, tmp32, src);
2153
            switch ((insn >> 3) & 7) {
2154
            case 3:
2155
                tcg_gen_addi_i32(tmp32, tmp32, 8);
2156
                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2157
                break;
2158
            case 4:
2159
                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2160
                break;
2161
            }
2162
            tcg_temp_free_i32(tmp32);
2163
            return;
2164
        case 6:
2165
            opsize = OS_BYTE;
2166
            gen_helper_f64_to_i32(tmp32, cpu_env, src);
2167
            break;
2168
        default:
2169
            goto undef;
2170
        }
2171
        DEST_EA(insn, opsize, tmp32, NULL);
2172
        tcg_temp_free_i32(tmp32);
2173
        return;
2174
    case 4: /* fmove to control register.  */
2175
        switch ((ext >> 10) & 7) {
2176
        case 4: /* FPCR */
2177
            /* Not implemented.  Ignore writes.  */
2178
            break;
2179
        case 1: /* FPIAR */
2180
        case 2: /* FPSR */
2181
        default:
2182
            cpu_abort(NULL, "Unimplemented: fmove to control %d",
2183
                      (ext >> 10) & 7);
2184
        }
2185
        break;
2186
    case 5: /* fmove from control register.  */
2187
        switch ((ext >> 10) & 7) {
2188
        case 4: /* FPCR */
2189
            /* Not implemented.  Always return zero.  */
2190
            tmp32 = tcg_const_i32(0);
2191
            break;
2192
        case 1: /* FPIAR */
2193
        case 2: /* FPSR */
2194
        default:
2195
            cpu_abort(NULL, "Unimplemented: fmove from control %d",
2196
                      (ext >> 10) & 7);
2197
            goto undef;
2198
        }
2199
        DEST_EA(insn, OS_LONG, tmp32, NULL);
2200
        break;
2201
    case 6: /* fmovem */
2202
    case 7:
2203
        {
2204
            TCGv addr;
2205
            uint16_t mask;
2206
            int i;
2207
            if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
2208
                goto undef;
2209
            tmp32 = gen_lea(s, insn, OS_LONG);
2210
            if (IS_NULL_QREG(tmp32)) {
2211
                gen_addr_fault(s);
2212
                return;
2213
            }
2214
            addr = tcg_temp_new_i32();
2215
            tcg_gen_mov_i32(addr, tmp32);
2216
            mask = 0x80;
2217
            for (i = 0; i < 8; i++) {
2218
                if (ext & mask) {
2219
                    s->is_mem = 1;
2220
                    dest = FREG(i, 0);
2221
                    if (ext & (1 << 13)) {
2222
                        /* store */
2223
                        tcg_gen_qemu_stf64(dest, addr, IS_USER(s));
2224
                    } else {
2225
                        /* load */
2226
                        tcg_gen_qemu_ldf64(dest, addr, IS_USER(s));
2227
                    }
2228
                    if (ext & (mask - 1))
2229
                        tcg_gen_addi_i32(addr, addr, 8);
2230
                }
2231
                mask >>= 1;
2232
            }
2233
            tcg_temp_free_i32(addr);
2234
        }
2235
        return;
2236
    }
2237
    if (ext & (1 << 14)) {
2238
        /* Source effective address.  */
2239
        switch ((ext >> 10) & 7) {
2240
        case 0: opsize = OS_LONG; break;
2241
        case 1: opsize = OS_SINGLE; break;
2242
        case 4: opsize = OS_WORD; break;
2243
        case 5: opsize = OS_DOUBLE; break;
2244
        case 6: opsize = OS_BYTE; break;
2245
        default:
2246
            goto undef;
2247
        }
2248
        if (opsize == OS_DOUBLE) {
2249
            tmp32 = tcg_temp_new_i32();
2250
            tcg_gen_mov_i32(tmp32, AREG(insn, 0));
2251
            switch ((insn >> 3) & 7) {
2252
            case 2:
2253
            case 3:
2254
                break;
2255
            case 4:
2256
                tcg_gen_addi_i32(tmp32, tmp32, -8);
2257
                break;
2258
            case 5:
2259
                offset = ldsw_code(s->pc);
2260
                s->pc += 2;
2261
                tcg_gen_addi_i32(tmp32, tmp32, offset);
2262
                break;
2263
            case 7:
2264
                offset = ldsw_code(s->pc);
2265
                offset += s->pc - 2;
2266
                s->pc += 2;
2267
                tcg_gen_addi_i32(tmp32, tmp32, offset);
2268
                break;
2269
            default:
2270
                goto undef;
2271
            }
2272
            src = gen_load64(s, tmp32);
2273
            switch ((insn >> 3) & 7) {
2274
            case 3:
2275
                tcg_gen_addi_i32(tmp32, tmp32, 8);
2276
                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2277
                break;
2278
            case 4:
2279
                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2280
                break;
2281
            }
2282
            tcg_temp_free_i32(tmp32);
2283
        } else {
2284
            SRC_EA(tmp32, opsize, 1, NULL);
2285
            src = tcg_temp_new_i64();
2286
            switch (opsize) {
2287
            case OS_LONG:
2288
            case OS_WORD:
2289
            case OS_BYTE:
2290
                gen_helper_i32_to_f64(src, cpu_env, tmp32);
2291
                break;
2292
            case OS_SINGLE:
2293
                gen_helper_f32_to_f64(src, cpu_env, tmp32);
2294
                break;
2295
            }
2296
        }
2297
    } else {
2298
        /* Source register.  */
2299
        src = FREG(ext, 10);
2300
    }
2301
    dest = FREG(ext, 7);
2302
    res = tcg_temp_new_i64();
2303
    if (opmode != 0x3a)
2304
        tcg_gen_mov_f64(res, dest);
2305
    round = 1;
2306
    set_dest = 1;
2307
    switch (opmode) {
2308
    case 0: case 0x40: case 0x44: /* fmove */
2309
        tcg_gen_mov_f64(res, src);
2310
        break;
2311
    case 1: /* fint */
2312
        gen_helper_iround_f64(res, cpu_env, src);
2313
        round = 0;
2314
        break;
2315
    case 3: /* fintrz */
2316
        gen_helper_itrunc_f64(res, cpu_env, src);
2317
        round = 0;
2318
        break;
2319
    case 4: case 0x41: case 0x45: /* fsqrt */
2320
        gen_helper_sqrt_f64(res, cpu_env, src);
2321
        break;
2322
    case 0x18: case 0x58: case 0x5c: /* fabs */
2323
        gen_helper_abs_f64(res, src);
2324
        break;
2325
    case 0x1a: case 0x5a: case 0x5e: /* fneg */
2326
        gen_helper_chs_f64(res, src);
2327
        break;
2328
    case 0x20: case 0x60: case 0x64: /* fdiv */
2329
        gen_helper_div_f64(res, cpu_env, res, src);
2330
        break;
2331
    case 0x22: case 0x62: case 0x66: /* fadd */
2332
        gen_helper_add_f64(res, cpu_env, res, src);
2333
        break;
2334
    case 0x23: case 0x63: case 0x67: /* fmul */
2335
        gen_helper_mul_f64(res, cpu_env, res, src);
2336
        break;
2337
    case 0x28: case 0x68: case 0x6c: /* fsub */
2338
        gen_helper_sub_f64(res, cpu_env, res, src);
2339
        break;
2340
    case 0x38: /* fcmp */
2341
        gen_helper_sub_cmp_f64(res, cpu_env, res, src);
2342
        set_dest = 0;
2343
        round = 0;
2344
        break;
2345
    case 0x3a: /* ftst */
2346
        tcg_gen_mov_f64(res, src);
2347
        set_dest = 0;
2348
        round = 0;
2349
        break;
2350
    default:
2351
        goto undef;
2352
    }
2353
    if (ext & (1 << 14)) {
2354
        tcg_temp_free_i64(src);
2355
    }
2356
    if (round) {
2357
        if (opmode & 0x40) {
2358
            if ((opmode & 0x4) != 0)
2359
                round = 0;
2360
        } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
2361
            round = 0;
2362
        }
2363
    }
2364
    if (round) {
2365
        TCGv tmp = tcg_temp_new_i32();
2366
        gen_helper_f64_to_f32(tmp, cpu_env, res);
2367
        gen_helper_f32_to_f64(res, cpu_env, tmp);
2368
        tcg_temp_free_i32(tmp);
2369
    }
2370
    tcg_gen_mov_f64(QREG_FP_RESULT, res);
2371
    if (set_dest) {
2372
        tcg_gen_mov_f64(dest, res);
2373
    }
2374
    tcg_temp_free_i64(res);
2375
    return;
2376
undef:
2377
    /* FIXME: Is this right for offset addressing modes?  */
2378
    s->pc -= 2;
2379
    disas_undef_fpu(s, insn);
2380
}
2381

    
2382
DISAS_INSN(fbcc)
2383
{
2384
    uint32_t offset;
2385
    uint32_t addr;
2386
    TCGv flag;
2387
    int l1;
2388

    
2389
    addr = s->pc;
2390
    offset = ldsw_code(s->pc);
2391
    s->pc += 2;
2392
    if (insn & (1 << 6)) {
2393
        offset = (offset << 16) | lduw_code(s->pc);
2394
        s->pc += 2;
2395
    }
2396

    
2397
    l1 = gen_new_label();
2398
    /* TODO: Raise BSUN exception.  */
2399
    flag = tcg_temp_new();
2400
    gen_helper_compare_f64(flag, cpu_env, QREG_FP_RESULT);
2401
    /* Jump to l1 if condition is true.  */
2402
    switch (insn & 0xf) {
2403
    case 0: /* f */
2404
        break;
2405
    case 1: /* eq (=0) */
2406
        tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1);
2407
        break;
2408
    case 2: /* ogt (=1) */
2409
        tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(1), l1);
2410
        break;
2411
    case 3: /* oge (=0 or =1) */
2412
        tcg_gen_brcond_i32(TCG_COND_LEU, flag, tcg_const_i32(1), l1);
2413
        break;
2414
    case 4: /* olt (=-1) */
2415
        tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(0), l1);
2416
        break;
2417
    case 5: /* ole (=-1 or =0) */
2418
        tcg_gen_brcond_i32(TCG_COND_LE, flag, tcg_const_i32(0), l1);
2419
        break;
2420
    case 6: /* ogl (=-1 or =1) */
2421
        tcg_gen_andi_i32(flag, flag, 1);
2422
        tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1);
2423
        break;
2424
    case 7: /* or (=2) */
2425
        tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(2), l1);
2426
        break;
2427
    case 8: /* un (<2) */
2428
        tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(2), l1);
2429
        break;
2430
    case 9: /* ueq (=0 or =2) */
2431
        tcg_gen_andi_i32(flag, flag, 1);
2432
        tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1);
2433
        break;
2434
    case 10: /* ugt (>0) */
2435
        tcg_gen_brcond_i32(TCG_COND_GT, flag, tcg_const_i32(0), l1);
2436
        break;
2437
    case 11: /* uge (>=0) */
2438
        tcg_gen_brcond_i32(TCG_COND_GE, flag, tcg_const_i32(0), l1);
2439
        break;
2440
    case 12: /* ult (=-1 or =2) */
2441
        tcg_gen_brcond_i32(TCG_COND_GEU, flag, tcg_const_i32(2), l1);
2442
        break;
2443
    case 13: /* ule (!=1) */
2444
        tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(1), l1);
2445
        break;
2446
    case 14: /* ne (!=0) */
2447
        tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1);
2448
        break;
2449
    case 15: /* t */
2450
        tcg_gen_br(l1);
2451
        break;
2452
    }
2453
    gen_jmp_tb(s, 0, s->pc);
2454
    gen_set_label(l1);
2455
    gen_jmp_tb(s, 1, addr + offset);
2456
}
2457

    
2458
DISAS_INSN(frestore)
2459
{
2460
    /* TODO: Implement frestore.  */
2461
    qemu_assert(0, "FRESTORE not implemented");
2462
}
2463

    
2464
DISAS_INSN(fsave)
2465
{
2466
    /* TODO: Implement fsave.  */
2467
    qemu_assert(0, "FSAVE not implemented");
2468
}
2469

    
2470
static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
2471
{
2472
    TCGv tmp = tcg_temp_new();
2473
    if (s->env->macsr & MACSR_FI) {
2474
        if (upper)
2475
            tcg_gen_andi_i32(tmp, val, 0xffff0000);
2476
        else
2477
            tcg_gen_shli_i32(tmp, val, 16);
2478
    } else if (s->env->macsr & MACSR_SU) {
2479
        if (upper)
2480
            tcg_gen_sari_i32(tmp, val, 16);
2481
        else
2482
            tcg_gen_ext16s_i32(tmp, val);
2483
    } else {
2484
        if (upper)
2485
            tcg_gen_shri_i32(tmp, val, 16);
2486
        else
2487
            tcg_gen_ext16u_i32(tmp, val);
2488
    }
2489
    return tmp;
2490
}
2491

    
2492
static void gen_mac_clear_flags(void)
2493
{
2494
    tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR,
2495
                     ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV));
2496
}
2497

    
2498
DISAS_INSN(mac)
2499
{
2500
    TCGv rx;
2501
    TCGv ry;
2502
    uint16_t ext;
2503
    int acc;
2504
    TCGv tmp;
2505
    TCGv addr;
2506
    TCGv loadval;
2507
    int dual;
2508
    TCGv saved_flags;
2509

    
2510
    if (!s->done_mac) {
2511
        s->mactmp = tcg_temp_new_i64();
2512
        s->done_mac = 1;
2513
    }
2514

    
2515
    ext = lduw_code(s->pc);
2516
    s->pc += 2;
2517

    
2518
    acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
2519
    dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
2520
    if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
2521
        disas_undef(s, insn);
2522
        return;
2523
    }
2524
    if (insn & 0x30) {
2525
        /* MAC with load.  */
2526
        tmp = gen_lea(s, insn, OS_LONG);
2527
        addr = tcg_temp_new();
2528
        tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK);
2529
        /* Load the value now to ensure correct exception behavior.
2530
           Perform writeback after reading the MAC inputs.  */
2531
        loadval = gen_load(s, OS_LONG, addr, 0);
2532

    
2533
        acc ^= 1;
2534
        rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12);
2535
        ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0);
2536
    } else {
2537
        loadval = addr = NULL_QREG;
2538
        rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
2539
        ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2540
    }
2541

    
2542
    gen_mac_clear_flags();
2543
#if 0
2544
    l1 = -1;
2545
    /* Disabled because conditional branches clobber temporary vars.  */
2546
    if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
2547
        /* Skip the multiply if we know we will ignore it.  */
2548
        l1 = gen_new_label();
2549
        tmp = tcg_temp_new();
2550
        tcg_gen_andi_i32(tmp, QREG_MACSR, 1 << (acc + 8));
2551
        gen_op_jmp_nz32(tmp, l1);
2552
    }
2553
#endif
2554

    
2555
    if ((ext & 0x0800) == 0) {
2556
        /* Word.  */
2557
        rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0);
2558
        ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0);
2559
    }
2560
    if (s->env->macsr & MACSR_FI) {
2561
        gen_helper_macmulf(s->mactmp, cpu_env, rx, ry);
2562
    } else {
2563
        if (s->env->macsr & MACSR_SU)
2564
            gen_helper_macmuls(s->mactmp, cpu_env, rx, ry);
2565
        else
2566
            gen_helper_macmulu(s->mactmp, cpu_env, rx, ry);
2567
        switch ((ext >> 9) & 3) {
2568
        case 1:
2569
            tcg_gen_shli_i64(s->mactmp, s->mactmp, 1);
2570
            break;
2571
        case 3:
2572
            tcg_gen_shri_i64(s->mactmp, s->mactmp, 1);
2573
            break;
2574
        }
2575
    }
2576

    
2577
    if (dual) {
2578
        /* Save the overflow flag from the multiply.  */
2579
        saved_flags = tcg_temp_new();
2580
        tcg_gen_mov_i32(saved_flags, QREG_MACSR);
2581
    } else {
2582
        saved_flags = NULL_QREG;
2583
    }
2584

    
2585
#if 0
2586
    /* Disabled because conditional branches clobber temporary vars.  */
2587
    if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
2588
        /* Skip the accumulate if the value is already saturated.  */
2589
        l1 = gen_new_label();
2590
        tmp = tcg_temp_new();
2591
        gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc));
2592
        gen_op_jmp_nz32(tmp, l1);
2593
    }
2594
#endif
2595

    
2596
    if (insn & 0x100)
2597
        tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
2598
    else
2599
        tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
2600

    
2601
    if (s->env->macsr & MACSR_FI)
2602
        gen_helper_macsatf(cpu_env, tcg_const_i32(acc));
2603
    else if (s->env->macsr & MACSR_SU)
2604
        gen_helper_macsats(cpu_env, tcg_const_i32(acc));
2605
    else
2606
        gen_helper_macsatu(cpu_env, tcg_const_i32(acc));
2607

    
2608
#if 0
2609
    /* Disabled because conditional branches clobber temporary vars.  */
2610
    if (l1 != -1)
2611
        gen_set_label(l1);
2612
#endif
2613

    
2614
    if (dual) {
2615
        /* Dual accumulate variant.  */
2616
        acc = (ext >> 2) & 3;
2617
        /* Restore the overflow flag from the multiplier.  */
2618
        tcg_gen_mov_i32(QREG_MACSR, saved_flags);
2619
#if 0
2620
        /* Disabled because conditional branches clobber temporary vars.  */
2621
        if ((s->env->macsr & MACSR_OMC) != 0) {
2622
            /* Skip the accumulate if the value is already saturated.  */
2623
            l1 = gen_new_label();
2624
            tmp = tcg_temp_new();
2625
            gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc));
2626
            gen_op_jmp_nz32(tmp, l1);
2627
        }
2628
#endif
2629
        if (ext & 2)
2630
            tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
2631
        else
2632
            tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
2633
        if (s->env->macsr & MACSR_FI)
2634
            gen_helper_macsatf(cpu_env, tcg_const_i32(acc));
2635
        else if (s->env->macsr & MACSR_SU)
2636
            gen_helper_macsats(cpu_env, tcg_const_i32(acc));
2637
        else
2638
            gen_helper_macsatu(cpu_env, tcg_const_i32(acc));
2639
#if 0
2640
        /* Disabled because conditional branches clobber temporary vars.  */
2641
        if (l1 != -1)
2642
            gen_set_label(l1);
2643
#endif
2644
    }
2645
    gen_helper_mac_set_flags(cpu_env, tcg_const_i32(acc));
2646

    
2647
    if (insn & 0x30) {
2648
        TCGv rw;
2649
        rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
2650
        tcg_gen_mov_i32(rw, loadval);
2651
        /* FIXME: Should address writeback happen with the masked or
2652
           unmasked value?  */
2653
        switch ((insn >> 3) & 7) {
2654
        case 3: /* Post-increment.  */
2655
            tcg_gen_addi_i32(AREG(insn, 0), addr, 4);
2656
            break;
2657
        case 4: /* Pre-decrement.  */
2658
            tcg_gen_mov_i32(AREG(insn, 0), addr);
2659
        }
2660
    }
2661
}
2662

    
2663
DISAS_INSN(from_mac)
2664
{
2665
    TCGv rx;
2666
    TCGv_i64 acc;
2667
    int accnum;
2668

    
2669
    rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2670
    accnum = (insn >> 9) & 3;
2671
    acc = MACREG(accnum);
2672
    if (s->env->macsr & MACSR_FI) {
2673
        gen_helper_get_macf(rx, cpu_env, acc);
2674
    } else if ((s->env->macsr & MACSR_OMC) == 0) {
2675
        tcg_gen_trunc_i64_i32(rx, acc);
2676
    } else if (s->env->macsr & MACSR_SU) {
2677
        gen_helper_get_macs(rx, acc);
2678
    } else {
2679
        gen_helper_get_macu(rx, acc);
2680
    }
2681
    if (insn & 0x40) {
2682
        tcg_gen_movi_i64(acc, 0);
2683
        tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
2684
    }
2685
}
2686

    
2687
DISAS_INSN(move_mac)
2688
{
2689
    /* FIXME: This can be done without a helper.  */
2690
    int src;
2691
    TCGv dest;
2692
    src = insn & 3;
2693
    dest = tcg_const_i32((insn >> 9) & 3);
2694
    gen_helper_mac_move(cpu_env, dest, tcg_const_i32(src));
2695
    gen_mac_clear_flags();
2696
    gen_helper_mac_set_flags(cpu_env, dest);
2697
}
2698

    
2699
DISAS_INSN(from_macsr)
2700
{
2701
    TCGv reg;
2702

    
2703
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2704
    tcg_gen_mov_i32(reg, QREG_MACSR);
2705
}
2706

    
2707
DISAS_INSN(from_mask)
2708
{
2709
    TCGv reg;
2710
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2711
    tcg_gen_mov_i32(reg, QREG_MAC_MASK);
2712
}
2713

    
2714
DISAS_INSN(from_mext)
2715
{
2716
    TCGv reg;
2717
    TCGv acc;
2718
    reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2719
    acc = tcg_const_i32((insn & 0x400) ? 2 : 0);
2720
    if (s->env->macsr & MACSR_FI)
2721
        gen_helper_get_mac_extf(reg, cpu_env, acc);
2722
    else
2723
        gen_helper_get_mac_exti(reg, cpu_env, acc);
2724
}
2725

    
2726
DISAS_INSN(macsr_to_ccr)
2727
{
2728
    tcg_gen_movi_i32(QREG_CC_X, 0);
2729
    tcg_gen_andi_i32(QREG_CC_DEST, QREG_MACSR, 0xf);
2730
    s->cc_op = CC_OP_FLAGS;
2731
}
2732

    
2733
DISAS_INSN(to_mac)
2734
{
2735
    TCGv_i64 acc;
2736
    TCGv val;
2737
    int accnum;
2738
    accnum = (insn >> 9) & 3;
2739
    acc = MACREG(accnum);
2740
    SRC_EA(val, OS_LONG, 0, NULL);
2741
    if (s->env->macsr & MACSR_FI) {
2742
        tcg_gen_ext_i32_i64(acc, val);
2743
        tcg_gen_shli_i64(acc, acc, 8);
2744
    } else if (s->env->macsr & MACSR_SU) {
2745
        tcg_gen_ext_i32_i64(acc, val);
2746
    } else {
2747
        tcg_gen_extu_i32_i64(acc, val);
2748
    }
2749
    tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
2750
    gen_mac_clear_flags();
2751
    gen_helper_mac_set_flags(cpu_env, tcg_const_i32(accnum));
2752
}
2753

    
2754
DISAS_INSN(to_macsr)
2755
{
2756
    TCGv val;
2757
    SRC_EA(val, OS_LONG, 0, NULL);
2758
    gen_helper_set_macsr(cpu_env, val);
2759
    gen_lookup_tb(s);
2760
}
2761

    
2762
DISAS_INSN(to_mask)
2763
{
2764
    TCGv val;
2765
    SRC_EA(val, OS_LONG, 0, NULL);
2766
    tcg_gen_ori_i32(QREG_MAC_MASK, val, 0xffff0000);
2767
}
2768

    
2769
DISAS_INSN(to_mext)
2770
{
2771
    TCGv val;
2772
    TCGv acc;
2773
    SRC_EA(val, OS_LONG, 0, NULL);
2774
    acc = tcg_const_i32((insn & 0x400) ? 2 : 0);
2775
    if (s->env->macsr & MACSR_FI)
2776
        gen_helper_set_mac_extf(cpu_env, val, acc);
2777
    else if (s->env->macsr & MACSR_SU)
2778
        gen_helper_set_mac_exts(cpu_env, val, acc);
2779
    else
2780
        gen_helper_set_mac_extu(cpu_env, val, acc);
2781
}
2782

    
2783
static disas_proc opcode_table[65536];
2784

    
2785
static void
2786
register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2787
{
2788
  int i;
2789
  int from;
2790
  int to;
2791

    
2792
  /* Sanity check.  All set bits must be included in the mask.  */
2793
  if (opcode & ~mask) {
2794
      fprintf(stderr,
2795
              "qemu internal error: bogus opcode definition %04x/%04x\n",
2796
              opcode, mask);
2797
      abort();
2798
  }
2799
  /* This could probably be cleverer.  For now just optimize the case where
2800
     the top bits are known.  */
2801
  /* Find the first zero bit in the mask.  */
2802
  i = 0x8000;
2803
  while ((i & mask) != 0)
2804
      i >>= 1;
2805
  /* Iterate over all combinations of this and lower bits.  */
2806
  if (i == 0)
2807
      i = 1;
2808
  else
2809
      i <<= 1;
2810
  from = opcode & ~(i - 1);
2811
  to = from + i;
2812
  for (i = from; i < to; i++) {
2813
      if ((i & mask) == opcode)
2814
          opcode_table[i] = proc;
2815
  }
2816
}
2817

    
2818
/* Register m68k opcode handlers.  Order is important.
2819
   Later insn override earlier ones.  */
2820
void register_m68k_insns (CPUM68KState *env)
2821
{
2822
#define INSN(name, opcode, mask, feature) do { \
2823
    if (m68k_feature(env, M68K_FEATURE_##feature)) \
2824
        register_opcode(disas_##name, 0x##opcode, 0x##mask); \
2825
    } while(0)
2826
    INSN(undef,     0000, 0000, CF_ISA_A);
2827
    INSN(arith_im,  0080, fff8, CF_ISA_A);
2828
    INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
2829
    INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
2830
    INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
2831
    INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
2832
    INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
2833
    INSN(arith_im,  0280, fff8, CF_ISA_A);
2834
    INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
2835
    INSN(arith_im,  0480, fff8, CF_ISA_A);
2836
    INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
2837
    INSN(arith_im,  0680, fff8, CF_ISA_A);
2838
    INSN(bitop_im,  0800, ffc0, CF_ISA_A);
2839
    INSN(bitop_im,  0840, ffc0, CF_ISA_A);
2840
    INSN(bitop_im,  0880, ffc0, CF_ISA_A);
2841
    INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
2842
    INSN(arith_im,  0a80, fff8, CF_ISA_A);
2843
    INSN(arith_im,  0c00, ff38, CF_ISA_A);
2844
    INSN(move,      1000, f000, CF_ISA_A);
2845
    INSN(move,      2000, f000, CF_ISA_A);
2846
    INSN(move,      3000, f000, CF_ISA_A);
2847
    INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
2848
    INSN(negx,      4080, fff8, CF_ISA_A);
2849
    INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
2850
    INSN(lea,       41c0, f1c0, CF_ISA_A);
2851
    INSN(clr,       4200, ff00, CF_ISA_A);
2852
    INSN(undef,     42c0, ffc0, CF_ISA_A);
2853
    INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
2854
    INSN(neg,       4480, fff8, CF_ISA_A);
2855
    INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
2856
    INSN(not,       4680, fff8, CF_ISA_A);
2857
    INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
2858
    INSN(pea,       4840, ffc0, CF_ISA_A);
2859
    INSN(swap,      4840, fff8, CF_ISA_A);
2860
    INSN(movem,     48c0, fbc0, CF_ISA_A);
2861
    INSN(ext,       4880, fff8, CF_ISA_A);
2862
    INSN(ext,       48c0, fff8, CF_ISA_A);
2863
    INSN(ext,       49c0, fff8, CF_ISA_A);
2864
    INSN(tst,       4a00, ff00, CF_ISA_A);
2865
    INSN(tas,       4ac0, ffc0, CF_ISA_B);
2866
    INSN(halt,      4ac8, ffff, CF_ISA_A);
2867
    INSN(pulse,     4acc, ffff, CF_ISA_A);
2868
    INSN(illegal,   4afc, ffff, CF_ISA_A);
2869
    INSN(mull,      4c00, ffc0, CF_ISA_A);
2870
    INSN(divl,      4c40, ffc0, CF_ISA_A);
2871
    INSN(sats,      4c80, fff8, CF_ISA_B);
2872
    INSN(trap,      4e40, fff0, CF_ISA_A);
2873
    INSN(link,      4e50, fff8, CF_ISA_A);
2874
    INSN(unlk,      4e58, fff8, CF_ISA_A);
2875
    INSN(move_to_usp, 4e60, fff8, USP);
2876
    INSN(move_from_usp, 4e68, fff8, USP);
2877
    INSN(nop,       4e71, ffff, CF_ISA_A);
2878
    INSN(stop,      4e72, ffff, CF_ISA_A);
2879
    INSN(rte,       4e73, ffff, CF_ISA_A);
2880
    INSN(rts,       4e75, ffff, CF_ISA_A);
2881
    INSN(movec,     4e7b, ffff, CF_ISA_A);
2882
    INSN(jump,      4e80, ffc0, CF_ISA_A);
2883
    INSN(jump,      4ec0, ffc0, CF_ISA_A);
2884
    INSN(addsubq,   5180, f1c0, CF_ISA_A);
2885
    INSN(scc,       50c0, f0f8, CF_ISA_A);
2886
    INSN(addsubq,   5080, f1c0, CF_ISA_A);
2887
    INSN(tpf,       51f8, fff8, CF_ISA_A);
2888

    
2889
    /* Branch instructions.  */
2890
    INSN(branch,    6000, f000, CF_ISA_A);
2891
    /* Disable long branch instructions, then add back the ones we want.  */
2892
    INSN(undef,     60ff, f0ff, CF_ISA_A); /* All long branches.  */
2893
    INSN(branch,    60ff, f0ff, CF_ISA_B);
2894
    INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
2895
    INSN(branch,    60ff, ffff, BRAL);
2896

    
2897
    INSN(moveq,     7000, f100, CF_ISA_A);
2898
    INSN(mvzs,      7100, f100, CF_ISA_B);
2899
    INSN(or,        8000, f000, CF_ISA_A);
2900
    INSN(divw,      80c0, f0c0, CF_ISA_A);
2901
    INSN(addsub,    9000, f000, CF_ISA_A);
2902
    INSN(subx,      9180, f1f8, CF_ISA_A);
2903
    INSN(suba,      91c0, f1c0, CF_ISA_A);
2904

    
2905
    INSN(undef_mac, a000, f000, CF_ISA_A);
2906
    INSN(mac,       a000, f100, CF_EMAC);
2907
    INSN(from_mac,  a180, f9b0, CF_EMAC);
2908
    INSN(move_mac,  a110, f9fc, CF_EMAC);
2909
    INSN(from_macsr,a980, f9f0, CF_EMAC);
2910
    INSN(from_mask, ad80, fff0, CF_EMAC);
2911
    INSN(from_mext, ab80, fbf0, CF_EMAC);
2912
    INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC);
2913
    INSN(to_mac,    a100, f9c0, CF_EMAC);
2914
    INSN(to_macsr,  a900, ffc0, CF_EMAC);
2915
    INSN(to_mext,   ab00, fbc0, CF_EMAC);
2916
    INSN(to_mask,   ad00, ffc0, CF_EMAC);
2917

    
2918
    INSN(mov3q,     a140, f1c0, CF_ISA_B);
2919
    INSN(cmp,       b000, f1c0, CF_ISA_B); /* cmp.b */
2920
    INSN(cmp,       b040, f1c0, CF_ISA_B); /* cmp.w */
2921
    INSN(cmpa,      b0c0, f1c0, CF_ISA_B); /* cmpa.w */
2922
    INSN(cmp,       b080, f1c0, CF_ISA_A);
2923
    INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
2924
    INSN(eor,       b180, f1c0, CF_ISA_A);
2925
    INSN(and,       c000, f000, CF_ISA_A);
2926
    INSN(mulw,      c0c0, f0c0, CF_ISA_A);
2927
    INSN(addsub,    d000, f000, CF_ISA_A);
2928
    INSN(addx,      d180, f1f8, CF_ISA_A);
2929
    INSN(adda,      d1c0, f1c0, CF_ISA_A);
2930
    INSN(shift_im,  e080, f0f0, CF_ISA_A);
2931
    INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
2932
    INSN(undef_fpu, f000, f000, CF_ISA_A);
2933
    INSN(fpu,       f200, ffc0, CF_FPU);
2934
    INSN(fbcc,      f280, ffc0, CF_FPU);
2935
    INSN(frestore,  f340, ffc0, CF_FPU);
2936
    INSN(fsave,     f340, ffc0, CF_FPU);
2937
    INSN(intouch,   f340, ffc0, CF_ISA_A);
2938
    INSN(cpushl,    f428, ff38, CF_ISA_A);
2939
    INSN(wddata,    fb00, ff00, CF_ISA_A);
2940
    INSN(wdebug,    fbc0, ffc0, CF_ISA_A);
2941
#undef INSN
2942
}
2943

    
2944
/* ??? Some of this implementation is not exception safe.  We should always
2945
   write back the result to memory before setting the condition codes.  */
2946
static void disas_m68k_insn(CPUState * env, DisasContext *s)
2947
{
2948
    uint16_t insn;
2949

    
2950
    insn = lduw_code(s->pc);
2951
    s->pc += 2;
2952

    
2953
    opcode_table[insn](s, insn);
2954
}
2955

    
2956
/* generate intermediate code for basic block 'tb'.  */
2957
static inline void
2958
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2959
                               int search_pc)
2960
{
2961
    DisasContext dc1, *dc = &dc1;
2962
    uint16_t *gen_opc_end;
2963
    CPUBreakpoint *bp;
2964
    int j, lj;
2965
    target_ulong pc_start;
2966
    int pc_offset;
2967
    int num_insns;
2968
    int max_insns;
2969

    
2970
    /* generate intermediate code */
2971
    pc_start = tb->pc;
2972

    
2973
    dc->tb = tb;
2974

    
2975
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2976

    
2977
    dc->env = env;
2978
    dc->is_jmp = DISAS_NEXT;
2979
    dc->pc = pc_start;
2980
    dc->cc_op = CC_OP_DYNAMIC;
2981
    dc->singlestep_enabled = env->singlestep_enabled;
2982
    dc->fpcr = env->fpcr;
2983
    dc->user = (env->sr & SR_S) == 0;
2984
    dc->is_mem = 0;
2985
    dc->done_mac = 0;
2986
    lj = -1;
2987
    num_insns = 0;
2988
    max_insns = tb->cflags & CF_COUNT_MASK;
2989
    if (max_insns == 0)
2990
        max_insns = CF_COUNT_MASK;
2991

    
2992
    gen_icount_start();
2993
    do {
2994
        pc_offset = dc->pc - pc_start;
2995
        gen_throws_exception = NULL;
2996
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
2997
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
2998
                if (bp->pc == dc->pc) {
2999
                    gen_exception(dc, dc->pc, EXCP_DEBUG);
3000
                    dc->is_jmp = DISAS_JUMP;
3001
                    break;
3002
                }
3003
            }
3004
            if (dc->is_jmp)
3005
                break;
3006
        }
3007
        if (search_pc) {
3008
            j = gen_opc_ptr - gen_opc_buf;
3009
            if (lj < j) {
3010
                lj++;
3011
                while (lj < j)
3012
                    gen_opc_instr_start[lj++] = 0;
3013
            }
3014
            gen_opc_pc[lj] = dc->pc;
3015
            gen_opc_instr_start[lj] = 1;
3016
            gen_opc_icount[lj] = num_insns;
3017
        }
3018
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3019
            gen_io_start();
3020
        dc->insn_pc = dc->pc;
3021
        disas_m68k_insn(env, dc);
3022
        num_insns++;
3023
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3024
             !env->singlestep_enabled &&
3025
             !singlestep &&
3026
             (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
3027
             num_insns < max_insns);
3028

    
3029
    if (tb->cflags & CF_LAST_IO)
3030
        gen_io_end();
3031
    if (unlikely(env->singlestep_enabled)) {
3032
        /* Make sure the pc is updated, and raise a debug exception.  */
3033
        if (!dc->is_jmp) {
3034
            gen_flush_cc_op(dc);
3035
            tcg_gen_movi_i32(QREG_PC, dc->pc);
3036
        }
3037
        gen_helper_raise_exception(tcg_const_i32(EXCP_DEBUG));
3038
    } else {
3039
        switch(dc->is_jmp) {
3040
        case DISAS_NEXT:
3041
            gen_flush_cc_op(dc);
3042
            gen_jmp_tb(dc, 0, dc->pc);
3043
            break;
3044
        default:
3045
        case DISAS_JUMP:
3046
        case DISAS_UPDATE:
3047
            gen_flush_cc_op(dc);
3048
            /* indicate that the hash table must be used to find the next TB */
3049
            tcg_gen_exit_tb(0);
3050
            break;
3051
        case DISAS_TB_JUMP:
3052
            /* nothing more to generate */
3053
            break;
3054
        }
3055
    }
3056
    gen_icount_end(tb, num_insns);
3057
    *gen_opc_ptr = INDEX_op_end;
3058

    
3059
#ifdef DEBUG_DISAS
3060
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
3061
        qemu_log("----------------\n");
3062
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
3063
        log_target_disas(pc_start, dc->pc - pc_start, 0);
3064
        qemu_log("\n");
3065
    }
3066
#endif
3067
    if (search_pc) {
3068
        j = gen_opc_ptr - gen_opc_buf;
3069
        lj++;
3070
        while (lj <= j)
3071
            gen_opc_instr_start[lj++] = 0;
3072
    } else {
3073
        tb->size = dc->pc - pc_start;
3074
        tb->icount = num_insns;
3075
    }
3076

    
3077
    //optimize_flags();
3078
    //expand_target_qops();
3079
}
3080

    
3081
void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
3082
{
3083
    gen_intermediate_code_internal(env, tb, 0);
3084
}
3085

    
3086
void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
3087
{
3088
    gen_intermediate_code_internal(env, tb, 1);
3089
}
3090

    
3091
void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
3092
                    int flags)
3093
{
3094
    int i;
3095
    uint16_t sr;
3096
    CPU_DoubleU u;
3097
    for (i = 0; i < 8; i++)
3098
      {
3099
        u.d = env->fregs[i];
3100
        cpu_fprintf (f, "D%d = %08x   A%d = %08x   F%d = %08x%08x (%12g)\n",
3101
                     i, env->dregs[i], i, env->aregs[i],
3102
                     i, u.l.upper, u.l.lower, *(double *)&u.d);
3103
      }
3104
    cpu_fprintf (f, "PC = %08x   ", env->pc);
3105
    sr = env->sr;
3106
    cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
3107
                 (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
3108
                 (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
3109
    cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
3110
}
3111

    
3112
void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
3113
{
3114
    env->pc = gen_opc_pc[pc_pos];
3115
}