Revision 8170028d

b/target-cris/translate.c
1
/*
2
 *  CRIS emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2007 AXIS Communications AB
5
 *  Written by Edgar E. Iglesias.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21

  
22
/*
23
 * This file implements a CRIS decoder-stage in SW. The decoder translates the
24
 * guest (CRIS) machine-code into host machine code via dyngen using the
25
 * micro-operations described in op.c
26
 *
27
 * The micro-operations for CRIS translation implement a RISC style ISA.
28
 * Note that the micro-operations typically order their operands
29
 * starting with the dst. CRIS asm, does the opposite.
30
 *
31
 * For example the following CRIS code:
32
 * add.d [$r0], $r1
33
 *
34
 * translates into:
35
 *
36
 * gen_movl_T0_reg(0);   // Fetch $r0 into T0
37
 * gen_load_T0_T0();     // Load T0, @T0
38
 * gen_movl_reg_T0(1);   // Writeback T0 into $r1
39
 *
40
 * The actual names for the micro-code generators vary but the example
41
 * illustrates the point.
42
 */
43

  
44
#include <stdarg.h>
45
#include <stdlib.h>
46
#include <stdio.h>
47
#include <string.h>
48
#include <inttypes.h>
49
#include <assert.h>
50

  
51
#include "cpu.h"
52
#include "exec-all.h"
53
#include "disas.h"
54
#include "crisv32-decode.h"
55

  
56
#define CRIS_STATS 0
57
#if CRIS_STATS
58
#define STATS(x) x
59
#else
60
#define STATS(x)
61
#endif
62

  
63
#define DISAS_CRIS 0
64
#if DISAS_CRIS
65
#define DIS(x) x
66
#else
67
#define DIS(x)
68
#endif
69

  
70
#ifdef USE_DIRECT_JUMP
71
#define TBPARAM(x)
72
#else
73
#define TBPARAM(x) (long)(x)
74
#endif
75

  
76
#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
77
#define BUG_ON(x) ({if (x) BUG();})
78

  
79
/* Used by the decoder.  */
80
#define EXTRACT_FIELD(src, start, end) \
81
            (((src) >> start) & ((1 << (end - start + 1)) - 1))
82

  
83
#define CC_MASK_NZ 0xc
84
#define CC_MASK_NZV 0xe
85
#define CC_MASK_NZVC 0xf
86
#define CC_MASK_RNZV 0x10e
87

  
88
static uint16_t *gen_opc_ptr;
89
static uint32_t *gen_opparam_ptr;
90

  
91
enum {
92
#define DEF(s, n, copy_size) INDEX_op_ ## s,
93
#include "opc.h"
94
#undef DEF
95
    NB_OPS,
96
};
97
#include "gen-op.h"
98

  
99
/* This is the state at translation time.  */
100
typedef struct DisasContext {
101
	CPUState *env;
102
	target_ulong pc, insn_pc;
103

  
104
	/* Decoder.  */
105
	uint32_t ir;
106
	uint32_t opcode;
107
	unsigned int op1;
108
	unsigned int op2;
109
	unsigned int zsize, zzsize;
110
	unsigned int mode;
111
	unsigned int postinc;
112

  
113

  
114
	struct
115
	{
116
		int op;
117
		int size;
118
		unsigned int mask;
119
	} cc_state[3];
120
	int cc_i;
121

  
122
	int update_cc;
123
	int cc_op;
124
	int cc_size;
125
	uint32_t cc_mask;
126
	int flags_live;
127
	int flagx_live;
128
	int flags_x;
129
	uint32_t tb_entry_flags;
130

  
131
	int memidx; /* user or kernel mode.  */
132
	int is_jmp;
133
	int dyn_jmp;
134

  
135
	uint32_t delayed_pc;
136
	int delayed_branch;
137
	int bcc;
138
	uint32_t condlabel;
139

  
140
	struct TranslationBlock *tb;
141
	int singlestep_enabled;
142
} DisasContext;
143

  
144
void cris_prepare_jmp (DisasContext *dc, uint32_t dst);
145
static void gen_BUG(DisasContext *dc, char *file, int line)
146
{
147
	printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
148
	fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line);
149
	cpu_dump_state (dc->env, stdout, fprintf, 0);
150
	fflush(NULL);
151
	cris_prepare_jmp (dc, 0x70000000 + line);
