translate.c 83.9 KB
Newer Older
1 2 3
/*
 *  CRIS emulation for qemu: main translation routines.
 *
4
 *  Copyright (c) 2008 AXIS Communications AB
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *  Written by Edgar E. Iglesias.
 *
 * 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
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
20 21
 */

E
edgar_igl 已提交
22 23
/*
 * FIXME:
24
 * The condition code translation is in need of attention.
E
edgar_igl 已提交
25 26
 */

27 28 29 30 31 32 33 34 35 36
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>

#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
B
bellard 已提交
37
#include "tcg-op.h"
38
#include "helper.h"
39
#include "crisv32-decode.h"
40
#include "qemu-common.h"
41

P
pbrook 已提交
42 43 44
#define GEN_HELPER 1
#include "helper.h"

45 46
#define DISAS_CRIS 0
#if DISAS_CRIS
47
#define DIS(x) if (loglevel & CPU_LOG_TB_IN_ASM) x
48 49 50 51
#else
#define DIS(x)
#endif

E
edgar_igl 已提交
52
#define D(x)
53 54 55
#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
#define BUG_ON(x) ({if (x) BUG();})

56 57
#define DISAS_SWI 5

58 59 60 61 62 63 64 65 66
/* Used by the decoder.  */
#define EXTRACT_FIELD(src, start, end) \
            (((src) >> start) & ((1 << (end - start + 1)) - 1))

#define CC_MASK_NZ 0xc
#define CC_MASK_NZV 0xe
#define CC_MASK_NZVC 0xf
#define CC_MASK_RNZV 0x10e

P
pbrook 已提交
67
static TCGv_ptr cpu_env;
E
edgar_igl 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80
static TCGv cpu_R[16];
static TCGv cpu_PR[16];
static TCGv cc_x;
static TCGv cc_src;
static TCGv cc_dest;
static TCGv cc_result;
static TCGv cc_op;
static TCGv cc_size;
static TCGv cc_mask;

static TCGv env_btaken;
static TCGv env_btarget;
static TCGv env_pc;
E
edgar_igl 已提交
81

P
pbrook 已提交
82 83
#include "gen-icount.h"

84 85 86
/* This is the state at translation time.  */
typedef struct DisasContext {
	CPUState *env;
E
edgar_igl 已提交
87
	target_ulong pc, ppc;
88 89 90 91 92 93 94 95 96 97 98 99 100 101

	/* Decoder.  */
	uint32_t ir;
	uint32_t opcode;
	unsigned int op1;
	unsigned int op2;
	unsigned int zsize, zzsize;
	unsigned int mode;
	unsigned int postinc;

	int update_cc;
	int cc_op;
	int cc_size;
	uint32_t cc_mask;
102 103 104 105 106 107 108

	int cc_size_uptodate; /* -1 invalid or last written value.  */

	int cc_x_uptodate;  /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate.  */
	int flags_uptodate; /* Wether or not $ccs is uptodate.  */
	int flagx_known; /* Wether or not flags_x has the x flag known at
			    translation time.  */
109 110
	int flags_x;

111
	int clear_x; /* Clear x after this insn?  */
E
edgar_igl 已提交
112 113
	int cpustate_changed;
	unsigned int tb_flags; /* tb dependent flags.  */
114 115
	int is_jmp;

E
edgar_igl 已提交
116 117 118 119 120 121
#define JMP_NOJMP    0
#define JMP_DIRECT   1
#define JMP_INDIRECT 2
	int jmp; /* 0=nojmp, 1=direct, 2=indirect.  */ 
	uint32_t jmp_pc;

122 123 124 125 126 127
	int delayed_branch;

	struct TranslationBlock *tb;
	int singlestep_enabled;
} DisasContext;

128
static void gen_BUG(DisasContext *dc, const char *file, int line)
129 130 131
{
	printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
	fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line);
132
	cpu_abort(dc->env, "%s:%d\n", file, line);
133 134
}

E
edgar_igl 已提交
135
static const char *regnames[] =
E
edgar_igl 已提交
136 137 138 139 140 141
{
	"$r0", "$r1", "$r2", "$r3",
	"$r4", "$r5", "$r6", "$r7",
	"$r8", "$r9", "$r10", "$r11",
	"$r12", "$r13", "$sp", "$acr",
};
E
edgar_igl 已提交
142
static const char *pregnames[] =
E
edgar_igl 已提交
143 144 145 146 147 148 149
{
	"$bz", "$vr", "$pid", "$srs",
	"$wz", "$exs", "$eda", "$mof",
	"$dz", "$ebp", "$erp", "$srp",
	"$nrp", "$ccs", "$usp", "$spc",
};

150
/* We need this table to handle preg-moves with implicit width.  */
E
edgar_igl 已提交
151
static int preg_sizes[] = {
152 153 154 155 156 157 158 159 160 161 162
	1, /* bz.  */
	1, /* vr.  */
	4, /* pid.  */
	1, /* srs.  */
	2, /* wz.  */
	4, 4, 4,
	4, 4, 4, 4,
	4, 4, 4, 4,
};

#define t_gen_mov_TN_env(tn, member) \
E
edgar_igl 已提交
163
 _t_gen_mov_TN_env((tn), offsetof(CPUState, member))
164
#define t_gen_mov_env_TN(member, tn) \
E
edgar_igl 已提交
165
 _t_gen_mov_env_TN(offsetof(CPUState, member), (tn))
166

E
edgar_igl 已提交
167 168 169 170 171 172 173 174 175 176 177 178
static inline void t_gen_mov_TN_reg(TCGv tn, int r)
{
	if (r < 0 || r > 15)
		fprintf(stderr, "wrong register read $r%d\n", r);
	tcg_gen_mov_tl(tn, cpu_R[r]);
}
static inline void t_gen_mov_reg_TN(int r, TCGv tn)
{
	if (r < 0 || r > 15)
		fprintf(stderr, "wrong register write $r%d\n", r);
	tcg_gen_mov_tl(cpu_R[r], tn);
}
179 180 181

static inline void _t_gen_mov_TN_env(TCGv tn, int offset)
{
E
edgar_igl 已提交
182 183
	if (offset > sizeof (CPUState))
		fprintf(stderr, "wrong load from env from off=%d\n", offset);
184 185 186 187
	tcg_gen_ld_tl(tn, cpu_env, offset);
}
static inline void _t_gen_mov_env_TN(int offset, TCGv tn)
{
E
edgar_igl 已提交
188 189
	if (offset > sizeof (CPUState))
		fprintf(stderr, "wrong store to env at off=%d\n", offset);
190 191 192 193 194
	tcg_gen_st_tl(tn, cpu_env, offset);
}

static inline void t_gen_mov_TN_preg(TCGv tn, int r)
{
E
edgar_igl 已提交
195 196
	if (r < 0 || r > 15)
		fprintf(stderr, "wrong register read $p%d\n", r);
197
	if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
E
edgar_igl 已提交
198
		tcg_gen_mov_tl(tn, tcg_const_tl(0));
199
	else if (r == PR_VR)
E
edgar_igl 已提交
200
		tcg_gen_mov_tl(tn, tcg_const_tl(32));
E
edgar_igl 已提交
201 202 203 204
	else if (r == PR_EDA) {
		printf("read from EDA!\n");
		tcg_gen_mov_tl(tn, cpu_PR[r]);
	}
205
	else
E
edgar_igl 已提交
206
		tcg_gen_mov_tl(tn, cpu_PR[r]);
207
}
208
static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn)
209
{
E
edgar_igl 已提交
210 211
	if (r < 0 || r > 15)
		fprintf(stderr, "wrong register write $p%d\n", r);
212 213
	if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
		return;
E
edgar_igl 已提交
214 215 216
	else if (r == PR_SRS)
		tcg_gen_andi_tl(cpu_PR[r], tn, 3);
	else {
E
edgar_igl 已提交
217
		if (r == PR_PID) 
P
pbrook 已提交
218
			gen_helper_tlb_flush_pid(tn);
219
		if (dc->tb_flags & S_FLAG && r == PR_SPC) 
P
pbrook 已提交
220
			gen_helper_spc_write(tn);
E
edgar_igl 已提交
221 222
		else if (r == PR_CCS)
			dc->cpustate_changed = 1;
223
		tcg_gen_mov_tl(cpu_PR[r], tn);
E
edgar_igl 已提交
224
	}
225 226
}

E
edgar_igl 已提交
227
static inline void t_gen_raise_exception(uint32_t index)
228
{
P
pbrook 已提交
229 230 231
        TCGv_i32 tmp = tcg_const_i32(index);
	gen_helper_raise_exception(tmp);
        tcg_temp_free_i32(tmp);
232 233 234 235
}

static void t_gen_lsl(TCGv d, TCGv a, TCGv b)
{
236
	TCGv t0, t_31;
237

P
pbrook 已提交
238
	t0 = tcg_temp_new();
E
edgar_igl 已提交
239
	t_31 = tcg_const_tl(31);
240
	tcg_gen_shl_tl(d, a, b);
241 242 243 244 245 246 247

	tcg_gen_sub_tl(t0, t_31, b);
	tcg_gen_sar_tl(t0, t0, t_31);
	tcg_gen_and_tl(t0, t0, d);
	tcg_gen_xor_tl(d, d, t0);
	tcg_temp_free(t0);
	tcg_temp_free(t_31);
248 249 250 251
}

static void t_gen_lsr(TCGv d, TCGv a, TCGv b)
{
252
	TCGv t0, t_31;
253

P
pbrook 已提交
254 255
	t0 = tcg_temp_new();
	t_31 = tcg_temp_new();
256
	tcg_gen_shr_tl(d, a, b);
257 258 259 260 261 262 263 264

	tcg_gen_movi_tl(t_31, 31);
	tcg_gen_sub_tl(t0, t_31, b);
	tcg_gen_sar_tl(t0, t0, t_31);
	tcg_gen_and_tl(t0, t0, d);
	tcg_gen_xor_tl(d, d, t0);
	tcg_temp_free(t0);
	tcg_temp_free(t_31);
265 266 267 268
}

static void t_gen_asr(TCGv d, TCGv a, TCGv b)
{
269
	TCGv t0, t_31;
270

P
pbrook 已提交
271 272
	t0 = tcg_temp_new();
	t_31 = tcg_temp_new();
273
	tcg_gen_sar_tl(d, a, b);
274 275 276 277 278 279 280

	tcg_gen_movi_tl(t_31, 31);
	tcg_gen_sub_tl(t0, t_31, b);
	tcg_gen_sar_tl(t0, t0, t_31);
	tcg_gen_or_tl(d, d, t0);
	tcg_temp_free(t0);
	tcg_temp_free(t_31);
281 282
}

E
edgar_igl 已提交
283 284 285
/* 64-bit signed mul, lower result in d and upper in d2.  */
static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
{
P
pbrook 已提交
286
	TCGv_i64 t0, t1;
E
edgar_igl 已提交
287

P
pbrook 已提交
288 289
	t0 = tcg_temp_new_i64();
	t1 = tcg_temp_new_i64();
E
edgar_igl 已提交
290

P
pbrook 已提交
291 292
	tcg_gen_ext_i32_i64(t0, a);
	tcg_gen_ext_i32_i64(t1, b);
E
edgar_igl 已提交
293 294 295 296 297
	tcg_gen_mul_i64(t0, t0, t1);

	tcg_gen_trunc_i64_i32(d, t0);
	tcg_gen_shri_i64(t0, t0, 32);
	tcg_gen_trunc_i64_i32(d2, t0);
E
edgar_igl 已提交
298

P
pbrook 已提交
299 300
	tcg_temp_free_i64(t0);
	tcg_temp_free_i64(t1);
E
edgar_igl 已提交
301 302 303 304 305
}

/* 64-bit unsigned muls, lower result in d and upper in d2.  */
static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
{
P
pbrook 已提交
306
	TCGv_i64 t0, t1;
E
edgar_igl 已提交
307

P
pbrook 已提交
308 309
	t0 = tcg_temp_new_i64();
	t1 = tcg_temp_new_i64();
E
edgar_igl 已提交
310 311 312 313 314 315 316 317

	tcg_gen_extu_i32_i64(t0, a);
	tcg_gen_extu_i32_i64(t1, b);
	tcg_gen_mul_i64(t0, t0, t1);

	tcg_gen_trunc_i64_i32(d, t0);
	tcg_gen_shri_i64(t0, t0, 32);
	tcg_gen_trunc_i64_i32(d2, t0);
E
edgar_igl 已提交
318

P
pbrook 已提交
319 320
	tcg_temp_free_i64(t0);
	tcg_temp_free_i64(t1);
E
edgar_igl 已提交
321 322
}

323 324 325
/* 32bit branch-free binary search for counting leading zeros.  */
static void t_gen_lz_i32(TCGv d, TCGv x)
{
P
pbrook 已提交
326
	TCGv_i32 y, m, n;
327

P
pbrook 已提交
328 329 330
	y = tcg_temp_new_i32();
	m = tcg_temp_new_i32();
	n = tcg_temp_new_i32();
331 332 333

	/* y = -(x >> 16)  */
	tcg_gen_shri_i32(y, x, 16);
P
pbrook 已提交
334
	tcg_gen_neg_i32(y, y);
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378

	/* m = (y >> 16) & 16  */
	tcg_gen_sari_i32(m, y, 16);
	tcg_gen_andi_i32(m, m, 16);

	/* n = 16 - m  */
	tcg_gen_sub_i32(n, tcg_const_i32(16), m);
	/* x = x >> m  */
	tcg_gen_shr_i32(x, x, m);

	/* y = x - 0x100  */
	tcg_gen_subi_i32(y, x, 0x100);
	/* m = (y >> 16) & 8  */
	tcg_gen_sari_i32(m, y, 16);
	tcg_gen_andi_i32(m, m, 8);
	/* n = n + m  */
	tcg_gen_add_i32(n, n, m);
	/* x = x << m  */
	tcg_gen_shl_i32(x, x, m);

	/* y = x - 0x1000  */
	tcg_gen_subi_i32(y, x, 0x1000);
	/* m = (y >> 16) & 4  */
	tcg_gen_sari_i32(m, y, 16);
	tcg_gen_andi_i32(m, m, 4);
	/* n = n + m  */
	tcg_gen_add_i32(n, n, m);
	/* x = x << m  */
	tcg_gen_shl_i32(x, x, m);

	/* y = x - 0x4000  */
	tcg_gen_subi_i32(y, x, 0x4000);
	/* m = (y >> 16) & 2  */
	tcg_gen_sari_i32(m, y, 16);
	tcg_gen_andi_i32(m, m, 2);
	/* n = n + m  */
	tcg_gen_add_i32(n, n, m);
	/* x = x << m  */
	tcg_gen_shl_i32(x, x, m);

	/* y = x >> 14  */
	tcg_gen_shri_i32(y, x, 14);
	/* m = y & ~(y >> 1)  */
	tcg_gen_sari_i32(m, y, 1);
E
edgar_igl 已提交
379
	tcg_gen_not_i32(m, m);
380 381 382 383 384 385
	tcg_gen_and_i32(m, m, y);

	/* d = n + 2 - m  */
	tcg_gen_addi_i32(d, n, 2);
	tcg_gen_sub_i32(d, d, m);

386 387 388
	tcg_temp_free(y);
	tcg_temp_free(m);
	tcg_temp_free(n);
389 390
}

391
static void t_gen_btst(TCGv d, TCGv a, TCGv b)
E
edgar_igl 已提交
392 393 394
{
        TCGv sbit;
        TCGv bset;
395
        TCGv t0;
E
edgar_igl 已提交
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
	int l1;

        /* des ref:
           The N flag is set according to the selected bit in the dest reg.
           The Z flag is set if the selected bit and all bits to the right are
           zero.
           The X flag is cleared.
           Other flags are left untouched.
           The destination reg is not affected.

        unsigned int fz, sbit, bset, mask, masked_t0;

        sbit = T1 & 31;
        bset = !!(T0 & (1 << sbit));
        mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
        masked_t0 = T0 & mask;
        fz = !(masked_t0 | bset);

        // Clear the X, N and Z flags.
        T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG);
        // Set the N and Z flags accordingly.
        T0 |= (bset << 3) | (fz << 2);
        */

	l1 = gen_new_label();
P
pbrook 已提交
421 422 423
        sbit = tcg_temp_new();
        bset = tcg_temp_new();
        t0 = tcg_temp_new();
E
edgar_igl 已提交
424 425

        /* Compute bset and sbit.  */
426 427 428
        tcg_gen_andi_tl(sbit, b, 31);
        tcg_gen_shl_tl(t0, tcg_const_tl(1), sbit);
        tcg_gen_and_tl(bset, a, t0);
E
edgar_igl 已提交
429 430 431 432 433 434
        tcg_gen_shr_tl(bset, bset, sbit);
	/* Displace to N_FLAG.  */
        tcg_gen_shli_tl(bset, bset, 3);

        tcg_gen_shl_tl(sbit, tcg_const_tl(2), sbit);
        tcg_gen_subi_tl(sbit, sbit, 1);
435
        tcg_gen_and_tl(sbit, a, sbit);
E
edgar_igl 已提交
436 437 438 439

        tcg_gen_andi_tl(d, cpu_PR[PR_CCS], ~(X_FLAG | N_FLAG | Z_FLAG));
	/* or in the N_FLAG.  */
        tcg_gen_or_tl(d, d, bset);
P
pbrook 已提交
440
	tcg_gen_brcondi_tl(TCG_COND_NE, sbit, 0, l1);
E
edgar_igl 已提交
441 442 443 444
	/* or in the Z_FLAG.  */
	tcg_gen_ori_tl(d, d, Z_FLAG);
	gen_set_label(l1);

445 446
        tcg_temp_free(sbit);
        tcg_temp_free(bset);
E
edgar_igl 已提交
447 448
}

