translate.c 62 KB
Newer Older
bellard's avatar
bellard committed
1
2
/*
 *  SH4 translation
3
 *
bellard's avatar
bellard committed
4
5
6
7
8
9
10
11
12
13
14
15
16
 *  Copyright (c) 2005 Samuel Tardieu
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard's avatar
bellard committed
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 */
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#define DEBUG_DISAS
#define SH4_DEBUG_DISAS
//#define SH4_SINGLE_STEP

#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
bellard's avatar
bellard committed
32
#include "tcg-op.h"
33
#include "qemu-common.h"
bellard's avatar
bellard committed
34

pbrook's avatar
pbrook committed
35
36
37
38
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

bellard's avatar
bellard committed
39
40
41
42
typedef struct DisasContext {
    struct TranslationBlock *tb;
    target_ulong pc;
    uint32_t sr;
bellard's avatar
bellard committed
43
    uint32_t fpscr;
bellard's avatar
bellard committed
44
45
    uint16_t opcode;
    uint32_t flags;
46
    int bstate;
bellard's avatar
bellard committed
47
48
49
    int memidx;
    uint32_t delayed_pc;
    int singlestep_enabled;
aurel32's avatar
aurel32 committed
50
    uint32_t features;
51
    int has_movcal;
bellard's avatar
bellard committed
52
53
} DisasContext;

54
55
56
57
58
59
#if defined(CONFIG_USER_ONLY)
#define IS_USER(ctx) 1
#else
#define IS_USER(ctx) (!(ctx->sr & SR_MD))
#endif

60
61
62
63
64
65
66
67
68
enum {
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
                      * exception condition
                      */
    BS_STOP     = 1, /* We want to stop translation for any reason */
    BS_BRANCH   = 2, /* We reached a branch condition     */
    BS_EXCP     = 3, /* We reached an exception condition */
};

aurel32's avatar
aurel32 committed
69
/* global register indexes */
pbrook's avatar
pbrook committed
70
static TCGv_ptr cpu_env;
aurel32's avatar
aurel32 committed
71
static TCGv cpu_gregs[24];
72
73
static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr;
static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
aurel32's avatar
aurel32 committed
74
static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_ldst;
75
static TCGv cpu_fregs[32];
76
77
78

/* internal register indexes */
static TCGv cpu_flags, cpu_delayed_pc;
aurel32's avatar
aurel32 committed
79

80
81
static uint32_t gen_opc_hflags[OPC_BUF_SIZE];

pbrook's avatar
pbrook committed
82
83
#include "gen-icount.h"

84
static void sh4_translate_init(void)
pbrook's avatar
pbrook committed
85
{
aurel32's avatar
aurel32 committed
86
    int i;
pbrook's avatar
pbrook committed
87
    static int done_init = 0;
88
    static const char * const gregnames[24] = {
aurel32's avatar
aurel32 committed
89
90
91
92
93
94
        "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
        "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
        "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
        "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
        "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
    };
95
96
97
98
99
100
101
102
103
104
    static const char * const fregnames[32] = {
         "FPR0_BANK0",  "FPR1_BANK0",  "FPR2_BANK0",  "FPR3_BANK0",
         "FPR4_BANK0",  "FPR5_BANK0",  "FPR6_BANK0",  "FPR7_BANK0",
         "FPR8_BANK0",  "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0",
        "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0",
         "FPR0_BANK1",  "FPR1_BANK1",  "FPR2_BANK1",  "FPR3_BANK1",
         "FPR4_BANK1",  "FPR5_BANK1",  "FPR6_BANK1",  "FPR7_BANK1",
         "FPR8_BANK1",  "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1",
        "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1",
    };
aurel32's avatar
aurel32 committed
105

pbrook's avatar
pbrook committed
106
107
    if (done_init)
        return;
aurel32's avatar
aurel32 committed
108

pbrook's avatar
pbrook committed
109
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
aurel32's avatar
aurel32 committed
110
111

    for (i = 0; i < 24; i++)
pbrook's avatar
pbrook committed
112
        cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
113
114
                                              offsetof(CPUState, gregs[i]),
                                              gregnames[i]);
aurel32's avatar
aurel32 committed
115

pbrook's avatar
pbrook committed
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
                                    offsetof(CPUState, pc), "PC");
    cpu_sr = tcg_global_mem_new_i32(TCG_AREG0,
                                    offsetof(CPUState, sr), "SR");
    cpu_ssr = tcg_global_mem_new_i32(TCG_AREG0,
                                     offsetof(CPUState, ssr), "SSR");
    cpu_spc = tcg_global_mem_new_i32(TCG_AREG0,
                                     offsetof(CPUState, spc), "SPC");
    cpu_gbr = tcg_global_mem_new_i32(TCG_AREG0,
                                     offsetof(CPUState, gbr), "GBR");
    cpu_vbr = tcg_global_mem_new_i32(TCG_AREG0,
                                     offsetof(CPUState, vbr), "VBR");
    cpu_sgr = tcg_global_mem_new_i32(TCG_AREG0,
                                     offsetof(CPUState, sgr), "SGR");
    cpu_dbr = tcg_global_mem_new_i32(TCG_AREG0,
                                     offsetof(CPUState, dbr), "DBR");
    cpu_mach = tcg_global_mem_new_i32(TCG_AREG0,
                                      offsetof(CPUState, mach), "MACH");
    cpu_macl = tcg_global_mem_new_i32(TCG_AREG0,
                                      offsetof(CPUState, macl), "MACL");
    cpu_pr = tcg_global_mem_new_i32(TCG_AREG0,
                                    offsetof(CPUState, pr), "PR");
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                       offsetof(CPUState, fpscr), "FPSCR");
    cpu_fpul = tcg_global_mem_new_i32(TCG_AREG0,
                                      offsetof(CPUState, fpul), "FPUL");

    cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
				       offsetof(CPUState, flags), "_flags_");
    cpu_delayed_pc = tcg_global_mem_new_i32(TCG_AREG0,
					    offsetof(CPUState, delayed_pc),
					    "_delayed_pc_");