152
}
153

  
154
/* Table to generate quick moves from T0 onto any register.  */
155
static GenOpFunc *gen_movl_reg_T0[16] =
156
{
157
	gen_op_movl_r0_T0, gen_op_movl_r1_T0,
158
	gen_op_movl_r2_T0, gen_op_movl_r3_T0,
159
	gen_op_movl_r4_T0, gen_op_movl_r5_T0,
160
	gen_op_movl_r6_T0, gen_op_movl_r7_T0,
161
	gen_op_movl_r8_T0, gen_op_movl_r9_T0,
162
	gen_op_movl_r10_T0, gen_op_movl_r11_T0,
163
	gen_op_movl_r12_T0, gen_op_movl_r13_T0,
164
	gen_op_movl_r14_T0, gen_op_movl_r15_T0,
165
};
166
static GenOpFunc *gen_movl_T0_reg[16] =
167
{
168
	gen_op_movl_T0_r0, gen_op_movl_T0_r1,
169
	gen_op_movl_T0_r2, gen_op_movl_T0_r3,
170
	gen_op_movl_T0_r4, gen_op_movl_T0_r5,
171
	gen_op_movl_T0_r6, gen_op_movl_T0_r7,
172
	gen_op_movl_T0_r8, gen_op_movl_T0_r9,
173
	gen_op_movl_T0_r10, gen_op_movl_T0_r11,
174
	gen_op_movl_T0_r12, gen_op_movl_T0_r13,
175
	gen_op_movl_T0_r14, gen_op_movl_T0_r15,
176
};
177

  
178
static void noop_write(void) {
179
	/* nop.  */
180
}
181

  
182
static void gen_vr_read(void) {
183
	gen_op_movl_T0_im(32);
184
}
185

  
186
static void gen_ccs_read(void) {
187
	gen_op_movl_T0_p13();
188
}
189

  
190
static void gen_ccs_write(void) {
191
	gen_op_movl_p13_T0();
192
}
193

  
194
/* Table to generate quick moves from T0 onto any register.  */
195
static GenOpFunc *gen_movl_preg_T0[16] =
196
{
197
	noop_write,  /* bz, not writeable.  */
198
	noop_write,  /* vr, not writeable.  */
199
	gen_op_movl_p2_T0, gen_op_movl_p3_T0,
200
	noop_write,  /* wz, not writeable.  */
201
	gen_op_movl_p5_T0,
202
	gen_op_movl_p6_T0, gen_op_movl_p7_T0,
203
	noop_write,  /* dz, not writeable.  */
204
	gen_op_movl_p9_T0,
205
	gen_op_movl_p10_T0, gen_op_movl_p11_T0,
206
	gen_op_movl_p12_T0,
207
	gen_ccs_write, /* ccs needs special treatment.  */
208
	gen_op_movl_p14_T0, gen_op_movl_p15_T0,
209
};
210
static GenOpFunc *gen_movl_T0_preg[16] =
211
{
212
	gen_op_movl_T0_p0,
213
	gen_vr_read,
214
	gen_op_movl_T0_p2, gen_op_movl_T0_p3,
215
	gen_op_movl_T0_p4, gen_op_movl_T0_p5,
216
	gen_op_movl_T0_p6, gen_op_movl_T0_p7,
217
	gen_op_movl_T0_p8, gen_op_movl_T0_p9,
218
	gen_op_movl_T0_p10, gen_op_movl_T0_p11,
219
	gen_op_movl_T0_p12,
220
	gen_ccs_read, /* ccs needs special treatment.  */
221
	gen_op_movl_T0_p14, gen_op_movl_T0_p15,
222
};
223

  
224
/* We need this table to handle moves with implicit width.  */
225
int preg_sizes[] = {
226
	1, /* bz.  */
227
	1, /* vr.  */
228
	4, /* pid.  */
229
	1, /* srs.  */
230
	2, /* wz.  */
231
	4, 4, 4,
232
	4, 4, 4, 4,
233
	4, 4, 4, 4,
234
};
235

  
236
#ifdef CONFIG_USER_ONLY
237
#define GEN_OP_LD(width, reg) \
238
  void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
239
    gen_op_ld##width##_T0_##reg##_raw(); \
240
  }
241
#define GEN_OP_ST(width, reg) \
242
  void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
243
    gen_op_st##width##_##reg##_T1_raw(); \
244
  }
245
#else
246
#define GEN_OP_LD(width, reg) \
247
  void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
248
    if (dc->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
249
    else gen_op_ld##width##_T0_##reg##_user();\
250
  }
251
#define GEN_OP_ST(width, reg) \
252
  void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
253
    if (dc->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
254
    else gen_op_st##width##_##reg##_T1_user();\
255
  }
256
#endif
257

  
258
GEN_OP_LD(ub, T0)
259
GEN_OP_LD(b, T0)
260
GEN_OP_ST(b, T0)
261
GEN_OP_LD(uw, T0)
262
GEN_OP_LD(w, T0)
263
GEN_OP_ST(w, T0)
264
GEN_OP_LD(l, T0)
265
GEN_OP_ST(l, T0)
266

  
267
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
268
{
269
	TranslationBlock *tb;
270
	tb = dc->tb;
271
	if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
272
		if (n == 0)
273
			gen_op_goto_tb0(TBPARAM(tb));
274
		else
275
			gen_op_goto_tb1(TBPARAM(tb));
276
		gen_op_movl_T0_0();
277
	} else {
278
		gen_op_movl_T0_0();
279
	}
280
	gen_op_exit_tb();
281
}
282

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

  
288
	/* LSL.  */
289
	val <<= 31 - width;
290
	sval = val;
291
	/* ASR.  */
292
	sval >>= 31 - width;
293
	return sval;
294
}
295

  
296
static void cris_evaluate_flags(DisasContext *dc)
297
{
298
	if (!dc->flags_live) {
299

  
300
		switch (dc->cc_op)
301
		{
302
			case CC_OP_MCP:
303
				gen_op_evaluate_flags_mcp ();
304
				break;
305
			case CC_OP_MULS:
306
				gen_op_evaluate_flags_muls ();
307
				break;
308
			case CC_OP_MULU:
309
				gen_op_evaluate_flags_mulu ();
310
				break;
311
			case CC_OP_MOVE:
312
				switch (dc->cc_size)
313
				{
314
					case 4:
315
						gen_op_evaluate_flags_move_4();
316
						break;
317
					case 2:
318
						gen_op_evaluate_flags_move_2();
319
						break;
320
					default:
321
						gen_op_evaluate_flags ();
322
						break;
323
				}
324
				break;
325

  
326
			default:
327
			{
328
				switch (dc->cc_size)
329
				{
330
					case 4:
331
						gen_op_evaluate_flags_alu_4 ();
332
						break;
333
					default:
334
						gen_op_evaluate_flags ();
335
						break;
336
				}
337
			}
338
			break;
339
		}
340
		dc->flags_live = 1;
341
	}
342
}
343

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

  
348
	ovl = (dc->cc_mask ^ mask) & ~mask;
349
	if (ovl) {
350
		/* TODO: optimize this case. It trigs all the time.  */
351
		cris_evaluate_flags (dc);
352
	}
353
	dc->cc_mask = mask;
354

  
355
	dc->update_cc = 1;
356
	if (mask == 0)
357
		dc->update_cc = 0;
358
	else {
359
		gen_op_update_cc_mask(mask);
360
		dc->flags_live = 0;
361
	}