449
static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
E
edgar_igl 已提交
450 451 452 453 454 455 456 457 458 459
{
	int l1;

	l1 = gen_new_label();

	/* 
	 * d <<= 1
	 * if (d >= s)
	 *    d -= s;
	 */
460 461 462
	tcg_gen_shli_tl(d, a, 1);
	tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1);
	tcg_gen_sub_tl(d, d, b);
E
edgar_igl 已提交
463 464 465
	gen_set_label(l1);
}

E
edgar_igl 已提交
466 467 468 469 470
/* Extended arithmetics on CRIS.  */
static inline void t_gen_add_flag(TCGv d, int flag)
{
	TCGv c;

P
pbrook 已提交
471
	c = tcg_temp_new();
E
edgar_igl 已提交
472 473 474 475 476 477
	t_gen_mov_TN_preg(c, PR_CCS);
	/* Propagate carry into d.  */
	tcg_gen_andi_tl(c, c, 1 << flag);
	if (flag)
		tcg_gen_shri_tl(c, c, flag);
	tcg_gen_add_tl(d, d, c);
478
	tcg_temp_free(c);
E
edgar_igl 已提交
479 480
}

481
static inline void t_gen_addx_carry(DisasContext *dc, TCGv d)
E
edgar_igl 已提交
482
{
483 484 485 486
	if (dc->flagx_known) {
		if (dc->flags_x) {
			TCGv c;
            
P
pbrook 已提交
487
			c = tcg_temp_new();
488 489 490 491 492 493 494 495
			t_gen_mov_TN_preg(c, PR_CCS);
			/* C flag is already at bit 0.  */
			tcg_gen_andi_tl(c, c, C_FLAG);
			tcg_gen_add_tl(d, d, c);
			tcg_temp_free(c);
		}
	} else {
		TCGv x, c;
E
edgar_igl 已提交
496

P
pbrook 已提交
497 498
		x = tcg_temp_new();
		c = tcg_temp_new();
499 500
		t_gen_mov_TN_preg(x, PR_CCS);
		tcg_gen_mov_tl(c, x);
E
edgar_igl 已提交
501

502 503 504 505
		/* Propagate carry into d if X is set. Branch free.  */
		tcg_gen_andi_tl(c, c, C_FLAG);
		tcg_gen_andi_tl(x, x, X_FLAG);
		tcg_gen_shri_tl(x, x, 4);
E
edgar_igl 已提交
506

507 508 509 510 511
		tcg_gen_and_tl(x, x, c);
		tcg_gen_add_tl(d, d, x);        
		tcg_temp_free(x);
		tcg_temp_free(c);
	}
E
edgar_igl 已提交
512 513
}

514
static inline void t_gen_subx_carry(DisasContext *dc, TCGv d)
E
edgar_igl 已提交
515
{
516 517 518 519
	if (dc->flagx_known) {
		if (dc->flags_x) {
			TCGv c;
            
P
pbrook 已提交
520
			c = tcg_temp_new();
521 522 523 524 525 526 527
			t_gen_mov_TN_preg(c, PR_CCS);
			/* C flag is already at bit 0.  */
			tcg_gen_andi_tl(c, c, C_FLAG);
			tcg_gen_sub_tl(d, d, c);
			tcg_temp_free(c);
		}
	} else {
528 529
		TCGv x, c;

P
pbrook 已提交
530 531
		x = tcg_temp_new();
		c = tcg_temp_new();
532 533 534 535 536 537 538 539 540 541
		t_gen_mov_TN_preg(x, PR_CCS);
		tcg_gen_mov_tl(c, x);

		/* Propagate carry into d if X is set. Branch free.  */
		tcg_gen_andi_tl(c, c, C_FLAG);
		tcg_gen_andi_tl(x, x, X_FLAG);
		tcg_gen_shri_tl(x, x, 4);

		tcg_gen_and_tl(x, x, c);
		tcg_gen_sub_tl(d, d, x);
542 543
		tcg_temp_free(x);
		tcg_temp_free(c);
544
	}
E
edgar_igl 已提交
545 546 547 548 549 550 551 552
}

/* Swap the two bytes within each half word of the s operand.
   T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff)  */
static inline void t_gen_swapb(TCGv d, TCGv s)
{
	TCGv t, org_s;

P
pbrook 已提交
553 554
	t = tcg_temp_new();
	org_s = tcg_temp_new();
E
edgar_igl 已提交
555 556 557 558 559 560 561 562

	/* d and s may refer to the same object.  */
	tcg_gen_mov_tl(org_s, s);
	tcg_gen_shli_tl(t, org_s, 8);
	tcg_gen_andi_tl(d, t, 0xff00ff00);
	tcg_gen_shri_tl(t, org_s, 8);
	tcg_gen_andi_tl(t, t, 0x00ff00ff);
	tcg_gen_or_tl(d, d, t);
563 564
	tcg_temp_free(t);
	tcg_temp_free(org_s);
E
edgar_igl 已提交
565 566 567 568 569 570 571
}

/* Swap the halfwords of the s operand.  */
static inline void t_gen_swapw(TCGv d, TCGv s)
{
	TCGv t;
	/* d and s refer the same object.  */
P
pbrook 已提交
572
	t = tcg_temp_new();
E
edgar_igl 已提交
573 574 575 576
	tcg_gen_mov_tl(t, s);
	tcg_gen_shli_tl(d, t, 16);
	tcg_gen_shri_tl(t, t, 16);
	tcg_gen_or_tl(d, d, t);
577
	tcg_temp_free(t);
E
edgar_igl 已提交
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
}

/* Reverse the within each byte.
   T0 = (((T0 << 7) & 0x80808080) |
   ((T0 << 5) & 0x40404040) |
   ((T0 << 3) & 0x20202020) |
   ((T0 << 1) & 0x10101010) |
   ((T0 >> 1) & 0x08080808) |
   ((T0 >> 3) & 0x04040404) |
   ((T0 >> 5) & 0x02020202) |
   ((T0 >> 7) & 0x01010101));
 */
static inline void t_gen_swapr(TCGv d, TCGv s)
{
	struct {
		int shift; /* LSL when positive, LSR when negative.  */
		uint32_t mask;
	} bitrev [] = {
		{7, 0x80808080},
		{5, 0x40404040},
		{3, 0x20202020},
		{1, 0x10101010},
		{-1, 0x08080808},
		{-3, 0x04040404},
		{-5, 0x02020202},
		{-7, 0x01010101}
	};
	int i;
	TCGv t, org_s;

	/* d and s refer the same object.  */
P
pbrook 已提交
609 610
	t = tcg_temp_new();
	org_s = tcg_temp_new();
E
edgar_igl 已提交
611 612 613 614
	tcg_gen_mov_tl(org_s, s);

	tcg_gen_shli_tl(t, org_s,  bitrev[0].shift);
	tcg_gen_andi_tl(d, t,  bitrev[0].mask);
615
	for (i = 1; i < ARRAY_SIZE(bitrev); i++) {
E
edgar_igl 已提交
616 617 618 619 620 621 622 623
		if (bitrev[i].shift >= 0) {
			tcg_gen_shli_tl(t, org_s,  bitrev[i].shift);
		} else {
			tcg_gen_shri_tl(t, org_s,  -bitrev[i].shift);
		}
		tcg_gen_andi_tl(t, t,  bitrev[i].mask);
		tcg_gen_or_tl(d, d, t);
	}
624 625
	tcg_temp_free(t);
	tcg_temp_free(org_s);
E
edgar_igl 已提交
626 627
}

628
static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
E
edgar_igl 已提交
629 630 631 632 633
{
	TCGv btaken;
	int l1;

	l1 = gen_new_label();
P
pbrook 已提交
634
	btaken = tcg_temp_new();
E
edgar_igl 已提交
635 636

	/* Conditional jmp.  */
E
edgar_igl 已提交
637
	tcg_gen_mov_tl(btaken, env_btaken);
638
	tcg_gen_mov_tl(env_pc, pc_false);
P
pbrook 已提交
639
	tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1);
640
	tcg_gen_mov_tl(env_pc, pc_true);
E
edgar_igl 已提交
641 642
	gen_set_label(l1);

643
	tcg_temp_free(btaken);
E
edgar_igl 已提交
644 645
}

646 647 648 649 650
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
{
	TranslationBlock *tb;
	tb = dc->tb;
	if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
651
		tcg_gen_goto_tb(n);
652
		tcg_gen_movi_tl(env_pc, dest);
653
		tcg_gen_exit_tb((long)tb + n);
654
	} else {
E
edgar_igl 已提交
655
		tcg_gen_movi_tl(env_pc, dest);
656
		tcg_gen_exit_tb(0);
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
	}
}

/* Sign extend at translation time.  */
static int sign_extend(unsigned int val, unsigned int width)
{
	int sval;

	/* LSL.  */
	val <<= 31 - width;
	sval = val;
	/* ASR.  */
	sval >>= 31 - width;
	return sval;
}

673 674
static inline void cris_clear_x_flag(DisasContext *dc)
{
E
edgar_igl 已提交
675 676 677
	if (dc->flagx_known && dc->flags_x)
		dc->flags_uptodate = 0;

678
	dc->flagx_known = 1;
E
edgar_igl 已提交
679
	dc->flags_x = 0;
680 681
}

682
static void cris_flush_cc_state(DisasContext *dc)
683
{
684
	if (dc->cc_size_uptodate != dc->cc_size) {
E
edgar_igl 已提交
685
		tcg_gen_movi_tl(cc_size, dc->cc_size);
686 687 688 689 690 691 692 693 694 695
		dc->cc_size_uptodate = dc->cc_size;
	}
	tcg_gen_movi_tl(cc_op, dc->cc_op);
	tcg_gen_movi_tl(cc_mask, dc->cc_mask);
}

static void cris_evaluate_flags(DisasContext *dc)
{
	if (!dc->flags_uptodate) {
		cris_flush_cc_state(dc);
E
edgar_igl 已提交
696

697 698 699
		switch (dc->cc_op)
		{
			case CC_OP_MCP:
P
pbrook 已提交
700
				gen_helper_evaluate_flags_mcp();
701 702
				break;
			case CC_OP_MULS:
P
pbrook 已提交
703
				gen_helper_evaluate_flags_muls();
704 705
				break;
			case CC_OP_MULU:
P
pbrook 已提交
706
				gen_helper_evaluate_flags_mulu();
707 708
				break;
			case CC_OP_MOVE:
709 710 711 712 713 714
			case CC_OP_AND:
			case CC_OP_OR:
			case CC_OP_XOR:
			case CC_OP_ASR:
			case CC_OP_LSR:
			case CC_OP_LSL:
715 716 717
				switch (dc->cc_size)
				{
					case 4:
P
pbrook 已提交
718
						gen_helper_evaluate_flags_move_4();
719 720
						break;
					case 2:
P
pbrook 已提交
721
						gen_helper_evaluate_flags_move_2();
722 723
						break;
					default:
P
pbrook 已提交
724
						gen_helper_evaluate_flags();
725 726 727
						break;
				}
				break;
E
edgar_igl 已提交
728 729 730
			case CC_OP_FLAGS:
				/* live.  */
				break;
731 732 733 734 735 736 737 738
			case CC_OP_SUB:
			case CC_OP_CMP:
				if (dc->cc_size == 4)
					gen_helper_evaluate_flags_sub_4();
				else
					gen_helper_evaluate_flags();

				break;
739 740 741 742
			default:
				switch (dc->cc_size)
				{
					case 4:
P
pbrook 已提交
743
						gen_helper_evaluate_flags_alu_4();
744 745
						break;
					default:
P
pbrook 已提交
746
						gen_helper_evaluate_flags();
747 748 749 750
						break;
				}
			break;
		}
E
edgar_igl 已提交
751 752 753 754 755 756 757
		if (dc->flagx_known) {
			if (dc->flags_x)
				tcg_gen_ori_tl(cpu_PR[PR_CCS], 
					       cpu_PR[PR_CCS], X_FLAG);
			else
				tcg_gen_andi_tl(cpu_PR[PR_CCS], 
						cpu_PR[PR_CCS], ~X_FLAG);
E
edgar_igl 已提交
758
	        }
E
edgar_igl 已提交
759

760
		dc->flags_uptodate = 1;
761 762 763 764 765 766 767
	}
}

static void cris_cc_mask(DisasContext *dc, unsigned int mask)
{
	uint32_t ovl;

E
edgar_igl 已提交
768 769 770 771 772
	if (!mask) {
		dc->update_cc = 0;
		return;
	}	

773 774
	/* Check if we need to evaluate the condition codes due to 
	   CC overlaying.  */
775 776 777 778 779 780 781 782 783
	ovl = (dc->cc_mask ^ mask) & ~mask;
	if (ovl) {
		/* TODO: optimize this case. It trigs all the time.  */
		cris_evaluate_flags (dc);
	}
	dc->cc_mask = mask;
	dc->update_cc = 1;
}

E
edgar_igl 已提交
784
static void cris_update_cc_op(DisasContext *dc, int op, int size)
785 786 787
{
	dc->cc_op = op;
	dc->cc_size = size;
788
	dc->flags_uptodate = 0;
789 790
}

791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
static inline void cris_update_cc_x(DisasContext *dc)
{
	/* Save the x flag state at the time of the cc snapshot.  */
	if (dc->flagx_known) {
		if (dc->cc_x_uptodate == (2 | dc->flags_x))
			return;
		tcg_gen_movi_tl(cc_x, dc->flags_x);
		dc->cc_x_uptodate = 2 | dc->flags_x;
	}
	else {
		tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG);
		dc->cc_x_uptodate = 1;
	}
}

/* Update cc prior to executing ALU op. Needs source operands untouched.  */
static void cris_pre_alu_update_cc(DisasContext *dc, int op, 
				   TCGv dst, TCGv src, int size)
809 810
{
	if (dc->update_cc) {
E
edgar_igl 已提交
811
		cris_update_cc_op(dc, op, size);
812 813 814 815 816 817 818 819 820 821 822 823 824 825
		tcg_gen_mov_tl(cc_src, src);

		if (op != CC_OP_MOVE
		    && op != CC_OP_AND
		    && op != CC_OP_OR
		    && op != CC_OP_XOR
		    && op != CC_OP_ASR
		    && op != CC_OP_LSR
		    && op != CC_OP_LSL)
			tcg_gen_mov_tl(cc_dest, dst);

		cris_update_cc_x(dc);
	}
}
E
edgar_igl 已提交
826

827 828 829
/* Update cc after executing ALU op. needs the result.  */
static inline void cris_update_result(DisasContext *dc, TCGv res)
{
830
	if (dc->update_cc)
831 832
		tcg_gen_mov_tl(cc_result, res);
}
833

