translate.c 63.9 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
 */

#define DEBUG_DISAS
//#define SH4_SINGLE_STEP

#include "cpu.h"
24
#include "disas/disas.h"
bellard's avatar
bellard committed
25
#include "tcg-op.h"
bellard's avatar
bellard committed
26

pbrook's avatar
pbrook committed
27 28 29 30
#include "helper.h"
#define GEN_HELPER 1
#include "helper.h"

bellard's avatar
bellard committed
31 32 33 34 35
typedef struct DisasContext {
    struct TranslationBlock *tb;
    target_ulong pc;
    uint16_t opcode;
    uint32_t flags;
36
    int bstate;
bellard's avatar
bellard committed
37 38 39
    int memidx;
    uint32_t delayed_pc;
    int singlestep_enabled;
aurel32's avatar
aurel32 committed
40
    uint32_t features;
41
    int has_movcal;
bellard's avatar
bellard committed
42 43
} DisasContext;

44 45 46
#if defined(CONFIG_USER_ONLY)
#define IS_USER(ctx) 1
#else
47
#define IS_USER(ctx) (!(ctx->flags & SR_MD))
48 49
#endif

50 51 52 53 54 55 56 57 58
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
59
/* global register indexes */
pbrook's avatar
pbrook committed
60
static TCGv_ptr cpu_env;
aurel32's avatar
aurel32 committed
61
static TCGv cpu_gregs[24];
62 63
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
64
static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_ldst;
65
static TCGv cpu_fregs[32];
66 67 68

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

70 71
static uint32_t gen_opc_hflags[OPC_BUF_SIZE];

72
#include "exec/gen-icount.h"
pbrook's avatar
pbrook committed
73

74
void sh4_translate_init(void)
pbrook's avatar
pbrook committed
75
{
aurel32's avatar
aurel32 committed
76
    int i;
pbrook's avatar
pbrook committed
77
    static int done_init = 0;
78
    static const char * const gregnames[24] = {
aurel32's avatar
aurel32 committed
79 80 81 82 83 84
        "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"
    };
85 86 87 88 89 90 91 92 93 94
    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
95

pbrook's avatar
pbrook committed
96 97
    if (done_init)
        return;
aurel32's avatar
aurel32 committed
98

pbrook's avatar
pbrook committed
99
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
aurel32's avatar
aurel32 committed
100 101

    for (i = 0; i < 24; i++)
pbrook's avatar
pbrook committed
102
        cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
103
                                              offsetof(CPUSH4State, gregs[i]),
104
                                              gregnames[i]);
aurel32's avatar
aurel32 committed
105

pbrook's avatar
pbrook committed
106
    cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
107
                                    offsetof(CPUSH4State, pc), "PC");
pbrook's avatar
pbrook committed
108
    cpu_sr = tcg_global_mem_new_i32(TCG_AREG0,
109
                                    offsetof(CPUSH4State, sr), "SR");
pbrook's avatar
pbrook committed
110
    cpu_ssr = tcg_global_mem_new_i32(TCG_AREG0,
111
                                     offsetof(CPUSH4State, ssr), "SSR");
pbrook's avatar
pbrook committed
112
    cpu_spc = tcg_global_mem_new_i32(TCG_AREG0,
113
                                     offsetof(CPUSH4State, spc), "SPC");
pbrook's avatar
pbrook committed
114
    cpu_gbr = tcg_global_mem_new_i32(TCG_AREG0,
115
                                     offsetof(CPUSH4State, gbr), "GBR");
pbrook's avatar
pbrook committed
116
    cpu_vbr = tcg_global_mem_new_i32(TCG_AREG0,
117
                                     offsetof(CPUSH4State, vbr), "VBR");
pbrook's avatar
pbrook committed
118
    cpu_sgr = tcg_global_mem_new_i32(TCG_AREG0,
119
                                     offsetof(CPUSH4State, sgr), "SGR");
pbrook's avatar
pbrook committed
120
    cpu_dbr = tcg_global_mem_new_i32(TCG_AREG0,
121
                                     offsetof(CPUSH4State, dbr), "DBR");
pbrook's avatar
pbrook committed
122
    cpu_mach = tcg_global_mem_new_i32(TCG_AREG0,
123
                                      offsetof(CPUSH4State, mach), "MACH");