362
}
363

  
364
static void cris_update_cc_op(DisasContext *dc, int op)
365
{
366
	dc->cc_op = op;
367
	gen_op_update_cc_op(op);
368
	dc->flags_live = 0;
369
}
370
static void cris_update_cc_size(DisasContext *dc, int size)
371
{
372
	dc->cc_size = size;
373
	gen_op_update_cc_size_im(size);
374
}
375

  
376
/* op is the operation.
377
   T0, T1 are the operands.
378
   dst is the destination reg.
379
*/
380
static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
381
{
382
	int writeback = 1;
383
	if (dc->update_cc) {
384
		cris_update_cc_op(dc, op);
385
		cris_update_cc_size(dc, size);
386
		gen_op_update_cc_x(dc->flagx_live, dc->flags_x);
387
		gen_op_update_cc_dest_T0();
388
	}
389

  
390
	/* Emit the ALU insns.  */
391
	switch (op)
392
	{
393
		case CC_OP_ADD:
394
			gen_op_addl_T0_T1();
395
			/* Extended arithmetics.  */
396
			if (!dc->flagx_live)
397
				gen_op_addxl_T0_C();
398
			else if (dc->flags_x)
399
				gen_op_addxl_T0_C();
400
			break;
401
		case CC_OP_ADDC:
402
			gen_op_addl_T0_T1();
403
			gen_op_addl_T0_C();
404
			break;
405
		case CC_OP_MCP:
406
			gen_op_addl_T0_T1();
407
			gen_op_addl_T0_R();
408
			break;
409
		case CC_OP_SUB:
410
			gen_op_negl_T1_T1();
411
			gen_op_addl_T0_T1();
412
			/* CRIS flag evaluation needs ~src.  */
413
			gen_op_negl_T1_T1();
414
			gen_op_not_T1_T1();
415

  
416
			/* Extended arithmetics.  */
417
			if (!dc->flagx_live)
418
				gen_op_subxl_T0_C();
419
			else if (dc->flags_x)
420
				gen_op_subxl_T0_C();
421
			break;
422
		case CC_OP_MOVE:
423
			gen_op_movl_T0_T1();
424
			break;
425
		case CC_OP_OR:
426
			gen_op_orl_T0_T1();
427
			break;
428
		case CC_OP_AND:
429
			gen_op_andl_T0_T1();
430
			break;
431
		case CC_OP_XOR:
432
			gen_op_xorl_T0_T1();
433
			break;
434
		case CC_OP_LSL:
435
			gen_op_lsll_T0_T1();
436
			break;
437
		case CC_OP_LSR:
438
			gen_op_lsrl_T0_T1();
439
			break;
440
		case CC_OP_ASR:
441
			gen_op_asrl_T0_T1();
442
			break;
443
		case CC_OP_NEG:
444
			gen_op_negl_T0_T1();
445
			/* Extended arithmetics.  */
446
			gen_op_subxl_T0_C();
447
			break;
448
		case CC_OP_LZ:
449
			gen_op_lz_T0_T1();
450
			break;
451
		case CC_OP_BTST:
452
			gen_op_btst_T0_T1();
453
			writeback = 0;
454
			break;
455
		case CC_OP_MULS:
456
			gen_op_muls_T0_T1();
457
			break;
458
		case CC_OP_MULU:
459
			gen_op_mulu_T0_T1();
460
			break;
461
		case CC_OP_DSTEP:
462
			gen_op_dstep_T0_T1();
463
			break;
464
		case CC_OP_BOUND:
465
			gen_op_bound_T0_T1();
466
			break;
467
		case CC_OP_CMP:
468
			gen_op_negl_T1_T1();
469
			gen_op_addl_T0_T1();
470
			/* CRIS flag evaluation needs ~src.  */
471
			gen_op_negl_T1_T1();
472
			gen_op_not_T1_T1();
473

  
474
			/* Extended arithmetics.  */
475
			gen_op_subxl_T0_C();
476
			writeback = 0;
477
			break;
478
		default:
479
			fprintf (logfile, "illegal ALU op.\n");
480
			BUG();
481
			break;
482
	}
483

  
484
	if (dc->update_cc)
485
		gen_op_update_cc_src_T1();
486

  
487
	if (size == 1)
488
		gen_op_andl_T0_im(0xff);
489
	else if (size == 2)
490
		gen_op_andl_T0_im(0xffff);
491
	/* Writeback.  */
492
	if (writeback) {
493
		if (size == 4)
494
			gen_movl_reg_T0[rd]();
495
		else {
496
			gen_op_movl_T1_T0();
497
			gen_movl_T0_reg[rd]();
498
			if (size == 1)
499
				gen_op_andl_T0_im(~0xff);
500
			else
501
				gen_op_andl_T0_im(~0xffff);
502
			gen_op_orl_T0_T1();
503
			gen_movl_reg_T0[rd]();
504
			gen_op_movl_T0_T1();
505
		}
506
	}
507
	if (dc->update_cc)
508
		gen_op_update_cc_result_T0();
509

  
510
	{
511
		/* TODO: Optimize this.  */
512
		if (!dc->flagx_live)
513
			cris_evaluate_flags(dc);
514
	}
515
}
516

  
517
static int arith_cc(DisasContext *dc)
518
{
519
	if (dc->update_cc) {
520
		switch (dc->cc_op) {
521
			case CC_OP_ADD: return 1;
522
			case CC_OP_SUB: return 1;
523
			case CC_OP_LSL: return 1;
524
			case CC_OP_LSR: return 1;
525
			case CC_OP_ASR: return 1;
526
			case CC_OP_CMP: return 1;
527
			default:
528
				return 0;
529
		}
530
	}
531
	return 0;
532
}
533

  
534
static void gen_tst_cc (DisasContext *dc, int cond)
535
{
536
	int arith_opt;
537

  
538
	/* TODO: optimize more condition codes.  */
539
	arith_opt = arith_cc(dc) && !dc->flags_live;
540
	switch (cond) {
541
		case CC_EQ:
542
			if (arith_opt)
543
				gen_op_tst_cc_eq_fast ();
544
			else {
545
				cris_evaluate_flags(dc);
546
				gen_op_tst_cc_eq ();
547
			}
548
			break;
549
		case CC_NE:
550
			if (arith_opt)
551
				gen_op_tst_cc_ne_fast ();
552
			else {
553
				cris_evaluate_flags(dc);
554
				gen_op_tst_cc_ne ();
555
			}
556
			break;
557
		case CC_CS:
558
			cris_evaluate_flags(dc);
559
			gen_op_tst_cc_cs ();
560
			break;
561
		case CC_CC:
562
			cris_evaluate_flags(dc);
563
			gen_op_tst_cc_cc ();
564
			break;
565
		case CC_VS:
566
			cris_evaluate_flags(dc);
567
			gen_op_tst_cc_vs ();
568
			break;
569
		case CC_VC:
570
			cris_evaluate_flags(dc);
571
			gen_op_tst_cc_vc ();
572
			break;
573
		case CC_PL:
574
			if (arith_opt)
575
				gen_op_tst_cc_pl_fast ();
576
			else {
577
				cris_evaluate_flags(dc);
578
				gen_op_tst_cc_pl ();
579
			}
580
			break;
581
		case CC_MI:
582
			if (arith_opt)
583
				gen_op_tst_cc_mi_fast ();
584
			else {
585
				cris_evaluate_flags(dc);
586
				gen_op_tst_cc_mi ();
587
			}
588
			break;
589
		case CC_LS:
590
			cris_evaluate_flags(dc);
591
			gen_op_tst_cc_ls ();
592
			break;
593
		case CC_HI:
594
			cris_evaluate_flags(dc);
595
			gen_op_tst_cc_hi ();
596
			break;
597
		case CC_GE:
598
			cris_evaluate_flags(dc);
599
			gen_op_tst_cc_ge ();
600
			break;
601
		case CC_LT:
602
			cris_evaluate_flags(dc);
603
			gen_op_tst_cc_lt ();
604
			break;
605
		case CC_GT:
606
			cris_evaluate_flags(dc);
607
			gen_op_tst_cc_gt ();
608
			break;
609
		case CC_LE:
610
			cris_evaluate_flags(dc);
611
			gen_op_tst_cc_le ();
612
			break;
613
		case CC_P:
614
			cris_evaluate_flags(dc);
615
			gen_op_tst_cc_p ();
616
			break;
617
		case CC_A:
618
			cris_evaluate_flags(dc);
619
			gen_op_movl_T0_im (1);
620
			break;
621
		default:
622
			BUG();
623
			break;
624
	};
625
}
626

  
627
static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
628
{
629
	/* This helps us re-schedule the micro-code to insns in delay-slots
630
	   before the actual jump.  */
631
	dc->delayed_branch = 2;
632
	dc->delayed_pc = dc->pc + offset;
633
	dc->bcc = cond;
634
	if (cond != CC_A)
635
	{
636
		gen_tst_cc (dc, cond);
637
		gen_op_evaluate_bcc ();
638
	}
639
	gen_op_movl_T0_im (dc->delayed_pc);
640
	gen_op_movl_btarget_T0 ();
641
}
642

  
643
/* Dynamic jumps, when the dest is in a live reg for example.  */
644
void cris_prepare_dyn_jmp (DisasContext *dc)
645
{
646
	/* This helps us re-schedule the micro-code to insns in delay-slots
647
	   before the actual jump.  */
648
	dc->delayed_branch = 2;
649
	dc->dyn_jmp = 1;
650
	dc->bcc = CC_A;
651
}
652

  
653
void cris_prepare_jmp (DisasContext *dc, uint32_t dst)
654
{
655
	/* This helps us re-schedule the micro-code to insns in delay-slots
656
	   before the actual jump.  */
657
	dc->delayed_branch = 2;
658
	dc->delayed_pc = dst;
659
	dc->dyn_jmp = 0;
660
	dc->bcc = CC_A;
661
}
662

  
663
void gen_load_T0_T0 (DisasContext *dc, unsigned int size, int sign)
664
{
665
	if (size == 1) {
666
		if (sign)
667
			gen_op_ldb_T0_T0(dc);
668
		else
669
			gen_op_ldub_T0_T0(dc);
670
	}
671
	else if (size == 2) {
672
		if (sign)
673
			gen_op_ldw_T0_T0(dc);
674
		else
675
			gen_op_lduw_T0_T0(dc);
676
	}
677
	else {
678
		gen_op_ldl_T0_T0(dc);
679
	}
680
}
681

  
682
void gen_store_T0_T1 (DisasContext *dc, unsigned int size)
683
{
684
	/* Remember, operands are flipped. CRIS has reversed order.  */
685
	if (size == 1) {
686
		gen_op_stb_T0_T1(dc);
687
	}
688
	else if (size == 2) {
689
		gen_op_stw_T0_T1(dc);
690
	}
691
	else
692
		gen_op_stl_T0_T1(dc);
693
}
694

  
695
/* sign extend T1 according to size.  */
696
static void gen_sext_T1_T0(int size)
697
{
698
	if (size == 1)
699
		gen_op_extb_T1_T0();
700
	else if (size == 2)
701
		gen_op_extw_T1_T0();
702
}
703

  
704
static void gen_sext_T1_T1(int size)
705
{
706
	if (size == 1)
707
		gen_op_extb_T1_T1();
708
	else if (size == 2)
709
		gen_op_extw_T1_T1();
710
}
711

  
712
static void gen_sext_T0_T0(int size)
713
{
714
	if (size == 1)
715
		gen_op_extb_T0_T0();
716
	else if (size == 2)
717
		gen_op_extw_T0_T0();
718
}
719

  
720
static void gen_zext_T0_T0(int size)
721
{
722
	if (size == 1)
723
		gen_op_zextb_T0_T0();
724
	else if (size == 2)
725
		gen_op_zextw_T0_T0();
726
}
727

  
728
static void gen_zext_T1_T0(int size)
729
{
730
	if (size == 1)
731
		gen_op_zextb_T1_T0();
732
	else if (size == 2)
733
		gen_op_zextw_T1_T0();
734
}
735

  
736
static void gen_zext_T1_T1(int size)
737
{
738
	if (size == 1)
739
		gen_op_zextb_T1_T1();
740
	else if (size == 2)
741
		gen_op_zextw_T1_T1();
742
}
743

  
744
#if DISAS_CRIS
745
static char memsize_char(int size)
746
{
747
	switch (size)
748
	{
749
		case 1: return 'b';  break;
750
		case 2: return 'w';  break;
751
		case 4: return 'd';  break;
752
		default:
753
			return 'x';
754
			break;
755
	}
756
}
757
#endif
758

  
759
static unsigned int memsize_z(DisasContext *dc)
760
{
761
	return dc->zsize + 1;
762
}
763

  
764
static unsigned int memsize_zz(DisasContext *dc)
765
{
766
	switch (dc->zzsize)
767
	{
768
		case 0: return 1;
769
		case 1: return 2;
770
		default:
771
			return 4;
772
	}
773
}
774

  
775
static void do_postinc (DisasContext *dc, int size)
776
{
777
	if (!dc->postinc)
778
		return;
779
	gen_movl_T0_reg[dc->op1]();
780
	gen_op_addl_T0_im(size);
781
	gen_movl_reg_T0[dc->op1]();
782
}
783

  
784

  
785
static void dec_prep_move_r(DisasContext *dc, int rs, int rd,
786
			    int size, int s_ext)