834 835 836 837
/* Returns one if the write back stage should execute.  */
static void cris_alu_op_exec(DisasContext *dc, int op, 
			       TCGv dst, TCGv a, TCGv b, int size)
{
838 839 840 841
	/* Emit the ALU insns.  */
	switch (op)
	{
		case CC_OP_ADD:
842
			tcg_gen_add_tl(dst, a, b);
843
			/* Extended arithmetics.  */
844
			t_gen_addx_carry(dc, dst);
845 846
			break;
		case CC_OP_ADDC:
847 848
			tcg_gen_add_tl(dst, a, b);
			t_gen_add_flag(dst, 0); /* C_FLAG.  */
849 850
			break;
		case CC_OP_MCP:
851 852
			tcg_gen_add_tl(dst, a, b);
			t_gen_add_flag(dst, 8); /* R_FLAG.  */
853 854
			break;
		case CC_OP_SUB:
855
			tcg_gen_sub_tl(dst, a, b);
856
			/* Extended arithmetics.  */
857
			t_gen_subx_carry(dc, dst);
858 859
			break;
		case CC_OP_MOVE:
860
			tcg_gen_mov_tl(dst, b);
861 862
			break;
		case CC_OP_OR:
863
			tcg_gen_or_tl(dst, a, b);
864 865
			break;
		case CC_OP_AND:
866
			tcg_gen_and_tl(dst, a, b);
867 868
			break;
		case CC_OP_XOR:
869
			tcg_gen_xor_tl(dst, a, b);
870 871
			break;
		case CC_OP_LSL:
872
			t_gen_lsl(dst, a, b);
873 874
			break;
		case CC_OP_LSR:
875
			t_gen_lsr(dst, a, b);
876 877
			break;
		case CC_OP_ASR:
878
			t_gen_asr(dst, a, b);
879 880
			break;
		case CC_OP_NEG:
881
			tcg_gen_neg_tl(dst, b);
882
			/* Extended arithmetics.  */
883
			t_gen_subx_carry(dc, dst);
884 885
			break;
		case CC_OP_LZ:
886
			t_gen_lz_i32(dst, b);
887 888
			break;
		case CC_OP_BTST:
889
			t_gen_btst(dst, a, b);
890 891
			break;
		case CC_OP_MULS:
892 893
			t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
			break;
894
		case CC_OP_MULU:
895 896
			t_gen_mulu(dst, cpu_PR[PR_MOF], a, b);
			break;
897
		case CC_OP_DSTEP:
898
			t_gen_cris_dstep(dst, a, b);
899 900
			break;
		case CC_OP_BOUND:
E
edgar_igl 已提交
901 902 903
		{
			int l1;
			l1 = gen_new_label();
904 905 906
			tcg_gen_mov_tl(dst, a);
			tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1);
			tcg_gen_mov_tl(dst, b);
E
edgar_igl 已提交
907 908 909
			gen_set_label(l1);
		}
		break;
910
		case CC_OP_CMP:
911
			tcg_gen_sub_tl(dst, a, b);
912
			/* Extended arithmetics.  */
913
			t_gen_subx_carry(dc, dst);
914 915 916 917 918 919 920 921
			break;
		default:
			fprintf (logfile, "illegal ALU op.\n");
			BUG();
			break;
	}

	if (size == 1)
922
		tcg_gen_andi_tl(dst, dst, 0xff);
923
	else if (size == 2)
924 925 926 927 928 929 930 931 932 933
		tcg_gen_andi_tl(dst, dst, 0xffff);
}

static void cris_alu(DisasContext *dc, int op,
			       TCGv d, TCGv op_a, TCGv op_b, int size)
{
	TCGv tmp;
	int writeback;

	writeback = 1;
E
edgar_igl 已提交
934 935

	if (op == CC_OP_BOUND || op == CC_OP_BTST)
P
pbrook 已提交
936
		tmp = tcg_temp_local_new();
E
edgar_igl 已提交
937 938

	if (op == CC_OP_CMP) {
P
pbrook 已提交
939
		tmp = tcg_temp_new();
940
		writeback = 0;
E
edgar_igl 已提交
941
	} else if (size == 4) {
942 943
		tmp = d;
		writeback = 0;
E
edgar_igl 已提交
944
	} else
P
pbrook 已提交
945
		tmp = tcg_temp_new();
E
edgar_igl 已提交
946

947 948 949 950

	cris_pre_alu_update_cc(dc, op, op_a, op_b, size);
	cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);
	cris_update_result(dc, tmp);
951

952 953
	/* Writeback.  */
	if (writeback) {
954 955 956 957 958
		if (size == 1)
			tcg_gen_andi_tl(d, d, ~0xff);
		else
			tcg_gen_andi_tl(d, d, ~0xffff);
		tcg_gen_or_tl(d, d, tmp);
959
	}
P
pbrook 已提交
960
	if (!TCGV_EQUAL(tmp, d))
E
edgar_igl 已提交
961
		tcg_temp_free(tmp);
962 963 964 965 966 967
}

static int arith_cc(DisasContext *dc)
{
	if (dc->update_cc) {
		switch (dc->cc_op) {
968
			case CC_OP_ADDC: return 1;
969 970
			case CC_OP_ADD: return 1;
			case CC_OP_SUB: return 1;
971
			case CC_OP_DSTEP: return 1;
972 973 974 975
			case CC_OP_LSL: return 1;
			case CC_OP_LSR: return 1;
			case CC_OP_ASR: return 1;
			case CC_OP_CMP: return 1;
976 977 978 979 980
			case CC_OP_NEG: return 1;
			case CC_OP_OR: return 1;
			case CC_OP_XOR: return 1;
			case CC_OP_MULU: return 1;
			case CC_OP_MULS: return 1;
981 982 983 984 985 986 987
			default:
				return 0;
		}
	}
	return 0;
}

988
static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
989
{
E
edgar_igl 已提交
990
	int arith_opt, move_opt;
991 992

	/* TODO: optimize more condition codes.  */
E
edgar_igl 已提交
993 994 995 996 997 998 999 1000 1001

	/*
	 * If the flags are live, we've gotta look into the bits of CCS.
	 * Otherwise, if we just did an arithmetic operation we try to
	 * evaluate the condition code faster.
	 *
	 * When this function is done, T0 should be non-zero if the condition
	 * code is true.
	 */
1002
	arith_opt = arith_cc(dc) && !dc->flags_uptodate;
1003
	move_opt = (dc->cc_op == CC_OP_MOVE) && dc->flags_uptodate;
1004 1005
	switch (cond) {
		case CC_EQ:
E
edgar_igl 已提交
1006
			if (arith_opt || move_opt) {
E
edgar_igl 已提交
1007 1008 1009 1010
				/* If cc_result is zero, T0 should be 
				   non-zero otherwise T0 should be zero.  */
				int l1;
				l1 = gen_new_label();
1011
				tcg_gen_movi_tl(cc, 0);
P
pbrook 已提交
1012 1013
				tcg_gen_brcondi_tl(TCG_COND_NE, cc_result, 
						   0, l1);
1014
				tcg_gen_movi_tl(cc, 1);
E
edgar_igl 已提交
1015 1016
				gen_set_label(l1);
			}
1017 1018
			else {
				cris_evaluate_flags(dc);
1019
				tcg_gen_andi_tl(cc, 
E
edgar_igl 已提交
1020
						cpu_PR[PR_CCS], Z_FLAG);
1021 1022 1023
			}
			break;
		case CC_NE:
E
edgar_igl 已提交
1024
			if (arith_opt || move_opt)
1025
				tcg_gen_mov_tl(cc, cc_result);
1026 1027
			else {
				cris_evaluate_flags(dc);
1028
				tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
E
edgar_igl 已提交
1029
						Z_FLAG);
1030
				tcg_gen_andi_tl(cc, cc, Z_FLAG);
1031 1032 1033 1034
			}
			break;
		case CC_CS:
			cris_evaluate_flags(dc);
1035
			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG);
1036 1037 1038
			break;
		case CC_CC:
			cris_evaluate_flags(dc);
1039 1040
			tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG);
			tcg_gen_andi_tl(cc, cc, C_FLAG);
1041 1042 1043
			break;
		case CC_VS:
			cris_evaluate_flags(dc);
1044
			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG);
1045 1046 1047
			break;
		case CC_VC:
			cris_evaluate_flags(dc);
1048
			tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
E
edgar_igl 已提交
1049
					V_FLAG);
1050
			tcg_gen_andi_tl(cc, cc, V_FLAG);
1051 1052
			break;
		case CC_PL:
E
edgar_igl 已提交
1053 1054 1055 1056 1057 1058 1059 1060
			if (arith_opt || move_opt) {
				int bits = 31;

				if (dc->cc_size == 1)
					bits = 7;
				else if (dc->cc_size == 2)
					bits = 15;	

1061 1062
				tcg_gen_shri_tl(cc, cc_result, bits);
				tcg_gen_xori_tl(cc, cc, 1);
E
edgar_igl 已提交
1063
			} else {
1064
				cris_evaluate_flags(dc);
1065
				tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
E
edgar_igl 已提交
1066
						N_FLAG);
1067
				tcg_gen_andi_tl(cc, cc, N_FLAG);
1068 1069 1070
			}
			break;
		case CC_MI:
E
edgar_igl 已提交
1071 1072 1073 1074 1075 1076 1077 1078
			if (arith_opt || move_opt) {
				int bits = 31;

				if (dc->cc_size == 1)
					bits = 7;
				else if (dc->cc_size == 2)
					bits = 15;	

1079
				tcg_gen_shri_tl(cc, cc_result, 31);
E
edgar_igl 已提交
1080
			}
1081 1082
			else {
				cris_evaluate_flags(dc);
1083
				tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
E
edgar_igl 已提交
1084
						N_FLAG);
1085 1086 1087 1088
			}
			break;
		case CC_LS:
			cris_evaluate_flags(dc);
1089
			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
E
edgar_igl 已提交
1090
					C_FLAG | Z_FLAG);
1091 1092 1093
			break;
		case CC_HI:
			cris_evaluate_flags(dc);
E
edgar_igl 已提交
1094 1095 1096
			{
				TCGv tmp;

P
pbrook 已提交
1097
				tmp = tcg_temp_new();
E
edgar_igl 已提交
1098 1099 1100
				tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS],
						C_FLAG | Z_FLAG);
				/* Overlay the C flag on top of the Z.  */
1101 1102 1103
				tcg_gen_shli_tl(cc, tmp, 2);
				tcg_gen_and_tl(cc, tmp, cc);
				tcg_gen_andi_tl(cc, cc, Z_FLAG);
E
edgar_igl 已提交
1104

1105
				tcg_temp_free(tmp);
E
edgar_igl 已提交
1106
			}
1107 1108 1109
			break;
		case CC_GE:
			cris_evaluate_flags(dc);
E
edgar_igl 已提交
1110
			/* Overlay the V flag on top of the N.  */
1111 1112 1113 1114 1115
			tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
			tcg_gen_xor_tl(cc,
				       cpu_PR[PR_CCS], cc);
			tcg_gen_andi_tl(cc, cc, N_FLAG);
			tcg_gen_xori_tl(cc, cc, N_FLAG);
1116 1117 1118
			break;
		case CC_LT:
			cris_evaluate_flags(dc);
E
edgar_igl 已提交
1119
			/* Overlay the V flag on top of the N.  */
1120 1121 1122 1123
			tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
			tcg_gen_xor_tl(cc,
				       cpu_PR[PR_CCS], cc);
			tcg_gen_andi_tl(cc, cc, N_FLAG);
1124 1125 1126
			break;
		case CC_GT:
			cris_evaluate_flags(dc);
E
edgar_igl 已提交
1127 1128 1129
			{
				TCGv n, z;

P
pbrook 已提交
1130 1131
				n = tcg_temp_new();
				z = tcg_temp_new();
E
edgar_igl 已提交
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141

				/* To avoid a shift we overlay everything on
				   the V flag.  */
				tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
				tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
				/* invert Z.  */
				tcg_gen_xori_tl(z, z, 2);

				tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
				tcg_gen_xori_tl(n, n, 2);
1142 1143
				tcg_gen_and_tl(cc, z, n);
				tcg_gen_andi_tl(cc, cc, 2);
E
edgar_igl 已提交
1144

1145 1146
				tcg_temp_free(n);
				tcg_temp_free(z);
E
edgar_igl 已提交
1147
			}
1148 1149 1150
			break;
		case CC_LE:
			cris_evaluate_flags(dc);
E
edgar_igl 已提交
1151 1152 1153
			{
				TCGv n, z;

P
pbrook 已提交
1154 1155
				n = tcg_temp_new();
				z = tcg_temp_new();
E
edgar_igl 已提交
1156 1157 1158 1159 1160 1161 1162

				/* To avoid a shift we overlay everything on
				   the V flag.  */
				tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
				tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);

				tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
1163 1164
				tcg_gen_or_tl(cc, z, n);
				tcg_gen_andi_tl(cc, cc, 2);
E
edgar_igl 已提交
1165

1166 1167
				tcg_temp_free(n);
				tcg_temp_free(z);
E
edgar_igl 已提交
1168
			}
1169 1170 1171
			break;
		case CC_P:
			cris_evaluate_flags(dc);
1172
			tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], P_FLAG);
1173 1174
			break;
		case CC_A:
1175
			tcg_gen_movi_tl(cc, 1);
1176 1177 1178 1179 1180 1181 1182
			break;
		default:
			BUG();
			break;
	};
}

E
edgar_igl 已提交
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
static void cris_store_direct_jmp(DisasContext *dc)
{
	/* Store the direct jmp state into the cpu-state.  */
	if (dc->jmp == JMP_DIRECT) {
		tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
		tcg_gen_movi_tl(env_btaken, 1);
	}
}

static void cris_prepare_cc_branch (DisasContext *dc, 
				    int offset, int cond)
1194 1195 1196 1197
{
	/* This helps us re-schedule the micro-code to insns in delay-slots
	   before the actual jump.  */
	dc->delayed_branch = 2;
E
edgar_igl 已提交
1198 1199
	dc->jmp_pc = dc->pc + offset;

1200 1201
	if (cond != CC_A)
	{
E
edgar_igl 已提交
1202
		dc->jmp = JMP_INDIRECT;
1203
		gen_tst_cc (dc, env_btaken, cond);
E
edgar_igl 已提交
1204 1205 1206 1207 1208
		tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
	} else {
		/* Allow chaining.  */
		dc->jmp = JMP_DIRECT;
	}
1209 1210
}

E
edgar_igl 已提交
1211

E
edgar_igl 已提交
1212 1213 1214
/* jumps, when the dest is in a live reg for example. Direct should be set
   when the dest addr is constant to allow tb chaining.  */
static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
1215 1216 1217 1218
{
	/* This helps us re-schedule the micro-code to insns in delay-slots
	   before the actual jump.  */
	dc->delayed_branch = 2;
E
edgar_igl 已提交
1219 1220 1221
	dc->jmp = type;
	if (type == JMP_INDIRECT)
		tcg_gen_movi_tl(env_btaken, 1);
1222 1223
}

P
pbrook 已提交
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
{
	int mem_index = cpu_mmu_index(dc->env);

	/* If we get a fault on a delayslot we must keep the jmp state in
	   the cpu-state to be able to re-execute the jmp.  */
	if (dc->delayed_branch == 1)
		cris_store_direct_jmp(dc);

        tcg_gen_qemu_ld64(dst, addr, mem_index);
}

E
edgar_igl 已提交
1236 1237
static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, 
		     unsigned int size, int sign)
1238
{
E
edgar_igl 已提交
1239 1240
	int mem_index = cpu_mmu_index(dc->env);

E
edgar_igl 已提交
1241 1242 1243 1244 1245
	/* If we get a fault on a delayslot we must keep the jmp state in
	   the cpu-state to be able to re-execute the jmp.  */
	if (dc->delayed_branch == 1)
		cris_store_direct_jmp(dc);

1246 1247
	if (size == 1) {
		if (sign)
E
edgar_igl 已提交
1248
			tcg_gen_qemu_ld8s(dst, addr, mem_index);
1249
		else
E
edgar_igl 已提交
1250
			tcg_gen_qemu_ld8u(dst, addr, mem_index);
1251 1252 1253
	}
	else if (size == 2) {
		if (sign)
E
edgar_igl 已提交
1254
			tcg_gen_qemu_ld16s(dst, addr, mem_index);
1255
		else
E
edgar_igl 已提交
1256
			tcg_gen_qemu_ld16u(dst, addr, mem_index);
1257
	}
1258
	else if (size == 4) {
1259
		tcg_gen_qemu_ld32u(dst, addr, mem_index);
1260
	}
P
pbrook 已提交
1261 1262
	else {
		abort();
1263
	}
1264 1265
}

E
edgar_igl 已提交
1266 1267
static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
		       unsigned int size)
1268
{
E
edgar_igl 已提交
1269 1270
	int mem_index = cpu_mmu_index(dc->env);

E
edgar_igl 已提交
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
	/* If we get a fault on a delayslot we must keep the jmp state in
	   the cpu-state to be able to re-execute the jmp.  */
	if (dc->delayed_branch == 1)
 		cris_store_direct_jmp(dc);


	/* Conditional writes. We only support the kind were X and P are known
	   at translation time.  */
	if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) {
		dc->postinc = 0;
		cris_evaluate_flags(dc);
		tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG);
		return;
	}

E
edgar_igl 已提交
1286
	if (size == 1)
E
edgar_igl 已提交
1287
		tcg_gen_qemu_st8(val, addr, mem_index);
E
edgar_igl 已提交
1288
	else if (size == 2)
E
edgar_igl 已提交
1289
		tcg_gen_qemu_st16(val, addr, mem_index);
1290
	else
E
edgar_igl 已提交
1291
		tcg_gen_qemu_st32(val, addr, mem_index);