pbrook's avatar
pbrook committed
124
    cpu_macl = tcg_global_mem_new_i32(TCG_AREG0,
125
                                      offsetof(CPUSH4State, macl), "MACL");
pbrook's avatar
pbrook committed
126
    cpu_pr = tcg_global_mem_new_i32(TCG_AREG0,
127
                                    offsetof(CPUSH4State, pr), "PR");
pbrook's avatar
pbrook committed
128
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
129
                                       offsetof(CPUSH4State, fpscr), "FPSCR");
pbrook's avatar
pbrook committed
130
    cpu_fpul = tcg_global_mem_new_i32(TCG_AREG0,
131
                                      offsetof(CPUSH4State, fpul), "FPUL");
pbrook's avatar
pbrook committed
132 133

    cpu_flags = tcg_global_mem_new_i32(TCG_AREG0,
134
				       offsetof(CPUSH4State, flags), "_flags_");
pbrook's avatar
pbrook committed
135
    cpu_delayed_pc = tcg_global_mem_new_i32(TCG_AREG0,
136
					    offsetof(CPUSH4State, delayed_pc),
pbrook's avatar
pbrook committed
137
					    "_delayed_pc_");
aurel32's avatar
aurel32 committed
138
    cpu_ldst = tcg_global_mem_new_i32(TCG_AREG0,
139
				      offsetof(CPUSH4State, ldst), "_ldst_");
140

141 142
    for (i = 0; i < 32; i++)
        cpu_fregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
143
                                              offsetof(CPUSH4State, fregs[i]),
144 145
                                              fregnames[i]);

pbrook's avatar
pbrook committed
146 147 148
    done_init = 1;
}

149 150
void superh_cpu_dump_state(CPUState *cs, FILE *f,
                           fprintf_function cpu_fprintf, int flags)
bellard's avatar
bellard committed
151
{
152 153
    SuperHCPU *cpu = SUPERH_CPU(cs);
    CPUSH4State *env = &cpu->env;
bellard's avatar
bellard committed
154
    int i;
155 156
    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
157 158 159 160
    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
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    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);
    }
}

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
183
        tcg_gen_goto_tb(n);
184
        tcg_gen_movi_i32(cpu_pc, dest);
185
        tcg_gen_exit_tb((uintptr_t)tb + n);
bellard's avatar
bellard committed
186
    } else {
187
        tcg_gen_movi_i32(cpu_pc, dest);
bellard's avatar
bellard committed
188
        if (ctx->singlestep_enabled)
189
            gen_helper_debug(cpu_env);
bellard's avatar
bellard committed
190
        tcg_gen_exit_tb(0);
bellard's avatar
bellard committed
191 192 193 194 195 196 197 198
    }
}

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 */
199
	tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
bellard's avatar
bellard committed
200
	if (ctx->singlestep_enabled)
201
            gen_helper_debug(cpu_env);
bellard's avatar
bellard committed
202
	tcg_gen_exit_tb(0);
bellard's avatar
bellard committed
203 204 205 206 207
    } else {
	gen_goto_tb(ctx, 0, ctx->delayed_pc);
    }
}

208 209
static inline void gen_branch_slot(uint32_t delayed_pc, int t)
{
210
    TCGv sr;
211 212
    int label = gen_new_label();
    tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
pbrook's avatar
pbrook committed
213
    sr = tcg_temp_new();
214
    tcg_gen_andi_i32(sr, cpu_sr, SR_T);
215
    tcg_gen_brcondi_i32(t ? TCG_COND_EQ:TCG_COND_NE, sr, 0, label);
216 217 218 219
    tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
    gen_set_label(label);
}