787
{
788
	gen_movl_T0_reg[rs]();
789
	gen_op_movl_T1_T0();
790
	if (s_ext)
791
		gen_sext_T1_T1(size);
792
	else
793
		gen_zext_T1_T1(size);
794
}
795

  
796
/* Prepare T0 and T1 for a register alu operation.
797
   s_ext decides if the operand1 should be sign-extended or zero-extended when
798
   needed.  */
799
static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
800
			  int size, int s_ext)
801
{
802
	dec_prep_move_r(dc, rs, rd, size, s_ext);
803

  
804
	gen_movl_T0_reg[rd]();
805
	if (s_ext)
806
		gen_sext_T0_T0(size);
807
	else
808
		gen_zext_T0_T0(size);
809
}
810

  
811
/* Prepare T0 and T1 for a memory + alu operation.
812
   s_ext decides if the operand1 should be sign-extended or zero-extended when
813
   needed.  */
814
static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize)
815
{
816
	unsigned int rs, rd;
817
	uint32_t imm;
818
	int is_imm;
819
	int insn_len = 2;
820

  
821
	rs = dc->op1;
822
	rd = dc->op2;
823
	is_imm = rs == 15 && dc->postinc;
824

  
825
	/* Load [$rs] onto T1.  */
826
	if (is_imm) {
827
		insn_len = 2 + memsize;
828
		if (memsize == 1)
829
			insn_len++;
830

  
831
		imm = ldl_code(dc->pc + 2);
832
		if (memsize != 4) {
833
			if (s_ext) {
834
				imm = sign_extend(imm, (memsize * 8) - 1);
835
			} else {
836
				if (memsize == 1)
837
					imm &= 0xff;
838
				else
839
					imm &= 0xffff;
840
			}
841
		}
842
		DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n",
843
			    imm, rd, s_ext, memsize));