E
edgar_igl 已提交
1292 1293 1294 1295 1296

	if (dc->flagx_known && dc->flags_x) {
		cris_evaluate_flags(dc);
		tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG);
	}
1297 1298
}

1299
static inline void t_gen_sext(TCGv d, TCGv s, int size)
1300 1301
{
	if (size == 1)
1302
		tcg_gen_ext8s_i32(d, s);
1303
	else if (size == 2)
1304
		tcg_gen_ext16s_i32(d, s);
P
pbrook 已提交
1305
	else if(!TCGV_EQUAL(d, s))
1306
		tcg_gen_mov_tl(d, s);
1307 1308
}

1309
static inline void t_gen_zext(TCGv d, TCGv s, int size)
1310 1311
{
	if (size == 1)
P
pbrook 已提交
1312
		tcg_gen_ext8u_i32(d, s);
1313
	else if (size == 2)
P
pbrook 已提交
1314
		tcg_gen_ext16u_i32(d, s);
P
pbrook 已提交
1315
	else if (!TCGV_EQUAL(d, s))
1316
		tcg_gen_mov_tl(d, s);
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
}

#if DISAS_CRIS
static char memsize_char(int size)
{
	switch (size)
	{
		case 1: return 'b';  break;
		case 2: return 'w';  break;
		case 4: return 'd';  break;
		default:
			return 'x';
			break;
	}
}
#endif

1334
static inline unsigned int memsize_z(DisasContext *dc)
1335 1336 1337 1338
{
	return dc->zsize + 1;
}

1339
static inline unsigned int memsize_zz(DisasContext *dc)
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
{
	switch (dc->zzsize)
	{
		case 0: return 1;
		case 1: return 2;
		default:
			return 4;
	}
}

1350
static inline void do_postinc (DisasContext *dc, int size)
1351
{
1352 1353
	if (dc->postinc)
		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size);
1354 1355
}

1356
static inline void dec_prep_move_r(DisasContext *dc, int rs, int rd,
E
edgar_igl 已提交
1357
				   int size, int s_ext, TCGv dst)
1358 1359
{
	if (s_ext)
1360
		t_gen_sext(dst, cpu_R[rs], size);
1361
	else
1362
		t_gen_zext(dst, cpu_R[rs], size);
1363 1364 1365 1366 1367 1368
}

/* Prepare T0 and T1 for a register alu operation.
   s_ext decides if the operand1 should be sign-extended or zero-extended when
   needed.  */
static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
E
edgar_igl 已提交
1369
			  int size, int s_ext, TCGv dst, TCGv src)
1370
{
E
edgar_igl 已提交
1371
	dec_prep_move_r(dc, rs, rd, size, s_ext, src);
1372 1373

	if (s_ext)
E
edgar_igl 已提交
1374
		t_gen_sext(dst, cpu_R[rd], size);
1375
	else
E
edgar_igl 已提交
1376
		t_gen_zext(dst, cpu_R[rd], size);
1377 1378
}

1379 1380
static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize,
			   TCGv dst)
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
{
	unsigned int rs, rd;
	uint32_t imm;
	int is_imm;
	int insn_len = 2;

	rs = dc->op1;
	rd = dc->op2;
	is_imm = rs == 15 && dc->postinc;

	/* Load [$rs] onto T1.  */
	if (is_imm) {
		insn_len = 2 + memsize;
		if (memsize == 1)
			insn_len++;

		if (memsize != 4) {
			if (s_ext) {
E
edgar_igl 已提交
1399 1400 1401 1402
				if (memsize == 1)
					imm = ldsb_code(dc->pc + 2);
				else
					imm = ldsw_code(dc->pc + 2);
1403 1404
			} else {
				if (memsize == 1)
E
edgar_igl 已提交
1405
					imm = ldub_code(dc->pc + 2);
1406
				else
E
edgar_igl 已提交
1407
					imm = lduw_code(dc->pc + 2);
1408
			}
E
edgar_igl 已提交
1409 1410 1411
		} else
			imm = ldl_code(dc->pc + 2);
			
1412
		tcg_gen_movi_tl(dst, imm);
1413 1414
		dc->postinc = 0;
	} else {
1415 1416
		cris_flush_cc_state(dc);
		gen_load(dc, dst, cpu_R[rs], memsize, 0);
1417
		if (s_ext)
1418
			t_gen_sext(dst, dst, memsize);
1419
		else
1420
			t_gen_zext(dst, dst, memsize);
1421
	}
1422 1423 1424 1425 1426 1427
	return insn_len;
}

/* Prepare T0 and T1 for a memory + alu operation.
   s_ext decides if the operand1 should be sign-extended or zero-extended when
   needed.  */
E
edgar_igl 已提交
1428 1429
static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize,
			  TCGv dst, TCGv src)
1430 1431 1432
{
	int insn_len;

E
edgar_igl 已提交
1433 1434
	insn_len = dec_prep_move_m(dc, s_ext, memsize, src);
	tcg_gen_mov_tl(dst, cpu_R[dc->op2]);
1435 1436 1437 1438 1439 1440
	return insn_len;
}

#if DISAS_CRIS
static const char *cc_name(int cc)
{
E
edgar_igl 已提交
1441
	static const char *cc_names[16] = {
1442 1443 1444 1445 1446 1447 1448 1449
		"cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
		"ls", "hi", "ge", "lt", "gt", "le", "a", "p"
	};
	assert(cc < 16);
	return cc_names[cc];
}
#endif

E
edgar_igl 已提交
1450 1451
/* Start of insn decoders.  */

1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
static unsigned int dec_bccq(DisasContext *dc)
{
	int32_t offset;
	int sign;
	uint32_t cond = dc->op2;
	int tmp;

	offset = EXTRACT_FIELD (dc->ir, 1, 7);
	sign = EXTRACT_FIELD(dc->ir, 0, 0);

	offset *= 2;
	offset |= sign << 8;
	tmp = offset;
	offset = sign_extend(offset, 8);

E
edgar_igl 已提交
1467 1468
	DIS(fprintf (logfile, "b%s %x\n", cc_name(cond), dc->pc + offset));

1469 1470 1471 1472 1473 1474 1475
	/* op2 holds the condition-code.  */
	cris_cc_mask(dc, 0);
	cris_prepare_cc_branch (dc, offset, cond);
	return 2;
}
static unsigned int dec_addoq(DisasContext *dc)
{
E
edgar_igl 已提交
1476
	int32_t imm;
1477 1478 1479 1480 1481 1482 1483

	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
	imm = sign_extend(dc->op1, 7);

	DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2));
	cris_cc_mask(dc, 0);
	/* Fetch register operand,  */
E
edgar_igl 已提交
1484
	tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm);
E
edgar_igl 已提交
1485

1486 1487 1488 1489 1490 1491 1492 1493 1494
	return 2;
}
static unsigned int dec_addq(DisasContext *dc)
{
	DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2));

	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);

	cris_cc_mask(dc, CC_MASK_NZVC);
1495 1496 1497

	cris_alu(dc, CC_OP_ADD,
		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
	return 2;
}
static unsigned int dec_moveq(DisasContext *dc)
{
	uint32_t imm;

	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
	imm = sign_extend(dc->op1, 5);
	DIS(fprintf (logfile, "moveq %d, $r%u\n", imm, dc->op2));

1508
	tcg_gen_mov_tl(cpu_R[dc->op2], tcg_const_tl(imm));
1509 1510 1511 1512 1513 1514 1515 1516 1517
	return 2;
}
static unsigned int dec_subq(DisasContext *dc)
{
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);

	DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZVC);
1518 1519
	cris_alu(dc, CC_OP_SUB,
		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
	return 2;
}
static unsigned int dec_cmpq(DisasContext *dc)
{
	uint32_t imm;
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
	imm = sign_extend(dc->op1, 5);

	DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZVC);
1530 1531 1532

	cris_alu(dc, CC_OP_CMP,
		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
	return 2;
}
static unsigned int dec_andq(DisasContext *dc)
{
	uint32_t imm;
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
	imm = sign_extend(dc->op1, 5);

	DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
1543 1544 1545

	cris_alu(dc, CC_OP_AND,
		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
1546 1547 1548 1549 1550 1551 1552 1553 1554
	return 2;
}
static unsigned int dec_orq(DisasContext *dc)
{
	uint32_t imm;
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
	imm = sign_extend(dc->op1, 5);
	DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
1555 1556 1557

	cris_alu(dc, CC_OP_OR,
		    cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
1558 1559 1560 1561
	return 2;
}
static unsigned int dec_btstq(DisasContext *dc)
{
E
edgar_igl 已提交
1562
	TCGv l0;
1563 1564
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
	DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
E
edgar_igl 已提交
1565

1566
	cris_cc_mask(dc, CC_MASK_NZ);
P
pbrook 已提交
1567
	l0 = tcg_temp_local_new();
1568
	cris_alu(dc, CC_OP_BTST,
E
edgar_igl 已提交
1569
		 l0, cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
E
edgar_igl 已提交
1570
	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
E
edgar_igl 已提交
1571
	t_gen_mov_preg_TN(dc, PR_CCS, l0);
1572
	dc->flags_uptodate = 1;
E
edgar_igl 已提交
1573
	tcg_temp_free(l0);
1574 1575 1576 1577 1578 1579 1580
	return 2;
}
static unsigned int dec_asrq(DisasContext *dc)
{
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
	DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
1581

E
edgar_igl 已提交
1582 1583
	tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
	cris_alu(dc, CC_OP_MOVE,
1584
		    cpu_R[dc->op2],
E
edgar_igl 已提交
1585
		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
1586 1587 1588 1589 1590 1591 1592 1593
	return 2;
}
static unsigned int dec_lslq(DisasContext *dc)
{
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
	DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZ);
1594

E
edgar_igl 已提交
1595 1596 1597
	tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);

	cris_alu(dc, CC_OP_MOVE,
1598
		    cpu_R[dc->op2],
E
edgar_igl 已提交
1599
		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
1600 1601 1602 1603 1604 1605 1606 1607
	return 2;
}
static unsigned int dec_lsrq(DisasContext *dc)
{
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
	DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZ);
1608

E
edgar_igl 已提交
1609 1610
	tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
	cris_alu(dc, CC_OP_MOVE,
1611
		    cpu_R[dc->op2],
E
edgar_igl 已提交
1612
		    cpu_R[dc->op2], cpu_R[dc->op2], 4);
1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623
	return 2;
}

static unsigned int dec_move_r(DisasContext *dc)
{
	int size = memsize_zz(dc);

	DIS(fprintf (logfile, "move.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZ);
1624 1625 1626 1627 1628 1629 1630 1631
	if (size == 4) {
		dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
		cris_cc_mask(dc, CC_MASK_NZ);
		cris_update_cc_op(dc, CC_OP_MOVE, 4);
		cris_update_cc_x(dc);
		cris_update_result(dc, cpu_R[dc->op2]);
	}
	else {
E
edgar_igl 已提交
1632 1633
		TCGv t0;

P
pbrook 已提交
1634
		t0 = tcg_temp_new();
E
edgar_igl 已提交
1635
		dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
1636 1637
		cris_alu(dc, CC_OP_MOVE,
			 cpu_R[dc->op2],
E
edgar_igl 已提交
1638 1639
			 cpu_R[dc->op2], t0, size);
		tcg_temp_free(t0);
1640
	}
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
	return 2;
}

static unsigned int dec_scc_r(DisasContext *dc)
{
	int cond = dc->op2;

	DIS(fprintf (logfile, "s%s $r%u\n",
		    cc_name(cond), dc->op1));

	if (cond != CC_A)
	{
E
edgar_igl 已提交
1653 1654
		int l1;

1655
		gen_tst_cc (dc, cpu_R[dc->op1], cond);
E
edgar_igl 已提交
1656
		l1 = gen_new_label();
1657
		tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->op1], 0, l1);
E
edgar_igl 已提交
1658 1659
		tcg_gen_movi_tl(cpu_R[dc->op1], 1);
		gen_set_label(l1);
1660 1661
	}
	else
E
edgar_igl 已提交
1662
		tcg_gen_movi_tl(cpu_R[dc->op1], 1);
1663 1664 1665 1666 1667

	cris_cc_mask(dc, 0);
	return 2;
}

E
edgar_igl 已提交
1668 1669 1670 1671 1672 1673
static inline void cris_alu_alloc_temps(DisasContext *dc, int size, TCGv *t)
{
	if (size == 4) {
		t[0] = cpu_R[dc->op2];
		t[1] = cpu_R[dc->op1];
	} else {
P
pbrook 已提交
1674 1675
		t[0] = tcg_temp_new();
		t[1] = tcg_temp_new();
E
edgar_igl 已提交
1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686
	}
}

static inline void cris_alu_free_temps(DisasContext *dc, int size, TCGv *t)
{
	if (size != 4) {
		tcg_temp_free(t[0]);
		tcg_temp_free(t[1]);
	}
}

1687 1688
static unsigned int dec_and_r(DisasContext *dc)
{
E
edgar_igl 已提交
1689
	TCGv t[2];
1690 1691 1692 1693
	int size = memsize_zz(dc);

	DIS(fprintf (logfile, "and.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
E
edgar_igl 已提交
1694

1695
	cris_cc_mask(dc, CC_MASK_NZ);
1696

E
edgar_igl 已提交
1697 1698 1699 1700
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
	cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
1701 1702 1703 1704 1705
	return 2;
}

static unsigned int dec_lz_r(DisasContext *dc)
{
E
edgar_igl 已提交
1706
	TCGv t0;
1707 1708 1709
	DIS(fprintf (logfile, "lz $r%u, $r%u\n",
		    dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
P
pbrook 已提交
1710
	t0 = tcg_temp_new();
E
edgar_igl 已提交
1711 1712 1713
	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0);
	cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
	tcg_temp_free(t0);
1714 1715 1716 1717 1718
	return 2;
}

static unsigned int dec_lsl_r(DisasContext *dc)
{
E
edgar_igl 已提交
1719
	TCGv t[2];
1720 1721 1722 1723
	int size = memsize_zz(dc);

	DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
1724

E
edgar_igl 已提交
1725 1726 1727 1728 1729 1730
	cris_cc_mask(dc, CC_MASK_NZ);
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
	tcg_gen_andi_tl(t[1], t[1], 63);
	cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_alloc_temps(dc, size, t);
1731 1732 1733 1734 1735
	return 2;
}

static unsigned int dec_lsr_r(DisasContext *dc)
{
E
edgar_igl 已提交
1736
	TCGv t[2];
1737 1738 1739 1740
	int size = memsize_zz(dc);

	DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
1741

E
edgar_igl 已提交
1742 1743 1744 1745 1746 1747
	cris_cc_mask(dc, CC_MASK_NZ);
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
	tcg_gen_andi_tl(t[1], t[1], 63);
	cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
1748 1749 1750 1751 1752
	return 2;
}

static unsigned int dec_asr_r(DisasContext *dc)
{
E
edgar_igl 已提交
1753
	TCGv t[2];
1754 1755 1756 1757
	int size = memsize_zz(dc);

	DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
1758

E
edgar_igl 已提交
1759 1760 1761 1762 1763 1764
	cris_cc_mask(dc, CC_MASK_NZ);
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
	tcg_gen_andi_tl(t[1], t[1], 63);
	cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
1765 1766 1767 1768 1769
	return 2;
}

static unsigned int dec_muls_r(DisasContext *dc)
{
E
edgar_igl 已提交
1770
	TCGv t[2];
1771 1772 1773 1774 1775
	int size = memsize_zz(dc);

	DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZV);
E
edgar_igl 已提交
1776 1777
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
1778

E
edgar_igl 已提交
1779 1780
	cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4);
	cris_alu_free_temps(dc, size, t);
1781 1782 1783 1784 1785
	return 2;
}

static unsigned int dec_mulu_r(DisasContext *dc)
{
E
edgar_igl 已提交
1786
	TCGv t[2];
1787 1788 1789 1790 1791
	int size = memsize_zz(dc);

	DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZV);
E
edgar_igl 已提交
1792 1793
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1794

E
edgar_igl 已提交
1795 1796
	cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4);
	cris_alu_alloc_temps(dc, size, t);
1797 1798 1799 1800 1801 1802 1803 1804
	return 2;
}


static unsigned int dec_dstep_r(DisasContext *dc)
{
	DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
1805 1806
	cris_alu(dc, CC_OP_DSTEP,
		    cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
1807 1808 1809 1810 1811
	return 2;
}

static unsigned int dec_xor_r(DisasContext *dc)
{
E
edgar_igl 已提交
1812
	TCGv t[2];
1813 1814 1815 1816 1817
	int size = memsize_zz(dc);
	DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	BUG_ON(size != 4); /* xor is dword.  */
	cris_cc_mask(dc, CC_MASK_NZ);
E
edgar_igl 已提交
1818 1819
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1820

E
edgar_igl 已提交
1821 1822
	cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4);
	cris_alu_free_temps(dc, size, t);
1823 1824 1825 1826 1827
	return 2;
}

static unsigned int dec_bound_r(DisasContext *dc)
{
E
edgar_igl 已提交
1828
	TCGv l0;
1829 1830 1831 1832
	int size = memsize_zz(dc);
	DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
P
pbrook 已提交
1833
	l0 = tcg_temp_local_new();
E
edgar_igl 已提交
1834
	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0);
E
edgar_igl 已提交
1835 1836
	cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4);
	tcg_temp_free(l0);