bellard's avatar
bellard committed
220 221 222 223 224
/* Immediate conditional jump (bt or bf) */
static void gen_conditional_jump(DisasContext * ctx,
				 target_ulong ift, target_ulong ifnott)
{
    int l1;
225
    TCGv sr;
bellard's avatar
bellard committed
226 227

    l1 = gen_new_label();
pbrook's avatar
pbrook committed
228
    sr = tcg_temp_new();
229
    tcg_gen_andi_i32(sr, cpu_sr, SR_T);
230
    tcg_gen_brcondi_i32(TCG_COND_NE, sr, 0, l1);
bellard's avatar
bellard committed
231 232 233 234 235 236 237 238 239
    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;
240
    TCGv ds;
bellard's avatar
bellard committed
241 242

    l1 = gen_new_label();
pbrook's avatar
pbrook committed
243
    ds = tcg_temp_new();
244
    tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
245
    tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
246
    gen_goto_tb(ctx, 1, ctx->pc + 2);
bellard's avatar
bellard committed
247
    gen_set_label(l1);
248
    tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
pbrook's avatar
pbrook committed
249
    gen_jump(ctx);
bellard's avatar
bellard committed
250 251
}

252 253
static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
{
254 255 256 257 258 259 260 261
    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);
262 263 264 265
}

static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
{
266 267 268 269 270 271 272 273
    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);
274 275
}

276 277 278 279 280 281
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);
}

282 283
static inline void gen_copy_bit_i32(TCGv t0, int p0, TCGv t1, int p1)
{
pbrook's avatar
pbrook committed
284
    TCGv tmp = tcg_temp_new();
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

    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
300
static inline void gen_load_fpr64(TCGv_i64 t, int reg)
301
{
302
    tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
303 304
}

pbrook's avatar
pbrook committed
305
static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
306
{
pbrook's avatar
pbrook committed
307
    TCGv_i32 tmp = tcg_temp_new_i32();
308
    tcg_gen_trunc_i64_i32(tmp, t);
309
    tcg_gen_mov_i32(cpu_fregs[reg + 1], tmp);
310 311
    tcg_gen_shri_i64(t, t, 32);
    tcg_gen_trunc_i64_i32(tmp, t);
312
    tcg_gen_mov_i32(cpu_fregs[reg], tmp);
pbrook's avatar
pbrook committed
313
    tcg_temp_free_i32(tmp);
314 315
}

bellard's avatar
bellard committed
316 317 318 319 320 321 322 323 324 325
#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)

326 327
#define REG(x) ((x) < 8 && (ctx->flags & (SR_MD | SR_RB)) == (SR_MD | SR_RB) \
                ? (cpu_gregs[x + 16]) : (cpu_gregs[x]))
bellard's avatar
bellard committed
328

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

332
#define FREG(x) (ctx->flags & FPSCR_FR ? (x) ^ 0x10 : (x))
333
#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
334
#define XREG(x) (ctx->flags & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
335
#define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
336

bellard's avatar
bellard committed
337
#define CHECK_NOT_DELAY_SLOT \
aurel32's avatar
aurel32 committed
338 339
  if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))     \
  {                                                           \
340
      tcg_gen_movi_i32(cpu_pc, ctx->pc);                      \
341
      gen_helper_raise_slot_illegal_instruction(cpu_env);     \
342
      ctx->bstate = BS_BRANCH;                                \
aurel32's avatar
aurel32 committed
343 344
      return;                                                 \
  }
bellard's avatar
bellard committed
345

346 347
#define CHECK_PRIVILEGED                                        \
  if (IS_USER(ctx)) {                                           \
348
      tcg_gen_movi_i32(cpu_pc, ctx->pc);                        \
349
      if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
350
          gen_helper_raise_slot_illegal_instruction(cpu_env);   \
351
      } else {                                                  \
352
          gen_helper_raise_illegal_instruction(cpu_env);        \
353
      }                                                         \
354
      ctx->bstate = BS_BRANCH;                                  \
355
      return;                                                   \
356 357
  }

aurel32's avatar
aurel32 committed
358 359
#define CHECK_FPU_ENABLED                                       \
  if (ctx->flags & SR_FD) {                                     \
360
      tcg_gen_movi_i32(cpu_pc, ctx->pc);                        \
aurel32's avatar
aurel32 committed
361
      if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
362
          gen_helper_raise_slot_fpu_disable(cpu_env);           \
aurel32's avatar
aurel32 committed
363
      } else {                                                  \
364
          gen_helper_raise_fpu_disable(cpu_env);                \
aurel32's avatar
aurel32 committed
365
      }                                                         \
366
      ctx->bstate = BS_BRANCH;                                  \
aurel32's avatar
aurel32 committed
367 368 369
      return;                                                   \
  }