844
		gen_op_movl_T1_im (imm);
845
		dc->postinc = 0;
846
	} else {
847
		gen_movl_T0_reg[rs]();
848
		gen_load_T0_T0(dc, memsize, 0);
849
		gen_op_movl_T1_T0();
850
		if (s_ext)
851
			gen_sext_T1_T1(memsize);
852
		else
853
			gen_zext_T1_T1(memsize);
854
	}
855

  
856
	/* put dest in T0.  */
857
	gen_movl_T0_reg[rd]();
858
	return insn_len;
859
}
860

  
861
#if DISAS_CRIS
862
static const char *cc_name(int cc)
863
{
864
	static char *cc_names[16] = {
865
		"cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
866
		"ls", "hi", "ge", "lt", "gt", "le", "a", "p"
867
	};
868
	assert(cc < 16);
869
	return cc_names[cc];
870
}
871
#endif
872

  
873
static unsigned int dec_bccq(DisasContext *dc)
874
{
875
	int32_t offset;
876
	int sign;
877
	uint32_t cond = dc->op2;
878
	int tmp;
879

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

  
883
	offset *= 2;
884
	offset |= sign << 8;
885
	tmp = offset;
886
	offset = sign_extend(offset, 8);
887

  
888
	/* op2 holds the condition-code.  */
889
	cris_cc_mask(dc, 0);
890
	cris_prepare_cc_branch (dc, offset, cond);
891
	return 2;
892
}
893
static unsigned int dec_addoq(DisasContext *dc)
894
{
895
	uint32_t imm;
896

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

  
900
	DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2));
901
	cris_cc_mask(dc, 0);
902
	/* Fetch register operand,  */
903
	gen_movl_T0_reg[dc->op2]();
904
	gen_op_movl_T1_im(imm);
905
	crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4);
906
	return 2;
907
}
908
static unsigned int dec_addq(DisasContext *dc)
909
{
910
	DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2));
911

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

  
914
	cris_cc_mask(dc, CC_MASK_NZVC);
915
	/* Fetch register operand,  */
916
	gen_movl_T0_reg[dc->op2]();
917
	gen_op_movl_T1_im(dc->op1);
918
	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
919
	return 2;
920
}
921
static unsigned int dec_moveq(DisasContext *dc)
922
{
923
	uint32_t imm;
924

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

  
929
	cris_cc_mask(dc, 0);
930
	gen_op_movl_T1_im(imm);
931
	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
932

  
933
	return 2;
934
}
935
static unsigned int dec_subq(DisasContext *dc)
936
{
937
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
938

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

  
941
	cris_cc_mask(dc, CC_MASK_NZVC);
942
	/* Fetch register operand,  */
943
	gen_movl_T0_reg[dc->op2]();
944
	gen_op_movl_T1_im(dc->op1);
945
	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
946
	return 2;
947
}
948
static unsigned int dec_cmpq(DisasContext *dc)
949
{
950
	uint32_t imm;
951
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
952
	imm = sign_extend(dc->op1, 5);
953

  
954
	DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
955
	cris_cc_mask(dc, CC_MASK_NZVC);
956
	gen_movl_T0_reg[dc->op2]();
957
	gen_op_movl_T1_im(imm);
958
	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
959
	return 2;
960
}
961
static unsigned int dec_andq(DisasContext *dc)
962
{
963
	uint32_t imm;
964
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
965
	imm = sign_extend(dc->op1, 5);
966

  
967
	DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
968
	cris_cc_mask(dc, CC_MASK_NZ);
969
	gen_movl_T0_reg[dc->op2]();
970
	gen_op_movl_T1_im(imm);
971
	crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4);
972
	return 2;