1837 1838 1839 1840 1841
	return 2;
}

static unsigned int dec_cmp_r(DisasContext *dc)
{
E
edgar_igl 已提交
1842
	TCGv t[2];
1843 1844 1845 1846
	int size = memsize_zz(dc);
	DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
1847 1848
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1849

E
edgar_igl 已提交
1850 1851
	cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
1852 1853 1854 1855 1856
	return 2;
}

static unsigned int dec_abs_r(DisasContext *dc)
{
1857
	TCGv t0;
E
edgar_igl 已提交
1858

1859 1860 1861
	DIS(fprintf (logfile, "abs $r%u, $r%u\n",
		    dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
E
edgar_igl 已提交
1862

P
pbrook 已提交
1863
	t0 = tcg_temp_new();
1864 1865 1866 1867 1868
	tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31);
	tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0);
	tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0);
	tcg_temp_free(t0);

1869
	cris_alu(dc, CC_OP_MOVE,
1870
		    cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
1871 1872 1873 1874 1875
	return 2;
}

static unsigned int dec_add_r(DisasContext *dc)
{
E
edgar_igl 已提交
1876
	TCGv t[2];
1877 1878 1879 1880
	int size = memsize_zz(dc);
	DIS(fprintf (logfile, "add.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
1881 1882
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1883

E
edgar_igl 已提交
1884 1885
	cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
1886 1887 1888 1889 1890 1891 1892 1893
	return 2;
}

static unsigned int dec_addc_r(DisasContext *dc)
{
	DIS(fprintf (logfile, "addc $r%u, $r%u\n",
		    dc->op1, dc->op2));
	cris_evaluate_flags(dc);
1894 1895 1896 1897
	/* Set for this insn.  */
	dc->flagx_known = 1;
	dc->flags_x = X_FLAG;

1898
	cris_cc_mask(dc, CC_MASK_NZVC);
1899
	cris_alu(dc, CC_OP_ADDC,
E
edgar_igl 已提交
1900
		 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
1901 1902 1903 1904 1905 1906 1907 1908 1909
	return 2;
}

static unsigned int dec_mcp_r(DisasContext *dc)
{
	DIS(fprintf (logfile, "mcp $p%u, $r%u\n",
		     dc->op2, dc->op1));
	cris_evaluate_flags(dc);
	cris_cc_mask(dc, CC_MASK_RNZV);
1910 1911
	cris_alu(dc, CC_OP_MCP,
		    cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932
	return 2;
}

#if DISAS_CRIS
static char * swapmode_name(int mode, char *modename) {
	int i = 0;
	if (mode & 8)
		modename[i++] = 'n';
	if (mode & 4)
		modename[i++] = 'w';
	if (mode & 2)
		modename[i++] = 'b';
	if (mode & 1)
		modename[i++] = 'r';
	modename[i++] = 0;
	return modename;
}
#endif

static unsigned int dec_swap_r(DisasContext *dc)
{
E
edgar_igl 已提交
1933
	TCGv t0;
1934 1935 1936
#if DISAS_CRIS
	char modename[4];
#endif
1937 1938 1939 1940
	DIS(fprintf (logfile, "swap%s $r%u\n",
		     swapmode_name(dc->op2, modename), dc->op1));

	cris_cc_mask(dc, CC_MASK_NZ);
P
pbrook 已提交
1941
	t0 = tcg_temp_new();
E
edgar_igl 已提交
1942
	t_gen_mov_TN_reg(t0, dc->op1);
1943
	if (dc->op2 & 8)
E
edgar_igl 已提交
1944
		tcg_gen_not_tl(t0, t0);
1945
	if (dc->op2 & 4)
E
edgar_igl 已提交
1946
		t_gen_swapw(t0, t0);
1947
	if (dc->op2 & 2)
E
edgar_igl 已提交
1948
		t_gen_swapb(t0, t0);
1949
	if (dc->op2 & 1)
E
edgar_igl 已提交
1950
		t_gen_swapr(t0, t0);
1951
	cris_alu(dc, CC_OP_MOVE,
E
edgar_igl 已提交
1952
		    cpu_R[dc->op1], cpu_R[dc->op1], t0, 4);
E
edgar_igl 已提交
1953
	tcg_temp_free(t0);
1954 1955 1956 1957 1958
	return 2;
}

static unsigned int dec_or_r(DisasContext *dc)
{
E
edgar_igl 已提交
1959
	TCGv t[2];
1960 1961 1962 1963
	int size = memsize_zz(dc);
	DIS(fprintf (logfile, "or.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);
E
edgar_igl 已提交
1964 1965 1966 1967
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
	cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
1968 1969 1970 1971 1972
	return 2;
}

static unsigned int dec_addi_r(DisasContext *dc)
{
E
edgar_igl 已提交
1973
	TCGv t0;
1974 1975 1976
	DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
		    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
	cris_cc_mask(dc, 0);
P
pbrook 已提交
1977
	t0 = tcg_temp_new();
E
edgar_igl 已提交
1978 1979
	tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
	tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0);
E
edgar_igl 已提交
1980
	tcg_temp_free(t0);
1981 1982 1983 1984 1985
	return 2;
}

static unsigned int dec_addi_acr(DisasContext *dc)
{
E
edgar_igl 已提交
1986
	TCGv t0;
1987
	DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
E
edgar_igl 已提交
1988
		  memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1989
	cris_cc_mask(dc, 0);
P
pbrook 已提交
1990
	t0 = tcg_temp_new();
E
edgar_igl 已提交
1991 1992
	tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
	tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0);
E
edgar_igl 已提交
1993
	tcg_temp_free(t0);
1994 1995 1996 1997 1998
	return 2;
}

static unsigned int dec_neg_r(DisasContext *dc)
{
E
edgar_igl 已提交
1999
	TCGv t[2];
2000 2001 2002 2003
	int size = memsize_zz(dc);
	DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2004 2005
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
2006

E
edgar_igl 已提交
2007 2008
	cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
2009 2010 2011 2012 2013
	return 2;
}

static unsigned int dec_btst_r(DisasContext *dc)
{
E
edgar_igl 已提交
2014
	TCGv l0;
2015 2016 2017 2018
	DIS(fprintf (logfile, "btst $r%u, $r%u\n",
		    dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZ);

P
pbrook 已提交
2019
	l0 = tcg_temp_local_new();
E
edgar_igl 已提交
2020
	cris_alu(dc, CC_OP_BTST, l0, cpu_R[dc->op2], cpu_R[dc->op1], 4);
E
edgar_igl 已提交
2021
	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
E
edgar_igl 已提交
2022
	t_gen_mov_preg_TN(dc, PR_CCS, l0);
2023
	dc->flags_uptodate = 1;
E
edgar_igl 已提交
2024
	tcg_temp_free(l0);
2025 2026 2027 2028 2029
	return 2;
}

static unsigned int dec_sub_r(DisasContext *dc)
{
E
edgar_igl 已提交
2030
	TCGv t[2];
2031 2032 2033 2034
	int size = memsize_zz(dc);
	DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n",
		    memsize_char(size), dc->op1, dc->op2));
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2035 2036 2037 2038
	cris_alu_alloc_temps(dc, size, t);
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size);
	cris_alu_free_temps(dc, size, t);
2039 2040 2041 2042 2043 2044
	return 2;
}

/* Zero extension. From size to dword.  */
static unsigned int dec_movu_r(DisasContext *dc)
{
E
edgar_igl 已提交
2045
	TCGv t0;
2046 2047 2048 2049 2050 2051
	int size = memsize_z(dc);
	DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n",
		    memsize_char(size),
		    dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZ);
P
pbrook 已提交
2052
	t0 = tcg_temp_new();
E
edgar_igl 已提交
2053 2054 2055
	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
	cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
	tcg_temp_free(t0);
2056 2057 2058 2059 2060 2061
	return 2;
}

/* Sign extension. From size to dword.  */
static unsigned int dec_movs_r(DisasContext *dc)
{
E
edgar_igl 已提交
2062
	TCGv t0;
2063 2064 2065 2066 2067 2068
	int size = memsize_z(dc);
	DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n",
		    memsize_char(size),
		    dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZ);
P
pbrook 已提交
2069
	t0 = tcg_temp_new();
2070
	/* Size can only be qi or hi.  */
E
edgar_igl 已提交
2071
	t_gen_sext(t0, cpu_R[dc->op1], size);
2072
	cris_alu(dc, CC_OP_MOVE,
E
edgar_igl 已提交
2073 2074
		    cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
	tcg_temp_free(t0);
2075 2076 2077 2078 2079 2080
	return 2;
}

/* zero extension. From size to dword.  */
static unsigned int dec_addu_r(DisasContext *dc)
{
E
edgar_igl 已提交
2081
	TCGv t0;
2082 2083 2084 2085 2086 2087
	int size = memsize_z(dc);
	DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n",
		    memsize_char(size),
		    dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZVC);
P
pbrook 已提交
2088
	t0 = tcg_temp_new();
2089
	/* Size can only be qi or hi.  */
E
edgar_igl 已提交
2090
	t_gen_zext(t0, cpu_R[dc->op1], size);
2091
	cris_alu(dc, CC_OP_ADD,
E
edgar_igl 已提交
2092 2093
		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
	tcg_temp_free(t0);
2094 2095
	return 2;
}
2096

2097 2098 2099
/* Sign extension. From size to dword.  */
static unsigned int dec_adds_r(DisasContext *dc)
{
E
edgar_igl 已提交
2100
	TCGv t0;
2101 2102 2103 2104 2105 2106
	int size = memsize_z(dc);
	DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n",
		    memsize_char(size),
		    dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZVC);
P
pbrook 已提交
2107
	t0 = tcg_temp_new();
2108
	/* Size can only be qi or hi.  */
E
edgar_igl 已提交
2109
	t_gen_sext(t0, cpu_R[dc->op1], size);
2110
	cris_alu(dc, CC_OP_ADD,
E
edgar_igl 已提交
2111 2112
		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
	tcg_temp_free(t0);
2113 2114 2115 2116 2117 2118
	return 2;
}

/* Zero extension. From size to dword.  */
static unsigned int dec_subu_r(DisasContext *dc)
{
E
edgar_igl 已提交
2119
	TCGv t0;
2120 2121 2122 2123 2124 2125
	int size = memsize_z(dc);
	DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n",
		    memsize_char(size),
		    dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZVC);
P
pbrook 已提交
2126
	t0 = tcg_temp_new();
2127
	/* Size can only be qi or hi.  */
E
edgar_igl 已提交
2128
	t_gen_zext(t0, cpu_R[dc->op1], size);
2129
	cris_alu(dc, CC_OP_SUB,
E
edgar_igl 已提交
2130 2131
		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
	tcg_temp_free(t0);
2132 2133 2134 2135 2136 2137
	return 2;
}

/* Sign extension. From size to dword.  */
static unsigned int dec_subs_r(DisasContext *dc)
{
E
edgar_igl 已提交
2138
	TCGv t0;
2139 2140 2141 2142 2143 2144
	int size = memsize_z(dc);
	DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n",
		    memsize_char(size),
		    dc->op1, dc->op2));

	cris_cc_mask(dc, CC_MASK_NZVC);
P
pbrook 已提交
2145
	t0 = tcg_temp_new();
2146
	/* Size can only be qi or hi.  */
E
edgar_igl 已提交
2147
	t_gen_sext(t0, cpu_R[dc->op1], size);
2148
	cris_alu(dc, CC_OP_SUB,
E
edgar_igl 已提交
2149 2150
		    cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
	tcg_temp_free(t0);
2151 2152 2153 2154 2155 2156 2157 2158
	return 2;
}

static unsigned int dec_setclrf(DisasContext *dc)
{
	uint32_t flags;
	int set = (~dc->opcode >> 2) & 1;

E
edgar_igl 已提交
2159

2160 2161
	flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
		| EXTRACT_FIELD(dc->ir, 0, 3);
2162
	if (set && flags == 0) {
2163
		DIS(fprintf (logfile, "nop\n"));
2164
		return 2;
2165
	} else if (!set && (flags & 0x20)) {
2166
		DIS(fprintf (logfile, "di\n"));
2167 2168
	}
	else {
2169
		DIS(fprintf (logfile, "%sf %x\n",
2170
			     set ? "set" : "clr",
2171
			    flags));
2172
	}
2173

E
edgar_igl 已提交
2174
	/* User space is not allowed to touch these. Silently ignore.  */
E
edgar_igl 已提交
2175
	if (dc->tb_flags & U_FLAG) {
2176
		flags &= ~(S_FLAG | I_FLAG | U_FLAG);
E
edgar_igl 已提交
2177 2178 2179
	}

	if (flags & X_FLAG) {
2180
		dc->flagx_known = 1;
E
edgar_igl 已提交
2181 2182 2183 2184
		if (set)
			dc->flags_x = X_FLAG;
		else
			dc->flags_x = 0;
2185 2186
	}

E
edgar_igl 已提交
2187 2188 2189 2190 2191 2192 2193 2194 2195
	/* Break the TB if the P flag changes.  */
	if (flags & P_FLAG) {
		if ((set && !(dc->tb_flags & P_FLAG))
		    || (!set && (dc->tb_flags & P_FLAG))) {
			tcg_gen_movi_tl(env_pc, dc->pc + 2);
			dc->is_jmp = DISAS_UPDATE;
			dc->cpustate_changed = 1;
		}
	}
2196 2197 2198
	if (flags & S_FLAG) {
		dc->cpustate_changed = 1;
	}
E
edgar_igl 已提交
2199 2200


2201 2202
	/* Simply decode the flags.  */
	cris_evaluate_flags (dc);
E
edgar_igl 已提交
2203
	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
2204
	cris_update_cc_x(dc);
E
edgar_igl 已提交
2205 2206
	tcg_gen_movi_tl(cc_op, dc->cc_op);

E
edgar_igl 已提交
2207
	if (set) {
E
edgar_igl 已提交
2208
		if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
E
edgar_igl 已提交
2209 2210 2211
			/* Enter user mode.  */
			t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
			tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
E
edgar_igl 已提交
2212
			dc->cpustate_changed = 1;
E
edgar_igl 已提交
2213 2214 2215
		}
		tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
	}
2216
	else
E
edgar_igl 已提交
2217 2218
		tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);

2219
	dc->flags_uptodate = 1;
E
edgar_igl 已提交
2220
	dc->clear_x = 0;
2221 2222 2223 2224 2225 2226 2227
	return 2;
}

static unsigned int dec_move_rs(DisasContext *dc)
{
	DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2));
	cris_cc_mask(dc, 0);
P
pbrook 已提交
2228
	gen_helper_movl_sreg_reg(tcg_const_tl(dc->op2), tcg_const_tl(dc->op1));
2229 2230 2231 2232
	return 2;
}
static unsigned int dec_move_sr(DisasContext *dc)
{
2233
	DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op2, dc->op1));
2234
	cris_cc_mask(dc, 0);
P
pbrook 已提交
2235
	gen_helper_movl_reg_sreg(tcg_const_tl(dc->op1), tcg_const_tl(dc->op2));
2236 2237
	return 2;
}
E
edgar_igl 已提交
2238

2239 2240
static unsigned int dec_move_rp(DisasContext *dc)
{
E
edgar_igl 已提交
2241
	TCGv t[2];
2242 2243
	DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2244

P
pbrook 已提交
2245
	t[0] = tcg_temp_new();
E
edgar_igl 已提交
2246 2247
	if (dc->op2 == PR_CCS) {
		cris_evaluate_flags(dc);
E
edgar_igl 已提交
2248
		t_gen_mov_TN_reg(t[0], dc->op1);
E
edgar_igl 已提交
2249
		if (dc->tb_flags & U_FLAG) {
P
pbrook 已提交
2250
			t[1] = tcg_temp_new();
E
edgar_igl 已提交
2251
			/* User space is not allowed to touch all flags.  */
E
edgar_igl 已提交
2252 2253 2254 2255
			tcg_gen_andi_tl(t[0], t[0], 0x39f);
			tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f);
			tcg_gen_or_tl(t[0], t[1], t[0]);
			tcg_temp_free(t[1]);
E
edgar_igl 已提交
2256 2257 2258
		}
	}
	else