370
static void _decode_opc(DisasContext * ctx)
bellard's avatar
bellard committed
371
{
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
    /* 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 */)
	      {
398
                  gen_helper_discard_movcal_backup(cpu_env);
399 400 401 402
		  ctx->has_movcal = 0;
	      }
	}

bellard's avatar
bellard committed
403 404 405
#if 0
    fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
#endif
406

bellard's avatar
bellard committed
407 408
    switch (ctx->opcode) {
    case 0x0019:		/* div0u */
409
	tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T));
bellard's avatar
bellard committed
410 411
	return;
    case 0x000b:		/* rts */
412 413
	CHECK_NOT_DELAY_SLOT
	tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
bellard's avatar
bellard committed
414 415 416 417
	ctx->flags |= DELAY_SLOT;
	ctx->delayed_pc = (uint32_t) - 1;
	return;
    case 0x0028:		/* clrmac */
418 419
	tcg_gen_movi_i32(cpu_mach, 0);
	tcg_gen_movi_i32(cpu_macl, 0);
bellard's avatar
bellard committed
420 421
	return;
    case 0x0048:		/* clrs */
422
	tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_S);
bellard's avatar
bellard committed
423 424
	return;
    case 0x0008:		/* clrt */
425
        tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
bellard's avatar
bellard committed
426 427
	return;
    case 0x0038:		/* ldtlb */
428
	CHECK_PRIVILEGED
429
        gen_helper_ldtlb(cpu_env);
bellard's avatar
bellard committed
430
	return;
ths's avatar
ths committed
431
    case 0x002b:		/* rte */
432
	CHECK_PRIVILEGED
433 434 435
	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
436 437 438 439
	ctx->flags |= DELAY_SLOT;
	ctx->delayed_pc = (uint32_t) - 1;
	return;
    case 0x0058:		/* sets */
440
	tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_S);
bellard's avatar
bellard committed
441 442
	return;
    case 0x0018:		/* sett */
443
        tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
bellard's avatar
bellard committed
444
	return;
aurel32's avatar
aurel32 committed
445
    case 0xfbfd:		/* frchg */
446
	tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
447
	ctx->bstate = BS_STOP;
bellard's avatar
bellard committed
448
	return;
aurel32's avatar
aurel32 committed
449
    case 0xf3fd:		/* fschg */
450
        tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
451
	ctx->bstate = BS_STOP;
bellard's avatar
bellard committed
452 453 454 455
	return;
    case 0x0009:		/* nop */
	return;
    case 0x001b:		/* sleep */
456
	CHECK_PRIVILEGED
457 458
        tcg_gen_movi_i32(cpu_pc, ctx->pc + 2);
        gen_helper_sleep(cpu_env);
bellard's avatar
bellard committed
459 460 461 462 463
	return;
    }

    switch (ctx->opcode & 0xf000) {
    case 0x1000:		/* mov.l Rm,@(disp,Rn) */
464
	{
pbrook's avatar
pbrook committed
465
	    TCGv addr = tcg_temp_new();
466
	    tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
467
            tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
468 469
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
470 471
	return;
    case 0x5000:		/* mov.l @(disp,Rm),Rn */
472
	{
pbrook's avatar
pbrook committed
473
	    TCGv addr = tcg_temp_new();
474
	    tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
475
            tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
476 477
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
478
	return;
aurel32's avatar
aurel32 committed
479
    case 0xe000:		/* mov #imm,Rn */
aurel32's avatar
aurel32 committed
480
	tcg_gen_movi_i32(REG(B11_8), B7_0s);
bellard's avatar
bellard committed
481 482
	return;
    case 0x9000:		/* mov.w @(disp,PC),Rn */
483 484
	{
	    TCGv addr = tcg_const_i32(ctx->pc + 4 + B7_0 * 2);
485
            tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
486 487
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
488 489
	return;
    case 0xd000:		/* mov.l @(disp,PC),Rn */
490 491
	{
	    TCGv addr = tcg_const_i32((ctx->pc + 4 + B7_0 * 4) & ~3);
492
            tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
493 494
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
495
	return;
aurel32's avatar
aurel32 committed
496
    case 0x7000:		/* add #imm,Rn */
aurel32's avatar
aurel32 committed
497
	tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
bellard's avatar
bellard committed
498 499 500
	return;
    case 0xa000:		/* bra disp */
	CHECK_NOT_DELAY_SLOT
501 502
	ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
	tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
bellard's avatar
bellard committed
503 504 505 506
	ctx->flags |= DELAY_SLOT;
	return;
    case 0xb000:		/* bsr disp */
	CHECK_NOT_DELAY_SLOT
507 508 509
	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
510 511 512 513 514 515
	ctx->flags |= DELAY_SLOT;
	return;
    }

    switch (ctx->opcode & 0xf00f) {
    case 0x6003:		/* mov Rm,Rn */
aurel32's avatar
aurel32 committed
516
	tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
517 518
	return;
    case 0x2000:		/* mov.b Rm,@Rn */
519
        tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
bellard's avatar
bellard committed
520 521
	return;
    case 0x2001:		/* mov.w Rm,@Rn */
522
        tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW);
bellard's avatar
bellard committed
523 524
	return;
    case 0x2002:		/* mov.l Rm,@Rn */
525
        tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
bellard's avatar
bellard committed
526 527
	return;
    case 0x6000:		/* mov.b @Rm,Rn */
528
        tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
bellard's avatar
bellard committed
529 530
	return;
    case 0x6001:		/* mov.w @Rm,Rn */
531
        tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
bellard's avatar
bellard committed
532 533
	return;
    case 0x6002:		/* mov.l @Rm,Rn */
534
        tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
bellard's avatar
bellard committed
535 536
	return;
    case 0x2004:		/* mov.b Rm,@-Rn */
537
	{
pbrook's avatar
pbrook committed
538
	    TCGv addr = tcg_temp_new();
539
	    tcg_gen_subi_i32(addr, REG(B11_8), 1);
540 541
            /* might cause re-execution */
            tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
542
	    tcg_gen_mov_i32(REG(B11_8), addr);			/* modify register status */
543 544
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
545 546
	return;
    case 0x2005:		/* mov.w Rm,@-Rn */
547
	{
pbrook's avatar
pbrook committed
548
	    TCGv addr = tcg_temp_new();
549
	    tcg_gen_subi_i32(addr, REG(B11_8), 2);
550
            tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
551
	    tcg_gen_mov_i32(REG(B11_8), addr);
552 553
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
554 555
	return;
    case 0x2006:		/* mov.l Rm,@-Rn */
556
	{
pbrook's avatar
pbrook committed
557
	    TCGv addr = tcg_temp_new();
558
	    tcg_gen_subi_i32(addr, REG(B11_8), 4);
559
            tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
560
	    tcg_gen_mov_i32(REG(B11_8), addr);
561
	}
bellard's avatar
bellard committed
562
	return;
563
    case 0x6004:		/* mov.b @Rm+,Rn */
564
        tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
aurel32's avatar
aurel32 committed
565
	if ( B11_8 != B7_4 )
aurel32's avatar
aurel32 committed
566
		tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
bellard's avatar
bellard committed
567 568
	return;
    case 0x6005:		/* mov.w @Rm+,Rn */
569
        tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
aurel32's avatar
aurel32 committed
570
	if ( B11_8 != B7_4 )
aurel32's avatar
aurel32 committed
571
		tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
bellard's avatar
bellard committed
572 573
	return;
    case 0x6006:		/* mov.l @Rm+,Rn */
574
        tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
aurel32's avatar
aurel32 committed
575
	if ( B11_8 != B7_4 )
aurel32's avatar
aurel32 committed
576
		tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
bellard's avatar
bellard committed
577 578
	return;
    case 0x0004:		/* mov.b Rm,@(R0,Rn) */
579
	{
pbrook's avatar
pbrook committed
580
	    TCGv addr = tcg_temp_new();
581
	    tcg_gen_add_i32(addr, REG(B11_8), REG(0));
582
            tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB);
583 584
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
585 586
	return;
    case 0x0005:		/* mov.w Rm,@(R0,Rn) */
587
	{
pbrook's avatar
pbrook committed
588
	    TCGv addr = tcg_temp_new();
589
	    tcg_gen_add_i32(addr, REG(B11_8), REG(0));
590
            tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
591 592
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
593 594
	return;
    case 0x0006:		/* mov.l Rm,@(R0,Rn) */
595
	{
pbrook's avatar
pbrook committed
596
	    TCGv addr = tcg_temp_new();
597
	    tcg_gen_add_i32(addr, REG(B11_8), REG(0));
598
            tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
599 600
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
601 602
	return;
    case 0x000c:		/* mov.b @(R0,Rm),Rn */
603
	{
pbrook's avatar
pbrook committed
604
	    TCGv addr = tcg_temp_new();
605
	    tcg_gen_add_i32(addr, REG(B7_4), REG(0));
606
            tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB);
607 608
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
609 610
	return;
    case 0x000d:		/* mov.w @(R0,Rm),Rn */
611
	{
pbrook's avatar
pbrook committed
612
	    TCGv addr = tcg_temp_new();
613
	    tcg_gen_add_i32(addr, REG(B7_4), REG(0));
614
            tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
615 616
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
617 618
	return;
    case 0x000e:		/* mov.l @(R0,Rm),Rn */
619
	{
pbrook's avatar
pbrook committed
620
	    TCGv addr = tcg_temp_new();
621
	    tcg_gen_add_i32(addr, REG(B7_4), REG(0));
622
            tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
623 624
	    tcg_temp_free(addr);
	}
bellard's avatar
bellard committed
625 626
	return;
    case 0x6008:		/* swap.b Rm,Rn */
627
	{
628
	    TCGv high, low;
pbrook's avatar
pbrook committed
629
	    high = tcg_temp_new();
630
	    tcg_gen_andi_i32(high, REG(B7_4), 0xffff0000);
pbrook's avatar
pbrook committed
631
	    low = tcg_temp_new();
632 633
	    tcg_gen_ext16u_i32(low, REG(B7_4));
	    tcg_gen_bswap16_i32(low, low);
634 635 636 637
	    tcg_gen_or_i32(REG(B11_8), high, low);
	    tcg_temp_free(low);
	    tcg_temp_free(high);
	}
bellard's avatar
bellard committed
638 639
	return;
    case 0x6009:		/* swap.w Rm,Rn */
Aurelien Jarno's avatar
Aurelien Jarno committed
640
        tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
bellard's avatar
bellard committed
641 642
	return;
    case 0x200d:		/* xtrct Rm,Rn */
643 644
	{
	    TCGv high, low;
pbrook's avatar
pbrook committed
645
	    high = tcg_temp_new();
646
	    tcg_gen_shli_i32(high, REG(B7_4), 16);
pbrook's avatar
pbrook committed
647
	    low = tcg_temp_new();
648 649 650 651 652
	    tcg_gen_shri_i32(low, REG(B11_8), 16);
	    tcg_gen_or_i32(REG(B11_8), high, low);
	    tcg_temp_free(low);
	    tcg_temp_free(high);
	}
bellard's avatar
bellard committed
653 654
	return;
    case 0x300c:		/* add Rm,Rn */
aurel32's avatar
aurel32 committed
655
	tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
656 657
	return;
    case 0x300e:		/* addc Rm,Rn */
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
        {
            TCGv t0, t1, t2;
            t0 = tcg_temp_new();
            tcg_gen_andi_i32(t0, cpu_sr, SR_T);
            t1 = tcg_temp_new();
            tcg_gen_add_i32(t1, REG(B7_4), REG(B11_8));
            tcg_gen_add_i32(t0, t0, t1);
            t2 = tcg_temp_new();
            tcg_gen_setcond_i32(TCG_COND_GTU, t2, REG(B11_8), t1);
            tcg_gen_setcond_i32(TCG_COND_GTU, t1, t1, t0);
            tcg_gen_or_i32(t1, t1, t2);
            tcg_temp_free(t2);
            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
            tcg_temp_free(t1);
            tcg_gen_mov_i32(REG(B11_8), t0);
            tcg_temp_free(t0);
        }
bellard's avatar
bellard committed
676 677
	return;
    case 0x300f:		/* addv Rm,Rn */
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
        {
            TCGv t0, t1, t2;
            t0 = tcg_temp_new();
            tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8));
            t1 = tcg_temp_new();
            tcg_gen_xor_i32(t1, t0, REG(B11_8));
            t2 = tcg_temp_new();
            tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8));
            tcg_gen_andc_i32(t1, t1, t2);
            tcg_temp_free(t2);
            tcg_gen_shri_i32(t1, t1, 31);
            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
            tcg_temp_free(t1);
            tcg_gen_mov_i32(REG(B7_4), t0);
            tcg_temp_free(t0);
        }
bellard's avatar
bellard committed
695 696
	return;
    case 0x2009:		/* and Rm,Rn */
aurel32's avatar
aurel32 committed
697
	tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
698 699
	return;
    case 0x3000:		/* cmp/eq Rm,Rn */
aurel32's avatar
aurel32 committed
700
	gen_cmp(TCG_COND_EQ, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
701 702
	return;
    case 0x3003:		/* cmp/ge Rm,Rn */
aurel32's avatar
aurel32 committed
703
	gen_cmp(TCG_COND_GE, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
704 705
	return;
    case 0x3007:		/* cmp/gt Rm,Rn */
aurel32's avatar
aurel32 committed
706
	gen_cmp(TCG_COND_GT, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
707 708
	return;
    case 0x3006:		/* cmp/hi Rm,Rn */
aurel32's avatar
aurel32 committed
709
	gen_cmp(TCG_COND_GTU, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
710 711
	return;
    case 0x3002:		/* cmp/hs Rm,Rn */
aurel32's avatar
aurel32 committed
712
	gen_cmp(TCG_COND_GEU, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
713 714
	return;
    case 0x200c:		/* cmp/str Rm,Rn */
715
	{
716 717 718
	    TCGv cmp1 = tcg_temp_new();
	    TCGv cmp2 = tcg_temp_new();
	    tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
719 720
	    tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
	    tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
721 722
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
723
	    tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
724 725
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
726
	    tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
727 728
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
729
	    tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
730 731
	    tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
	    tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
732 733
	    tcg_temp_free(cmp2);
	    tcg_temp_free(cmp1);
734
	}
bellard's avatar
bellard committed
735 736
	return;
    case 0x2007:		/* div0s Rm,Rn */
737 738 739
	{
	    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
740
	    TCGv val = tcg_temp_new();
741 742 743 744
	    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
745 746
	return;
    case 0x3004:		/* div1 Rm,Rn */
747
        gen_helper_div1(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
748 749
	return;
    case 0x300d:		/* dmuls.l Rm,Rn */
750
        tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
751 752
	return;
    case 0x3005:		/* dmulu.l Rm,Rn */
753
        tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
754 755
	return;
    case 0x600e:		/* exts.b Rm,Rn */
aurel32's avatar
aurel32 committed
756
	tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
757 758
	return;
    case 0x600f:		/* exts.w Rm,Rn */
aurel32's avatar
aurel32 committed
759
	tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
760 761
	return;
    case 0x600c:		/* extu.b Rm,Rn */
aurel32's avatar
aurel32 committed
762
	tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
763 764
	return;
    case 0x600d:		/* extu.w Rm,Rn */
aurel32's avatar
aurel32 committed
765
	tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
766
	return;
aurel32's avatar
aurel32 committed
767
    case 0x000f:		/* mac.l @Rm+,@Rn+ */
768 769
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
770
	    arg0 = tcg_temp_new();
771
            tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
pbrook's avatar
pbrook committed
772
	    arg1 = tcg_temp_new();
773
            tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
774
            gen_helper_macl(cpu_env, arg0, arg1);
775 776 777 778 779
	    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
780 781
	return;
    case 0x400f:		/* mac.w @Rm+,@Rn+ */
782 783
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
784
	    arg0 = tcg_temp_new();
785
            tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL);
pbrook's avatar
pbrook committed
786
	    arg1 = tcg_temp_new();
787
            tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL);
788
            gen_helper_macw(cpu_env, arg0, arg1);
789 790 791 792 793
	    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
794 795
	return;
    case 0x0007:		/* mul.l Rm,Rn */
aurel32's avatar
aurel32 committed
796
	tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
bellard's avatar
bellard committed
797 798
	return;
    case 0x200f:		/* muls.w Rm,Rn */
799 800
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
801
	    arg0 = tcg_temp_new();
802
	    tcg_gen_ext16s_i32(arg0, REG(B7_4));
pbrook's avatar
pbrook committed
803
	    arg1 = tcg_temp_new();
804 805 806 807 808
	    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
809 810
	return;
    case 0x200e:		/* mulu.w Rm,Rn */
811 812
	{
	    TCGv arg0, arg1;
pbrook's avatar
pbrook committed
813
	    arg0 = tcg_temp_new();
814
	    tcg_gen_ext16u_i32(arg0, REG(B7_4));
pbrook's avatar
pbrook committed
815
	    arg1 = tcg_temp_new();
816 817 818 819 820
	    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
821 822
	return;
    case 0x600b:		/* neg Rm,Rn */
aurel32's avatar
aurel32 committed
823
	tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
824 825
	return;
    case 0x600a:		/* negc Rm,Rn */
826 827 828 829 830 831 832 833
        {
	    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
834
            tcg_gen_setcondi_i32(TCG_COND_GTU, t1, t0, 0);
835
            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
Aurelien Jarno's avatar
Aurelien Jarno committed
836
            tcg_gen_setcond_i32(TCG_COND_GTU, t1, REG(B11_8), t0);
837 838 839 840
            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
            tcg_temp_free(t0);
            tcg_temp_free(t1);
        }
bellard's avatar
bellard committed
841 842
	return;
    case 0x6007:		/* not Rm,Rn */
aurel32's avatar
aurel32 committed
843
	tcg_gen_not_i32(REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
844 845
	return;
    case 0x200b:		/* or Rm,Rn */
aurel32's avatar
aurel32 committed
846
	tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
847 848
	return;
    case 0x400c:		/* shad Rm,Rn */
849 850 851 852 853
	{
	    int label1 = gen_new_label();
	    int label2 = gen_new_label();
	    int label3 = gen_new_label();
	    int label4 = gen_new_label();
854
	    TCGv shift;
aurel32's avatar
aurel32 committed
855
	    tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
856
	    /* Rm positive, shift to the left */
857
            shift = tcg_temp_new();
858 859
	    tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
	    tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
860
	    tcg_temp_free(shift);
861 862 863
	    tcg_gen_br(label4);
	    /* Rm negative, shift to the right */
	    gen_set_label(label1);
864
            shift = tcg_temp_new();
865 866 867 868 869 870
	    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);
871
	    tcg_temp_free(shift);
872 873 874
	    tcg_gen_br(label4);
	    /* Rm = -32 */
	    gen_set_label(label2);
aurel32's avatar
aurel32 committed
875 876
	    tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3);
	    tcg_gen_movi_i32(REG(B11_8), 0);
877 878
	    tcg_gen_br(label4);
	    gen_set_label(label3);
aurel32's avatar
aurel32 committed
879
	    tcg_gen_movi_i32(REG(B11_8), 0xffffffff);
880 881
	    gen_set_label(label4);
	}
bellard's avatar
bellard committed
882 883
	return;
    case 0x400d:		/* shld Rm,Rn */
884 885 886 887
	{
	    int label1 = gen_new_label();
	    int label2 = gen_new_label();
	    int label3 = gen_new_label();
888
	    TCGv shift;
aurel32's avatar
aurel32 committed
889
	    tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
890
	    /* Rm positive, shift to the left */
891
            shift = tcg_temp_new();
892 893
	    tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
	    tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
894
	    tcg_temp_free(shift);
895 896 897
	    tcg_gen_br(label3);
	    /* Rm negative, shift to the right */
	    gen_set_label(label1);
898
            shift = tcg_temp_new();
899 900 901 902 903 904
	    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_shr_i32(REG(B11_8), REG(B11_8), shift);
905
	    tcg_temp_free(shift);
906 907 908
	    tcg_gen_br(label3);
	    /* Rm = -32 */
	    gen_set_label(label2);
aurel32's avatar
aurel32 committed
909
	    tcg_gen_movi_i32(REG(B11_8), 0);
910 911
	    gen_set_label(label3);
	}
bellard's avatar
bellard committed
912 913
	return;
    case 0x3008:		/* sub Rm,Rn */
aurel32's avatar
aurel32 committed
914
	tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
bellard's avatar
bellard committed
915