973
}
974
static unsigned int dec_orq(DisasContext *dc)
975
{
976
	uint32_t imm;
977
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
978
	imm = sign_extend(dc->op1, 5);
979
	DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
980
	cris_cc_mask(dc, CC_MASK_NZ);
981
	gen_movl_T0_reg[dc->op2]();
982
	gen_op_movl_T1_im(imm);
983
	crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4);
984
	return 2;
985
}
986
static unsigned int dec_btstq(DisasContext *dc)
987
{
988
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
989
	DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
990
	cris_evaluate_flags(dc);
991
	cris_cc_mask(dc, CC_MASK_NZ);
992
	gen_movl_T0_reg[dc->op2]();
993
	gen_op_movl_T1_im(dc->op1);
994
	crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
995

  
996
	cris_update_cc_op(dc, CC_OP_FLAGS);
997
	gen_op_movl_flags_T0();
998
	dc->flags_live = 1;
999
	return 2;
1000
}
1001
static unsigned int dec_asrq(DisasContext *dc)
1002
{
1003
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1004
	DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
1005
	cris_cc_mask(dc, CC_MASK_NZ);
1006
	gen_movl_T0_reg[dc->op2]();
1007
	gen_op_movl_T1_im(dc->op1);
1008
	crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4);
1009
	return 2;
1010
}
1011
static unsigned int dec_lslq(DisasContext *dc)
1012
{
1013
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1014
	DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));
1015

  
1016
	cris_cc_mask(dc, CC_MASK_NZ);
1017
	gen_movl_T0_reg[dc->op2]();
1018
	gen_op_movl_T1_im(dc->op1);
1019
	crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4);
1020
	return 2;
1021
}
1022
static unsigned int dec_lsrq(DisasContext *dc)
1023
{
1024
	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1025
	DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));
1026

  
1027
	cris_cc_mask(dc, CC_MASK_NZ);
1028
	gen_movl_T0_reg[dc->op2]();
1029
	gen_op_movl_T1_im(dc->op1);
1030
	crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4);
1031
	return 2;
1032
}
1033

  
1034
static unsigned int dec_move_r(DisasContext *dc)
1035
{
1036
	int size = memsize_zz(dc);
1037

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

  
1041
	cris_cc_mask(dc, CC_MASK_NZ);
1042
	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1043
	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, size);
1044
	return 2;
1045
}
1046

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

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

  
1054
	if (cond != CC_A)
1055
	{
1056
		gen_tst_cc (dc, cond);
1057
		gen_op_movl_T1_T0();
1058
	}
1059
	else
1060
		gen_op_movl_T1_im(1);
1061

  
1062
	cris_cc_mask(dc, 0);
1063
	crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1064
	return 2;
1065
}
1066

  
1067
static unsigned int dec_and_r(DisasContext *dc)
1068
{
1069
	int size = memsize_zz(dc);
1070

  
1071
	DIS(fprintf (logfile, "and.%c $r%u, $r%u\n",
1072
		    memsize_char(size), dc->op1, dc->op2));
1073
	cris_cc_mask(dc, CC_MASK_NZ);
1074
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1075
	crisv32_alu_op(dc, CC_OP_AND, dc->op2, size);
1076
	return 2;
1077
}
1078

  
1079
static unsigned int dec_lz_r(DisasContext *dc)
1080
{
1081
	DIS(fprintf (logfile, "lz $r%u, $r%u\n",
1082
		    dc->op1, dc->op2));
1083
	cris_cc_mask(dc, CC_MASK_NZ);
1084
	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1085
	crisv32_alu_op(dc, CC_OP_LZ, dc->op2, 4);
1086
	return 2;
1087
}
1088

  
1089
static unsigned int dec_lsl_r(DisasContext *dc)
1090
{
1091
	int size = memsize_zz(dc);
1092

  
1093
	DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n",
1094
		    memsize_char(size), dc->op1, dc->op2));
1095
	cris_cc_mask(dc, CC_MASK_NZ);
1096
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1097
	gen_op_andl_T1_im(63);
1098
	crisv32_alu_op(dc, CC_OP_LSL, dc->op2, size);
1099
	return 2;
1100
}
1101

  
1102
static unsigned int dec_lsr_r(DisasContext *dc)
1103
{
1104
	int size = memsize_zz(dc);
1105

  
1106
	DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n",
1107
		    memsize_char(size), dc->op1, dc->op2));
1108
	cris_cc_mask(dc, CC_MASK_NZ);
1109
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1110
	gen_op_andl_T1_im(63);
1111
	crisv32_alu_op(dc, CC_OP_LSR, dc->op2, size);
1112
	return 2;
1113
}
1114

  
1115
static unsigned int dec_asr_r(DisasContext *dc)
1116
{
1117
	int size = memsize_zz(dc);
1118

  
1119
	DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n",
1120
		    memsize_char(size), dc->op1, dc->op2));
1121
	cris_cc_mask(dc, CC_MASK_NZ);
1122
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1123
	gen_op_andl_T1_im(63);
1124
	crisv32_alu_op(dc, CC_OP_ASR, dc->op2, size);
1125
	return 2;
1126
}
1127

  
1128
static unsigned int dec_muls_r(DisasContext *dc)
1129
{
1130
	int size = memsize_zz(dc);
1131

  
1132
	DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n",
1133
		    memsize_char(size), dc->op1, dc->op2));
1134
	cris_cc_mask(dc, CC_MASK_NZV);
1135
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1136
	gen_sext_T0_T0(size);
1137
	crisv32_alu_op(dc, CC_OP_MULS, dc->op2, 4);
1138
	return 2;
1139
}
1140

  
1141
static unsigned int dec_mulu_r(DisasContext *dc)
1142
{
1143
	int size = memsize_zz(dc);
1144

  
1145
	DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n",
1146
		    memsize_char(size), dc->op1, dc->op2));
1147
	cris_cc_mask(dc, CC_MASK_NZV);
1148
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1149
	gen_zext_T0_T0(size);
1150
	crisv32_alu_op(dc, CC_OP_MULU, dc->op2, 4);
1151
	return 2;
1152
}
1153

  
1154

  
1155
static unsigned int dec_dstep_r(DisasContext *dc)
1156
{
1157
	DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2));