E
edgar_igl 已提交
2259
		t_gen_mov_TN_reg(t[0], dc->op1);
E
edgar_igl 已提交
2260

E
edgar_igl 已提交
2261
	t_gen_mov_preg_TN(dc, dc->op2, t[0]);
E
edgar_igl 已提交
2262 2263
	if (dc->op2 == PR_CCS) {
		cris_update_cc_op(dc, CC_OP_FLAGS, 4);
2264
		dc->flags_uptodate = 1;
E
edgar_igl 已提交
2265
	}
E
edgar_igl 已提交
2266
	tcg_temp_free(t[0]);
2267 2268 2269 2270
	return 2;
}
static unsigned int dec_move_pr(DisasContext *dc)
{
E
edgar_igl 已提交
2271
	TCGv t0;
2272 2273
	DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2274 2275

	if (dc->op2 == PR_CCS)
E
edgar_igl 已提交
2276
		cris_evaluate_flags(dc);
E
edgar_igl 已提交
2277

P
pbrook 已提交
2278
	t0 = tcg_temp_new();
E
edgar_igl 已提交
2279
	t_gen_mov_TN_preg(t0, dc->op2);
E
edgar_igl 已提交
2280
	cris_alu(dc, CC_OP_MOVE,
E
edgar_igl 已提交
2281 2282
		 cpu_R[dc->op1], cpu_R[dc->op1], t0, preg_sizes[dc->op2]);
	tcg_temp_free(t0);
2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294
	return 2;
}

static unsigned int dec_move_mr(DisasContext *dc)
{
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

2295 2296 2297 2298 2299 2300 2301 2302
	if (memsize == 4) {
		insn_len = dec_prep_move_m(dc, 0, 4, cpu_R[dc->op2]);
		cris_cc_mask(dc, CC_MASK_NZ);
		cris_update_cc_op(dc, CC_OP_MOVE, 4);
		cris_update_cc_x(dc);
		cris_update_result(dc, cpu_R[dc->op2]);
	}
	else {
E
edgar_igl 已提交
2303 2304
		TCGv t0;

P
pbrook 已提交
2305
		t0 = tcg_temp_new();
E
edgar_igl 已提交
2306
		insn_len = dec_prep_move_m(dc, 0, memsize, t0);
2307 2308
		cris_cc_mask(dc, CC_MASK_NZ);
		cris_alu(dc, CC_OP_MOVE,
E
edgar_igl 已提交
2309 2310
			    cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize);
		tcg_temp_free(t0);
2311
	}
2312 2313 2314 2315
	do_postinc(dc, memsize);
	return insn_len;
}

E
edgar_igl 已提交
2316 2317
static inline void cris_alu_m_alloc_temps(TCGv *t)
{
P
pbrook 已提交
2318 2319
	t[0] = tcg_temp_new();
	t[1] = tcg_temp_new();
E
edgar_igl 已提交
2320 2321 2322 2323 2324 2325 2326 2327
}

static inline void cris_alu_m_free_temps(TCGv *t)
{
	tcg_temp_free(t[0]);
	tcg_temp_free(t[1]);
}

2328 2329
static unsigned int dec_movs_m(DisasContext *dc)
{
E
edgar_igl 已提交
2330
	TCGv t[2];
2331 2332 2333 2334 2335 2336 2337
	int memsize = memsize_z(dc);
	int insn_len;
	DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2338
	cris_alu_m_alloc_temps(t);
2339
	/* sign extend.  */
E
edgar_igl 已提交
2340
	insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
E
edgar_igl 已提交
2341
	cris_cc_mask(dc, CC_MASK_NZ);
2342
	cris_alu(dc, CC_OP_MOVE,
E
edgar_igl 已提交
2343
		    cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2344
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2345
	cris_alu_m_free_temps(t);
2346 2347 2348 2349 2350
	return insn_len;
}

static unsigned int dec_addu_m(DisasContext *dc)
{
E
edgar_igl 已提交
2351
	TCGv t[2];
2352 2353 2354 2355 2356 2357 2358
	int memsize = memsize_z(dc);
	int insn_len;
	DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2359
	cris_alu_m_alloc_temps(t);
2360
	/* sign extend.  */
E
edgar_igl 已提交
2361
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2362
	cris_cc_mask(dc, CC_MASK_NZVC);
2363
	cris_alu(dc, CC_OP_ADD,
E
edgar_igl 已提交
2364
		    cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2365
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2366
	cris_alu_m_free_temps(t);
2367 2368 2369 2370 2371
	return insn_len;
}

static unsigned int dec_adds_m(DisasContext *dc)
{
E
edgar_igl 已提交
2372
	TCGv t[2];
2373 2374 2375 2376 2377 2378 2379
	int memsize = memsize_z(dc);
	int insn_len;
	DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2380
	cris_alu_m_alloc_temps(t);
2381
	/* sign extend.  */
E
edgar_igl 已提交
2382
	insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
E
edgar_igl 已提交
2383
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2384
	cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2385
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2386
	cris_alu_m_free_temps(t);
2387 2388 2389 2390 2391
	return insn_len;
}

static unsigned int dec_subu_m(DisasContext *dc)
{
E
edgar_igl 已提交
2392
	TCGv t[2];
2393 2394 2395 2396 2397 2398 2399
	int memsize = memsize_z(dc);
	int insn_len;
	DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2400
	cris_alu_m_alloc_temps(t);
2401
	/* sign extend.  */
E
edgar_igl 已提交
2402
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2403
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2404
	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2405
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2406
	cris_alu_m_free_temps(t);
2407 2408 2409 2410 2411
	return insn_len;
}

static unsigned int dec_subs_m(DisasContext *dc)
{
E
edgar_igl 已提交
2412
	TCGv t[2];
2413 2414 2415 2416 2417 2418 2419
	int memsize = memsize_z(dc);
	int insn_len;
	DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2420
	cris_alu_m_alloc_temps(t);
2421
	/* sign extend.  */
E
edgar_igl 已提交
2422
	insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
E
edgar_igl 已提交
2423
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2424
	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2425
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2426
	cris_alu_m_free_temps(t);
2427 2428 2429 2430 2431
	return insn_len;
}

static unsigned int dec_movu_m(DisasContext *dc)
{
E
edgar_igl 已提交
2432
	TCGv t[2];
2433 2434 2435 2436 2437 2438 2439 2440
	int memsize = memsize_z(dc);
	int insn_len;

	DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2441 2442
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2443
	cris_cc_mask(dc, CC_MASK_NZ);
E
edgar_igl 已提交
2444
	cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2445
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2446
	cris_alu_m_free_temps(t);
2447 2448 2449 2450 2451
	return insn_len;
}

static unsigned int dec_cmpu_m(DisasContext *dc)
{
E
edgar_igl 已提交
2452
	TCGv t[2];
2453 2454 2455 2456 2457 2458 2459
	int memsize = memsize_z(dc);
	int insn_len;
	DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2460 2461
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2462
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2463
	cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2464
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2465
	cris_alu_m_free_temps(t);
2466 2467 2468 2469 2470
	return insn_len;
}

static unsigned int dec_cmps_m(DisasContext *dc)
{
E
edgar_igl 已提交
2471
	TCGv t[2];
2472 2473 2474 2475 2476 2477 2478
	int memsize = memsize_z(dc);
	int insn_len;
	DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2479 2480
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
E
edgar_igl 已提交
2481
	cris_cc_mask(dc, CC_MASK_NZVC);
2482
	cris_alu(dc, CC_OP_CMP,
E
edgar_igl 已提交
2483
		    cpu_R[dc->op2], cpu_R[dc->op2], t[1],
2484
		    memsize_zz(dc));
2485
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2486
	cris_alu_m_free_temps(t);
2487 2488 2489 2490 2491
	return insn_len;
}

static unsigned int dec_cmp_m(DisasContext *dc)
{
E
edgar_igl 已提交
2492
	TCGv t[2];
2493 2494 2495 2496 2497 2498 2499
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2500 2501
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2502
	cris_cc_mask(dc, CC_MASK_NZVC);
2503
	cris_alu(dc, CC_OP_CMP,
E
edgar_igl 已提交
2504
		    cpu_R[dc->op2], cpu_R[dc->op2], t[1],
2505
		    memsize_zz(dc));
2506
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2507
	cris_alu_m_free_temps(t);
2508 2509 2510 2511 2512
	return insn_len;
}

static unsigned int dec_test_m(DisasContext *dc)
{
E
edgar_igl 已提交
2513
	TCGv t[2];
2514 2515 2516 2517 2518 2519 2520
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2521 2522
	cris_evaluate_flags(dc);

E
edgar_igl 已提交
2523 2524
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
2525
	cris_cc_mask(dc, CC_MASK_NZ);
E
edgar_igl 已提交
2526
	tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
E
edgar_igl 已提交
2527

2528
	cris_alu(dc, CC_OP_CMP,
E
edgar_igl 已提交
2529
		 cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc));
2530
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2531
	cris_alu_m_free_temps(t);
2532 2533 2534 2535 2536
	return insn_len;
}

static unsigned int dec_and_m(DisasContext *dc)
{
E
edgar_igl 已提交
2537
	TCGv t[2];
2538 2539 2540 2541 2542 2543 2544
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2545 2546
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2547
	cris_cc_mask(dc, CC_MASK_NZ);
E
edgar_igl 已提交
2548
	cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
2549
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2550
	cris_alu_m_free_temps(t);
2551 2552 2553 2554 2555
	return insn_len;
}

static unsigned int dec_add_m(DisasContext *dc)
{
E
edgar_igl 已提交
2556
	TCGv t[2];
2557 2558 2559 2560 2561 2562 2563
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2564 2565
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2566
	cris_cc_mask(dc, CC_MASK_NZVC);
2567
	cris_alu(dc, CC_OP_ADD,
E
edgar_igl 已提交
2568
		 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
2569
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2570
	cris_alu_m_free_temps(t);
2571 2572 2573 2574 2575
	return insn_len;
}

static unsigned int dec_addo_m(DisasContext *dc)
{
E
edgar_igl 已提交
2576
	TCGv t[2];
2577 2578 2579 2580 2581 2582 2583
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2584 2585
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
E
edgar_igl 已提交
2586
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2587
	cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4);
2588
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2589
	cris_alu_m_free_temps(t);
2590 2591 2592 2593 2594
	return insn_len;
}

static unsigned int dec_bound_m(DisasContext *dc)
{
E
edgar_igl 已提交
2595
	TCGv l[2];
2596 2597 2598 2599 2600 2601 2602
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

P
pbrook 已提交
2603 2604
	l[0] = tcg_temp_local_new();
	l[1] = tcg_temp_local_new();
E
edgar_igl 已提交
2605
	insn_len = dec_prep_alu_m(dc, 0, memsize, l[0], l[1]);
E
edgar_igl 已提交
2606
	cris_cc_mask(dc, CC_MASK_NZ);
E
edgar_igl 已提交
2607
	cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4);
2608
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2609 2610
	tcg_temp_free(l[0]);
	tcg_temp_free(l[1]);
2611 2612 2613 2614 2615
	return insn_len;
}

static unsigned int dec_addc_mr(DisasContext *dc)
{
E
edgar_igl 已提交
2616
	TCGv t[2];
2617 2618 2619 2620 2621 2622
	int insn_len = 2;
	DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n",
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2));

	cris_evaluate_flags(dc);
2623 2624 2625 2626 2627

	/* Set for this insn.  */
	dc->flagx_known = 1;
	dc->flags_x = X_FLAG;

E
edgar_igl 已提交
2628 2629
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]);
E
edgar_igl 已提交
2630
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2631
	cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4);
2632
	do_postinc(dc, 4);
E
edgar_igl 已提交
2633
	cris_alu_m_free_temps(t);
2634 2635 2636 2637 2638
	return insn_len;
}

static unsigned int dec_sub_m(DisasContext *dc)
{
E
edgar_igl 已提交
2639
	TCGv t[2];
2640 2641 2642 2643 2644 2645 2646
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2, dc->ir, dc->zzsize));

E
edgar_igl 已提交
2647 2648
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2649
	cris_cc_mask(dc, CC_MASK_NZVC);
E
edgar_igl 已提交
2650
	cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize);
2651
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2652
	cris_alu_m_free_temps(t);
2653 2654 2655 2656 2657
	return insn_len;
}

static unsigned int dec_or_m(DisasContext *dc)
{
E
edgar_igl 已提交
2658
	TCGv t[2];
2659 2660 2661 2662 2663 2664 2665
	int memsize = memsize_zz(dc);
	int insn_len;
	DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n",
		    memsize_char(memsize),
		    dc->op1, dc->postinc ? "+]" : "]",
		    dc->op2, dc->pc));

E
edgar_igl 已提交
2666 2667
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2668
	cris_cc_mask(dc, CC_MASK_NZ);
2669
	cris_alu(dc, CC_OP_OR,
E
edgar_igl 已提交
2670
		    cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
2671
	do_postinc(dc, memsize);
E
edgar_igl 已提交
2672
	cris_alu_m_free_temps(t);
2673 2674 2675 2676 2677
	return insn_len;
}

static unsigned int dec_move_mp(DisasContext *dc)
{
E
edgar_igl 已提交
2678
	TCGv t[2];
2679 2680 2681 2682 2683 2684 2685 2686 2687
	int memsize = memsize_zz(dc);
	int insn_len = 2;

	DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n",
		    memsize_char(memsize),
		    dc->op1,
		    dc->postinc ? "+]" : "]",
		    dc->op2));

E
edgar_igl 已提交
2688 2689
	cris_alu_m_alloc_temps(t);
	insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
E
edgar_igl 已提交
2690 2691 2692
	cris_cc_mask(dc, 0);
	if (dc->op2 == PR_CCS) {
		cris_evaluate_flags(dc);
E
edgar_igl 已提交
2693
		if (dc->tb_flags & U_FLAG) {
E
edgar_igl 已提交
2694
			/* User space is not allowed to touch all flags.  */
E
edgar_igl 已提交
2695 2696 2697
			tcg_gen_andi_tl(t[1], t[1], 0x39f);
			tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f);
			tcg_gen_or_tl(t[1], t[0], t[1]);
E
edgar_igl 已提交
2698 2699 2700
		}
	}

E
edgar_igl 已提交
2701
	t_gen_mov_preg_TN(dc, dc->op2, t[1]);
2702 2703

	do_postinc(dc, memsize);
E
edgar_igl 已提交
2704
	cris_alu_m_free_temps(t);
2705 2706 2707 2708 2709
	return insn_len;
}

static unsigned int dec_move_pm(DisasContext *dc)
{
E
edgar_igl 已提交
2710
	TCGv t0;
2711 2712 2713 2714
	int memsize;

	memsize = preg_sizes[dc->op2];

2715 2716 2717
	DIS(fprintf (logfile, "move.%c $p%u, [$r%u%s\n",
		     memsize_char(memsize), 
		     dc->op2, dc->op1, dc->postinc ? "+]" : "]"));
2718

2719
	/* prepare store. Address in T0, value in T1.  */
E
edgar_igl 已提交
2720 2721
	if (dc->op2 == PR_CCS)
		cris_evaluate_flags(dc);
P
pbrook 已提交
2722
	t0 = tcg_temp_new();
E
edgar_igl 已提交
2723
	t_gen_mov_TN_preg(t0, dc->op2);
2724
	cris_flush_cc_state(dc);
E
edgar_igl 已提交
2725 2726
	gen_store(dc, cpu_R[dc->op1], t0, memsize);
	tcg_temp_free(t0);
E
edgar_igl 已提交
2727

E
edgar_igl 已提交
2728
	cris_cc_mask(dc, 0);
2729
	if (dc->postinc)
E
edgar_igl 已提交
2730
		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
2731 2732 2733 2734 2735
	return 2;
}

static unsigned int dec_movem_mr(DisasContext *dc)
{
P
pbrook 已提交
2736 2737
	TCGv_i64 tmp[16];
        TCGv tmp32;
E
edgar_igl 已提交
2738
	TCGv addr;
2739
	int i;
2740
	int nr = dc->op2 + 1;
2741 2742 2743 2744

	DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1,
		    dc->postinc ? "+]" : "]", dc->op2));

P
pbrook 已提交
2745
	addr = tcg_temp_new();
2746
	/* There are probably better ways of doing this.  */
2747
	cris_flush_cc_state(dc);
2748
	for (i = 0; i < (nr >> 1); i++) {
P
pbrook 已提交
2749
		tmp[i] = tcg_temp_new_i64();
E
edgar_igl 已提交
2750
		tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
P
pbrook 已提交
2751
		gen_load64(dc, tmp[i], addr);
2752 2753
	}
	if (nr & 1) {
P
pbrook 已提交
2754
		tmp32 = tcg_temp_new_i32();
E
edgar_igl 已提交
2755
		tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
P
pbrook 已提交
2756
		gen_load(dc, tmp32, addr, 4, 0);
2757
	}