aurel32's avatar
aurel32 committed
148
149
    cpu_ldst = tcg_global_mem_new_i32(TCG_AREG0,
				      offsetof(CPUState, ldst), "_ldst_");
150

151
152
153
154
155
    for (i = 0; i < 32; i++)
        cpu_fregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                              offsetof(CPUState, fregs[i]),
                                              fregnames[i]);

aurel32's avatar
aurel32 committed
156
    /* register helpers */
pbrook's avatar
pbrook committed
157
#define GEN_HELPER 2
aurel32's avatar
aurel32 committed
158
159
#include "helper.h"

pbrook's avatar
pbrook committed
160
161
162
    done_init = 1;
}

bellard's avatar
bellard committed
163
164
165
166
167
void cpu_dump_state(CPUState * env, FILE * f,
		    int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
		    int flags)
{
    int i;
bellard's avatar
bellard committed
168
169
    cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
		env->pc, env->sr, env->pr, env->fpscr);
aurel32's avatar
aurel32 committed
170
171
172
173
    cpu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
		env->spc, env->ssr, env->gbr, env->vbr);
    cpu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
		env->sgr, env->dbr, env->delayed_pc, env->fpul);
bellard's avatar
bellard committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    for (i = 0; i < 24; i += 4) {
	cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
		    i, env->gregs[i], i + 1, env->gregs[i + 1],
		    i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
    }
    if (env->flags & DELAY_SLOT) {
	cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
		    env->delayed_pc);
    } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
	cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
		    env->delayed_pc);
    }
}

Aurelien Jarno's avatar
Aurelien Jarno committed
188
void cpu_reset(CPUSH4State * env)
bellard's avatar
bellard committed
189
{
aliguori's avatar
aliguori committed
190
191
192
193
194
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
        log_cpu_state(env, 0);
    }

Aurelien Jarno's avatar
Aurelien Jarno committed
195
196
197
    memset(env, 0, offsetof(CPUSH4State, breakpoints));
    tlb_flush(env, 1);

bellard's avatar
bellard committed
198
    env->pc = 0xA0000000;
199
200
#if defined(CONFIG_USER_ONLY)
    env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
bellard's avatar
bellard committed
201
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
202
#else
Aurelien Jarno's avatar
Aurelien Jarno committed
203
    env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
204
    env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
bellard's avatar
bellard committed
205
    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
206
    set_flush_to_zero(1, &env->fp_status);
207
#endif
208
    set_default_nan_mode(1, &env->fp_status);
bellard's avatar
bellard committed
209
210
}

aurel32's avatar
aurel32 committed
211
typedef struct {
212
    const char *name;
aurel32's avatar
aurel32 committed
213
214
215
216
    int id;
    uint32_t pvr;
    uint32_t prr;
    uint32_t cvr;
aurel32's avatar
aurel32 committed
217
    uint32_t features;
aurel32's avatar
aurel32 committed
218
219
220
221
222
223
224
225
226
} sh4_def_t;

static sh4_def_t sh4_defs[] = {
    {
	.name = "SH7750R",
	.id = SH_CPU_SH7750R,
	.pvr = 0x00050000,
	.prr = 0x00000100,
	.cvr = 0x00110000,
227
	.features = SH_FEATURE_BCR3_AND_BCR4,
aurel32's avatar
aurel32 committed
228
229
230
231
232
233
    }, {
	.name = "SH7751R",
	.id = SH_CPU_SH7751R,
	.pvr = 0x04050005,
	.prr = 0x00000113,
	.cvr = 0x00110000,	/* Neutered caches, should be 0x20480000 */
234
	.features = SH_FEATURE_BCR3_AND_BCR4,
aurel32's avatar
aurel32 committed
235
236
237
238
239
240
    }, {
	.name = "SH7785",
	.id = SH_CPU_SH7785,
	.pvr = 0x10300700,
	.prr = 0x00000200,
	.cvr = 0x71440211,
aurel32's avatar
aurel32 committed
241
	.features = SH_FEATURE_SH4A,
aurel32's avatar
aurel32 committed
242
     },
aurel32's avatar
aurel32 committed
243
244
};

245
static const sh4_def_t *cpu_sh4_find_by_name(const char *name)
aurel32's avatar
aurel32 committed
246
247
248
249
250
251
{
    int i;

    if (strcasecmp(name, "any") == 0)
	return &sh4_defs[0];

252
    for (i = 0; i < ARRAY_SIZE(sh4_defs); i++)
aurel32's avatar
aurel32 committed
253
254
255
256
257
258
	if (strcasecmp(name, sh4_defs[i].name) == 0)
	    return &sh4_defs[i];

    return NULL;
}

259
void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf)
aurel32's avatar
aurel32 committed
260
261
262
{
    int i;

263
    for (i = 0; i < ARRAY_SIZE(sh4_defs); i++)
aurel32's avatar
aurel32 committed
264
265
266
	(*cpu_fprintf)(f, "%s\n", sh4_defs[i].name);
}

Aurelien Jarno's avatar
Aurelien Jarno committed
267
static void cpu_register(CPUSH4State *env, const sh4_def_t *def)
aurel32's avatar
aurel32 committed
268
269
270
271
272
273
274
{
    env->pvr = def->pvr;
    env->prr = def->prr;
    env->cvr = def->cvr;
    env->id = def->id;
}