1158
	cris_cc_mask(dc, CC_MASK_NZ);
1159
	gen_movl_T0_reg[dc->op1]();
1160
	gen_op_movl_T1_T0();
1161
	gen_movl_T0_reg[dc->op2]();
1162
	crisv32_alu_op(dc, CC_OP_DSTEP, dc->op2, 4);
1163
	return 2;
1164
}
1165

  
1166
static unsigned int dec_xor_r(DisasContext *dc)
1167
{
1168
	int size = memsize_zz(dc);
1169
	DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n",
1170
		    memsize_char(size), dc->op1, dc->op2));
1171
	BUG_ON(size != 4); /* xor is dword.  */
1172
	cris_cc_mask(dc, CC_MASK_NZ);
1173
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1174
	crisv32_alu_op(dc, CC_OP_XOR, dc->op2, 4);
1175
	return 2;
1176
}
1177

  
1178
static unsigned int dec_bound_r(DisasContext *dc)
1179
{
1180
	int size = memsize_zz(dc);
1181
	DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n",
1182
		    memsize_char(size), dc->op1, dc->op2));
1183
	cris_cc_mask(dc, CC_MASK_NZ);
1184
	/* TODO: needs optmimization.  */
1185
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1186
	/* rd should be 4.  */
1187
	gen_movl_T0_reg[dc->op2]();
1188
	crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
1189
	return 2;
1190
}
1191

  
1192
static unsigned int dec_cmp_r(DisasContext *dc)
1193
{
1194
	int size = memsize_zz(dc);
1195
	DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n",
1196
		    memsize_char(size), dc->op1, dc->op2));
1197
	cris_cc_mask(dc, CC_MASK_NZVC);
1198
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1199
	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, size);
1200
	return 2;
1201
}
1202

  
1203
static unsigned int dec_abs_r(DisasContext *dc)
1204
{
1205
	DIS(fprintf (logfile, "abs $r%u, $r%u\n",
1206
		    dc->op1, dc->op2));
1207
	cris_cc_mask(dc, CC_MASK_NZ);
1208
	dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0);
1209
	gen_op_absl_T1_T1();
1210
	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1211
	return 2;
1212
}
1213

  
1214
static unsigned int dec_add_r(DisasContext *dc)
1215
{
1216
	int size = memsize_zz(dc);
1217
	DIS(fprintf (logfile, "add.%c $r%u, $r%u\n",
1218
		    memsize_char(size), dc->op1, dc->op2));
1219
	cris_cc_mask(dc, CC_MASK_NZVC);
1220
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1221
	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, size);
1222
	return 2;
1223
}
1224

  
1225
static unsigned int dec_addc_r(DisasContext *dc)
1226
{
1227
	DIS(fprintf (logfile, "addc $r%u, $r%u\n",
1228
		    dc->op1, dc->op2));
1229
	cris_evaluate_flags(dc);
1230
	cris_cc_mask(dc, CC_MASK_NZVC);
1231
	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1232
	crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
1233
	return 2;
1234
}
1235

  
1236
static unsigned int dec_mcp_r(DisasContext *dc)
1237
{
1238
	DIS(fprintf (logfile, "mcp $p%u, $r%u\n",
1239
		     dc->op2, dc->op1));
1240
	cris_evaluate_flags(dc);
1241
	cris_cc_mask(dc, CC_MASK_RNZV);
1242
	gen_movl_T0_preg[dc->op2]();
1243
	gen_op_movl_T1_T0();
1244
	gen_movl_T0_reg[dc->op1]();
1245
	crisv32_alu_op(dc, CC_OP_MCP, dc->op1, 4);
1246
	return 2;
1247
}
1248

  
1249
#if DISAS_CRIS
1250
static char * swapmode_name(int mode, char *modename) {
1251
	int i = 0;
1252
	if (mode & 8)
1253
		modename[i++] = 'n';
1254
	if (mode & 4)
1255
		modename[i++] = 'w';
1256
	if (mode & 2)
1257
		modename[i++] = 'b';
1258
	if (mode & 1)
1259
		modename[i++] = 'r';
1260
	modename[i++] = 0;
1261
	return modename;
1262
}
1263
#endif
1264

  
1265
static unsigned int dec_swap_r(DisasContext *dc)
1266
{
1267
	DIS(char modename[4]);
1268
	DIS(fprintf (logfile, "swap%s $r%u\n",
1269
		     swapmode_name(dc->op2, modename), dc->op1));
1270

  
1271
	cris_cc_mask(dc, CC_MASK_NZ);
1272
	gen_movl_T0_reg[dc->op1]();
1273
	if (dc->op2 & 8)
1274
		gen_op_not_T0_T0();
1275
	if (dc->op2 & 4)
1276
		gen_op_swapw_T0_T0();
1277
	if (dc->op2 & 2)
1278
		gen_op_swapb_T0_T0();
1279
	if (dc->op2 & 1)
1280
		gen_op_swapr_T0_T0();
1281
	gen_op_movl_T1_T0();
1282
	crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1283
	return 2;
1284
}
1285

  
1286
static unsigned int dec_or_r(DisasContext *dc)
1287
{
1288
	int size = memsize_zz(dc);
1289
	DIS(fprintf (logfile, "or.%c $r%u, $r%u\n",
1290
		    memsize_char(size), dc->op1, dc->op2));
1291
	cris_cc_mask(dc, CC_MASK_NZ);
1292
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1293
	crisv32_alu_op(dc, CC_OP_OR, dc->op2, size);
1294
	return 2;
1295
}
1296

  
1297
static unsigned int dec_addi_r(DisasContext *dc)
1298
{
1299
	DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
1300
		    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1301
	cris_cc_mask(dc, 0);
1302
	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1303
	gen_op_lsll_T0_im(dc->zzsize);
1304
	gen_op_addl_T0_T1();
1305
	gen_movl_reg_T0[dc->op1]();
1306
	return 2;
1307
}
1308

  
1309
static unsigned int dec_addi_acr(DisasContext *dc)
1310
{
1311
	DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
1312
		    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1313
	cris_cc_mask(dc, 0);
1314
	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1315
	gen_op_lsll_T0_im(dc->zzsize);
1316
	gen_op_addl_T0_T1();
1317
	gen_movl_reg_T0[REG_ACR]();
1318
	return 2;
1319
}
1320

  
1321
static unsigned int dec_neg_r(DisasContext *dc)
1322
{
1323
	int size = memsize_zz(dc);
1324
	DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n",
1325
		    memsize_char(size), dc->op1, dc->op2));