E
edgar_igl 已提交
2758
	tcg_temp_free(addr);
E
edgar_igl 已提交
2759

2760 2761 2762 2763
	for (i = 0; i < (nr >> 1); i++) {
		tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
		tcg_gen_shri_i64(tmp[i], tmp[i], 32);
		tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
P
pbrook 已提交
2764
		tcg_temp_free_i64(tmp[i]);
2765 2766
	}
	if (nr & 1) {
P
pbrook 已提交
2767 2768
		tcg_gen_mov_tl(cpu_R[dc->op2], tmp32);
		tcg_temp_free(tmp32);
E
edgar_igl 已提交
2769 2770
	}

2771 2772
	/* writeback the updated pointer value.  */
	if (dc->postinc)
2773
		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
E
edgar_igl 已提交
2774 2775 2776

	/* gen_load might want to evaluate the previous insns flags.  */
	cris_cc_mask(dc, 0);
2777 2778 2779 2780 2781
	return 2;
}

static unsigned int dec_movem_rm(DisasContext *dc)
{
2782
	TCGv tmp;
E
edgar_igl 已提交
2783
	TCGv addr;
2784 2785 2786 2787 2788
	int i;

	DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
		     dc->postinc ? "+]" : "]"));

2789 2790
	cris_flush_cc_state(dc);

P
pbrook 已提交
2791 2792
	tmp = tcg_temp_new();
	addr = tcg_temp_new();
2793
	tcg_gen_movi_tl(tmp, 4);
E
edgar_igl 已提交
2794
	tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
2795
	for (i = 0; i <= dc->op2; i++) {
E
edgar_igl 已提交
2796
		/* Displace addr.  */
2797
		/* Perform the store.  */
E
edgar_igl 已提交
2798 2799
		gen_store(dc, addr, cpu_R[i], 4);
		tcg_gen_add_tl(addr, addr, tmp);
2800
	}
E
edgar_igl 已提交
2801
	if (dc->postinc)
E
edgar_igl 已提交
2802
		tcg_gen_mov_tl(cpu_R[dc->op1], addr);
E
edgar_igl 已提交
2803
	cris_cc_mask(dc, 0);
2804
	tcg_temp_free(tmp);
E
edgar_igl 已提交
2805
	tcg_temp_free(addr);
2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818
	return 2;
}

static unsigned int dec_move_rm(DisasContext *dc)
{
	int memsize;

	memsize = memsize_zz(dc);

	DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n",
		     memsize, dc->op2, dc->op1));

	/* prepare store.  */
2819
	cris_flush_cc_state(dc);
E
edgar_igl 已提交
2820 2821
	gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);

2822
	if (dc->postinc)
E
edgar_igl 已提交
2823
		tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
E
edgar_igl 已提交
2824
	cris_cc_mask(dc, 0);
2825 2826 2827 2828 2829 2830 2831 2832
	return 2;
}

static unsigned int dec_lapcq(DisasContext *dc)
{
	DIS(fprintf (logfile, "lapcq %x, $r%u\n",
		    dc->pc + dc->op1*2, dc->op2));
	cris_cc_mask(dc, 0);
2833
	tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
2834 2835 2836 2837 2838 2839 2840
	return 2;
}

static unsigned int dec_lapc_im(DisasContext *dc)
{
	unsigned int rd;
	int32_t imm;
E
edgar_igl 已提交
2841
	int32_t pc;
2842 2843 2844 2845 2846 2847

	rd = dc->op2;

	cris_cc_mask(dc, 0);
	imm = ldl_code(dc->pc + 2);
	DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2));
E
edgar_igl 已提交
2848 2849 2850 2851

	pc = dc->pc;
	pc += imm;
	t_gen_mov_reg_TN(rd, tcg_const_tl(pc));
2852
	return 6;
2853 2854 2855 2856 2857 2858
}

/* Jump to special reg.  */
static unsigned int dec_jump_p(DisasContext *dc)
{
	DIS(fprintf (logfile, "jump $p%u\n", dc->op2));
E
edgar_igl 已提交
2859

E
edgar_igl 已提交
2860 2861
	if (dc->op2 == PR_CCS)
		cris_evaluate_flags(dc);
E
edgar_igl 已提交
2862
	t_gen_mov_TN_preg(env_btarget, dc->op2);
E
edgar_igl 已提交
2863
	/* rete will often have low bit set to indicate delayslot.  */
E
edgar_igl 已提交
2864
	tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
E
edgar_igl 已提交
2865
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2866
	cris_prepare_jmp(dc, JMP_INDIRECT);
2867 2868 2869 2870 2871 2872 2873 2874
	return 2;
}

/* Jump and save.  */
static unsigned int dec_jas_r(DisasContext *dc)
{
	DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2875 2876 2877 2878
	/* Store the return address in Pd.  */
	tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
	if (dc->op2 > 15)
		abort();
2879
	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
E
edgar_igl 已提交
2880

E
edgar_igl 已提交
2881
	cris_prepare_jmp(dc, JMP_INDIRECT);
2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892
	return 2;
}

static unsigned int dec_jas_im(DisasContext *dc)
{
	uint32_t imm;

	imm = ldl_code(dc->pc + 2);

	DIS(fprintf (logfile, "jas 0x%x\n", imm));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2893
	/* Store the return address in Pd.  */
2894
	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
E
edgar_igl 已提交
2895 2896 2897

	dc->jmp_pc = imm;
	cris_prepare_jmp(dc, JMP_DIRECT);
2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908
	return 6;
}

static unsigned int dec_jasc_im(DisasContext *dc)
{
	uint32_t imm;

	imm = ldl_code(dc->pc + 2);

	DIS(fprintf (logfile, "jasc 0x%x\n", imm));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2909
	/* Store the return address in Pd.  */
E
edgar_igl 已提交
2910 2911 2912 2913
	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));

	dc->jmp_pc = imm;
	cris_prepare_jmp(dc, JMP_DIRECT);
2914 2915 2916 2917 2918 2919 2920
	return 6;
}

static unsigned int dec_jasc_r(DisasContext *dc)
{
	DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2921
	/* Store the return address in Pd.  */
E
edgar_igl 已提交
2922 2923 2924
	tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
	cris_prepare_jmp(dc, JMP_INDIRECT);
2925 2926 2927 2928 2929 2930 2931 2932
	return 2;
}

static unsigned int dec_bcc_im(DisasContext *dc)
{
	int32_t offset;
	uint32_t cond = dc->op2;

E
edgar_igl 已提交
2933
	offset = ldsw_code(dc->pc + 2);
2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953

	DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n",
		    cc_name(cond), offset,
		    dc->pc, dc->pc + offset));

	cris_cc_mask(dc, 0);
	/* op2 holds the condition-code.  */
	cris_prepare_cc_branch (dc, offset, cond);
	return 4;
}

static unsigned int dec_bas_im(DisasContext *dc)
{
	int32_t simm;


	simm = ldl_code(dc->pc + 2);

	DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2954 2955 2956 2957 2958
	/* Store the return address in Pd.  */
	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));

	dc->jmp_pc = dc->pc + simm;
	cris_prepare_jmp(dc, JMP_DIRECT);
2959 2960 2961 2962 2963 2964 2965 2966 2967 2968
	return 6;
}

static unsigned int dec_basc_im(DisasContext *dc)
{
	int32_t simm;
	simm = ldl_code(dc->pc + 2);

	DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2));
	cris_cc_mask(dc, 0);
E
edgar_igl 已提交
2969 2970 2971 2972 2973
	/* Store the return address in Pd.  */
	t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));

	dc->jmp_pc = dc->pc + simm;
	cris_prepare_jmp(dc, JMP_DIRECT);
2974 2975 2976 2977 2978 2979 2980 2981
	return 6;
}

static unsigned int dec_rfe_etc(DisasContext *dc)
{
	cris_cc_mask(dc, 0);

	if (dc->op2 == 15) /* ignore halt.  */
2982
		return 2;
2983 2984 2985 2986

	switch (dc->op2 & 7) {
		case 2:
			/* rfe.  */
2987
			DIS(fprintf(logfile, "rfe\n"));
2988
			cris_evaluate_flags(dc);
P
pbrook 已提交
2989
			gen_helper_rfe();
E
edgar_igl 已提交
2990
			dc->is_jmp = DISAS_UPDATE;
2991 2992 2993
			break;
		case 5:
			/* rfn.  */
2994
			DIS(fprintf(logfile, "rfn\n"));
E
edgar_igl 已提交
2995
			cris_evaluate_flags(dc);
P
pbrook 已提交
2996
			gen_helper_rfn();
E
edgar_igl 已提交
2997
			dc->is_jmp = DISAS_UPDATE;
2998 2999
			break;
		case 6:
3000 3001
			DIS(fprintf(logfile, "break %d\n", dc->op1));
			cris_evaluate_flags (dc);
3002
			/* break.  */
3003
			tcg_gen_movi_tl(env_pc, dc->pc + 2);
3004

3005
			/* Breaks start at 16 in the exception vector.  */
E
edgar_igl 已提交
3006 3007 3008
			t_gen_mov_env_TN(trap_vector, 
					 tcg_const_tl(dc->op1 + 16));
			t_gen_raise_exception(EXCP_BREAK);
E
edgar_igl 已提交
3009
			dc->is_jmp = DISAS_UPDATE;
3010 3011 3012 3013 3014 3015 3016 3017 3018 3019
			break;
		default:
			printf ("op2=%x\n", dc->op2);
			BUG();
			break;

	}
	return 2;
}

3020 3021 3022 3023 3024 3025 3026 3027 3028 3029
static unsigned int dec_ftag_fidx_d_m(DisasContext *dc)
{
	return 2;
}

static unsigned int dec_ftag_fidx_i_m(DisasContext *dc)
{
	return 2;
}

3030 3031 3032 3033 3034 3035 3036 3037 3038
static unsigned int dec_null(DisasContext *dc)
{
	printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
		dc->pc, dc->opcode, dc->op1, dc->op2);
	fflush(NULL);
	BUG();
	return 2;
}

E
edgar_igl 已提交
3039
static struct decoder_info {
3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119
	struct {
		uint32_t bits;
		uint32_t mask;
	};
	unsigned int (*dec)(DisasContext *dc);
} decinfo[] = {
	/* Order matters here.  */
	{DEC_MOVEQ, dec_moveq},
	{DEC_BTSTQ, dec_btstq},
	{DEC_CMPQ, dec_cmpq},
	{DEC_ADDOQ, dec_addoq},
	{DEC_ADDQ, dec_addq},
	{DEC_SUBQ, dec_subq},
	{DEC_ANDQ, dec_andq},
	{DEC_ORQ, dec_orq},
	{DEC_ASRQ, dec_asrq},
	{DEC_LSLQ, dec_lslq},
	{DEC_LSRQ, dec_lsrq},
	{DEC_BCCQ, dec_bccq},

	{DEC_BCC_IM, dec_bcc_im},
	{DEC_JAS_IM, dec_jas_im},
	{DEC_JAS_R, dec_jas_r},
	{DEC_JASC_IM, dec_jasc_im},
	{DEC_JASC_R, dec_jasc_r},
	{DEC_BAS_IM, dec_bas_im},
	{DEC_BASC_IM, dec_basc_im},
	{DEC_JUMP_P, dec_jump_p},
	{DEC_LAPC_IM, dec_lapc_im},
	{DEC_LAPCQ, dec_lapcq},

	{DEC_RFE_ETC, dec_rfe_etc},
	{DEC_ADDC_MR, dec_addc_mr},

	{DEC_MOVE_MP, dec_move_mp},
	{DEC_MOVE_PM, dec_move_pm},
	{DEC_MOVEM_MR, dec_movem_mr},
	{DEC_MOVEM_RM, dec_movem_rm},
	{DEC_MOVE_PR, dec_move_pr},
	{DEC_SCC_R, dec_scc_r},
	{DEC_SETF, dec_setclrf},
	{DEC_CLEARF, dec_setclrf},

	{DEC_MOVE_SR, dec_move_sr},
	{DEC_MOVE_RP, dec_move_rp},
	{DEC_SWAP_R, dec_swap_r},
	{DEC_ABS_R, dec_abs_r},
	{DEC_LZ_R, dec_lz_r},
	{DEC_MOVE_RS, dec_move_rs},
	{DEC_BTST_R, dec_btst_r},
	{DEC_ADDC_R, dec_addc_r},

	{DEC_DSTEP_R, dec_dstep_r},
	{DEC_XOR_R, dec_xor_r},
	{DEC_MCP_R, dec_mcp_r},
	{DEC_CMP_R, dec_cmp_r},

	{DEC_ADDI_R, dec_addi_r},
	{DEC_ADDI_ACR, dec_addi_acr},

	{DEC_ADD_R, dec_add_r},
	{DEC_SUB_R, dec_sub_r},

	{DEC_ADDU_R, dec_addu_r},
	{DEC_ADDS_R, dec_adds_r},
	{DEC_SUBU_R, dec_subu_r},
	{DEC_SUBS_R, dec_subs_r},
	{DEC_LSL_R, dec_lsl_r},

	{DEC_AND_R, dec_and_r},
	{DEC_OR_R, dec_or_r},
	{DEC_BOUND_R, dec_bound_r},
	{DEC_ASR_R, dec_asr_r},
	{DEC_LSR_R, dec_lsr_r},

	{DEC_MOVU_R, dec_movu_r},
	{DEC_MOVS_R, dec_movs_r},
	{DEC_NEG_R, dec_neg_r},
	{DEC_MOVE_R, dec_move_r},

3120 3121
	{DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
	{DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155

	{DEC_MULS_R, dec_muls_r},
	{DEC_MULU_R, dec_mulu_r},

	{DEC_ADDU_M, dec_addu_m},
	{DEC_ADDS_M, dec_adds_m},
	{DEC_SUBU_M, dec_subu_m},
	{DEC_SUBS_M, dec_subs_m},

	{DEC_CMPU_M, dec_cmpu_m},
	{DEC_CMPS_M, dec_cmps_m},
	{DEC_MOVU_M, dec_movu_m},
	{DEC_MOVS_M, dec_movs_m},

	{DEC_CMP_M, dec_cmp_m},
	{DEC_ADDO_M, dec_addo_m},
	{DEC_BOUND_M, dec_bound_m},
	{DEC_ADD_M, dec_add_m},
	{DEC_SUB_M, dec_sub_m},
	{DEC_AND_M, dec_and_m},
	{DEC_OR_M, dec_or_m},
	{DEC_MOVE_RM, dec_move_rm},
	{DEC_TEST_M, dec_test_m},
	{DEC_MOVE_MR, dec_move_mr},

	{{0, 0}, dec_null}
};

static inline unsigned int
cris_decoder(DisasContext *dc)
{
	unsigned int insn_len = 2;
	int i;

3156 3157 3158
	if (unlikely(loglevel & CPU_LOG_TB_OP))
		tcg_gen_debug_insn_start(dc->pc);

3159
	/* Load a halfword onto the instruction register.  */
E
edgar_igl 已提交
3160
	dc->ir = lduw_code(dc->pc);
3161 3162 3163 3164 3165 3166 3167 3168 3169 3170

	/* Now decode it.  */
	dc->opcode   = EXTRACT_FIELD(dc->ir, 4, 11);
	dc->op1      = EXTRACT_FIELD(dc->ir, 0, 3);
	dc->op2      = EXTRACT_FIELD(dc->ir, 12, 15);
	dc->zsize    = EXTRACT_FIELD(dc->ir, 4, 4);
	dc->zzsize   = EXTRACT_FIELD(dc->ir, 4, 5);
	dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);

	/* Large switch for all insns.  */
3171
	for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
3172 3173 3174 3175 3176 3177 3178
		if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
		{
			insn_len = decinfo[i].dec(dc);
			break;
		}
	}

E
edgar_igl 已提交
3179
#if !defined(CONFIG_USER_ONLY)
3180 3181 3182 3183 3184
	/* Single-stepping ?  */
	if (dc->tb_flags & S_FLAG) {
		int l1;

		l1 = gen_new_label();
E
edgar_igl 已提交
3185
		tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
3186 3187 3188 3189
		/* We treat SPC as a break with an odd trap vector.  */
		cris_evaluate_flags (dc);
		t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
		tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
3190
		tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
3191 3192 3193 3194
		t_gen_raise_exception(EXCP_BREAK);
		gen_set_label(l1);
	}
#endif
3195 3196 3197 3198 3199
	return insn_len;
}

static void check_breakpoint(CPUState *env, DisasContext *dc)
{
3200 3201
	CPUBreakpoint *bp;

3202 3203
	if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
		TAILQ_FOREACH(bp, &env->breakpoints, entry) {
3204
			if (bp->pc == dc->pc) {
3205
				cris_evaluate_flags (dc);
E
edgar_igl 已提交
3206
				tcg_gen_movi_tl(env_pc, dc->pc);
E
edgar_igl 已提交
3207
				t_gen_raise_exception(EXCP_DEBUG);
3208 3209 3210 3211 3212 3213
				dc->is_jmp = DISAS_UPDATE;
			}
		}
	}
}

3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248

/*
 * Delay slots on QEMU/CRIS.
 *
 * If an exception hits on a delayslot, the core will let ERP (the Exception
 * Return Pointer) point to the branch (the previous) insn and set the lsb to
 * to give SW a hint that the exception actually hit on the dslot.
 *
 * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by
 * the core and any jmp to an odd addresses will mask off that lsb. It is 
 * simply there to let sw know there was an exception on a dslot.
 *
 * When the software returns from an exception, the branch will re-execute.
 * On QEMU care needs to be taken when a branch+delayslot sequence is broken
 * and the branch and delayslot dont share pages.
 *
 * The TB contaning the branch insn will set up env->btarget and evaluate 
 * env->btaken. When the translation loop exits we will note that the branch 
 * sequence is broken and let env->dslot be the size of the branch insn (those
 * vary in length).
 *
 * The TB contaning the delayslot will have the PC of its real insn (i.e no lsb
 * set). It will also expect to have env->dslot setup with the size of the 
 * delay slot so that env->pc - env->dslot point to the branch insn. This TB 
 * will execute the dslot and take the branch, either to btarget or just one 
 * insn ahead.
 *
 * When exceptions occur, we check for env->dslot in do_interrupt to detect 
 * broken branch sequences and setup $erp accordingly (i.e let it point to the
 * branch and set lsb). Then env->dslot gets cleared so that the exception 
 * handler can enter. When returning from exceptions (jump $erp) the lsb gets
 * masked off and we will reexecute the branch insn.
 *
 */

3249
/* generate intermediate code for basic block 'tb'.  */
3250
static void
3251 3252 3253 3254 3255 3256 3257
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
                               int search_pc)
{
	uint16_t *gen_opc_end;
   	uint32_t pc_start;
	unsigned int insn_len;
	int j, lj;
3258
	struct DisasContext ctx;
3259 3260
	struct DisasContext *dc = &ctx;
	uint32_t next_page_start;
E
edgar_igl 已提交
3261
	target_ulong npc;
P
pbrook 已提交
3262 3263
        int num_insns;
        int max_insns;
3264

E
edgar_igl 已提交
3265 3266 3267
	if (!logfile)
		logfile = stderr;

3268 3269 3270 3271
	/* Odd PC indicates that branch is rexecuting due to exception in the
	 * delayslot, like in real hw.
	 */
	pc_start = tb->pc & ~1;
3272 3273 3274 3275 3276 3277
	dc->env = env;
	dc->tb = tb;

	gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;

	dc->is_jmp = DISAS_NEXT;
E
edgar_igl 已提交
3278
	dc->ppc = pc_start;
3279 3280
	dc->pc = pc_start;
	dc->singlestep_enabled = env->singlestep_enabled;
3281 3282 3283 3284
	dc->flags_uptodate = 1;
	dc->flagx_known = 1;
	dc->flags_x = tb->flags & X_FLAG;
	dc->cc_x_uptodate = 0;
E
edgar_igl 已提交
3285
	dc->cc_mask = 0;
3286
	dc->update_cc = 0;
3287

E
edgar_igl 已提交
3288
	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
3289
	dc->cc_size_uptodate = -1;
E
edgar_igl 已提交
3290

3291
	/* Decode TB flags.  */
3292
	dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
3293
	dc->delayed_branch = !!(tb->flags & 7);
E
edgar_igl 已提交
3294 3295 3296 3297 3298 3299
	if (dc->delayed_branch)
		dc->jmp = JMP_INDIRECT;
	else
		dc->jmp = JMP_NOJMP;

	dc->cpustate_changed = 0;
E
edgar_igl 已提交
3300 3301 3302

	if (loglevel & CPU_LOG_TB_IN_ASM) {
		fprintf(logfile,
3303
			"srch=%d pc=%x %x flg=%llx bt=%x ds=%u ccs=%x\n"
3304
			"pid=%x usp=%x\n"
E
edgar_igl 已提交
3305 3306 3307 3308
			"%x.%x.%x.%x\n"
			"%x.%x.%x.%x\n"
			"%x.%x.%x.%x\n"
			"%x.%x.%x.%x\n",
3309 3310 3311
			search_pc, dc->pc, dc->ppc,
			(unsigned long long)tb->flags,
			env->btarget, (unsigned)tb->flags & 7,
3312
			env->pregs[PR_CCS], 
E
edgar_igl 已提交
3313 3314 3315 3316 3317 3318 3319
			env->pregs[PR_PID], env->pregs[PR_USP],
			env->regs[0], env->regs[1], env->regs[2], env->regs[3],
			env->regs[4], env->regs[5], env->regs[6], env->regs[7],
			env->regs[8], env->regs[9],
			env->regs[10], env->regs[11],
			env->regs[12], env->regs[13],
			env->regs[14], env->regs[15]);
3320 3321
		fprintf(logfile, "--------------\n");
		fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
E
edgar_igl 已提交
3322
	}
E
edgar_igl 已提交
3323

3324 3325
	next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
	lj = -1;
P
pbrook 已提交
3326 3327 3328 3329 3330 3331
        num_insns = 0;
        max_insns = tb->cflags & CF_COUNT_MASK;
        if (max_insns == 0)
            max_insns = CF_COUNT_MASK;

        gen_icount_start();
3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342
	do
	{
		check_breakpoint(env, dc);

		if (search_pc) {
			j = gen_opc_ptr - gen_opc_buf;
			if (lj < j) {
				lj++;
				while (lj < j)
					gen_opc_instr_start[lj++] = 0;
			}
3343
			if (dc->delayed_branch == 1)
E
edgar_igl 已提交
3344
				gen_opc_pc[lj] = dc->ppc | 1;
3345
			else
E
edgar_igl 已提交
3346
				gen_opc_pc[lj] = dc->pc;
3347
			gen_opc_instr_start[lj] = 1;
P
pbrook 已提交
3348
                        gen_opc_icount[lj] = num_insns;
3349 3350 3351
		}

		/* Pretty disas.  */
3352
		DIS(fprintf(logfile, "%8.8x:\t", dc->pc));
3353

P
pbrook 已提交
3354 3355
                if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
                    gen_io_start();
E
edgar_igl 已提交
3356
		dc->clear_x = 1;
3357 3358

		insn_len = cris_decoder(dc);		
E
edgar_igl 已提交
3359
		dc->ppc = dc->pc;
3360
		dc->pc += insn_len;
E
edgar_igl 已提交
3361 3362
		if (dc->clear_x)
			cris_clear_x_flag(dc);
3363

P
pbrook 已提交
3364
                num_insns++;
3365
		/* Check for delayed branches here. If we do it before
T
ths 已提交
3366
		   actually generating any host code, the simulator will just
3367 3368 3369 3370 3371
		   loop doing nothing for on this program location.  */
		if (dc->delayed_branch) {
			dc->delayed_branch--;
			if (dc->delayed_branch == 0)
			{
E
edgar_igl 已提交
3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382
				if (tb->flags & 7)
					t_gen_mov_env_TN(dslot, 
						tcg_const_tl(0));
				if (dc->jmp == JMP_DIRECT) {
					dc->is_jmp = DISAS_NEXT;
				} else {
					t_gen_cc_jmp(env_btarget, 
						     tcg_const_tl(dc->pc));
					dc->is_jmp = DISAS_JUMP;
				}
				break;
3383 3384 3385
			}
		}

3386 3387 3388
		/* If we are rexecuting a branch due to exceptions on
		   delay slots dont break.  */
		if (!(tb->pc & 1) && env->singlestep_enabled)
3389
			break;
E
edgar_igl 已提交
3390 3391
	} while (!dc->is_jmp && !dc->cpustate_changed
		 && gen_opc_ptr < gen_opc_end
P
pbrook 已提交
3392 3393
		 && (dc->pc < next_page_start)
                 && num_insns < max_insns);
E
edgar_igl 已提交
3394

E
edgar_igl 已提交
3395 3396 3397 3398
	npc = dc->pc;
	if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
		npc = dc->jmp_pc;

P
pbrook 已提交
3399 3400
        if (tb->cflags & CF_LAST_IO)
            gen_io_end();
E
edgar_igl 已提交
3401 3402 3403 3404 3405 3406 3407
	/* Force an update if the per-tb cpu state has changed.  */
	if (dc->is_jmp == DISAS_NEXT
	    && (dc->cpustate_changed || !dc->flagx_known 
	    || (dc->flags_x != (tb->flags & X_FLAG)))) {
		dc->is_jmp = DISAS_UPDATE;
		tcg_gen_movi_tl(env_pc, npc);
	}
3408
	/* Broken branch+delayslot sequence.  */
E
edgar_igl 已提交
3409
	if (dc->delayed_branch == 1) {
3410 3411
		/* Set env->dslot to the size of the branch insn.  */
		t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
E
edgar_igl 已提交
3412
		cris_store_direct_jmp(dc);
3413 3414 3415
	}

	cris_evaluate_flags (dc);
E
edgar_igl 已提交
3416

3417
	if (unlikely(env->singlestep_enabled)) {
3418 3419
		if (dc->is_jmp == DISAS_NEXT)
			tcg_gen_movi_tl(env_pc, npc);
E
edgar_igl 已提交
3420
		t_gen_raise_exception(EXCP_DEBUG);
3421 3422 3423
	} else {
		switch(dc->is_jmp) {
			case DISAS_NEXT:
E
edgar_igl 已提交
3424
				gen_goto_tb(dc, 1, npc);
3425 3426 3427 3428 3429 3430
				break;
			default:
			case DISAS_JUMP:
			case DISAS_UPDATE:
				/* indicate that the hash table must be used
				   to find the next TB */
B
bellard 已提交
3431
				tcg_gen_exit_tb(0);
3432
				break;
3433
			case DISAS_SWI:
3434 3435 3436 3437 3438
			case DISAS_TB_JUMP:
				/* nothing more to generate */
				break;
		}
	}
P
pbrook 已提交
3439
        gen_icount_end(tb, num_insns);
3440 3441 3442 3443 3444 3445 3446 3447
	*gen_opc_ptr = INDEX_op_end;
	if (search_pc) {
		j = gen_opc_ptr - gen_opc_buf;
		lj++;
		while (lj <= j)
			gen_opc_instr_start[lj++] = 0;
	} else {
		tb->size = dc->pc - pc_start;
P
pbrook 已提交
3448
                tb->icount = num_insns;
3449 3450 3451
	}

#ifdef DEBUG_DISAS
3452
#if !DISAS_CRIS
3453
	if (loglevel & CPU_LOG_TB_IN_ASM) {
E
edgar_igl 已提交
3454
		target_disas(logfile, pc_start, dc->pc - pc_start, 0);
3455
		fprintf(logfile, "\nisize=%d osize=%zd\n",
E
edgar_igl 已提交
3456
			dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
3457 3458
	}
#endif
3459
#endif
3460 3461
}

3462
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
3463
{
3464
    gen_intermediate_code_internal(env, tb, 0);
3465 3466
}

3467
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
3468
{
3469
    gen_intermediate_code_internal(env, tb, 1);
3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482
}

void cpu_dump_state (CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
{
	int i;
	uint32_t srs;

	if (!env || !f)
		return;

	cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
3483
		    "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
3484
		    env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
3485
		    env->cc_op,
3486 3487
		    env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);

3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499

	for (i = 0; i < 16; i++) {
		cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
		if ((i + 1) % 4 == 0)
			cpu_fprintf(f, "\n");
	}
	cpu_fprintf(f, "\nspecial regs:\n");
	for (i = 0; i < 16; i++) {
		cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]);
		if ((i + 1) % 4 == 0)
			cpu_fprintf(f, "\n");
	}
3500
	srs = env->pregs[PR_SRS];
E
edgar_igl 已提交
3501
	cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513
	if (srs < 256) {
		for (i = 0; i < 16; i++) {
			cpu_fprintf(f, "s%2.2d=%8.8x ",
				    i, env->sregs[srs][i]);
			if ((i + 1) % 4 == 0)
				cpu_fprintf(f, "\n");
		}
	}
	cpu_fprintf(f, "\n\n");

}

B
bellard 已提交
3514
CPUCRISState *cpu_cris_init (const char *cpu_model)
3515 3516
{
	CPUCRISState *env;
E
edgar_igl 已提交
3517
	static int tcg_initialized = 0;
E
edgar_igl 已提交
3518
	int i;
3519 3520 3521 3522

	env = qemu_mallocz(sizeof(CPUCRISState));
	if (!env)
		return NULL;
E
edgar_igl 已提交
3523

3524
	cpu_exec_init(env);
E
edgar_igl 已提交
3525 3526 3527 3528 3529 3530
	cpu_reset(env);

	if (tcg_initialized)
		return env;

	tcg_initialized = 1;
3531

P
pbrook 已提交
3532 3533
	cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
	cc_x = tcg_global_mem_new(TCG_AREG0,
3534
				  offsetof(CPUState, cc_x), "cc_x");
P
pbrook 已提交
3535
	cc_src = tcg_global_mem_new(TCG_AREG0,
E
edgar_igl 已提交
3536
				    offsetof(CPUState, cc_src), "cc_src");
P
pbrook 已提交
3537
	cc_dest = tcg_global_mem_new(TCG_AREG0,
3538
				     offsetof(CPUState, cc_dest),
E
edgar_igl 已提交
3539
				     "cc_dest");
P
pbrook 已提交
3540
	cc_result = tcg_global_mem_new(TCG_AREG0,
3541
				       offsetof(CPUState, cc_result),
E
edgar_igl 已提交
3542
				       "cc_result");
P
pbrook 已提交
3543
	cc_op = tcg_global_mem_new(TCG_AREG0,
E
edgar_igl 已提交
3544
				   offsetof(CPUState, cc_op), "cc_op");
P
pbrook 已提交
3545
	cc_size = tcg_global_mem_new(TCG_AREG0,
3546
				     offsetof(CPUState, cc_size),
E
edgar_igl 已提交
3547
				     "cc_size");
P
pbrook 已提交
3548
	cc_mask = tcg_global_mem_new(TCG_AREG0,
E
edgar_igl 已提交
3549 3550 3551
				     offsetof(CPUState, cc_mask),
				     "cc_mask");

P
pbrook 已提交
3552
	env_pc = tcg_global_mem_new(TCG_AREG0, 
3553 3554
				    offsetof(CPUState, pc),
				    "pc");
P
pbrook 已提交
3555
	env_btarget = tcg_global_mem_new(TCG_AREG0,
3556 3557
					 offsetof(CPUState, btarget),
					 "btarget");
P
pbrook 已提交
3558
	env_btaken = tcg_global_mem_new(TCG_AREG0,
E
edgar_igl 已提交
3559 3560
					 offsetof(CPUState, btaken),
					 "btaken");
E
edgar_igl 已提交
3561
	for (i = 0; i < 16; i++) {
P
pbrook 已提交
3562
		cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
3563
					      offsetof(CPUState, regs[i]),
E
edgar_igl 已提交
3564 3565 3566
					      regnames[i]);
	}
	for (i = 0; i < 16; i++) {
P
pbrook 已提交
3567
		cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
3568
					       offsetof(CPUState, pregs[i]),
E
edgar_igl 已提交
3569 3570 3571
					       pregnames[i]);
	}

P
pbrook 已提交
3572 3573
#define GEN_HELPER 2
#include "helper.h"
E
edgar_igl 已提交
3574

3575 3576 3577 3578 3579 3580 3581
	return env;
}

void cpu_reset (CPUCRISState *env)
{
	memset(env, 0, offsetof(CPUCRISState, breakpoints));
	tlb_flush(env, 1);
E
edgar_igl 已提交
3582

3583
	env->pregs[PR_VR] = 32;
E
edgar_igl 已提交
3584 3585 3586 3587 3588 3589
#if defined(CONFIG_USER_ONLY)
	/* start in user mode with interrupts enabled.  */
	env->pregs[PR_CCS] |= U_FLAG | I_FLAG;
#else
	env->pregs[PR_CCS] = 0;
#endif
3590
}
A
aurel32 已提交
3591 3592 3593 3594

void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
                 unsigned long searched_pc, int pc_pos, void *puc)
{
E
edgar_igl 已提交
3595
	env->pc = gen_opc_pc[pc_pos];
A
aurel32 已提交
3596
}