275
CPUSH4State *cpu_sh4_init(const char *cpu_model)
bellard's avatar
bellard committed
276
277
{
    CPUSH4State *env;
aurel32's avatar
aurel32 committed
278
    const sh4_def_t *def;
bellard's avatar
bellard committed
279

aurel32's avatar
aurel32 committed
280
281
282
    def = cpu_sh4_find_by_name(cpu_model);
    if (!def)
	return NULL;
bellard's avatar
bellard committed
283
    env = qemu_mallocz(sizeof(CPUSH4State));
aurel32's avatar
aurel32 committed
284
    env->features = def->features;
bellard's avatar
bellard committed
285
    cpu_exec_init(env);
286
    env->movcal_backup_tail = &(env->movcal_backup);
pbrook's avatar
pbrook committed
287
    sh4_translate_init();
aurel32's avatar
aurel32 committed
288
    env->cpu_model_str = cpu_model;
Aurelien Jarno's avatar
Aurelien Jarno committed
289
290
    cpu_reset(env);
    cpu_register(env, def);
291
    qemu_init_vcpu(env);
bellard's avatar
bellard committed
292
293
294
295
296
297
298
299
300
301
302
    return env;
}

static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
{
    TranslationBlock *tb;
    tb = ctx->tb;

    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
	!ctx->singlestep_enabled) {
	/* Use a direct jump if in same page and singlestep not enabled */
bellard's avatar
bellard committed
303
        tcg_gen_goto_tb(n);
304
        tcg_gen_movi_i32(cpu_pc, dest);
bellard's avatar
bellard committed
305
        tcg_gen_exit_tb((long) tb + n);
bellard's avatar
bellard committed
306
    } else {
307
        tcg_gen_movi_i32(cpu_pc, dest);
bellard's avatar
bellard committed
308
        if (ctx->singlestep_enabled)
pbrook's avatar
pbrook committed
309
            gen_helper_debug();
bellard's avatar
bellard committed
310
        tcg_gen_exit_tb(0);
bellard's avatar
bellard committed
311
312
313
314
315
316
317
318
    }
}

static void gen_jump(DisasContext * ctx)
{
    if (ctx->delayed_pc == (uint32_t) - 1) {
	/* Target is not statically known, it comes necessarily from a
	   delayed jump as immediate jump are conditinal jumps */
319
	tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
bellard's avatar
bellard committed
320
	if (ctx->singlestep_enabled)
pbrook's avatar
pbrook committed
321
	    gen_helper_debug();
bellard's avatar
bellard committed
322
	tcg_gen_exit_tb(0);
bellard's avatar
bellard committed
323
324
325
326
327
    } else {
	gen_goto_tb(ctx, 0, ctx->delayed_pc);
    }
}

328
329
static inline void gen_branch_slot(uint32_t delayed_pc, int t)
{
330
    TCGv sr;
331
332
    int label = gen_new_label();
    tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
pbrook's avatar
pbrook committed
333
    sr = tcg_temp_new();
334
    tcg_gen_andi_i32(sr, cpu_sr, SR_T);
335
    tcg_gen_brcondi_i32(t ? TCG_COND_EQ:TCG_COND_NE, sr, 0, label);
336
337
338
339
    tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
    gen_set_label(label);
}

bellard's avatar
bellard committed
340
341
342
343
344
/* Immediate conditional jump (bt or bf) */
static void gen_conditional_jump(DisasContext * ctx,
				 target_ulong ift, target_ulong ifnott)
{
    int l1;
345
    TCGv sr;
bellard's avatar
bellard committed
346
347

    l1 = gen_new_label();
pbrook's avatar
pbrook committed
348
    sr = tcg_temp_new();
349
    tcg_gen_andi_i32(sr, cpu_sr, SR_T);
350
    tcg_gen_brcondi_i32(TCG_COND_NE, sr, 0, l1);
bellard's avatar
bellard committed
351
352
353
354
355
356
357
358
359
    gen_goto_tb(ctx, 0, ifnott);
    gen_set_label(l1);
    gen_goto_tb(ctx, 1, ift);
}

/* Delayed conditional jump (bt or bf) */
static void gen_delayed_conditional_jump(DisasContext * ctx)
{
    int l1;
360
    TCGv ds;
bellard's avatar
bellard committed
361
362

    l1 = gen_new_label();
pbrook's avatar
pbrook committed
363
    ds = tcg_temp_new();
364
    tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
365
    tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
366
    gen_goto_tb(ctx, 1, ctx->pc + 2);
bellard's avatar
bellard committed
367
    gen_set_label(l1);
368
    tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
pbrook's avatar
pbrook committed
369
    gen_jump(ctx);
bellard's avatar
bellard committed
370
371
}

372
373
374
375
376
377
378
379
380
381
382
383
static inline void gen_set_t(void)
{
    tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
}

static inline void gen_clr_t(void)
{
    tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
}

static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
{
384
385
386
387
388
389
390
391
    TCGv t;

    t = tcg_temp_new();
    tcg_gen_setcond_i32(cond, t, t1, t0);
    tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
    tcg_gen_or_i32(cpu_sr, cpu_sr, t);

    tcg_temp_free(t);
392
393
394
395
}

static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
{
396
397
398
399
400
401
402
403
    TCGv t;

    t = tcg_temp_new();
    tcg_gen_setcondi_i32(cond, t, t0, imm);
    tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
    tcg_gen_or_i32(cpu_sr, cpu_sr, t);

    tcg_temp_free(t);
404
405
}

406
407
408
409
410
411
static inline void gen_store_flags(uint32_t flags)
{
    tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
    tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
}

412
413
static inline void gen_copy_bit_i32(TCGv t0, int p0, TCGv t1, int p1)
{
pbrook's avatar
pbrook committed
414
    TCGv tmp = tcg_temp_new();
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

    p0 &= 0x1f;
    p1 &= 0x1f;

    tcg_gen_andi_i32(tmp, t1, (1 << p1));
    tcg_gen_andi_i32(t0, t0, ~(1 << p0));
    if (p0 < p1)
        tcg_gen_shri_i32(tmp, tmp, p1 - p0);
    else if (p0 > p1)
        tcg_gen_shli_i32(tmp, tmp, p0 - p1);
    tcg_gen_or_i32(t0, t0, tmp);

    tcg_temp_free(tmp);
}

pbrook's avatar
pbrook committed
430
static inline void gen_load_fpr64(TCGv_i64 t, int reg)
431
{
432
    tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
433
434
}

pbrook's avatar
pbrook committed
435
static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
436
{
pbrook's avatar
pbrook committed
437
    TCGv_i32 tmp = tcg_temp_new_i32();
438
    tcg_gen_trunc_i64_i32(tmp, t);
439
    tcg_gen_mov_i32(cpu_fregs[reg + 1], tmp);
440
441
    tcg_gen_shri_i64(t, t, 32);
    tcg_gen_trunc_i64_i32(tmp, t);
442
    tcg_gen_mov_i32(cpu_fregs[reg], tmp);
pbrook's avatar
pbrook committed
443
    tcg_temp_free_i32(tmp);
444
445
}

bellard's avatar
bellard committed
446
447
448
449
450
451
452
453
454
455
456
#define B3_0 (ctx->opcode & 0xf)
#define B6_4 ((ctx->opcode >> 4) & 0x7)
#define B7_4 ((ctx->opcode >> 4) & 0xf)
#define B7_0 (ctx->opcode & 0xff)
#define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
#define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
  (ctx->opcode & 0xfff))
#define B11_8 ((ctx->opcode >> 8) & 0xf)
#define B15_12 ((ctx->opcode >> 12) & 0xf)

#define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
aurel32's avatar
aurel32 committed
457
		(cpu_gregs[x + 16]) : (cpu_gregs[x]))
bellard's avatar
bellard committed
458
459

#define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
aurel32's avatar
aurel32 committed
460
		? (cpu_gregs[x + 16]) : (cpu_gregs[x]))
bellard's avatar
bellard committed
461

bellard's avatar
bellard committed
462
#define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
463
#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
bellard's avatar
bellard committed
464
#define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
465
#define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
bellard's avatar
bellard committed
466

bellard's avatar
bellard committed
467
#define CHECK_NOT_DELAY_SLOT \
aurel32's avatar
aurel32 committed
468
469
470
471
472
473
  if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))     \
  {                                                           \
      gen_helper_raise_slot_illegal_instruction();            \
      ctx->bstate = BS_EXCP;                                  \
      return;                                                 \
  }
bellard's avatar
bellard committed
474

475
476
477
478
479
480
481
482
483
#define CHECK_PRIVILEGED                                        \
  if (IS_USER(ctx)) {                                           \
      if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
         gen_helper_raise_slot_illegal_instruction();           \
      } else {                                                  \
         gen_helper_raise_illegal_instruction();                \
      }                                                         \
      ctx->bstate = BS_EXCP;                                    \
      return;                                                   \
484
485
  }

aurel32's avatar
aurel32 committed
486
487
488
489
490
491
492
493
494
495
496
#define CHECK_FPU_ENABLED                                       \
  if (ctx->flags & SR_FD) {                                     \
      if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
          gen_helper_raise_slot_fpu_disable();                  \
      } else {                                                  \
          gen_helper_raise_fpu_disable();                       \
      }                                                         \
      ctx->bstate = BS_EXCP;                                    \
      return;                                                   \
  }

497
static void _decode_opc(DisasContext * ctx)
bellard's avatar
bellard committed
498
{
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
    /* This code tries to make movcal emulation sufficiently
       accurate for Linux purposes.  This instruction writes
       memory, and prior to that, always allocates a cache line.
       It is used in two contexts:
       - in memcpy, where data is copied in blocks, the first write
       of to a block uses movca.l for performance.
       - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
       to flush the cache. Here, the data written by movcal.l is never
       written to memory, and the data written is just bogus.

       To simulate this, we simulate movcal.l, we store the value to memory,
       but we also remember the previous content. If we see ocbi, we check
       if movcal.l for that address was done previously. If so, the write should
       not have hit the memory, so we restore the previous content.
       When we see an instruction that is neither movca.l
       nor ocbi, the previous content is discarded.

       To optimize, we only try to flush stores when we're at the start of
       TB, or if we already saw movca.l in this TB and did not flush stores
       yet.  */
    if (ctx->has_movcal)
	{
	  int opcode = ctx->opcode & 0xf0ff;
	  if (opcode != 0x0093 /* ocbi */
	      && opcode != 0x00c3 /* movca.l */)
	      {
		  gen_helper_discard_movcal_backup ();
		  ctx->has_movcal = 0;
	      }
	}

bellard's avatar
bellard committed
530
531
532
#if 0
    fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
#endif
533

bellard's avatar
bellard committed
534
535
    switch (ctx->opcode) {
    case 0x0019:		/* div0u */
536
	tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T));
bellard's avatar
bellard committed
537
538
	return;
    case 0x000b:		/* rts */
539
540
	CHECK_NOT_DELAY_SLOT
	tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
bellard's avatar
bellard committed
541
542
543
544
	ctx->flags |= DELAY_SLOT;
	ctx->delayed_pc = (uint32_t) - 1;
	return;
    case 0x0028:		/* clrmac */
545
546
	tcg_gen_movi_i32(cpu_mach, 0);
	tcg_gen_movi_i32(cpu_macl, 0);
bellard's avatar
bellard committed
547
548
	return;
    case 0x0048:		/* clrs */
549
	tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_S);
bellard's avatar
bellard committed
550
551
	return;
    case 0x0008:		/* clrt */
552
	gen_clr_t();
bellard's avatar
bellard committed
553
554
	return;
    case 0x0038:		/* ldtlb */
555
	CHECK_PRIVILEGED
pbrook's avatar
pbrook committed
556
	gen_helper_ldtlb();
bellard's avatar
bellard committed
557
	return;
ths's avatar
ths committed
558
    case 0x002b:		/* rte */
559
	CHECK_PRIVILEGED
560
561
562
	CHECK_NOT_DELAY_SLOT
	tcg_gen_mov_i32(cpu_sr, cpu_ssr);
	tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
bellard's avatar
bellard committed
563
564
565
566
	ctx->flags |= DELAY_SLOT;
	ctx->delayed_pc = (uint32_t) - 1;
	return;
    case 0x0058:		/* sets */
567
	tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_S);
bellard's avatar
bellard committed
568
569
	return;
    case 0x0018:		/* sett */
570
	gen_set_t();
bellard's avatar
bellard committed
571
	return;
aurel32's avatar
aurel32 committed
572
    case 0xfbfd:		/* frchg */
573
	tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
574
	ctx->bstate = BS_STOP;
bellard's avatar
bellard committed
575
	return;
aurel32's avatar
aurel32 committed
576
    case 0xf3fd:		/* fschg */
577
	tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
578
	ctx->bstate = BS_STOP;
bellard's avatar
bellard committed
579
580
581
582
	return;
    case 0x0009:		/* nop */
	return;
    case 0x001b:		/* sleep */
583
	CHECK_PRIVILEGED
pbrook's avatar
pbrook committed
584
	gen_helper_sleep(tcg_const_i32(ctx->pc + 2));
bellard's avatar
bellard committed
585
586
587
588
589
	return;
    }

    switch (ctx->opcode & 0xf000) {
    case 0x1000:		/* mov.l Rm,@(disp,Rn) */
590
	{
pbrook's avatar
pbrook committed
591
	    TCGv addr = tcg_temp_new();
592
593
594
595
	    tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
	    tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
596
597
	return;
    case 0x5000:		/* mov.l @(disp,Rm),Rn */
598
	{
pbrook's avatar
pbrook committed
599
	    TCGv addr = tcg_temp_new();
600
601
602
603
	    tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
	    tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
604
	return;
aurel32's avatar
aurel32 committed
605
    case 0xe000:		/* mov #imm,Rn */
aurel32's avatar
aurel32 committed
606
	tcg_gen_movi_i32(REG(B11_8), B7_0s);
bellard's avatar
bellard committed
607
608
	return;
    case 0x9000:		/* mov.w @(disp,PC),Rn */
609
610
611
612
613
	{
	    TCGv addr = tcg_const_i32(ctx->pc + 4 + B7_0 * 2);
	    tcg_gen_qemu_ld16s(REG(B11_8), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
614
615
	return;
    case 0xd000:		/* mov.l @(disp,PC),Rn */
616
617
618
619
620
	{
	    TCGv addr = tcg_const_i32((ctx->pc + 4 + B7_0 * 4) & ~3);
	    tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
621
	return;
aurel32's avatar
aurel32 committed
622
    case 0x7000:		/* add #imm,Rn */
aurel32's avatar
aurel32 committed
623
	tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
bellard's avatar
bellard committed
624
625
626
	return;
    case 0xa000:		/* bra disp */
	CHECK_NOT_DELAY_SLOT
627
628
	ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
	tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
bellard's avatar
bellard committed
629
630
631
632
	ctx->flags |= DELAY_SLOT;
	return;
    case 0xb000:		/* bsr disp */
	CHECK_NOT_DELAY_SLOT
633
634
635
	tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
	ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
	tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
bellard's avatar
bellard committed
636
637
638
639
640
641
	ctx->flags |= DELAY_SLOT;
	return;
    }

    switch (ctx->opcode & 0xf00f) {
    case 0x6003:		/* mov Rm,Rn */
aurel32's avatar
aurel32 committed
642
	tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
643
644
	return;
    case 0x2000:		/* mov.b Rm,@Rn */
aurel32's avatar
aurel32 committed
645
	tcg_gen_qemu_st8(REG(B7_4), REG(B11_8), ctx->memidx);
bellard's avatar
bellard committed
646
647
	return;
    case 0x2001:		/* mov.w Rm,@Rn */
aurel32's avatar
aurel32 committed
648
	tcg_gen_qemu_st16(REG(B7_4), REG(B11_8), ctx->memidx);
bellard's avatar
bellard committed
649
650
	return;
    case 0x2002:		/* mov.l Rm,@Rn */
aurel32's avatar
aurel32 committed
651
	tcg_gen_qemu_st32(REG(B7_4), REG(B11_8), ctx->memidx);
bellard's avatar
bellard committed
652
653
	return;
    case 0x6000:		/* mov.b @Rm,Rn */
aurel32's avatar
aurel32 committed
654
	tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
bellard's avatar
bellard committed
655
656
	return;
    case 0x6001:		/* mov.w @Rm,Rn */
aurel32's avatar
aurel32 committed
657
	tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
bellard's avatar
bellard committed
658
659
	return;
    case 0x6002:		/* mov.l @Rm,Rn */
aurel32's avatar
aurel32 committed
660
	tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
bellard's avatar
bellard committed
661
662
	return;
    case 0x2004:		/* mov.b Rm,@-Rn */
663
	{
pbrook's avatar
pbrook committed
664
	    TCGv addr = tcg_temp_new();
665
666
	    tcg_gen_subi_i32(addr, REG(B11_8), 1);
	    tcg_gen_qemu_st8(REG(B7_4), addr, ctx->memidx);	/* might cause re-execution */
667
	    tcg_gen_mov_i32(REG(B11_8), addr);			/* modify register status */
668
669
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
670
671
	return;
    case 0x2005:		/* mov.w Rm,@-Rn */
672
	{
pbrook's avatar
pbrook committed
673
	    TCGv addr = tcg_temp_new();
674
675
	    tcg_gen_subi_i32(addr, REG(B11_8), 2);
	    tcg_gen_qemu_st16(REG(B7_4), addr, ctx->memidx);
676
	    tcg_gen_mov_i32(REG(B11_8), addr);
677
678
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
679
680
	return;
    case 0x2006:		/* mov.l Rm,@-Rn */
681
	{
pbrook's avatar
pbrook committed
682
	    TCGv addr = tcg_temp_new();
683
684
	    tcg_gen_subi_i32(addr, REG(B11_8), 4);
	    tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
685
	    tcg_gen_mov_i32(REG(B11_8), addr);
686
	}
bellard's avatar
bellard committed
687
	return;
bellard's avatar
bellard committed
688
    case 0x6004:		/* mov.b @Rm+,Rn */
aurel32's avatar
aurel32 committed
689
	tcg_gen_qemu_ld8s(REG(B11_8), REG(B7_4), ctx->memidx);
aurel32's avatar
aurel32 committed
690
	if ( B11_8 != B7_4 )
aurel32's avatar
aurel32 committed
691
		tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
bellard's avatar
bellard committed
692
693
	return;
    case 0x6005:		/* mov.w @Rm+,Rn */
aurel32's avatar
aurel32 committed
694
	tcg_gen_qemu_ld16s(REG(B11_8), REG(B7_4), ctx->memidx);
aurel32's avatar
aurel32 committed
695
	if ( B11_8 != B7_4 )
aurel32's avatar
aurel32 committed
696
		tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
bellard's avatar
bellard committed
697
698
	return;
    case 0x6006:		/* mov.l @Rm+,Rn */
aurel32's avatar
aurel32 committed
699
	tcg_gen_qemu_ld32s(REG(B11_8), REG(B7_4), ctx->memidx);
aurel32's avatar
aurel32 committed
700
	if ( B11_8 != B7_4 )
aurel32's avatar
aurel32 committed
701
		tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
bellard's avatar
bellard committed
702
703
	return;
    case 0x0004:		/* mov.b Rm,@(R0,Rn) */
704
	{
pbrook's avatar
pbrook committed
705
	    TCGv addr = tcg_temp_new();
706
707
708
709
	    tcg_gen_add_i32(addr, REG(B11_8), REG(0));
	    tcg_gen_qemu_st8(REG(B7_4), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
710
711
	return;
    case 0x0005:		/* mov.w Rm,@(R0,Rn) */
712
	{
pbrook's avatar
pbrook committed
713
	    TCGv addr = tcg_temp_new();
714
715
716
717
	    tcg_gen_add_i32(addr, REG(B11_8), REG(0));
	    tcg_gen_qemu_st16(REG(B7_4), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
718
719
	return;
    case 0x0006:		/* mov.l Rm,@(R0,Rn) */
720
	{
pbrook's avatar
pbrook committed
721
	    TCGv addr = tcg_temp_new();
722
723
724
725
	    tcg_gen_add_i32(addr, REG(B11_8), REG(0));
	    tcg_gen_qemu_st32(REG(B7_4), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
726
727
	return;
    case 0x000c:		/* mov.b @(R0,Rm),Rn */
728
	{
pbrook's avatar
pbrook committed
729
	    TCGv addr = tcg_temp_new();
730
731
732
733
	    tcg_gen_add_i32(addr, REG(B7_4), REG(0));
	    tcg_gen_qemu_ld8s(REG(B11_8), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
734
735
	return;
    case 0x000d:		/* mov.w @(R0,Rm),Rn */
736
	{
pbrook's avatar
pbrook committed
737
	    TCGv addr = tcg_temp_new();
738
739
740
741
	    tcg_gen_add_i32(addr, REG(B7_4), REG(0));
	    tcg_gen_qemu_ld16s(REG(B11_8), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
742
743
	return;
    case 0x000e:		/* mov.l @(R0,Rm),Rn */
744
	{
pbrook's avatar
pbrook committed
745
	    TCGv addr = tcg_temp_new();
746
747
748
749
	    tcg_gen_add_i32(addr, REG(B7_4), REG(0));
	    tcg_gen_qemu_ld32s(REG(B11_8), addr, ctx->memidx);
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
750
751
	return;
    case 0x6008:		/* swap.b Rm,Rn */
752
	{
753
	    TCGv high, low;
pbrook's avatar
pbrook committed
754
	    high = tcg_temp_new();
755
	    tcg_gen_andi_i32(high, REG(B7_4), 0xffff0000);
pbrook's avatar
pbrook committed
756
	    low = tcg_temp_new();
757
758
	    tcg_gen_ext16u_i32(low, REG(B7_4));
	    tcg_gen_bswap16_i32(low, low);
759
760
761
762
	    tcg_gen_or_i32(REG(B11_8), high, low);
	    tcg_temp_free(low);
	    tcg_temp_free(high);
	}
bellard's avatar
bellard committed
763
764
	return;
    case 0x6009:		/* swap.w Rm,Rn */
765
766
	{
	    TCGv high, low;
pbrook's avatar
pbrook committed
767
	    high = tcg_temp_new();
768
	    tcg_gen_shli_i32(high, REG(B7_4), 16);
pbrook's avatar
pbrook committed
769
	    low = tcg_temp_new();
770
771
772
773
774
775
	    tcg_gen_shri_i32(low, REG(B7_4), 16);
	    tcg_gen_ext16u_i32(low, low);
	    tcg_gen_or_i32(REG(B11_8), high, low);
	    tcg_temp_free(low);
	    tcg_temp_free(high);
	}
bellard's avatar
bellard committed
776
777
	return;
    case 0x200d:		/* xtrct Rm,Rn */
778
779
	{
	    TCGv high, low;
pbrook's avatar
pbrook committed
780
	    high = tcg_temp_new();
781
	    tcg_gen_shli_i32(high, REG(B7_4), 16);
pbrook's avatar
pbrook committed
782
	    low = tcg_temp_new();
783
784
785
786
787
788
	    tcg_gen_shri_i32(low, REG(B11_8), 16);
	    tcg_gen_ext16u_i32(low, low);
	    tcg_gen_or_i32(REG(B11_8), high, low);
	    tcg_temp_free(low);
	    tcg_temp_free(high);
	}
bellard's avatar
bellard committed
789
790
	return;
    case 0x300c:		/* add Rm,Rn */
aurel32's avatar
aurel32 committed
791
	tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
792
793
	return;
    case 0x300e:		/* addc Rm,Rn */
pbrook's avatar
pbrook committed
794
	gen_helper_addc(REG(B11_8), REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
795
796
	return;
    case 0x300f:		/* addv Rm,Rn */
pbrook's avatar
pbrook committed
797
	gen_helper_addv(REG(B11_8), REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
798
799
	return;
    case 0x2009:		/* and Rm,Rn */
aurel32's avatar
aurel32 committed
800
	tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
801
802
	return;
    case 0x3000:		/* cmp/eq Rm,Rn */
aurel32's avatar
aurel32 committed
803
	gen_cmp(TCG_COND_EQ, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
804
805
	return;
    case 0x3003:		/* cmp/ge Rm,Rn */
aurel32's avatar
aurel32 committed
806
	gen_cmp(TCG_COND_GE, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
807
808
	return;
    case 0x3007:		/* cmp/gt Rm,Rn */
aurel32's avatar
aurel32 committed
809
	gen_cmp(TCG_COND_GT, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
810
811
	return;
    case 0x3006:		/* cmp/hi Rm,Rn */
aurel32's avatar
aurel32 committed
812
	gen_cmp(TCG_COND_GTU, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
813
814
	return;
    case 0x3002:		/* cmp/hs Rm,Rn */
aurel32's avatar
aurel32 committed
815
	gen_cmp(TCG_COND_GEU, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
816
817
	return;
    case 0x200c:		/* cmp/str Rm,Rn */
818
	{
819
820
821
	    TCGv cmp1 = tcg_temp_new();
	    TCGv cmp2 = tcg_temp_new();
	    tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
822
823
	    tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
	    tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
824
825
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
826
	    tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
827
828
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
829
	    tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
830
831
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
832
	    tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
833
834
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
835
836
	    tcg_temp_free(cmp2);
	    tcg_temp_free(cmp1);
837
	}
bellard's avatar
bellard committed
838
839
	return;
    case 0x2007:		/* div0s Rm,Rn */
840
841
842
	{
	    gen_copy_bit_i32(cpu_sr, 8, REG(B11_8), 31);	/* SR_Q */
	    gen_copy_bit_i32(cpu_sr, 9, REG(B7_4), 31);		/* SR_M */
pbrook's avatar
pbrook committed
843
	    TCGv val = tcg_temp_new();
844
845
846
847
	    tcg_gen_xor_i32(val, REG(B7_4), REG(B11_8));
	    gen_copy_bit_i32(cpu_sr, 0, val, 31);		/* SR_T */
	    tcg_temp_free(val);
	}
bellard's avatar
bellard committed
848
849
	return;
    case 0x3004:		/* div1 Rm,Rn */
pbrook's avatar
pbrook committed
850
	gen_helper_div1(REG(B11_8), REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
851
852
	return;
    case 0x300d:		/* dmuls.l Rm,Rn */
853
	{
pbrook's avatar
pbrook committed
854
855
	    TCGv_i64 tmp1 = tcg_temp_new_i64();
	    TCGv_i64 tmp2 = tcg_temp_new_i64();
856

aurel32's avatar
aurel32 committed
857
858
	    tcg_gen_ext_i32_i64(tmp1, REG(B7_4));
	    tcg_gen_ext_i32_i64(tmp2, REG(B11_8));
859
860
861
862
863
	    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
	    tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
	    tcg_gen_shri_i64(tmp1, tmp1, 32);
	    tcg_gen_trunc_i64_i32(cpu_mach, tmp1);

pbrook's avatar
pbrook committed
864
865
	    tcg_temp_free_i64(tmp2);
	    tcg_temp_free_i64(tmp1);
866
	}
bellard's avatar
bellard committed
867
868
	return;
    case 0x3005:		/* dmulu.l Rm,Rn */
869
	{
pbrook's avatar
pbrook committed
870
871
	    TCGv_i64 tmp1 = tcg_temp_new_i64();
	    TCGv_i64 tmp2 = tcg_temp_new_i64();
872

aurel32's avatar
aurel32 committed
873
874
	    tcg_gen_extu_i32_i64(tmp1, REG(B7_4));
	    tcg_gen_extu_i32_i64(tmp2, REG(B11_8));
875
876
877
878
879
	    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
	    tcg_gen_trunc_i64_i32(cpu_macl, tmp1);
	    tcg_gen_shri_i64(tmp1, tmp1, 32);
	    tcg_gen_trunc_i64_i32(cpu_mach, tmp1);

pbrook's avatar
pbrook committed
880
881
	    tcg_temp_free_i64(tmp2);
	    tcg_temp_free_i64(tmp1);
882
	}
bellard's avatar
bellard committed
883
884
	return;
    case 0x600e:		/* exts.b Rm,Rn */
aurel32's avatar
aurel32 committed
885
	tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
886
887
	return;
    case 0x600f:		/* exts.w Rm,Rn */
aurel32's avatar
aurel32 committed
888
	tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
889
890
	return;
    case 0x600c:		/* extu.b Rm,Rn */
aurel32's avatar
aurel32 committed
891
	tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
892
893
	return;
    case 0x600d:		/* extu.w Rm,Rn */
aurel32's avatar
aurel32 committed
894
	tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
895
	return;
aurel32's avatar
aurel32 committed
896
    case 0x000f:		/* mac.l @Rm+,@Rn+ */
897
898
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
899
	    arg0 = tcg_temp_new();
900
	    tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx);
pbrook's avatar
pbrook committed
901
	    arg1 = tcg_temp_new();
902
	    tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx);
pbrook's avatar
pbrook committed
903
	    gen_helper_macl(arg0, arg1);
904
905
906
907
908
	    tcg_temp_free(arg1);
	    tcg_temp_free(arg0);
	    tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
	    tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
	}
bellard's avatar
bellard committed
909
910
	return;
    case 0x400f:		/* mac.w @Rm+,@Rn+ */
911
912
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
913
	    arg0 = tcg_temp_new();
914
	    tcg_gen_qemu_ld32s(arg0, REG(B7_4), ctx->memidx);
pbrook's avatar
pbrook committed
915
	    arg1 = tcg_temp_new();
916
	    tcg_gen_qemu_ld32s(arg1, REG(B11_8), ctx->memidx);
pbrook's avatar
pbrook committed
917
	    gen_helper_macw(arg0, arg1);
918
919
920
921
922
	    tcg_temp_free(arg1);
	    tcg_temp_free(arg0);
	    tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
	    tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
	}
bellard's avatar
bellard committed
923
924
	return;
    case 0x0007:		/* mul.l Rm,Rn */
aurel32's avatar
aurel32 committed
925
	tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
926
927
	return;
    case 0x200f:		/* muls.w Rm,Rn */
928
929
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
930
	    arg0 = tcg_temp_new();
931
	    tcg_gen_ext16s_i32(arg0, REG(B7_4));
pbrook's avatar
pbrook committed
932
	    arg1 = tcg_temp_new();
933
934
935
936
937
	    tcg_gen_ext16s_i32(arg1, REG(B11_8));
	    tcg_gen_mul_i32(cpu_macl, arg0, arg1);
	    tcg_temp_free(arg1);
	    tcg_temp_free(arg0);
	}
bellard's avatar
bellard committed
938
939
	return;
    case 0x200e:		/* mulu.w Rm,Rn */
940
941
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
942
	    arg0 = tcg_temp_new();
943
	    tcg_gen_ext16u_i32(arg0, REG(B7_4));
pbrook's avatar
pbrook committed
944
	    arg1 = tcg_temp_new();
945
946
947
948
949
	    tcg_gen_ext16u_i32(arg1, REG(B11_8));
	    tcg_gen_mul_i32(cpu_macl, arg0, arg1);
	    tcg_temp_free(arg1);
	    tcg_temp_free(arg0);
	}
bellard's avatar
bellard committed
950
951
	return;
    case 0x600b:		/* neg Rm,Rn */
aurel32's avatar
aurel32 committed
952
	tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
953
954
	return;
    case 0x600a:		/* negc Rm,Rn */
955
956
957
958
959
960
961
962
        {
	    TCGv t0, t1;
            t0 = tcg_temp_new();
            tcg_gen_neg_i32(t0, REG(B7_4));
            t1 = tcg_temp_new();
            tcg_gen_andi_i32(t1, cpu_sr, SR_T);
            tcg_gen_sub_i32(REG(B11_8), t0, t1);
            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
Aurelien Jarno's avatar
Aurelien Jarno committed
963
            tcg_gen_setcondi_i32(TCG_COND_GTU, t1, t0, 0);
964
            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
Aurelien Jarno's avatar
Aurelien Jarno committed
965
            tcg_gen_setcond_i32(TCG_COND_GTU, t1, REG(B11_8), t0);
966
967
968
969
            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
            tcg_temp_free(t0);
            tcg_temp_free(t1);
        }
bellard's avatar
bellard committed
970
971
	return;
    case 0x6007:		/* not Rm,Rn */
aurel32's avatar
aurel32 committed
972
	tcg_gen_not_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
973
974
	return;
    case 0x200b:		/* or Rm,Rn */
aurel32's avatar
aurel32 committed
975
	tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
976
977
	return;
    case 0x400c:		/* shad Rm,Rn */
978
979
980
981
982
	{
	    int label1 = gen_new_label();
	    int label2 = gen_new_label();
	    int label3 = gen_new_label();
	    int label4 = gen_new_label();
983
	    TCGv shift;
aurel32's avatar
aurel32 committed
984
	    tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
985
	    /* Rm positive, shift to the left */
986
            shift = tcg_temp_new();
987
988
	    tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
	    tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
989
	    tcg_temp_free(shift);
990
991
992
	    tcg_gen_br(label4);
	    /* Rm negative, shift to the right */
	    gen_set_label(label1);
993
            shift = tcg_temp_new();
994
995
996
997
998
999
	    tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
	    tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
	    tcg_gen_not_i32(shift, REG(B7_4));
	    tcg_gen_andi_i32(shift, shift, 0x1f);
	    tcg_gen_addi_i32(shift, shift, 1);
	    tcg_gen_sar_i32(REG(B11_8), REG(B11_8), shift);