1326
	cris_cc_mask(dc, CC_MASK_NZVC);
1327
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1328
	crisv32_alu_op(dc, CC_OP_NEG, dc->op2, size);
1329
	return 2;
1330
}
1331

  
1332
static unsigned int dec_btst_r(DisasContext *dc)
1333
{
1334
	DIS(fprintf (logfile, "btst $r%u, $r%u\n",
1335
		    dc->op1, dc->op2));
1336
	cris_evaluate_flags(dc);
1337
	cris_cc_mask(dc, CC_MASK_NZ);
1338
	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1339
	crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
1340

  
1341
	cris_update_cc_op(dc, CC_OP_FLAGS);
1342
	gen_op_movl_flags_T0();
1343
	dc->flags_live = 1;
1344
	return 2;
1345
}
1346

  
1347
static unsigned int dec_sub_r(DisasContext *dc)
1348
{
1349
	int size = memsize_zz(dc);
1350
	DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n",
1351
		    memsize_char(size), dc->op1, dc->op2));
1352
	cris_cc_mask(dc, CC_MASK_NZVC);
1353
	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1354
	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, size);
1355
	return 2;
1356
}
1357

  
1358
/* Zero extension. From size to dword.  */
1359
static unsigned int dec_movu_r(DisasContext *dc)
1360
{
1361
	int size = memsize_z(dc);
1362
	DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n",
1363
		    memsize_char(size),
1364
		    dc->op1, dc->op2));
1365

  
1366
	cris_cc_mask(dc, CC_MASK_NZ);
1367
	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1368
	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1369
	return 2;
1370
}
1371

  
1372
/* Sign extension. From size to dword.  */
1373
static unsigned int dec_movs_r(DisasContext *dc)
1374
{
1375
	int size = memsize_z(dc);
1376
	DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n",
1377
		    memsize_char(size),
1378
		    dc->op1, dc->op2));
1379

  
1380
	cris_cc_mask(dc, CC_MASK_NZ);
1381
	gen_movl_T0_reg[dc->op1]();
1382
	/* Size can only be qi or hi.  */
1383
	gen_sext_T1_T0(size);
1384
	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1385
	return 2;
1386
}
1387

  
1388
/* zero extension. From size to dword.  */
1389
static unsigned int dec_addu_r(DisasContext *dc)
1390
{
1391
	int size = memsize_z(dc);
1392
	DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n",
1393
		    memsize_char(size),
1394
		    dc->op1, dc->op2));
1395

  
1396
	cris_cc_mask(dc, CC_MASK_NZVC);
1397
	gen_movl_T0_reg[dc->op1]();
1398
	/* Size can only be qi or hi.  */
1399
	gen_zext_T1_T0(size);
1400
	gen_movl_T0_reg[dc->op2]();
1401
	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1402
	return 2;
1403
}
1404
/* Sign extension. From size to dword.  */
1405
static unsigned int dec_adds_r(DisasContext *dc)
1406
{
1407
	int size = memsize_z(dc);
1408
	DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n",
1409
		    memsize_char(size),
1410
		    dc->op1, dc->op2));
1411

  
1412
	cris_cc_mask(dc, CC_MASK_NZVC);
1413
	gen_movl_T0_reg[dc->op1]();
1414
	/* Size can only be qi or hi.  */
1415
	gen_sext_T1_T0(size);
1416
	gen_movl_T0_reg[dc->op2]();
1417
	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1418
	return 2;
1419
}
1420

  
1421
/* Zero extension. From size to dword.  */
1422
static unsigned int dec_subu_r(DisasContext *dc)
1423
{
1424
	int size = memsize_z(dc);
1425
	DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n",
1426
		    memsize_char(size),
1427
		    dc->op1, dc->op2));
1428

  
1429
	cris_cc_mask(dc, CC_MASK_NZVC);
1430
	gen_movl_T0_reg[dc->op1]();
1431
	/* Size can only be qi or hi.  */
1432
	gen_zext_T1_T0(size);
1433
	gen_movl_T0_reg[dc->op2]();
1434
	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1435
	return 2;
1436
}
1437

  
1438
/* Sign extension. From size to dword.  */
1439
static unsigned int dec_subs_r(DisasContext *dc)
1440
{
1441
	int size = memsize_z(dc);
1442
	DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n",
1443
		    memsize_char(size),
1444
		    dc->op1, dc->op2));
1445

  
1446
	cris_cc_mask(dc, CC_MASK_NZVC);
1447
	gen_movl_T0_reg[dc->op1]();
1448
	/* Size can only be qi or hi.  */
1449
	gen_sext_T1_T0(size);
1450
	gen_movl_T0_reg[dc->op2]();
1451
	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1452
	return 2;
1453
}
1454

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

  
1460
	flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
1461
		| EXTRACT_FIELD(dc->ir, 0, 3);
1462
	DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags));
1463
	if (set && flags == 0)
1464
		DIS(fprintf (logfile, "nop\n"));
1465
	else if (!set && (flags & 0x20))
1466
		DIS(fprintf (logfile, "di\n"));
1467
	else
1468
		DIS(fprintf (logfile, "%sf %x\n",
1469
			    set ? "set" : "clr",
1470
			    flags));
1471

  
1472
	if (set && (flags & X_FLAG)) {
1473
		dc->flagx_live = 1;
1474
		dc->flags_x = 1;
1475
	}
1476

  
1477
	/* Simply decode the flags.  */
1478
	cris_evaluate_flags (dc);
1479
	cris_update_cc_op(dc, CC_OP_FLAGS);
1480
	if (set)
1481
		gen_op_setf (flags);
1482
	else
1483
		gen_op_clrf (flags);
1484
	dc->flags_live = 1;
1485
	return 2;
1486
}
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff