Statistics
| Branch: | Revision:

root / target-cris / translate.c @ 94cff60a

History | View | Annotate | Download (55.8 kB)

1 8170028d ths
/*
2 8170028d ths
 *  CRIS emulation for qemu: main translation routines.
3 8170028d ths
 *
4 8170028d ths
 *  Copyright (c) 2007 AXIS Communications AB
5 8170028d ths
 *  Written by Edgar E. Iglesias.
6 8170028d ths
 *
7 8170028d ths
 * This library is free software; you can redistribute it and/or
8 8170028d ths
 * modify it under the terms of the GNU Lesser General Public
9 8170028d ths
 * License as published by the Free Software Foundation; either
10 8170028d ths
 * version 2 of the License, or (at your option) any later version.
11 8170028d ths
 *
12 8170028d ths
 * This library is distributed in the hope that it will be useful,
13 8170028d ths
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 8170028d ths
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 8170028d ths
 * Lesser General Public License for more details.
16 8170028d ths
 *
17 8170028d ths
 * You should have received a copy of the GNU Lesser General Public
18 8170028d ths
 * License along with this library; if not, write to the Free Software
19 8170028d ths
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 8170028d ths
 */
21 8170028d ths
22 8170028d ths
/*
23 8170028d ths
 * This file implements a CRIS decoder-stage in SW. The decoder translates the
24 8170028d ths
 * guest (CRIS) machine-code into host machine code via dyngen using the
25 8170028d ths
 * micro-operations described in op.c
26 8170028d ths
 *
27 8170028d ths
 * The micro-operations for CRIS translation implement a RISC style ISA.
28 8170028d ths
 * Note that the micro-operations typically order their operands
29 8170028d ths
 * starting with the dst. CRIS asm, does the opposite.
30 8170028d ths
 *
31 8170028d ths
 * For example the following CRIS code:
32 8170028d ths
 * add.d [$r0], $r1
33 8170028d ths
 *
34 8170028d ths
 * translates into:
35 8170028d ths
 *
36 8170028d ths
 * gen_movl_T0_reg(0);   // Fetch $r0 into T0
37 8170028d ths
 * gen_load_T0_T0();     // Load T0, @T0
38 8170028d ths
 * gen_movl_reg_T0(1);   // Writeback T0 into $r1
39 8170028d ths
 *
40 8170028d ths
 * The actual names for the micro-code generators vary but the example
41 8170028d ths
 * illustrates the point.
42 8170028d ths
 */
43 8170028d ths
44 8170028d ths
#include <stdarg.h>
45 8170028d ths
#include <stdlib.h>
46 8170028d ths
#include <stdio.h>
47 8170028d ths
#include <string.h>
48 8170028d ths
#include <inttypes.h>
49 8170028d ths
#include <assert.h>
50 8170028d ths
51 8170028d ths
#include "cpu.h"
52 8170028d ths
#include "exec-all.h"
53 8170028d ths
#include "disas.h"
54 8170028d ths
#include "crisv32-decode.h"
55 8170028d ths
56 8170028d ths
#define CRIS_STATS 0
57 8170028d ths
#if CRIS_STATS
58 8170028d ths
#define STATS(x) x
59 8170028d ths
#else
60 8170028d ths
#define STATS(x)
61 8170028d ths
#endif
62 8170028d ths
63 8170028d ths
#define DISAS_CRIS 0
64 8170028d ths
#if DISAS_CRIS
65 8170028d ths
#define DIS(x) x
66 8170028d ths
#else
67 8170028d ths
#define DIS(x)
68 8170028d ths
#endif
69 8170028d ths
70 8170028d ths
#ifdef USE_DIRECT_JUMP
71 8170028d ths
#define TBPARAM(x)
72 8170028d ths
#else
73 8170028d ths
#define TBPARAM(x) (long)(x)
74 8170028d ths
#endif
75 8170028d ths
76 8170028d ths
#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
77 8170028d ths
#define BUG_ON(x) ({if (x) BUG();})
78 8170028d ths
79 8170028d ths
/* Used by the decoder.  */
80 8170028d ths
#define EXTRACT_FIELD(src, start, end) \
81 8170028d ths
            (((src) >> start) & ((1 << (end - start + 1)) - 1))
82 8170028d ths
83 8170028d ths
#define CC_MASK_NZ 0xc
84 8170028d ths
#define CC_MASK_NZV 0xe
85 8170028d ths
#define CC_MASK_NZVC 0xf
86 8170028d ths
#define CC_MASK_RNZV 0x10e
87 8170028d ths
88 8170028d ths
static uint16_t *gen_opc_ptr;
89 8170028d ths
static uint32_t *gen_opparam_ptr;
90 8170028d ths
91 8170028d ths
enum {
92 8170028d ths
#define DEF(s, n, copy_size) INDEX_op_ ## s,
93 8170028d ths
#include "opc.h"
94 8170028d ths
#undef DEF
95 8170028d ths
    NB_OPS,
96 8170028d ths
};
97 8170028d ths
#include "gen-op.h"
98 8170028d ths
99 8170028d ths
/* This is the state at translation time.  */
100 8170028d ths
typedef struct DisasContext {
101 8170028d ths
        CPUState *env;
102 8170028d ths
        target_ulong pc, insn_pc;
103 8170028d ths
104 8170028d ths
        /* Decoder.  */
105 8170028d ths
        uint32_t ir;
106 8170028d ths
        uint32_t opcode;
107 8170028d ths
        unsigned int op1;
108 8170028d ths
        unsigned int op2;
109 8170028d ths
        unsigned int zsize, zzsize;
110 8170028d ths
        unsigned int mode;
111 8170028d ths
        unsigned int postinc;
112 8170028d ths
113 8170028d ths
114 8170028d ths
        struct
115 8170028d ths
        {
116 8170028d ths
                int op;
117 8170028d ths
                int size;
118 8170028d ths
                unsigned int mask;
119 8170028d ths
        } cc_state[3];
120 8170028d ths
        int cc_i;
121 8170028d ths
122 8170028d ths
        int update_cc;
123 8170028d ths
        int cc_op;
124 8170028d ths
        int cc_size;
125 8170028d ths
        uint32_t cc_mask;
126 8170028d ths
        int flags_live;
127 8170028d ths
        int flagx_live;
128 8170028d ths
        int flags_x;
129 8170028d ths
        uint32_t tb_entry_flags;
130 8170028d ths
131 8170028d ths
        int memidx; /* user or kernel mode.  */
132 8170028d ths
        int is_jmp;
133 8170028d ths
        int dyn_jmp;
134 8170028d ths
135 8170028d ths
        uint32_t delayed_pc;
136 8170028d ths
        int delayed_branch;
137 8170028d ths
        int bcc;
138 8170028d ths
        uint32_t condlabel;
139 8170028d ths
140 8170028d ths
        struct TranslationBlock *tb;
141 8170028d ths
        int singlestep_enabled;
142 8170028d ths
} DisasContext;
143 8170028d ths
144 8170028d ths
void cris_prepare_jmp (DisasContext *dc, uint32_t dst);
145 8170028d ths
static void gen_BUG(DisasContext *dc, char *file, int line)
146 8170028d ths
{
147 8170028d ths
        printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
148 8170028d ths
        fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line);
149 8170028d ths
        cpu_dump_state (dc->env, stdout, fprintf, 0);
150 8170028d ths
        fflush(NULL);
151 8170028d ths
        cris_prepare_jmp (dc, 0x70000000 + line);
152 8170028d ths
}
153 8170028d ths
154 8170028d ths
/* Table to generate quick moves from T0 onto any register.  */
155 8170028d ths
static GenOpFunc *gen_movl_reg_T0[16] =
156 8170028d ths
{
157 8170028d ths
        gen_op_movl_r0_T0, gen_op_movl_r1_T0,
158 8170028d ths
        gen_op_movl_r2_T0, gen_op_movl_r3_T0,
159 8170028d ths
        gen_op_movl_r4_T0, gen_op_movl_r5_T0,
160 8170028d ths
        gen_op_movl_r6_T0, gen_op_movl_r7_T0,
161 8170028d ths
        gen_op_movl_r8_T0, gen_op_movl_r9_T0,
162 8170028d ths
        gen_op_movl_r10_T0, gen_op_movl_r11_T0,
163 8170028d ths
        gen_op_movl_r12_T0, gen_op_movl_r13_T0,
164 8170028d ths
        gen_op_movl_r14_T0, gen_op_movl_r15_T0,
165 8170028d ths
};
166 8170028d ths
static GenOpFunc *gen_movl_T0_reg[16] =
167 8170028d ths
{
168 8170028d ths
        gen_op_movl_T0_r0, gen_op_movl_T0_r1,
169 8170028d ths
        gen_op_movl_T0_r2, gen_op_movl_T0_r3,
170 8170028d ths
        gen_op_movl_T0_r4, gen_op_movl_T0_r5,
171 8170028d ths
        gen_op_movl_T0_r6, gen_op_movl_T0_r7,
172 8170028d ths
        gen_op_movl_T0_r8, gen_op_movl_T0_r9,
173 8170028d ths
        gen_op_movl_T0_r10, gen_op_movl_T0_r11,
174 8170028d ths
        gen_op_movl_T0_r12, gen_op_movl_T0_r13,
175 8170028d ths
        gen_op_movl_T0_r14, gen_op_movl_T0_r15,
176 8170028d ths
};
177 8170028d ths
178 8170028d ths
static void noop_write(void) {
179 8170028d ths
        /* nop.  */
180 8170028d ths
}
181 8170028d ths
182 8170028d ths
static void gen_vr_read(void) {
183 8170028d ths
        gen_op_movl_T0_im(32);
184 8170028d ths
}
185 8170028d ths
186 8170028d ths
static void gen_ccs_read(void) {
187 8170028d ths
        gen_op_movl_T0_p13();
188 8170028d ths
}
189 8170028d ths
190 8170028d ths
static void gen_ccs_write(void) {
191 8170028d ths
        gen_op_movl_p13_T0();
192 8170028d ths
}
193 8170028d ths
194 8170028d ths
/* Table to generate quick moves from T0 onto any register.  */
195 8170028d ths
static GenOpFunc *gen_movl_preg_T0[16] =
196 8170028d ths
{
197 8170028d ths
        noop_write,  /* bz, not writeable.  */
198 8170028d ths
        noop_write,  /* vr, not writeable.  */
199 8170028d ths
        gen_op_movl_p2_T0, gen_op_movl_p3_T0,
200 8170028d ths
        noop_write,  /* wz, not writeable.  */
201 8170028d ths
        gen_op_movl_p5_T0,
202 8170028d ths
        gen_op_movl_p6_T0, gen_op_movl_p7_T0,
203 8170028d ths
        noop_write,  /* dz, not writeable.  */
204 8170028d ths
        gen_op_movl_p9_T0,
205 8170028d ths
        gen_op_movl_p10_T0, gen_op_movl_p11_T0,
206 8170028d ths
        gen_op_movl_p12_T0,
207 8170028d ths
        gen_ccs_write, /* ccs needs special treatment.  */
208 8170028d ths
        gen_op_movl_p14_T0, gen_op_movl_p15_T0,
209 8170028d ths
};
210 8170028d ths
static GenOpFunc *gen_movl_T0_preg[16] =
211 8170028d ths
{
212 8170028d ths
        gen_op_movl_T0_p0,
213 8170028d ths
        gen_vr_read,
214 8170028d ths
        gen_op_movl_T0_p2, gen_op_movl_T0_p3,
215 8170028d ths
        gen_op_movl_T0_p4, gen_op_movl_T0_p5,
216 8170028d ths
        gen_op_movl_T0_p6, gen_op_movl_T0_p7,
217 8170028d ths
        gen_op_movl_T0_p8, gen_op_movl_T0_p9,
218 8170028d ths
        gen_op_movl_T0_p10, gen_op_movl_T0_p11,
219 8170028d ths
        gen_op_movl_T0_p12,
220 8170028d ths
        gen_ccs_read, /* ccs needs special treatment.  */
221 8170028d ths
        gen_op_movl_T0_p14, gen_op_movl_T0_p15,
222 8170028d ths
};
223 8170028d ths
224 8170028d ths
/* We need this table to handle moves with implicit width.  */
225 8170028d ths
int preg_sizes[] = {
226 8170028d ths
        1, /* bz.  */
227 8170028d ths
        1, /* vr.  */
228 8170028d ths
        4, /* pid.  */
229 8170028d ths
        1, /* srs.  */
230 8170028d ths
        2, /* wz.  */
231 8170028d ths
        4, 4, 4,
232 8170028d ths
        4, 4, 4, 4,
233 8170028d ths
        4, 4, 4, 4,
234 8170028d ths
};
235 8170028d ths
236 8170028d ths
#ifdef CONFIG_USER_ONLY
237 8170028d ths
#define GEN_OP_LD(width, reg) \
238 8170028d ths
  void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
239 8170028d ths
    gen_op_ld##width##_T0_##reg##_raw(); \
240 8170028d ths
  }
241 8170028d ths
#define GEN_OP_ST(width, reg) \
242 8170028d ths
  void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
243 8170028d ths
    gen_op_st##width##_##reg##_T1_raw(); \
244 8170028d ths
  }
245 8170028d ths
#else
246 8170028d ths
#define GEN_OP_LD(width, reg) \
247 8170028d ths
  void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
248 8170028d ths
    if (dc->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
249 8170028d ths
    else gen_op_ld##width##_T0_##reg##_user();\
250 8170028d ths
  }
251 8170028d ths
#define GEN_OP_ST(width, reg) \
252 8170028d ths
  void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
253 8170028d ths
    if (dc->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
254 8170028d ths
    else gen_op_st##width##_##reg##_T1_user();\
255 8170028d ths
  }
256 8170028d ths
#endif
257 8170028d ths
258 8170028d ths
GEN_OP_LD(ub, T0)
259 8170028d ths
GEN_OP_LD(b, T0)
260 8170028d ths
GEN_OP_ST(b, T0)
261 8170028d ths
GEN_OP_LD(uw, T0)
262 8170028d ths
GEN_OP_LD(w, T0)
263 8170028d ths
GEN_OP_ST(w, T0)
264 8170028d ths
GEN_OP_LD(l, T0)
265 8170028d ths
GEN_OP_ST(l, T0)
266 8170028d ths
267 8170028d ths
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
268 8170028d ths
{
269 8170028d ths
        TranslationBlock *tb;
270 8170028d ths
        tb = dc->tb;
271 8170028d ths
        if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
272 8170028d ths
                if (n == 0)
273 8170028d ths
                        gen_op_goto_tb0(TBPARAM(tb));
274 8170028d ths
                else
275 8170028d ths
                        gen_op_goto_tb1(TBPARAM(tb));
276 8170028d ths
                gen_op_movl_T0_0();
277 8170028d ths
        } else {
278 8170028d ths
                gen_op_movl_T0_0();
279 8170028d ths
        }
280 8170028d ths
        gen_op_exit_tb();
281 8170028d ths
}
282 8170028d ths
283 8170028d ths
/* Sign extend at translation time.  */
284 8170028d ths
static int sign_extend(unsigned int val, unsigned int width)
285 8170028d ths
{
286 8170028d ths
        int sval;
287 8170028d ths
288 8170028d ths
        /* LSL.  */
289 8170028d ths
        val <<= 31 - width;
290 8170028d ths
        sval = val;
291 8170028d ths
        /* ASR.  */
292 8170028d ths
        sval >>= 31 - width;
293 8170028d ths
        return sval;
294 8170028d ths
}
295 8170028d ths
296 8170028d ths
static void cris_evaluate_flags(DisasContext *dc)
297 8170028d ths
{
298 8170028d ths
        if (!dc->flags_live) {
299 8170028d ths
300 8170028d ths
                switch (dc->cc_op)
301 8170028d ths
                {
302 8170028d ths
                        case CC_OP_MCP:
303 8170028d ths
                                gen_op_evaluate_flags_mcp ();
304 8170028d ths
                                break;
305 8170028d ths
                        case CC_OP_MULS:
306 8170028d ths
                                gen_op_evaluate_flags_muls ();
307 8170028d ths
                                break;
308 8170028d ths
                        case CC_OP_MULU:
309 8170028d ths
                                gen_op_evaluate_flags_mulu ();
310 8170028d ths
                                break;
311 8170028d ths
                        case CC_OP_MOVE:
312 8170028d ths
                                switch (dc->cc_size)
313 8170028d ths
                                {
314 8170028d ths
                                        case 4:
315 8170028d ths
                                                gen_op_evaluate_flags_move_4();
316 8170028d ths
                                                break;
317 8170028d ths
                                        case 2:
318 8170028d ths
                                                gen_op_evaluate_flags_move_2();
319 8170028d ths
                                                break;
320 8170028d ths
                                        default:
321 8170028d ths
                                                gen_op_evaluate_flags ();
322 8170028d ths
                                                break;
323 8170028d ths
                                }
324 8170028d ths
                                break;
325 8170028d ths
326 8170028d ths
                        default:
327 8170028d ths
                        {
328 8170028d ths
                                switch (dc->cc_size)
329 8170028d ths
                                {
330 8170028d ths
                                        case 4:
331 8170028d ths
                                                gen_op_evaluate_flags_alu_4 ();
332 8170028d ths
                                                break;
333 8170028d ths
                                        default:
334 8170028d ths
                                                gen_op_evaluate_flags ();
335 8170028d ths
                                                break;
336 8170028d ths
                                }
337 8170028d ths
                        }
338 8170028d ths
                        break;
339 8170028d ths
                }
340 8170028d ths
                dc->flags_live = 1;
341 8170028d ths
        }
342 8170028d ths
}
343 8170028d ths
344 8170028d ths
static void cris_cc_mask(DisasContext *dc, unsigned int mask)
345 8170028d ths
{
346 8170028d ths
        uint32_t ovl;
347 8170028d ths
348 8170028d ths
        ovl = (dc->cc_mask ^ mask) & ~mask;
349 8170028d ths
        if (ovl) {
350 8170028d ths
                /* TODO: optimize this case. It trigs all the time.  */
351 8170028d ths
                cris_evaluate_flags (dc);
352 8170028d ths
        }
353 8170028d ths
        dc->cc_mask = mask;
354 8170028d ths
355 8170028d ths
        dc->update_cc = 1;
356 8170028d ths
        if (mask == 0)
357 8170028d ths
                dc->update_cc = 0;
358 8170028d ths
        else {
359 8170028d ths
                gen_op_update_cc_mask(mask);
360 8170028d ths
                dc->flags_live = 0;
361 8170028d ths
        }
362 8170028d ths
}
363 8170028d ths
364 8170028d ths
static void cris_update_cc_op(DisasContext *dc, int op)
365 8170028d ths
{
366 8170028d ths
        dc->cc_op = op;
367 8170028d ths
        gen_op_update_cc_op(op);
368 8170028d ths
        dc->flags_live = 0;
369 8170028d ths
}
370 8170028d ths
static void cris_update_cc_size(DisasContext *dc, int size)
371 8170028d ths
{
372 8170028d ths
        dc->cc_size = size;
373 8170028d ths
        gen_op_update_cc_size_im(size);
374 8170028d ths
}
375 8170028d ths
376 8170028d ths
/* op is the operation.
377 8170028d ths
   T0, T1 are the operands.
378 8170028d ths
   dst is the destination reg.
379 8170028d ths
*/
380 8170028d ths
static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
381 8170028d ths
{
382 8170028d ths
        int writeback = 1;
383 8170028d ths
        if (dc->update_cc) {
384 8170028d ths
                cris_update_cc_op(dc, op);
385 8170028d ths
                cris_update_cc_size(dc, size);
386 8170028d ths
                gen_op_update_cc_x(dc->flagx_live, dc->flags_x);
387 8170028d ths
                gen_op_update_cc_dest_T0();
388 8170028d ths
        }
389 8170028d ths
390 8170028d ths
        /* Emit the ALU insns.  */
391 8170028d ths
        switch (op)
392 8170028d ths
        {
393 8170028d ths
                case CC_OP_ADD:
394 8170028d ths
                        gen_op_addl_T0_T1();
395 8170028d ths
                        /* Extended arithmetics.  */
396 8170028d ths
                        if (!dc->flagx_live)
397 8170028d ths
                                gen_op_addxl_T0_C();
398 8170028d ths
                        else if (dc->flags_x)
399 8170028d ths
                                gen_op_addxl_T0_C();
400 8170028d ths
                        break;
401 8170028d ths
                case CC_OP_ADDC:
402 8170028d ths
                        gen_op_addl_T0_T1();
403 8170028d ths
                        gen_op_addl_T0_C();
404 8170028d ths
                        break;
405 8170028d ths
                case CC_OP_MCP:
406 8170028d ths
                        gen_op_addl_T0_T1();
407 8170028d ths
                        gen_op_addl_T0_R();
408 8170028d ths
                        break;
409 8170028d ths
                case CC_OP_SUB:
410 8170028d ths
                        gen_op_negl_T1_T1();
411 8170028d ths
                        gen_op_addl_T0_T1();
412 8170028d ths
                        /* CRIS flag evaluation needs ~src.  */
413 8170028d ths
                        gen_op_negl_T1_T1();
414 8170028d ths
                        gen_op_not_T1_T1();
415 8170028d ths
416 8170028d ths
                        /* Extended arithmetics.  */
417 8170028d ths
                        if (!dc->flagx_live)
418 8170028d ths
                                gen_op_subxl_T0_C();
419 8170028d ths
                        else if (dc->flags_x)
420 8170028d ths
                                gen_op_subxl_T0_C();
421 8170028d ths
                        break;
422 8170028d ths
                case CC_OP_MOVE:
423 8170028d ths
                        gen_op_movl_T0_T1();
424 8170028d ths
                        break;
425 8170028d ths
                case CC_OP_OR:
426 8170028d ths
                        gen_op_orl_T0_T1();
427 8170028d ths
                        break;
428 8170028d ths
                case CC_OP_AND:
429 8170028d ths
                        gen_op_andl_T0_T1();
430 8170028d ths
                        break;
431 8170028d ths
                case CC_OP_XOR:
432 8170028d ths
                        gen_op_xorl_T0_T1();
433 8170028d ths
                        break;
434 8170028d ths
                case CC_OP_LSL:
435 8170028d ths
                        gen_op_lsll_T0_T1();
436 8170028d ths
                        break;
437 8170028d ths
                case CC_OP_LSR:
438 8170028d ths
                        gen_op_lsrl_T0_T1();
439 8170028d ths
                        break;
440 8170028d ths
                case CC_OP_ASR:
441 8170028d ths
                        gen_op_asrl_T0_T1();
442 8170028d ths
                        break;
443 8170028d ths
                case CC_OP_NEG:
444 8170028d ths
                        gen_op_negl_T0_T1();
445 8170028d ths
                        /* Extended arithmetics.  */
446 8170028d ths
                        gen_op_subxl_T0_C();
447 8170028d ths
                        break;
448 8170028d ths
                case CC_OP_LZ:
449 8170028d ths
                        gen_op_lz_T0_T1();
450 8170028d ths
                        break;
451 8170028d ths
                case CC_OP_BTST:
452 8170028d ths
                        gen_op_btst_T0_T1();
453 8170028d ths
                        writeback = 0;
454 8170028d ths
                        break;
455 8170028d ths
                case CC_OP_MULS:
456 8170028d ths
                        gen_op_muls_T0_T1();
457 8170028d ths
                        break;
458 8170028d ths
                case CC_OP_MULU:
459 8170028d ths
                        gen_op_mulu_T0_T1();
460 8170028d ths
                        break;
461 8170028d ths
                case CC_OP_DSTEP:
462 8170028d ths
                        gen_op_dstep_T0_T1();
463 8170028d ths
                        break;
464 8170028d ths
                case CC_OP_BOUND:
465 8170028d ths
                        gen_op_bound_T0_T1();
466 8170028d ths
                        break;
467 8170028d ths
                case CC_OP_CMP:
468 8170028d ths
                        gen_op_negl_T1_T1();
469 8170028d ths
                        gen_op_addl_T0_T1();
470 8170028d ths
                        /* CRIS flag evaluation needs ~src.  */
471 8170028d ths
                        gen_op_negl_T1_T1();
472 8170028d ths
                        gen_op_not_T1_T1();
473 8170028d ths
474 8170028d ths
                        /* Extended arithmetics.  */
475 8170028d ths
                        gen_op_subxl_T0_C();
476 8170028d ths
                        writeback = 0;
477 8170028d ths
                        break;
478 8170028d ths
                default:
479 8170028d ths
                        fprintf (logfile, "illegal ALU op.\n");
480 8170028d ths
                        BUG();
481 8170028d ths
                        break;
482 8170028d ths
        }
483 8170028d ths
484 8170028d ths
        if (dc->update_cc)
485 8170028d ths
                gen_op_update_cc_src_T1();
486 8170028d ths
487 8170028d ths
        if (size == 1)
488 8170028d ths
                gen_op_andl_T0_im(0xff);
489 8170028d ths
        else if (size == 2)
490 8170028d ths
                gen_op_andl_T0_im(0xffff);
491 8170028d ths
        /* Writeback.  */
492 8170028d ths
        if (writeback) {
493 8170028d ths
                if (size == 4)
494 8170028d ths
                        gen_movl_reg_T0[rd]();
495 8170028d ths
                else {
496 8170028d ths
                        gen_op_movl_T1_T0();
497 8170028d ths
                        gen_movl_T0_reg[rd]();
498 8170028d ths
                        if (size == 1)
499 8170028d ths
                                gen_op_andl_T0_im(~0xff);
500 8170028d ths
                        else
501 8170028d ths
                                gen_op_andl_T0_im(~0xffff);
502 8170028d ths
                        gen_op_orl_T0_T1();
503 8170028d ths
                        gen_movl_reg_T0[rd]();
504 8170028d ths
                        gen_op_movl_T0_T1();
505 8170028d ths
                }
506 8170028d ths
        }
507 8170028d ths
        if (dc->update_cc)
508 8170028d ths
                gen_op_update_cc_result_T0();
509 8170028d ths
510 8170028d ths
        {
511 8170028d ths
                /* TODO: Optimize this.  */
512 8170028d ths
                if (!dc->flagx_live)
513 8170028d ths
                        cris_evaluate_flags(dc);
514 8170028d ths
        }
515 8170028d ths
}
516 8170028d ths
517 8170028d ths
static int arith_cc(DisasContext *dc)
518 8170028d ths
{
519 8170028d ths
        if (dc->update_cc) {
520 8170028d ths
                switch (dc->cc_op) {
521 8170028d ths
                        case CC_OP_ADD: return 1;
522 8170028d ths
                        case CC_OP_SUB: return 1;
523 8170028d ths
                        case CC_OP_LSL: return 1;
524 8170028d ths
                        case CC_OP_LSR: return 1;
525 8170028d ths
                        case CC_OP_ASR: return 1;
526 8170028d ths
                        case CC_OP_CMP: return 1;
527 8170028d ths
                        default:
528 8170028d ths
                                return 0;
529 8170028d ths
                }
530 8170028d ths
        }
531 8170028d ths
        return 0;
532 8170028d ths
}
533 8170028d ths
534 8170028d ths
static void gen_tst_cc (DisasContext *dc, int cond)
535 8170028d ths
{
536 8170028d ths
        int arith_opt;
537 8170028d ths
538 8170028d ths
        /* TODO: optimize more condition codes.  */
539 8170028d ths
        arith_opt = arith_cc(dc) && !dc->flags_live;
540 8170028d ths
        switch (cond) {
541 8170028d ths
                case CC_EQ:
542 8170028d ths
                        if (arith_opt)
543 8170028d ths
                                gen_op_tst_cc_eq_fast ();
544 8170028d ths
                        else {
545 8170028d ths
                                cris_evaluate_flags(dc);
546 8170028d ths
                                gen_op_tst_cc_eq ();
547 8170028d ths
                        }
548 8170028d ths
                        break;
549 8170028d ths
                case CC_NE:
550 8170028d ths
                        if (arith_opt)
551 8170028d ths
                                gen_op_tst_cc_ne_fast ();
552 8170028d ths
                        else {
553 8170028d ths
                                cris_evaluate_flags(dc);
554 8170028d ths
                                gen_op_tst_cc_ne ();
555 8170028d ths
                        }
556 8170028d ths
                        break;
557 8170028d ths
                case CC_CS:
558 8170028d ths
                        cris_evaluate_flags(dc);
559 8170028d ths
                        gen_op_tst_cc_cs ();
560 8170028d ths
                        break;
561 8170028d ths
                case CC_CC:
562 8170028d ths
                        cris_evaluate_flags(dc);
563 8170028d ths
                        gen_op_tst_cc_cc ();
564 8170028d ths
                        break;
565 8170028d ths
                case CC_VS:
566 8170028d ths
                        cris_evaluate_flags(dc);
567 8170028d ths
                        gen_op_tst_cc_vs ();
568 8170028d ths
                        break;
569 8170028d ths
                case CC_VC:
570 8170028d ths
                        cris_evaluate_flags(dc);
571 8170028d ths
                        gen_op_tst_cc_vc ();
572 8170028d ths
                        break;
573 8170028d ths
                case CC_PL:
574 8170028d ths
                        if (arith_opt)
575 8170028d ths
                                gen_op_tst_cc_pl_fast ();
576 8170028d ths
                        else {
577 8170028d ths
                                cris_evaluate_flags(dc);
578 8170028d ths
                                gen_op_tst_cc_pl ();
579 8170028d ths
                        }
580 8170028d ths
                        break;
581 8170028d ths
                case CC_MI:
582 8170028d ths
                        if (arith_opt)
583 8170028d ths
                                gen_op_tst_cc_mi_fast ();
584 8170028d ths
                        else {
585 8170028d ths
                                cris_evaluate_flags(dc);
586 8170028d ths
                                gen_op_tst_cc_mi ();
587 8170028d ths
                        }
588 8170028d ths
                        break;
589 8170028d ths
                case CC_LS:
590 8170028d ths
                        cris_evaluate_flags(dc);
591 8170028d ths
                        gen_op_tst_cc_ls ();
592 8170028d ths
                        break;
593 8170028d ths
                case CC_HI:
594 8170028d ths
                        cris_evaluate_flags(dc);
595 8170028d ths
                        gen_op_tst_cc_hi ();
596 8170028d ths
                        break;
597 8170028d ths
                case CC_GE:
598 8170028d ths
                        cris_evaluate_flags(dc);
599 8170028d ths
                        gen_op_tst_cc_ge ();
600 8170028d ths
                        break;
601 8170028d ths
                case CC_LT:
602 8170028d ths
                        cris_evaluate_flags(dc);
603 8170028d ths
                        gen_op_tst_cc_lt ();
604 8170028d ths
                        break;
605 8170028d ths
                case CC_GT:
606 8170028d ths
                        cris_evaluate_flags(dc);
607 8170028d ths
                        gen_op_tst_cc_gt ();
608 8170028d ths
                        break;
609 8170028d ths
                case CC_LE:
610 8170028d ths
                        cris_evaluate_flags(dc);
611 8170028d ths
                        gen_op_tst_cc_le ();
612 8170028d ths
                        break;
613 8170028d ths
                case CC_P:
614 8170028d ths
                        cris_evaluate_flags(dc);
615 8170028d ths
                        gen_op_tst_cc_p ();
616 8170028d ths
                        break;
617 8170028d ths
                case CC_A:
618 8170028d ths
                        cris_evaluate_flags(dc);
619 8170028d ths
                        gen_op_movl_T0_im (1);
620 8170028d ths
                        break;
621 8170028d ths
                default:
622 8170028d ths
                        BUG();
623 8170028d ths
                        break;
624 8170028d ths
        };
625 8170028d ths
}
626 8170028d ths
627 8170028d ths
static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
628 8170028d ths
{
629 8170028d ths
        /* This helps us re-schedule the micro-code to insns in delay-slots
630 8170028d ths
           before the actual jump.  */
631 8170028d ths
        dc->delayed_branch = 2;
632 8170028d ths
        dc->delayed_pc = dc->pc + offset;
633 8170028d ths
        dc->bcc = cond;
634 8170028d ths
        if (cond != CC_A)
635 8170028d ths
        {
636 8170028d ths
                gen_tst_cc (dc, cond);
637 8170028d ths
                gen_op_evaluate_bcc ();
638 8170028d ths
        }
639 8170028d ths
        gen_op_movl_T0_im (dc->delayed_pc);
640 8170028d ths
        gen_op_movl_btarget_T0 ();
641 8170028d ths
}
642 8170028d ths
643 8170028d ths
/* Dynamic jumps, when the dest is in a live reg for example.  */
644 8170028d ths
void cris_prepare_dyn_jmp (DisasContext *dc)
645 8170028d ths
{
646 8170028d ths
        /* This helps us re-schedule the micro-code to insns in delay-slots
647 8170028d ths
           before the actual jump.  */
648 8170028d ths
        dc->delayed_branch = 2;
649 8170028d ths
        dc->dyn_jmp = 1;
650 8170028d ths
        dc->bcc = CC_A;
651 8170028d ths
}
652 8170028d ths
653 8170028d ths
void cris_prepare_jmp (DisasContext *dc, uint32_t dst)
654 8170028d ths
{
655 8170028d ths
        /* This helps us re-schedule the micro-code to insns in delay-slots
656 8170028d ths
           before the actual jump.  */
657 8170028d ths
        dc->delayed_branch = 2;
658 8170028d ths
        dc->delayed_pc = dst;
659 8170028d ths
        dc->dyn_jmp = 0;
660 8170028d ths
        dc->bcc = CC_A;
661 8170028d ths
}
662 8170028d ths
663 8170028d ths
void gen_load_T0_T0 (DisasContext *dc, unsigned int size, int sign)
664 8170028d ths
{
665 8170028d ths
        if (size == 1) {
666 8170028d ths
                if (sign)
667 8170028d ths
                        gen_op_ldb_T0_T0(dc);
668 8170028d ths
                else
669 8170028d ths
                        gen_op_ldub_T0_T0(dc);
670 8170028d ths
        }
671 8170028d ths
        else if (size == 2) {
672 8170028d ths
                if (sign)
673 8170028d ths
                        gen_op_ldw_T0_T0(dc);
674 8170028d ths
                else
675 8170028d ths
                        gen_op_lduw_T0_T0(dc);
676 8170028d ths
        }
677 8170028d ths
        else {
678 8170028d ths
                gen_op_ldl_T0_T0(dc);
679 8170028d ths
        }
680 8170028d ths
}
681 8170028d ths
682 8170028d ths
void gen_store_T0_T1 (DisasContext *dc, unsigned int size)
683 8170028d ths
{
684 8170028d ths
        /* Remember, operands are flipped. CRIS has reversed order.  */
685 8170028d ths
        if (size == 1) {
686 8170028d ths
                gen_op_stb_T0_T1(dc);
687 8170028d ths
        }
688 8170028d ths
        else if (size == 2) {
689 8170028d ths
                gen_op_stw_T0_T1(dc);
690 8170028d ths
        }
691 8170028d ths
        else
692 8170028d ths
                gen_op_stl_T0_T1(dc);
693 8170028d ths
}
694 8170028d ths
695 8170028d ths
/* sign extend T1 according to size.  */
696 8170028d ths
static void gen_sext_T1_T0(int size)
697 8170028d ths
{
698 8170028d ths
        if (size == 1)
699 8170028d ths
                gen_op_extb_T1_T0();
700 8170028d ths
        else if (size == 2)
701 8170028d ths
                gen_op_extw_T1_T0();
702 8170028d ths
}
703 8170028d ths
704 8170028d ths
static void gen_sext_T1_T1(int size)
705 8170028d ths
{
706 8170028d ths
        if (size == 1)
707 8170028d ths
                gen_op_extb_T1_T1();
708 8170028d ths
        else if (size == 2)
709 8170028d ths
                gen_op_extw_T1_T1();
710 8170028d ths
}
711 8170028d ths
712 8170028d ths
static void gen_sext_T0_T0(int size)
713 8170028d ths
{
714 8170028d ths
        if (size == 1)
715 8170028d ths
                gen_op_extb_T0_T0();
716 8170028d ths
        else if (size == 2)
717 8170028d ths
                gen_op_extw_T0_T0();
718 8170028d ths
}
719 8170028d ths
720 8170028d ths
static void gen_zext_T0_T0(int size)
721 8170028d ths
{
722 8170028d ths
        if (size == 1)
723 8170028d ths
                gen_op_zextb_T0_T0();
724 8170028d ths
        else if (size == 2)
725 8170028d ths
                gen_op_zextw_T0_T0();
726 8170028d ths
}
727 8170028d ths
728 8170028d ths
static void gen_zext_T1_T0(int size)
729 8170028d ths
{
730 8170028d ths
        if (size == 1)
731 8170028d ths
                gen_op_zextb_T1_T0();
732 8170028d ths
        else if (size == 2)
733 8170028d ths
                gen_op_zextw_T1_T0();
734 8170028d ths
}
735 8170028d ths
736 8170028d ths
static void gen_zext_T1_T1(int size)
737 8170028d ths
{
738 8170028d ths
        if (size == 1)
739 8170028d ths
                gen_op_zextb_T1_T1();
740 8170028d ths
        else if (size == 2)
741 8170028d ths
                gen_op_zextw_T1_T1();
742 8170028d ths
}
743 8170028d ths
744 8170028d ths
#if DISAS_CRIS
745 8170028d ths
static char memsize_char(int size)
746 8170028d ths
{
747 8170028d ths
        switch (size)
748 8170028d ths
        {
749 8170028d ths
                case 1: return 'b';  break;
750 8170028d ths
                case 2: return 'w';  break;
751 8170028d ths
                case 4: return 'd';  break;
752 8170028d ths
                default:
753 8170028d ths
                        return 'x';
754 8170028d ths
                        break;
755 8170028d ths
        }
756 8170028d ths
}
757 8170028d ths
#endif
758 8170028d ths
759 8170028d ths
static unsigned int memsize_z(DisasContext *dc)
760 8170028d ths
{
761 8170028d ths
        return dc->zsize + 1;
762 8170028d ths
}
763 8170028d ths
764 8170028d ths
static unsigned int memsize_zz(DisasContext *dc)
765 8170028d ths
{
766 8170028d ths
        switch (dc->zzsize)
767 8170028d ths
        {
768 8170028d ths
                case 0: return 1;
769 8170028d ths
                case 1: return 2;
770 8170028d ths
                default:
771 8170028d ths
                        return 4;
772 8170028d ths
        }
773 8170028d ths
}
774 8170028d ths
775 8170028d ths
static void do_postinc (DisasContext *dc, int size)
776 8170028d ths
{
777 8170028d ths
        if (!dc->postinc)
778 8170028d ths
                return;
779 8170028d ths
        gen_movl_T0_reg[dc->op1]();
780 8170028d ths
        gen_op_addl_T0_im(size);
781 8170028d ths
        gen_movl_reg_T0[dc->op1]();
782 8170028d ths
}
783 8170028d ths
784 8170028d ths
785 8170028d ths
static void dec_prep_move_r(DisasContext *dc, int rs, int rd,
786 8170028d ths
                            int size, int s_ext)
787 8170028d ths
{
788 8170028d ths
        gen_movl_T0_reg[rs]();
789 8170028d ths
        gen_op_movl_T1_T0();
790 8170028d ths
        if (s_ext)
791 8170028d ths
                gen_sext_T1_T1(size);
792 8170028d ths
        else
793 8170028d ths
                gen_zext_T1_T1(size);
794 8170028d ths
}
795 8170028d ths
796 8170028d ths
/* Prepare T0 and T1 for a register alu operation.
797 8170028d ths
   s_ext decides if the operand1 should be sign-extended or zero-extended when
798 8170028d ths
   needed.  */
799 8170028d ths
static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
800 8170028d ths
                          int size, int s_ext)
801 8170028d ths
{
802 8170028d ths
        dec_prep_move_r(dc, rs, rd, size, s_ext);
803 8170028d ths
804 8170028d ths
        gen_movl_T0_reg[rd]();
805 8170028d ths
        if (s_ext)
806 8170028d ths
                gen_sext_T0_T0(size);
807 8170028d ths
        else
808 8170028d ths
                gen_zext_T0_T0(size);
809 8170028d ths
}
810 8170028d ths
811 8170028d ths
/* Prepare T0 and T1 for a memory + alu operation.
812 8170028d ths
   s_ext decides if the operand1 should be sign-extended or zero-extended when
813 8170028d ths
   needed.  */
814 8170028d ths
static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize)
815 8170028d ths
{
816 8170028d ths
        unsigned int rs, rd;
817 8170028d ths
        uint32_t imm;
818 8170028d ths
        int is_imm;
819 8170028d ths
        int insn_len = 2;
820 8170028d ths
821 8170028d ths
        rs = dc->op1;
822 8170028d ths
        rd = dc->op2;
823 8170028d ths
        is_imm = rs == 15 && dc->postinc;
824 8170028d ths
825 8170028d ths
        /* Load [$rs] onto T1.  */
826 8170028d ths
        if (is_imm) {
827 8170028d ths
                insn_len = 2 + memsize;
828 8170028d ths
                if (memsize == 1)
829 8170028d ths
                        insn_len++;
830 8170028d ths
831 8170028d ths
                imm = ldl_code(dc->pc + 2);
832 8170028d ths
                if (memsize != 4) {
833 8170028d ths
                        if (s_ext) {
834 8170028d ths
                                imm = sign_extend(imm, (memsize * 8) - 1);
835 8170028d ths
                        } else {
836 8170028d ths
                                if (memsize == 1)
837 8170028d ths
                                        imm &= 0xff;
838 8170028d ths
                                else
839 8170028d ths
                                        imm &= 0xffff;
840 8170028d ths
                        }
841 8170028d ths
                }
842 8170028d ths
                DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n",
843 8170028d ths
                            imm, rd, s_ext, memsize));
844 8170028d ths
                gen_op_movl_T1_im (imm);
845 8170028d ths
                dc->postinc = 0;
846 8170028d ths
        } else {
847 8170028d ths
                gen_movl_T0_reg[rs]();
848 8170028d ths
                gen_load_T0_T0(dc, memsize, 0);
849 8170028d ths
                gen_op_movl_T1_T0();
850 8170028d ths
                if (s_ext)
851 8170028d ths
                        gen_sext_T1_T1(memsize);
852 8170028d ths
                else
853 8170028d ths
                        gen_zext_T1_T1(memsize);
854 8170028d ths
        }
855 8170028d ths
856 8170028d ths
        /* put dest in T0.  */
857 8170028d ths
        gen_movl_T0_reg[rd]();
858 8170028d ths
        return insn_len;
859 8170028d ths
}
860 8170028d ths
861 8170028d ths
#if DISAS_CRIS
862 8170028d ths
static const char *cc_name(int cc)
863 8170028d ths
{
864 8170028d ths
        static char *cc_names[16] = {
865 8170028d ths
                "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
866 8170028d ths
                "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
867 8170028d ths
        };
868 8170028d ths
        assert(cc < 16);
869 8170028d ths
        return cc_names[cc];
870 8170028d ths
}
871 8170028d ths
#endif
872 8170028d ths
873 8170028d ths
static unsigned int dec_bccq(DisasContext *dc)
874 8170028d ths
{
875 8170028d ths
        int32_t offset;
876 8170028d ths
        int sign;
877 8170028d ths
        uint32_t cond = dc->op2;
878 8170028d ths
        int tmp;
879 8170028d ths
880 8170028d ths
        offset = EXTRACT_FIELD (dc->ir, 1, 7);
881 8170028d ths
        sign = EXTRACT_FIELD(dc->ir, 0, 0);
882 8170028d ths
883 8170028d ths
        offset *= 2;
884 8170028d ths
        offset |= sign << 8;
885 8170028d ths
        tmp = offset;
886 8170028d ths
        offset = sign_extend(offset, 8);
887 8170028d ths
888 8170028d ths
        /* op2 holds the condition-code.  */
889 8170028d ths
        cris_cc_mask(dc, 0);
890 8170028d ths
        cris_prepare_cc_branch (dc, offset, cond);
891 8170028d ths
        return 2;
892 8170028d ths
}
893 8170028d ths
static unsigned int dec_addoq(DisasContext *dc)
894 8170028d ths
{
895 8170028d ths
        uint32_t imm;
896 8170028d ths
897 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
898 8170028d ths
        imm = sign_extend(dc->op1, 7);
899 8170028d ths
900 8170028d ths
        DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2));
901 8170028d ths
        cris_cc_mask(dc, 0);
902 8170028d ths
        /* Fetch register operand,  */
903 8170028d ths
        gen_movl_T0_reg[dc->op2]();
904 8170028d ths
        gen_op_movl_T1_im(imm);
905 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4);
906 8170028d ths
        return 2;
907 8170028d ths
}
908 8170028d ths
static unsigned int dec_addq(DisasContext *dc)
909 8170028d ths
{
910 8170028d ths
        DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2));
911 8170028d ths
912 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
913 8170028d ths
914 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
915 8170028d ths
        /* Fetch register operand,  */
916 8170028d ths
        gen_movl_T0_reg[dc->op2]();
917 8170028d ths
        gen_op_movl_T1_im(dc->op1);
918 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
919 8170028d ths
        return 2;
920 8170028d ths
}
921 8170028d ths
static unsigned int dec_moveq(DisasContext *dc)
922 8170028d ths
{
923 8170028d ths
        uint32_t imm;
924 8170028d ths
925 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
926 8170028d ths
        imm = sign_extend(dc->op1, 5);
927 8170028d ths
        DIS(fprintf (logfile, "moveq %d, $r%u\n", imm, dc->op2));
928 8170028d ths
929 8170028d ths
        cris_cc_mask(dc, 0);
930 8170028d ths
        gen_op_movl_T1_im(imm);
931 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
932 8170028d ths
933 8170028d ths
        return 2;
934 8170028d ths
}
935 8170028d ths
static unsigned int dec_subq(DisasContext *dc)
936 8170028d ths
{
937 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
938 8170028d ths
939 8170028d ths
        DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2));
940 8170028d ths
941 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
942 8170028d ths
        /* Fetch register operand,  */
943 8170028d ths
        gen_movl_T0_reg[dc->op2]();
944 8170028d ths
        gen_op_movl_T1_im(dc->op1);
945 8170028d ths
        crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
946 8170028d ths
        return 2;
947 8170028d ths
}
948 8170028d ths
static unsigned int dec_cmpq(DisasContext *dc)
949 8170028d ths
{
950 8170028d ths
        uint32_t imm;
951 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
952 8170028d ths
        imm = sign_extend(dc->op1, 5);
953 8170028d ths
954 8170028d ths
        DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
955 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
956 8170028d ths
        gen_movl_T0_reg[dc->op2]();
957 8170028d ths
        gen_op_movl_T1_im(imm);
958 8170028d ths
        crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
959 8170028d ths
        return 2;
960 8170028d ths
}
961 8170028d ths
static unsigned int dec_andq(DisasContext *dc)
962 8170028d ths
{
963 8170028d ths
        uint32_t imm;
964 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
965 8170028d ths
        imm = sign_extend(dc->op1, 5);
966 8170028d ths
967 8170028d ths
        DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
968 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
969 8170028d ths
        gen_movl_T0_reg[dc->op2]();
970 8170028d ths
        gen_op_movl_T1_im(imm);
971 8170028d ths
        crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4);
972 8170028d ths
        return 2;
973 8170028d ths
}
974 8170028d ths
static unsigned int dec_orq(DisasContext *dc)
975 8170028d ths
{
976 8170028d ths
        uint32_t imm;
977 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
978 8170028d ths
        imm = sign_extend(dc->op1, 5);
979 8170028d ths
        DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
980 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
981 8170028d ths
        gen_movl_T0_reg[dc->op2]();
982 8170028d ths
        gen_op_movl_T1_im(imm);
983 8170028d ths
        crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4);
984 8170028d ths
        return 2;
985 8170028d ths
}
986 8170028d ths
static unsigned int dec_btstq(DisasContext *dc)
987 8170028d ths
{
988 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
989 8170028d ths
        DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
990 8170028d ths
        cris_evaluate_flags(dc);
991 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
992 8170028d ths
        gen_movl_T0_reg[dc->op2]();
993 8170028d ths
        gen_op_movl_T1_im(dc->op1);
994 8170028d ths
        crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
995 8170028d ths
996 8170028d ths
        cris_update_cc_op(dc, CC_OP_FLAGS);
997 8170028d ths
        gen_op_movl_flags_T0();
998 8170028d ths
        dc->flags_live = 1;
999 8170028d ths
        return 2;
1000 8170028d ths
}
1001 8170028d ths
static unsigned int dec_asrq(DisasContext *dc)
1002 8170028d ths
{
1003 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1004 8170028d ths
        DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
1005 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1006 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1007 8170028d ths
        gen_op_movl_T1_im(dc->op1);
1008 8170028d ths
        crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4);
1009 8170028d ths
        return 2;
1010 8170028d ths
}
1011 8170028d ths
static unsigned int dec_lslq(DisasContext *dc)
1012 8170028d ths
{
1013 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1014 8170028d ths
        DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));
1015 8170028d ths
1016 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1017 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1018 8170028d ths
        gen_op_movl_T1_im(dc->op1);
1019 8170028d ths
        crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4);
1020 8170028d ths
        return 2;
1021 8170028d ths
}
1022 8170028d ths
static unsigned int dec_lsrq(DisasContext *dc)
1023 8170028d ths
{
1024 8170028d ths
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1025 8170028d ths
        DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));
1026 8170028d ths
1027 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1028 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1029 8170028d ths
        gen_op_movl_T1_im(dc->op1);
1030 8170028d ths
        crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4);
1031 8170028d ths
        return 2;
1032 8170028d ths
}
1033 8170028d ths
1034 8170028d ths
static unsigned int dec_move_r(DisasContext *dc)
1035 8170028d ths
{
1036 8170028d ths
        int size = memsize_zz(dc);
1037 8170028d ths
1038 8170028d ths
        DIS(fprintf (logfile, "move.%c $r%u, $r%u\n",
1039 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1040 8170028d ths
1041 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1042 8170028d ths
        dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1043 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, size);
1044 8170028d ths
        return 2;
1045 8170028d ths
}
1046 8170028d ths
1047 8170028d ths
static unsigned int dec_scc_r(DisasContext *dc)
1048 8170028d ths
{
1049 8170028d ths
        int cond = dc->op2;
1050 8170028d ths
1051 8170028d ths
        DIS(fprintf (logfile, "s%s $r%u\n",
1052 8170028d ths
                    cc_name(cond), dc->op1));
1053 8170028d ths
1054 8170028d ths
        if (cond != CC_A)
1055 8170028d ths
        {
1056 8170028d ths
                gen_tst_cc (dc, cond);
1057 8170028d ths
                gen_op_movl_T1_T0();
1058 8170028d ths
        }
1059 8170028d ths
        else
1060 8170028d ths
                gen_op_movl_T1_im(1);
1061 8170028d ths
1062 8170028d ths
        cris_cc_mask(dc, 0);
1063 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1064 8170028d ths
        return 2;
1065 8170028d ths
}
1066 8170028d ths
1067 8170028d ths
static unsigned int dec_and_r(DisasContext *dc)
1068 8170028d ths
{
1069 8170028d ths
        int size = memsize_zz(dc);
1070 8170028d ths
1071 8170028d ths
        DIS(fprintf (logfile, "and.%c $r%u, $r%u\n",
1072 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1073 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1074 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1075 8170028d ths
        crisv32_alu_op(dc, CC_OP_AND, dc->op2, size);
1076 8170028d ths
        return 2;
1077 8170028d ths
}
1078 8170028d ths
1079 8170028d ths
static unsigned int dec_lz_r(DisasContext *dc)
1080 8170028d ths
{
1081 8170028d ths
        DIS(fprintf (logfile, "lz $r%u, $r%u\n",
1082 8170028d ths
                    dc->op1, dc->op2));
1083 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1084 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1085 8170028d ths
        crisv32_alu_op(dc, CC_OP_LZ, dc->op2, 4);
1086 8170028d ths
        return 2;
1087 8170028d ths
}
1088 8170028d ths
1089 8170028d ths
static unsigned int dec_lsl_r(DisasContext *dc)
1090 8170028d ths
{
1091 8170028d ths
        int size = memsize_zz(dc);
1092 8170028d ths
1093 8170028d ths
        DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n",
1094 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1095 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1096 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1097 8170028d ths
        gen_op_andl_T1_im(63);
1098 8170028d ths
        crisv32_alu_op(dc, CC_OP_LSL, dc->op2, size);
1099 8170028d ths
        return 2;
1100 8170028d ths
}
1101 8170028d ths
1102 8170028d ths
static unsigned int dec_lsr_r(DisasContext *dc)
1103 8170028d ths
{
1104 8170028d ths
        int size = memsize_zz(dc);
1105 8170028d ths
1106 8170028d ths
        DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n",
1107 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1108 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1109 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1110 8170028d ths
        gen_op_andl_T1_im(63);
1111 8170028d ths
        crisv32_alu_op(dc, CC_OP_LSR, dc->op2, size);
1112 8170028d ths
        return 2;
1113 8170028d ths
}
1114 8170028d ths
1115 8170028d ths
static unsigned int dec_asr_r(DisasContext *dc)
1116 8170028d ths
{
1117 8170028d ths
        int size = memsize_zz(dc);
1118 8170028d ths
1119 8170028d ths
        DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n",
1120 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1121 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1122 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1123 8170028d ths
        gen_op_andl_T1_im(63);
1124 8170028d ths
        crisv32_alu_op(dc, CC_OP_ASR, dc->op2, size);
1125 8170028d ths
        return 2;
1126 8170028d ths
}
1127 8170028d ths
1128 8170028d ths
static unsigned int dec_muls_r(DisasContext *dc)
1129 8170028d ths
{
1130 8170028d ths
        int size = memsize_zz(dc);
1131 8170028d ths
1132 8170028d ths
        DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n",
1133 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1134 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZV);
1135 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1136 8170028d ths
        gen_sext_T0_T0(size);
1137 8170028d ths
        crisv32_alu_op(dc, CC_OP_MULS, dc->op2, 4);
1138 8170028d ths
        return 2;
1139 8170028d ths
}
1140 8170028d ths
1141 8170028d ths
static unsigned int dec_mulu_r(DisasContext *dc)
1142 8170028d ths
{
1143 8170028d ths
        int size = memsize_zz(dc);
1144 8170028d ths
1145 8170028d ths
        DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n",
1146 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1147 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZV);
1148 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1149 8170028d ths
        gen_zext_T0_T0(size);
1150 8170028d ths
        crisv32_alu_op(dc, CC_OP_MULU, dc->op2, 4);
1151 8170028d ths
        return 2;
1152 8170028d ths
}
1153 8170028d ths
1154 8170028d ths
1155 8170028d ths
static unsigned int dec_dstep_r(DisasContext *dc)
1156 8170028d ths
{
1157 8170028d ths
        DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2));
1158 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1159 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1160 8170028d ths
        gen_op_movl_T1_T0();
1161 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1162 8170028d ths
        crisv32_alu_op(dc, CC_OP_DSTEP, dc->op2, 4);
1163 8170028d ths
        return 2;
1164 8170028d ths
}
1165 8170028d ths
1166 8170028d ths
static unsigned int dec_xor_r(DisasContext *dc)
1167 8170028d ths
{
1168 8170028d ths
        int size = memsize_zz(dc);
1169 8170028d ths
        DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n",
1170 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1171 8170028d ths
        BUG_ON(size != 4); /* xor is dword.  */
1172 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1173 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1174 8170028d ths
        crisv32_alu_op(dc, CC_OP_XOR, dc->op2, 4);
1175 8170028d ths
        return 2;
1176 8170028d ths
}
1177 8170028d ths
1178 8170028d ths
static unsigned int dec_bound_r(DisasContext *dc)
1179 8170028d ths
{
1180 8170028d ths
        int size = memsize_zz(dc);
1181 8170028d ths
        DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n",
1182 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1183 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1184 8170028d ths
        /* TODO: needs optmimization.  */
1185 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1186 8170028d ths
        /* rd should be 4.  */
1187 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1188 8170028d ths
        crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
1189 8170028d ths
        return 2;
1190 8170028d ths
}
1191 8170028d ths
1192 8170028d ths
static unsigned int dec_cmp_r(DisasContext *dc)
1193 8170028d ths
{
1194 8170028d ths
        int size = memsize_zz(dc);
1195 8170028d ths
        DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n",
1196 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1197 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1198 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1199 8170028d ths
        crisv32_alu_op(dc, CC_OP_CMP, dc->op2, size);
1200 8170028d ths
        return 2;
1201 8170028d ths
}
1202 8170028d ths
1203 8170028d ths
static unsigned int dec_abs_r(DisasContext *dc)
1204 8170028d ths
{
1205 8170028d ths
        DIS(fprintf (logfile, "abs $r%u, $r%u\n",
1206 8170028d ths
                    dc->op1, dc->op2));
1207 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1208 8170028d ths
        dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0);
1209 8170028d ths
        gen_op_absl_T1_T1();
1210 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1211 8170028d ths
        return 2;
1212 8170028d ths
}
1213 8170028d ths
1214 8170028d ths
static unsigned int dec_add_r(DisasContext *dc)
1215 8170028d ths
{
1216 8170028d ths
        int size = memsize_zz(dc);
1217 8170028d ths
        DIS(fprintf (logfile, "add.%c $r%u, $r%u\n",
1218 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1219 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1220 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1221 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, dc->op2, size);
1222 8170028d ths
        return 2;
1223 8170028d ths
}
1224 8170028d ths
1225 8170028d ths
static unsigned int dec_addc_r(DisasContext *dc)
1226 8170028d ths
{
1227 8170028d ths
        DIS(fprintf (logfile, "addc $r%u, $r%u\n",
1228 8170028d ths
                    dc->op1, dc->op2));
1229 8170028d ths
        cris_evaluate_flags(dc);
1230 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1231 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1232 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
1233 8170028d ths
        return 2;
1234 8170028d ths
}
1235 8170028d ths
1236 8170028d ths
static unsigned int dec_mcp_r(DisasContext *dc)
1237 8170028d ths
{
1238 8170028d ths
        DIS(fprintf (logfile, "mcp $p%u, $r%u\n",
1239 8170028d ths
                     dc->op2, dc->op1));
1240 8170028d ths
        cris_evaluate_flags(dc);
1241 8170028d ths
        cris_cc_mask(dc, CC_MASK_RNZV);
1242 8170028d ths
        gen_movl_T0_preg[dc->op2]();
1243 8170028d ths
        gen_op_movl_T1_T0();
1244 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1245 8170028d ths
        crisv32_alu_op(dc, CC_OP_MCP, dc->op1, 4);
1246 8170028d ths
        return 2;
1247 8170028d ths
}
1248 8170028d ths
1249 8170028d ths
#if DISAS_CRIS
1250 8170028d ths
static char * swapmode_name(int mode, char *modename) {
1251 8170028d ths
        int i = 0;
1252 8170028d ths
        if (mode & 8)
1253 8170028d ths
                modename[i++] = 'n';
1254 8170028d ths
        if (mode & 4)
1255 8170028d ths
                modename[i++] = 'w';
1256 8170028d ths
        if (mode & 2)
1257 8170028d ths
                modename[i++] = 'b';
1258 8170028d ths
        if (mode & 1)
1259 8170028d ths
                modename[i++] = 'r';
1260 8170028d ths
        modename[i++] = 0;
1261 8170028d ths
        return modename;
1262 8170028d ths
}
1263 8170028d ths
#endif
1264 8170028d ths
1265 8170028d ths
static unsigned int dec_swap_r(DisasContext *dc)
1266 8170028d ths
{
1267 8170028d ths
        DIS(char modename[4]);
1268 8170028d ths
        DIS(fprintf (logfile, "swap%s $r%u\n",
1269 8170028d ths
                     swapmode_name(dc->op2, modename), dc->op1));
1270 8170028d ths
1271 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1272 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1273 8170028d ths
        if (dc->op2 & 8)
1274 8170028d ths
                gen_op_not_T0_T0();
1275 8170028d ths
        if (dc->op2 & 4)
1276 8170028d ths
                gen_op_swapw_T0_T0();
1277 8170028d ths
        if (dc->op2 & 2)
1278 8170028d ths
                gen_op_swapb_T0_T0();
1279 8170028d ths
        if (dc->op2 & 1)
1280 8170028d ths
                gen_op_swapr_T0_T0();
1281 8170028d ths
        gen_op_movl_T1_T0();
1282 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1283 8170028d ths
        return 2;
1284 8170028d ths
}
1285 8170028d ths
1286 8170028d ths
static unsigned int dec_or_r(DisasContext *dc)
1287 8170028d ths
{
1288 8170028d ths
        int size = memsize_zz(dc);
1289 8170028d ths
        DIS(fprintf (logfile, "or.%c $r%u, $r%u\n",
1290 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1291 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1292 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1293 8170028d ths
        crisv32_alu_op(dc, CC_OP_OR, dc->op2, size);
1294 8170028d ths
        return 2;
1295 8170028d ths
}
1296 8170028d ths
1297 8170028d ths
static unsigned int dec_addi_r(DisasContext *dc)
1298 8170028d ths
{
1299 8170028d ths
        DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
1300 8170028d ths
                    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1301 8170028d ths
        cris_cc_mask(dc, 0);
1302 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1303 8170028d ths
        gen_op_lsll_T0_im(dc->zzsize);
1304 8170028d ths
        gen_op_addl_T0_T1();
1305 8170028d ths
        gen_movl_reg_T0[dc->op1]();
1306 8170028d ths
        return 2;
1307 8170028d ths
}
1308 8170028d ths
1309 8170028d ths
static unsigned int dec_addi_acr(DisasContext *dc)
1310 8170028d ths
{
1311 8170028d ths
        DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
1312 8170028d ths
                    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1313 8170028d ths
        cris_cc_mask(dc, 0);
1314 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1315 8170028d ths
        gen_op_lsll_T0_im(dc->zzsize);
1316 8170028d ths
        gen_op_addl_T0_T1();
1317 8170028d ths
        gen_movl_reg_T0[REG_ACR]();
1318 8170028d ths
        return 2;
1319 8170028d ths
}
1320 8170028d ths
1321 8170028d ths
static unsigned int dec_neg_r(DisasContext *dc)
1322 8170028d ths
{
1323 8170028d ths
        int size = memsize_zz(dc);
1324 8170028d ths
        DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n",
1325 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1326 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1327 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1328 8170028d ths
        crisv32_alu_op(dc, CC_OP_NEG, dc->op2, size);
1329 8170028d ths
        return 2;
1330 8170028d ths
}
1331 8170028d ths
1332 8170028d ths
static unsigned int dec_btst_r(DisasContext *dc)
1333 8170028d ths
{
1334 8170028d ths
        DIS(fprintf (logfile, "btst $r%u, $r%u\n",
1335 8170028d ths
                    dc->op1, dc->op2));
1336 8170028d ths
        cris_evaluate_flags(dc);
1337 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1338 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1339 8170028d ths
        crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
1340 8170028d ths
1341 8170028d ths
        cris_update_cc_op(dc, CC_OP_FLAGS);
1342 8170028d ths
        gen_op_movl_flags_T0();
1343 8170028d ths
        dc->flags_live = 1;
1344 8170028d ths
        return 2;
1345 8170028d ths
}
1346 8170028d ths
1347 8170028d ths
static unsigned int dec_sub_r(DisasContext *dc)
1348 8170028d ths
{
1349 8170028d ths
        int size = memsize_zz(dc);
1350 8170028d ths
        DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n",
1351 8170028d ths
                    memsize_char(size), dc->op1, dc->op2));
1352 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1353 8170028d ths
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1354 8170028d ths
        crisv32_alu_op(dc, CC_OP_SUB, dc->op2, size);
1355 8170028d ths
        return 2;
1356 8170028d ths
}
1357 8170028d ths
1358 8170028d ths
/* Zero extension. From size to dword.  */
1359 8170028d ths
static unsigned int dec_movu_r(DisasContext *dc)
1360 8170028d ths
{
1361 8170028d ths
        int size = memsize_z(dc);
1362 8170028d ths
        DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n",
1363 8170028d ths
                    memsize_char(size),
1364 8170028d ths
                    dc->op1, dc->op2));
1365 8170028d ths
1366 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1367 8170028d ths
        dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1368 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1369 8170028d ths
        return 2;
1370 8170028d ths
}
1371 8170028d ths
1372 8170028d ths
/* Sign extension. From size to dword.  */
1373 8170028d ths
static unsigned int dec_movs_r(DisasContext *dc)
1374 8170028d ths
{
1375 8170028d ths
        int size = memsize_z(dc);
1376 8170028d ths
        DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n",
1377 8170028d ths
                    memsize_char(size),
1378 8170028d ths
                    dc->op1, dc->op2));
1379 8170028d ths
1380 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1381 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1382 8170028d ths
        /* Size can only be qi or hi.  */
1383 8170028d ths
        gen_sext_T1_T0(size);
1384 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1385 8170028d ths
        return 2;
1386 8170028d ths
}
1387 8170028d ths
1388 8170028d ths
/* zero extension. From size to dword.  */
1389 8170028d ths
static unsigned int dec_addu_r(DisasContext *dc)
1390 8170028d ths
{
1391 8170028d ths
        int size = memsize_z(dc);
1392 8170028d ths
        DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n",
1393 8170028d ths
                    memsize_char(size),
1394 8170028d ths
                    dc->op1, dc->op2));
1395 8170028d ths
1396 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1397 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1398 8170028d ths
        /* Size can only be qi or hi.  */
1399 8170028d ths
        gen_zext_T1_T0(size);
1400 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1401 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1402 8170028d ths
        return 2;
1403 8170028d ths
}
1404 8170028d ths
/* Sign extension. From size to dword.  */
1405 8170028d ths
static unsigned int dec_adds_r(DisasContext *dc)
1406 8170028d ths
{
1407 8170028d ths
        int size = memsize_z(dc);
1408 8170028d ths
        DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n",
1409 8170028d ths
                    memsize_char(size),
1410 8170028d ths
                    dc->op1, dc->op2));
1411 8170028d ths
1412 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1413 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1414 8170028d ths
        /* Size can only be qi or hi.  */
1415 8170028d ths
        gen_sext_T1_T0(size);
1416 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1417 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1418 8170028d ths
        return 2;
1419 8170028d ths
}
1420 8170028d ths
1421 8170028d ths
/* Zero extension. From size to dword.  */
1422 8170028d ths
static unsigned int dec_subu_r(DisasContext *dc)
1423 8170028d ths
{
1424 8170028d ths
        int size = memsize_z(dc);
1425 8170028d ths
        DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n",
1426 8170028d ths
                    memsize_char(size),
1427 8170028d ths
                    dc->op1, dc->op2));
1428 8170028d ths
1429 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1430 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1431 8170028d ths
        /* Size can only be qi or hi.  */
1432 8170028d ths
        gen_zext_T1_T0(size);
1433 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1434 8170028d ths
        crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1435 8170028d ths
        return 2;
1436 8170028d ths
}
1437 8170028d ths
1438 8170028d ths
/* Sign extension. From size to dword.  */
1439 8170028d ths
static unsigned int dec_subs_r(DisasContext *dc)
1440 8170028d ths
{
1441 8170028d ths
        int size = memsize_z(dc);
1442 8170028d ths
        DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n",
1443 8170028d ths
                    memsize_char(size),
1444 8170028d ths
                    dc->op1, dc->op2));
1445 8170028d ths
1446 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1447 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1448 8170028d ths
        /* Size can only be qi or hi.  */
1449 8170028d ths
        gen_sext_T1_T0(size);
1450 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1451 8170028d ths
        crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1452 8170028d ths
        return 2;
1453 8170028d ths
}
1454 8170028d ths
1455 8170028d ths
static unsigned int dec_setclrf(DisasContext *dc)
1456 8170028d ths
{
1457 8170028d ths
        uint32_t flags;
1458 8170028d ths
        int set = (~dc->opcode >> 2) & 1;
1459 8170028d ths
1460 8170028d ths
        flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
1461 8170028d ths
                | EXTRACT_FIELD(dc->ir, 0, 3);
1462 8170028d ths
        DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags));
1463 8170028d ths
        if (set && flags == 0)
1464 8170028d ths
                DIS(fprintf (logfile, "nop\n"));
1465 8170028d ths
        else if (!set && (flags & 0x20))
1466 8170028d ths
                DIS(fprintf (logfile, "di\n"));
1467 8170028d ths
        else
1468 8170028d ths
                DIS(fprintf (logfile, "%sf %x\n",
1469 8170028d ths
                            set ? "set" : "clr",
1470 8170028d ths
                            flags));
1471 8170028d ths
1472 8170028d ths
        if (set && (flags & X_FLAG)) {
1473 8170028d ths
                dc->flagx_live = 1;
1474 8170028d ths
                dc->flags_x = 1;
1475 8170028d ths
        }
1476 8170028d ths
1477 8170028d ths
        /* Simply decode the flags.  */
1478 8170028d ths
        cris_evaluate_flags (dc);
1479 8170028d ths
        cris_update_cc_op(dc, CC_OP_FLAGS);
1480 8170028d ths
        if (set)
1481 8170028d ths
                gen_op_setf (flags);
1482 8170028d ths
        else
1483 8170028d ths
                gen_op_clrf (flags);
1484 8170028d ths
        dc->flags_live = 1;
1485 8170028d ths
        return 2;
1486 8170028d ths
}
1487 8170028d ths
1488 8170028d ths
static unsigned int dec_move_rs(DisasContext *dc)
1489 8170028d ths
{
1490 8170028d ths
        DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2));
1491 8170028d ths
        cris_cc_mask(dc, 0);
1492 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1493 8170028d ths
        gen_op_movl_sreg_T0(dc->op2);
1494 8170028d ths
1495 8170028d ths
        if (dc->op2 == 5) /* srs is checked at runtime.  */
1496 8170028d ths
                gen_op_movl_tlb_lo_T0();
1497 8170028d ths
        return 2;
1498 8170028d ths
}
1499 8170028d ths
static unsigned int dec_move_sr(DisasContext *dc)
1500 8170028d ths
{
1501 8170028d ths
        DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op1, dc->op2));
1502 8170028d ths
        cris_cc_mask(dc, 0);
1503 8170028d ths
        gen_op_movl_T0_sreg(dc->op1);
1504 8170028d ths
        gen_op_movl_T1_T0();
1505 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1506 8170028d ths
        return 2;
1507 8170028d ths
}
1508 8170028d ths
static unsigned int dec_move_rp(DisasContext *dc)
1509 8170028d ths
{
1510 8170028d ths
        DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2));
1511 8170028d ths
        cris_cc_mask(dc, 0);
1512 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1513 8170028d ths
        gen_op_movl_T1_T0();
1514 8170028d ths
        gen_movl_preg_T0[dc->op2]();
1515 8170028d ths
        return 2;
1516 8170028d ths
}
1517 8170028d ths
static unsigned int dec_move_pr(DisasContext *dc)
1518 8170028d ths
{
1519 8170028d ths
        DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
1520 8170028d ths
        cris_cc_mask(dc, 0);
1521 8170028d ths
        gen_movl_T0_preg[dc->op2]();
1522 8170028d ths
        gen_op_movl_T1_T0();
1523 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, preg_sizes[dc->op2]);
1524 8170028d ths
        return 2;
1525 8170028d ths
}
1526 8170028d ths
1527 8170028d ths
static unsigned int dec_move_mr(DisasContext *dc)
1528 8170028d ths
{
1529 8170028d ths
        int memsize = memsize_zz(dc);
1530 8170028d ths
        int insn_len;
1531 8170028d ths
        DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n",
1532 8170028d ths
                    memsize_char(memsize),
1533 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1534 8170028d ths
                    dc->op2));
1535 8170028d ths
1536 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1537 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1538 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, memsize);
1539 8170028d ths
        do_postinc(dc, memsize);
1540 8170028d ths
        return insn_len;
1541 8170028d ths
}
1542 8170028d ths
1543 8170028d ths
static unsigned int dec_movs_m(DisasContext *dc)
1544 8170028d ths
{
1545 8170028d ths
        int memsize = memsize_z(dc);
1546 8170028d ths
        int insn_len;
1547 8170028d ths
        DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n",
1548 8170028d ths
                    memsize_char(memsize),
1549 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1550 8170028d ths
                    dc->op2));
1551 8170028d ths
1552 8170028d ths
        /* sign extend.  */
1553 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1554 8170028d ths
        insn_len = dec_prep_alu_m(dc, 1, memsize);
1555 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1556 8170028d ths
        do_postinc(dc, memsize);
1557 8170028d ths
        return insn_len;
1558 8170028d ths
}
1559 8170028d ths
1560 8170028d ths
static unsigned int dec_addu_m(DisasContext *dc)
1561 8170028d ths
{
1562 8170028d ths
        int memsize = memsize_z(dc);
1563 8170028d ths
        int insn_len;
1564 8170028d ths
        DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n",
1565 8170028d ths
                    memsize_char(memsize),
1566 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1567 8170028d ths
                    dc->op2));
1568 8170028d ths
1569 8170028d ths
        /* sign extend.  */
1570 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1571 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1572 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1573 8170028d ths
        do_postinc(dc, memsize);
1574 8170028d ths
        return insn_len;
1575 8170028d ths
}
1576 8170028d ths
1577 8170028d ths
static unsigned int dec_adds_m(DisasContext *dc)
1578 8170028d ths
{
1579 8170028d ths
        int memsize = memsize_z(dc);
1580 8170028d ths
        int insn_len;
1581 8170028d ths
        DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n",
1582 8170028d ths
                    memsize_char(memsize),
1583 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1584 8170028d ths
                    dc->op2));
1585 8170028d ths
1586 8170028d ths
        /* sign extend.  */
1587 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1588 8170028d ths
        insn_len = dec_prep_alu_m(dc, 1, memsize);
1589 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1590 8170028d ths
        do_postinc(dc, memsize);
1591 8170028d ths
        return insn_len;
1592 8170028d ths
}
1593 8170028d ths
1594 8170028d ths
static unsigned int dec_subu_m(DisasContext *dc)
1595 8170028d ths
{
1596 8170028d ths
        int memsize = memsize_z(dc);
1597 8170028d ths
        int insn_len;
1598 8170028d ths
        DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n",
1599 8170028d ths
                    memsize_char(memsize),
1600 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1601 8170028d ths
                    dc->op2));
1602 8170028d ths
1603 8170028d ths
        /* sign extend.  */
1604 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1605 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1606 8170028d ths
        crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1607 8170028d ths
        do_postinc(dc, memsize);
1608 8170028d ths
        return insn_len;
1609 8170028d ths
}
1610 8170028d ths
1611 8170028d ths
static unsigned int dec_subs_m(DisasContext *dc)
1612 8170028d ths
{
1613 8170028d ths
        int memsize = memsize_z(dc);
1614 8170028d ths
        int insn_len;
1615 8170028d ths
        DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n",
1616 8170028d ths
                    memsize_char(memsize),
1617 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1618 8170028d ths
                    dc->op2));
1619 8170028d ths
1620 8170028d ths
        /* sign extend.  */
1621 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1622 8170028d ths
        insn_len = dec_prep_alu_m(dc, 1, memsize);
1623 8170028d ths
        crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1624 8170028d ths
        do_postinc(dc, memsize);
1625 8170028d ths
        return insn_len;
1626 8170028d ths
}
1627 8170028d ths
1628 8170028d ths
static unsigned int dec_movu_m(DisasContext *dc)
1629 8170028d ths
{
1630 8170028d ths
        int memsize = memsize_z(dc);
1631 8170028d ths
        int insn_len;
1632 8170028d ths
1633 8170028d ths
        DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n",
1634 8170028d ths
                    memsize_char(memsize),
1635 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1636 8170028d ths
                    dc->op2));
1637 8170028d ths
1638 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1639 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1640 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1641 8170028d ths
        do_postinc(dc, memsize);
1642 8170028d ths
        return insn_len;
1643 8170028d ths
}
1644 8170028d ths
1645 8170028d ths
static unsigned int dec_cmpu_m(DisasContext *dc)
1646 8170028d ths
{
1647 8170028d ths
        int memsize = memsize_z(dc);
1648 8170028d ths
        int insn_len;
1649 8170028d ths
        DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n",
1650 8170028d ths
                    memsize_char(memsize),
1651 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1652 8170028d ths
                    dc->op2));
1653 8170028d ths
1654 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1655 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1656 8170028d ths
        crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
1657 8170028d ths
        do_postinc(dc, memsize);
1658 8170028d ths
        return insn_len;
1659 8170028d ths
}
1660 8170028d ths
1661 8170028d ths
static unsigned int dec_cmps_m(DisasContext *dc)
1662 8170028d ths
{
1663 8170028d ths
        int memsize = memsize_z(dc);
1664 8170028d ths
        int insn_len;
1665 8170028d ths
        DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n",
1666 8170028d ths
                    memsize_char(memsize),
1667 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1668 8170028d ths
                    dc->op2));
1669 8170028d ths
1670 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1671 8170028d ths
        insn_len = dec_prep_alu_m(dc, 1, memsize);
1672 8170028d ths
        crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1673 8170028d ths
        do_postinc(dc, memsize);
1674 8170028d ths
        return insn_len;
1675 8170028d ths
}
1676 8170028d ths
1677 8170028d ths
static unsigned int dec_cmp_m(DisasContext *dc)
1678 8170028d ths
{
1679 8170028d ths
        int memsize = memsize_zz(dc);
1680 8170028d ths
        int insn_len;
1681 8170028d ths
        DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n",
1682 8170028d ths
                    memsize_char(memsize),
1683 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1684 8170028d ths
                    dc->op2));
1685 8170028d ths
1686 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1687 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1688 8170028d ths
        crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1689 8170028d ths
        do_postinc(dc, memsize);
1690 8170028d ths
        return insn_len;
1691 8170028d ths
}
1692 8170028d ths
1693 8170028d ths
static unsigned int dec_test_m(DisasContext *dc)
1694 8170028d ths
{
1695 8170028d ths
        int memsize = memsize_zz(dc);
1696 8170028d ths
        int insn_len;
1697 8170028d ths
        DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n",
1698 8170028d ths
                    memsize_char(memsize),
1699 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1700 8170028d ths
                    dc->op2));
1701 8170028d ths
1702 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1703 8170028d ths
        gen_op_clrf(3);
1704 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1705 8170028d ths
        gen_op_swp_T0_T1();
1706 8170028d ths
        gen_op_movl_T1_im(0);
1707 8170028d ths
        crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1708 8170028d ths
        do_postinc(dc, memsize);
1709 8170028d ths
        return insn_len;
1710 8170028d ths
}
1711 8170028d ths
1712 8170028d ths
static unsigned int dec_and_m(DisasContext *dc)
1713 8170028d ths
{
1714 8170028d ths
        int memsize = memsize_zz(dc);
1715 8170028d ths
        int insn_len;
1716 8170028d ths
        DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n",
1717 8170028d ths
                    memsize_char(memsize),
1718 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1719 8170028d ths
                    dc->op2));
1720 8170028d ths
1721 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1722 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1723 8170028d ths
        crisv32_alu_op(dc, CC_OP_AND, dc->op2, memsize_zz(dc));
1724 8170028d ths
        do_postinc(dc, memsize);
1725 8170028d ths
        return insn_len;
1726 8170028d ths
}
1727 8170028d ths
1728 8170028d ths
static unsigned int dec_add_m(DisasContext *dc)
1729 8170028d ths
{
1730 8170028d ths
        int memsize = memsize_zz(dc);
1731 8170028d ths
        int insn_len;
1732 8170028d ths
        DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
1733 8170028d ths
                    memsize_char(memsize),
1734 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1735 8170028d ths
                    dc->op2));
1736 8170028d ths
1737 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1738 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1739 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, dc->op2, memsize_zz(dc));
1740 8170028d ths
        do_postinc(dc, memsize);
1741 8170028d ths
        return insn_len;
1742 8170028d ths
}
1743 8170028d ths
1744 8170028d ths
static unsigned int dec_addo_m(DisasContext *dc)
1745 8170028d ths
{
1746 8170028d ths
        int memsize = memsize_zz(dc);
1747 8170028d ths
        int insn_len;
1748 8170028d ths
        DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
1749 8170028d ths
                    memsize_char(memsize),
1750 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1751 8170028d ths
                    dc->op2));
1752 8170028d ths
1753 8170028d ths
        cris_cc_mask(dc, 0);
1754 8170028d ths
        insn_len = dec_prep_alu_m(dc, 1, memsize);
1755 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4);
1756 8170028d ths
        do_postinc(dc, memsize);
1757 8170028d ths
        return insn_len;
1758 8170028d ths
}
1759 8170028d ths
1760 8170028d ths
static unsigned int dec_bound_m(DisasContext *dc)
1761 8170028d ths
{
1762 8170028d ths
        int memsize = memsize_zz(dc);
1763 8170028d ths
        int insn_len;
1764 8170028d ths
        DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n",
1765 8170028d ths
                    memsize_char(memsize),
1766 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1767 8170028d ths
                    dc->op2));
1768 8170028d ths
1769 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1770 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1771 8170028d ths
        crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
1772 8170028d ths
        do_postinc(dc, memsize);
1773 8170028d ths
        return insn_len;
1774 8170028d ths
}
1775 8170028d ths
1776 8170028d ths
static unsigned int dec_addc_mr(DisasContext *dc)
1777 8170028d ths
{
1778 8170028d ths
        int insn_len = 2;
1779 8170028d ths
        DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n",
1780 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1781 8170028d ths
                    dc->op2));
1782 8170028d ths
1783 8170028d ths
        cris_evaluate_flags(dc);
1784 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1785 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, 4);
1786 8170028d ths
        crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
1787 8170028d ths
        do_postinc(dc, 4);
1788 8170028d ths
        return insn_len;
1789 8170028d ths
}
1790 8170028d ths
1791 8170028d ths
static unsigned int dec_sub_m(DisasContext *dc)
1792 8170028d ths
{
1793 8170028d ths
        int memsize = memsize_zz(dc);
1794 8170028d ths
        int insn_len;
1795 8170028d ths
        DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
1796 8170028d ths
                    memsize_char(memsize),
1797 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1798 8170028d ths
                    dc->op2, dc->ir, dc->zzsize));
1799 8170028d ths
1800 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZVC);
1801 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1802 8170028d ths
        crisv32_alu_op(dc, CC_OP_SUB, dc->op2, memsize);
1803 8170028d ths
        do_postinc(dc, memsize);
1804 8170028d ths
        return insn_len;
1805 8170028d ths
}
1806 8170028d ths
1807 8170028d ths
static unsigned int dec_or_m(DisasContext *dc)
1808 8170028d ths
{
1809 8170028d ths
        int memsize = memsize_zz(dc);
1810 8170028d ths
        int insn_len;
1811 8170028d ths
        DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n",
1812 8170028d ths
                    memsize_char(memsize),
1813 8170028d ths
                    dc->op1, dc->postinc ? "+]" : "]",
1814 8170028d ths
                    dc->op2, dc->pc));
1815 8170028d ths
1816 8170028d ths
        cris_cc_mask(dc, CC_MASK_NZ);
1817 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1818 8170028d ths
        crisv32_alu_op(dc, CC_OP_OR, dc->op2, memsize_zz(dc));
1819 8170028d ths
        do_postinc(dc, memsize);
1820 8170028d ths
        return insn_len;
1821 8170028d ths
}
1822 8170028d ths
1823 8170028d ths
static unsigned int dec_move_mp(DisasContext *dc)
1824 8170028d ths
{
1825 8170028d ths
        int memsize = memsize_zz(dc);
1826 8170028d ths
        int insn_len = 2;
1827 8170028d ths
1828 8170028d ths
        DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n",
1829 8170028d ths
                    memsize_char(memsize),
1830 8170028d ths
                    dc->op1,
1831 8170028d ths
                    dc->postinc ? "+]" : "]",
1832 8170028d ths
                    dc->op2));
1833 8170028d ths
1834 8170028d ths
        cris_cc_mask(dc, 0);
1835 8170028d ths
        insn_len = dec_prep_alu_m(dc, 0, memsize);
1836 8170028d ths
        gen_op_movl_T0_T1();
1837 8170028d ths
        gen_movl_preg_T0[dc->op2]();
1838 8170028d ths
1839 8170028d ths
        do_postinc(dc, memsize);
1840 8170028d ths
        return insn_len;
1841 8170028d ths
}
1842 8170028d ths
1843 8170028d ths
static unsigned int dec_move_pm(DisasContext *dc)
1844 8170028d ths
{
1845 8170028d ths
        int memsize;
1846 8170028d ths
1847 8170028d ths
        memsize = preg_sizes[dc->op2];
1848 8170028d ths
1849 8170028d ths
        DIS(fprintf (logfile, "move.%d $p%u, [$r%u%s\n",
1850 8170028d ths
                     memsize, dc->op2, dc->op1, dc->postinc ? "+]" : "]"));
1851 8170028d ths
1852 8170028d ths
        cris_cc_mask(dc, 0);
1853 8170028d ths
        /* prepare store.  */
1854 8170028d ths
        gen_movl_T0_preg[dc->op2]();
1855 8170028d ths
        gen_op_movl_T1_T0();
1856 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1857 8170028d ths
        gen_store_T0_T1(dc, memsize);
1858 8170028d ths
        if (dc->postinc)
1859 8170028d ths
        {
1860 8170028d ths
                gen_op_addl_T0_im(memsize);
1861 8170028d ths
                gen_movl_reg_T0[dc->op1]();
1862 8170028d ths
        }
1863 8170028d ths
        return 2;
1864 8170028d ths
}
1865 8170028d ths
1866 8170028d ths
static unsigned int dec_movem_mr(DisasContext *dc)
1867 8170028d ths
{
1868 8170028d ths
        int i;
1869 8170028d ths
1870 8170028d ths
        DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1,
1871 8170028d ths
                    dc->postinc ? "+]" : "]", dc->op2));
1872 8170028d ths
1873 8170028d ths
        cris_cc_mask(dc, 0);
1874 8170028d ths
        /* fetch the address into T1.  */
1875 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1876 8170028d ths
        gen_op_movl_T1_T0();
1877 8170028d ths
        for (i = 0; i <= dc->op2; i++) {
1878 8170028d ths
                /* Perform the load onto regnum i. Always dword wide.  */
1879 8170028d ths
                gen_load_T0_T0(dc, 4, 0);
1880 8170028d ths
                gen_movl_reg_T0[i]();
1881 8170028d ths
                /* Update the address.  */
1882 8170028d ths
                gen_op_addl_T1_im(4);
1883 8170028d ths
                gen_op_movl_T0_T1();
1884 8170028d ths
        }
1885 8170028d ths
        if (dc->postinc) {
1886 8170028d ths
                /* writeback the updated pointer value.  */
1887 8170028d ths
                gen_movl_reg_T0[dc->op1]();
1888 8170028d ths
        }
1889 8170028d ths
        return 2;
1890 8170028d ths
}
1891 8170028d ths
1892 8170028d ths
static unsigned int dec_movem_rm(DisasContext *dc)
1893 8170028d ths
{
1894 8170028d ths
        int i;
1895 8170028d ths
1896 8170028d ths
        DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
1897 8170028d ths
                     dc->postinc ? "+]" : "]"));
1898 8170028d ths
1899 8170028d ths
        cris_cc_mask(dc, 0);
1900 8170028d ths
        for (i = 0; i <= dc->op2; i++) {
1901 8170028d ths
                /* Fetch register i into T1.  */
1902 8170028d ths
                gen_movl_T0_reg[i]();
1903 8170028d ths
                gen_op_movl_T1_T0();
1904 8170028d ths
1905 8170028d ths
                /* Fetch the address into T0.  */
1906 8170028d ths
                gen_movl_T0_reg[dc->op1]();
1907 8170028d ths
                /* Displace it.  */
1908 8170028d ths
                gen_op_addl_T0_im(i * 4);
1909 8170028d ths
1910 8170028d ths
                /* Perform the store.  */
1911 8170028d ths
                gen_store_T0_T1(dc, 4);
1912 8170028d ths
        }
1913 8170028d ths
        if (dc->postinc) {
1914 8170028d ths
                /* Update the address.  */
1915 8170028d ths
                gen_op_addl_T0_im(4);
1916 8170028d ths
                /* writeback the updated pointer value.  */
1917 8170028d ths
                gen_movl_reg_T0[dc->op1]();
1918 8170028d ths
        }
1919 8170028d ths
        return 2;
1920 8170028d ths
}
1921 8170028d ths
1922 8170028d ths
static unsigned int dec_move_rm(DisasContext *dc)
1923 8170028d ths
{
1924 8170028d ths
        int memsize;
1925 8170028d ths
1926 8170028d ths
        memsize = memsize_zz(dc);
1927 8170028d ths
1928 8170028d ths
        DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n",
1929 8170028d ths
                     memsize, dc->op2, dc->op1));
1930 8170028d ths
1931 8170028d ths
        cris_cc_mask(dc, 0);
1932 8170028d ths
        /* prepare store.  */
1933 8170028d ths
        gen_movl_T0_reg[dc->op2]();
1934 8170028d ths
        gen_op_movl_T1_T0();
1935 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1936 8170028d ths
        gen_store_T0_T1(dc, memsize);
1937 8170028d ths
        if (dc->postinc)
1938 8170028d ths
        {
1939 8170028d ths
                gen_op_addl_T0_im(memsize);
1940 8170028d ths
                gen_movl_reg_T0[dc->op1]();
1941 8170028d ths
        }
1942 8170028d ths
        return 2;
1943 8170028d ths
}
1944 8170028d ths
1945 8170028d ths
1946 8170028d ths
static unsigned int dec_lapcq(DisasContext *dc)
1947 8170028d ths
{
1948 8170028d ths
        DIS(fprintf (logfile, "lapcq %x, $r%u\n",
1949 8170028d ths
                    dc->pc + dc->op1*2, dc->op2));
1950 8170028d ths
        cris_cc_mask(dc, 0);
1951 8170028d ths
        gen_op_movl_T1_im(dc->pc + dc->op1*2);
1952 8170028d ths
        crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1953 8170028d ths
        return 2;
1954 8170028d ths
}
1955 8170028d ths
1956 8170028d ths
static unsigned int dec_lapc_im(DisasContext *dc)
1957 8170028d ths
{
1958 8170028d ths
        unsigned int rd;
1959 8170028d ths
        int32_t imm;
1960 8170028d ths
        int insn_len = 6;
1961 8170028d ths
1962 8170028d ths
        rd = dc->op2;
1963 8170028d ths
1964 8170028d ths
        cris_cc_mask(dc, 0);
1965 8170028d ths
        imm = ldl_code(dc->pc + 2);
1966 8170028d ths
        DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2));
1967 8170028d ths
        gen_op_movl_T0_im (dc->pc + imm);
1968 8170028d ths
        gen_movl_reg_T0[rd] ();
1969 8170028d ths
        return insn_len;
1970 8170028d ths
}
1971 8170028d ths
1972 8170028d ths
/* Jump to special reg.  */
1973 8170028d ths
static unsigned int dec_jump_p(DisasContext *dc)
1974 8170028d ths
{
1975 8170028d ths
        DIS(fprintf (logfile, "jump $p%u\n", dc->op2));
1976 8170028d ths
        cris_cc_mask(dc, 0);
1977 8170028d ths
        /* Store the return address in Pd.  */
1978 8170028d ths
        gen_movl_T0_preg[dc->op2]();
1979 8170028d ths
        gen_op_movl_btarget_T0();
1980 8170028d ths
        cris_prepare_dyn_jmp(dc);
1981 8170028d ths
        return 2;
1982 8170028d ths
}
1983 8170028d ths
1984 8170028d ths
/* Jump and save.  */
1985 8170028d ths
static unsigned int dec_jas_r(DisasContext *dc)
1986 8170028d ths
{
1987 8170028d ths
        DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2));
1988 8170028d ths
        cris_cc_mask(dc, 0);
1989 8170028d ths
        /* Stor the return address in Pd.  */
1990 8170028d ths
        gen_movl_T0_reg[dc->op1]();
1991 8170028d ths
        gen_op_movl_btarget_T0();
1992 8170028d ths
        gen_op_movl_T0_im(dc->pc + 4);
1993 8170028d ths
        gen_movl_preg_T0[dc->op2]();
1994 8170028d ths
        cris_prepare_dyn_jmp(dc);
1995 8170028d ths
        return 2;
1996 8170028d ths
}
1997 8170028d ths
1998 8170028d ths
static unsigned int dec_jas_im(DisasContext *dc)
1999 8170028d ths
{
2000 8170028d ths
        uint32_t imm;
2001 8170028d ths
2002 8170028d ths
        imm = ldl_code(dc->pc + 2);
2003 8170028d ths
2004 8170028d ths
        DIS(fprintf (logfile, "jas 0x%x\n", imm));
2005 8170028d ths
        cris_cc_mask(dc, 0);
2006 8170028d ths
        /* Stor the return address in Pd.  */
2007 8170028d ths
        gen_op_movl_T0_im(imm);
2008 8170028d ths
        gen_op_movl_btarget_T0();
2009 8170028d ths
        gen_op_movl_T0_im(dc->pc + 8);
2010 8170028d ths
        gen_movl_preg_T0[dc->op2]();
2011 8170028d ths
        cris_prepare_dyn_jmp(dc);
2012 8170028d ths
        return 6;
2013 8170028d ths
}
2014 8170028d ths
2015 8170028d ths
static unsigned int dec_jasc_im(DisasContext *dc)
2016 8170028d ths
{
2017 8170028d ths
        uint32_t imm;
2018 8170028d ths
2019 8170028d ths
        imm = ldl_code(dc->pc + 2);
2020 8170028d ths
2021 8170028d ths
        DIS(fprintf (logfile, "jasc 0x%x\n", imm));
2022 8170028d ths
        cris_cc_mask(dc, 0);
2023 8170028d ths
        /* Stor the return address in Pd.  */
2024 8170028d ths
        gen_op_movl_T0_im(imm);
2025 8170028d ths
        gen_op_movl_btarget_T0();
2026 8170028d ths
        gen_op_movl_T0_im(dc->pc + 8 + 4);
2027 8170028d ths
        gen_movl_preg_T0[dc->op2]();
2028 8170028d ths
        cris_prepare_dyn_jmp(dc);
2029 8170028d ths
        return 6;
2030 8170028d ths
}
2031 8170028d ths
2032 8170028d ths
static unsigned int dec_jasc_r(DisasContext *dc)
2033 8170028d ths
{
2034 8170028d ths
        DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2));
2035 8170028d ths
        cris_cc_mask(dc, 0);
2036 8170028d ths
        /* Stor the return address in Pd.  */
2037 8170028d ths
        gen_movl_T0_reg[dc->op1]();
2038 8170028d ths
        gen_op_movl_btarget_T0();
2039 8170028d ths
        gen_op_movl_T0_im(dc->pc + 4 + 4);
2040 8170028d ths
        gen_movl_preg_T0[dc->op2]();
2041 8170028d ths
        cris_prepare_dyn_jmp(dc);
2042 8170028d ths
        return 2;
2043 8170028d ths
}
2044 8170028d ths
2045 8170028d ths
static unsigned int dec_bcc_im(DisasContext *dc)
2046 8170028d ths
{
2047 8170028d ths
        int32_t offset;
2048 8170028d ths
        uint32_t cond = dc->op2;
2049 8170028d ths
2050 8170028d ths
        offset = ldl_code(dc->pc + 2);
2051 8170028d ths
        offset = sign_extend(offset, 15);
2052 8170028d ths
2053 8170028d ths
        DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n",
2054 8170028d ths
                    cc_name(cond), offset,
2055 8170028d ths
                    dc->pc, dc->pc + offset));
2056 8170028d ths
2057 8170028d ths
        cris_cc_mask(dc, 0);
2058 8170028d ths
        /* op2 holds the condition-code.  */
2059 8170028d ths
        cris_prepare_cc_branch (dc, offset, cond);
2060 8170028d ths
        return 4;
2061 8170028d ths
}
2062 8170028d ths
2063 8170028d ths
static unsigned int dec_bas_im(DisasContext *dc)
2064 8170028d ths
{
2065 8170028d ths
        int32_t simm;
2066 8170028d ths
2067 8170028d ths
2068 8170028d ths
        simm = ldl_code(dc->pc + 2);
2069 8170028d ths
2070 8170028d ths
        DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2071 8170028d ths
        cris_cc_mask(dc, 0);
2072 8170028d ths
        /* Stor the return address in Pd.  */
2073 8170028d ths
        gen_op_movl_T0_im(dc->pc + simm);
2074 8170028d ths
        gen_op_movl_btarget_T0();
2075 8170028d ths
        gen_op_movl_T0_im(dc->pc + 8);
2076 8170028d ths
        gen_movl_preg_T0[dc->op2]();
2077 8170028d ths
        cris_prepare_dyn_jmp(dc);
2078 8170028d ths
        return 6;
2079 8170028d ths
}
2080 8170028d ths
2081 8170028d ths
static unsigned int dec_basc_im(DisasContext *dc)
2082 8170028d ths
{
2083 8170028d ths
        int32_t simm;
2084 8170028d ths
        simm = ldl_code(dc->pc + 2);
2085 8170028d ths
2086 8170028d ths
        DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2087 8170028d ths
        cris_cc_mask(dc, 0);
2088 8170028d ths
        /* Stor the return address in Pd.  */
2089 8170028d ths
        gen_op_movl_T0_im(dc->pc + simm);
2090 8170028d ths
        gen_op_movl_btarget_T0();
2091 8170028d ths
        gen_op_movl_T0_im(dc->pc + 12);
2092 8170028d ths
        gen_movl_preg_T0[dc->op2]();
2093 8170028d ths
        cris_prepare_dyn_jmp(dc);
2094 8170028d ths
        return 6;
2095 8170028d ths
}
2096 8170028d ths
2097 8170028d ths
static unsigned int dec_rfe_etc(DisasContext *dc)
2098 8170028d ths
{
2099 8170028d ths
        DIS(fprintf (logfile, "rfe_etc opc=%x pc=0x%x op1=%d op2=%d\n",
2100 8170028d ths
                    dc->opcode, dc->pc, dc->op1, dc->op2));
2101 8170028d ths
2102 8170028d ths
        cris_cc_mask(dc, 0);
2103 8170028d ths
2104 8170028d ths
        if (dc->op2 == 15) /* ignore halt.  */
2105 8170028d ths
                goto done;
2106 8170028d ths
2107 8170028d ths
        switch (dc->op2 & 7) {
2108 8170028d ths
                case 2:
2109 8170028d ths
                        /* rfe.  */
2110 8170028d ths
                        cris_evaluate_flags(dc);
2111 8170028d ths
                        gen_op_ccs_rshift();
2112 8170028d ths
                        break;
2113 8170028d ths
                case 5:
2114 8170028d ths
                        /* rfn.  */
2115 8170028d ths
                        BUG();
2116 8170028d ths
                        break;
2117 8170028d ths
                case 6:
2118 8170028d ths
                        /* break.  */
2119 8170028d ths
                        gen_op_movl_T0_im(dc->pc);
2120 8170028d ths
                        gen_op_movl_pc_T0();
2121 8170028d ths
                        /* Breaks start at 16 in the exception vector.  */
2122 8170028d ths
                        gen_op_break_im(dc->op1 + 16);
2123 8170028d ths
                        break;
2124 8170028d ths
                default:
2125 8170028d ths
                        printf ("op2=%x\n", dc->op2);
2126 8170028d ths
                        BUG();
2127 8170028d ths
                        break;
2128 8170028d ths
2129 8170028d ths
        }
2130 8170028d ths
  done:
2131 8170028d ths
        return 2;
2132 8170028d ths
}
2133 8170028d ths
2134 8170028d ths
static unsigned int dec_null(DisasContext *dc)
2135 8170028d ths
{
2136 8170028d ths
        printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
2137 8170028d ths
                dc->pc, dc->opcode, dc->op1, dc->op2);
2138 8170028d ths
        fflush(NULL);
2139 8170028d ths
        BUG();
2140 8170028d ths
        return 2;
2141 8170028d ths
}
2142 8170028d ths
2143 8170028d ths
struct decoder_info {
2144 8170028d ths
        struct {
2145 8170028d ths
                uint32_t bits;
2146 8170028d ths
                uint32_t mask;
2147 8170028d ths
        };
2148 8170028d ths
        unsigned int (*dec)(DisasContext *dc);
2149 8170028d ths
} decinfo[] = {
2150 8170028d ths
        /* Order matters here.  */
2151 8170028d ths
        {DEC_MOVEQ, dec_moveq},
2152 8170028d ths
        {DEC_BTSTQ, dec_btstq},
2153 8170028d ths
        {DEC_CMPQ, dec_cmpq},
2154 8170028d ths
        {DEC_ADDOQ, dec_addoq},
2155 8170028d ths
        {DEC_ADDQ, dec_addq},
2156 8170028d ths
        {DEC_SUBQ, dec_subq},
2157 8170028d ths
        {DEC_ANDQ, dec_andq},
2158 8170028d ths
        {DEC_ORQ, dec_orq},
2159 8170028d ths
        {DEC_ASRQ, dec_asrq},
2160 8170028d ths
        {DEC_LSLQ, dec_lslq},
2161 8170028d ths
        {DEC_LSRQ, dec_lsrq},
2162 8170028d ths
        {DEC_BCCQ, dec_bccq},
2163 8170028d ths
2164 8170028d ths
        {DEC_BCC_IM, dec_bcc_im},
2165 8170028d ths
        {DEC_JAS_IM, dec_jas_im},
2166 8170028d ths
        {DEC_JAS_R, dec_jas_r},
2167 8170028d ths
        {DEC_JASC_IM, dec_jasc_im},
2168 8170028d ths
        {DEC_JASC_R, dec_jasc_r},
2169 8170028d ths
        {DEC_BAS_IM, dec_bas_im},
2170 8170028d ths
        {DEC_BASC_IM, dec_basc_im},
2171 8170028d ths
        {DEC_JUMP_P, dec_jump_p},
2172 8170028d ths
        {DEC_LAPC_IM, dec_lapc_im},
2173 8170028d ths
        {DEC_LAPCQ, dec_lapcq},
2174 8170028d ths
2175 8170028d ths
        {DEC_RFE_ETC, dec_rfe_etc},
2176 8170028d ths
        {DEC_ADDC_MR, dec_addc_mr},
2177 8170028d ths
2178 8170028d ths
        {DEC_MOVE_MP, dec_move_mp},
2179 8170028d ths
        {DEC_MOVE_PM, dec_move_pm},
2180 8170028d ths
        {DEC_MOVEM_MR, dec_movem_mr},
2181 8170028d ths
        {DEC_MOVEM_RM, dec_movem_rm},
2182 8170028d ths
        {DEC_MOVE_PR, dec_move_pr},
2183 8170028d ths
        {DEC_SCC_R, dec_scc_r},
2184 8170028d ths
        {DEC_SETF, dec_setclrf},
2185 8170028d ths
        {DEC_CLEARF, dec_setclrf},
2186 8170028d ths
2187 8170028d ths
        {DEC_MOVE_SR, dec_move_sr},
2188 8170028d ths
        {DEC_MOVE_RP, dec_move_rp},
2189 8170028d ths
        {DEC_SWAP_R, dec_swap_r},
2190 8170028d ths
        {DEC_ABS_R, dec_abs_r},
2191 8170028d ths
        {DEC_LZ_R, dec_lz_r},
2192 8170028d ths
        {DEC_MOVE_RS, dec_move_rs},
2193 8170028d ths
        {DEC_BTST_R, dec_btst_r},
2194 8170028d ths
        {DEC_ADDC_R, dec_addc_r},
2195 8170028d ths
2196 8170028d ths
        {DEC_DSTEP_R, dec_dstep_r},
2197 8170028d ths
        {DEC_XOR_R, dec_xor_r},
2198 8170028d ths
        {DEC_MCP_R, dec_mcp_r},
2199 8170028d ths
        {DEC_CMP_R, dec_cmp_r},
2200 8170028d ths
2201 8170028d ths
        {DEC_ADDI_R, dec_addi_r},
2202 8170028d ths
        {DEC_ADDI_ACR, dec_addi_acr},
2203 8170028d ths
2204 8170028d ths
        {DEC_ADD_R, dec_add_r},
2205 8170028d ths
        {DEC_SUB_R, dec_sub_r},
2206 8170028d ths
2207 8170028d ths
        {DEC_ADDU_R, dec_addu_r},
2208 8170028d ths
        {DEC_ADDS_R, dec_adds_r},
2209 8170028d ths
        {DEC_SUBU_R, dec_subu_r},
2210 8170028d ths
        {DEC_SUBS_R, dec_subs_r},
2211 8170028d ths
        {DEC_LSL_R, dec_lsl_r},
2212 8170028d ths
2213 8170028d ths
        {DEC_AND_R, dec_and_r},
2214 8170028d ths
        {DEC_OR_R, dec_or_r},
2215 8170028d ths
        {DEC_BOUND_R, dec_bound_r},
2216 8170028d ths
        {DEC_ASR_R, dec_asr_r},
2217 8170028d ths
        {DEC_LSR_R, dec_lsr_r},
2218 8170028d ths
2219 8170028d ths
        {DEC_MOVU_R, dec_movu_r},
2220 8170028d ths
        {DEC_MOVS_R, dec_movs_r},
2221 8170028d ths
        {DEC_NEG_R, dec_neg_r},
2222 8170028d ths
        {DEC_MOVE_R, dec_move_r},
2223 8170028d ths
2224 8170028d ths
        /* ftag_fidx_i_m.  */
2225 8170028d ths
        /* ftag_fidx_d_m.  */
2226 8170028d ths
2227 8170028d ths
        {DEC_MULS_R, dec_muls_r},
2228 8170028d ths
        {DEC_MULU_R, dec_mulu_r},
2229 8170028d ths
2230 8170028d ths
        {DEC_ADDU_M, dec_addu_m},
2231 8170028d ths
        {DEC_ADDS_M, dec_adds_m},
2232 8170028d ths
        {DEC_SUBU_M, dec_subu_m},
2233 8170028d ths
        {DEC_SUBS_M, dec_subs_m},
2234 8170028d ths
2235 8170028d ths
        {DEC_CMPU_M, dec_cmpu_m},
2236 8170028d ths
        {DEC_CMPS_M, dec_cmps_m},
2237 8170028d ths
        {DEC_MOVU_M, dec_movu_m},
2238 8170028d ths
        {DEC_MOVS_M, dec_movs_m},
2239 8170028d ths
2240 8170028d ths
        {DEC_CMP_M, dec_cmp_m},
2241 8170028d ths
        {DEC_ADDO_M, dec_addo_m},
2242 8170028d ths
        {DEC_BOUND_M, dec_bound_m},
2243 8170028d ths
        {DEC_ADD_M, dec_add_m},
2244 8170028d ths
        {DEC_SUB_M, dec_sub_m},
2245 8170028d ths
        {DEC_AND_M, dec_and_m},
2246 8170028d ths
        {DEC_OR_M, dec_or_m},
2247 8170028d ths
        {DEC_MOVE_RM, dec_move_rm},
2248 8170028d ths
        {DEC_TEST_M, dec_test_m},
2249 8170028d ths
        {DEC_MOVE_MR, dec_move_mr},
2250 8170028d ths
2251 8170028d ths
        {{0, 0}, dec_null}
2252 8170028d ths
};
2253 8170028d ths
2254 8170028d ths
static inline unsigned int
2255 8170028d ths
cris_decoder(DisasContext *dc)
2256 8170028d ths
{
2257 8170028d ths
        unsigned int insn_len = 2;
2258 8170028d ths
        uint32_t tmp;
2259 8170028d ths
        int i;
2260 8170028d ths
2261 8170028d ths
        /* Load a halfword onto the instruction register.  */
2262 8170028d ths
        tmp = ldl_code(dc->pc);
2263 8170028d ths
        dc->ir = tmp & 0xffff;
2264 8170028d ths
2265 8170028d ths
        /* Now decode it.  */
2266 8170028d ths
        dc->opcode   = EXTRACT_FIELD(dc->ir, 4, 11);
2267 8170028d ths
        dc->op1      = EXTRACT_FIELD(dc->ir, 0, 3);
2268 8170028d ths
        dc->op2      = EXTRACT_FIELD(dc->ir, 12, 15);
2269 8170028d ths
        dc->zsize    = EXTRACT_FIELD(dc->ir, 4, 4);
2270 8170028d ths
        dc->zzsize   = EXTRACT_FIELD(dc->ir, 4, 5);
2271 8170028d ths
        dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);
2272 8170028d ths
2273 8170028d ths
        /* Large switch for all insns.  */
2274 8170028d ths
        for (i = 0; i < sizeof decinfo / sizeof decinfo[0]; i++) {
2275 8170028d ths
                if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
2276 8170028d ths
                {
2277 8170028d ths
                        insn_len = decinfo[i].dec(dc);
2278 8170028d ths
                        break;
2279 8170028d ths
                }
2280 8170028d ths
        }
2281 8170028d ths
2282 8170028d ths
        return insn_len;
2283 8170028d ths
}
2284 8170028d ths
2285 8170028d ths
static void check_breakpoint(CPUState *env, DisasContext *dc)
2286 8170028d ths
{
2287 8170028d ths
        int j;
2288 8170028d ths
        if (env->nb_breakpoints > 0) {
2289 8170028d ths
                for(j = 0; j < env->nb_breakpoints; j++) {
2290 8170028d ths
                        if (env->breakpoints[j] == dc->pc) {
2291 8170028d ths
                                cris_evaluate_flags (dc);
2292 8170028d ths
                                gen_op_movl_T0_im((long)dc->pc);
2293 8170028d ths
                                gen_op_movl_pc_T0();
2294 8170028d ths
                                gen_op_debug();
2295 8170028d ths
                                dc->is_jmp = DISAS_UPDATE;
2296 8170028d ths
                        }
2297 8170028d ths
                }
2298 8170028d ths
        }
2299 8170028d ths
}
2300 8170028d ths
2301 8170028d ths
2302 8170028d ths
/* generate intermediate code for basic block 'tb'.  */
2303 8170028d ths
struct DisasContext ctx;
2304 8170028d ths
static int
2305 8170028d ths
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2306 8170028d ths
                               int search_pc)
2307 8170028d ths
{
2308 8170028d ths
        uint16_t *gen_opc_end;
2309 8170028d ths
           uint32_t pc_start;
2310 8170028d ths
        unsigned int insn_len;
2311 8170028d ths
        int j, lj;
2312 8170028d ths
        struct DisasContext *dc = &ctx;
2313 8170028d ths
        uint32_t next_page_start;
2314 8170028d ths
2315 8170028d ths
        pc_start = tb->pc;
2316 8170028d ths
        dc->env = env;
2317 8170028d ths
        dc->tb = tb;
2318 8170028d ths
2319 8170028d ths
        gen_opc_ptr = gen_opc_buf;
2320 8170028d ths
        gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2321 8170028d ths
        gen_opparam_ptr = gen_opparam_buf;
2322 8170028d ths
2323 8170028d ths
        dc->is_jmp = DISAS_NEXT;
2324 8170028d ths
        dc->pc = pc_start;
2325 8170028d ths
        dc->singlestep_enabled = env->singlestep_enabled;
2326 8170028d ths
        dc->flagx_live = 0;
2327 8170028d ths
        dc->flags_x = 0;
2328 8170028d ths
        next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2329 8170028d ths
        lj = -1;
2330 8170028d ths
        do
2331 8170028d ths
        {
2332 8170028d ths
                check_breakpoint(env, dc);
2333 8170028d ths
                if (dc->is_jmp == DISAS_JUMP)
2334 8170028d ths
                        goto done;
2335 8170028d ths
2336 8170028d ths
                if (search_pc) {
2337 8170028d ths
                        j = gen_opc_ptr - gen_opc_buf;
2338 8170028d ths
                        if (lj < j) {
2339 8170028d ths
                                lj++;
2340 8170028d ths
                                while (lj < j)
2341 8170028d ths
                                        gen_opc_instr_start[lj++] = 0;
2342 8170028d ths
                        }
2343 8170028d ths
                        gen_opc_pc[lj] = dc->pc;
2344 8170028d ths
                        gen_opc_instr_start[lj] = 1;
2345 8170028d ths
                }
2346 8170028d ths
2347 8170028d ths
                insn_len = cris_decoder(dc);
2348 8170028d ths
                STATS(gen_op_exec_insn());
2349 8170028d ths
                dc->pc += insn_len;
2350 8170028d ths
                if (!dc->flagx_live
2351 8170028d ths
                    || (dc->flagx_live &&
2352 8170028d ths
                        !(dc->cc_op == CC_OP_FLAGS && dc->flags_x))) {
2353 8170028d ths
                        gen_movl_T0_preg[SR_CCS]();
2354 8170028d ths
                        gen_op_andl_T0_im(~X_FLAG);
2355 8170028d ths
                        gen_movl_preg_T0[SR_CCS]();
2356 8170028d ths
                        dc->flagx_live = 1;
2357 8170028d ths
                        dc->flags_x = 0;
2358 8170028d ths
                }
2359 8170028d ths
2360 8170028d ths
                /* Check for delayed branches here. If we do it before
2361 8170028d ths
                   actually genereating any host code, the simulator will just
2362 8170028d ths
                   loop doing nothing for on this program location.  */
2363 8170028d ths
                if (dc->delayed_branch) {
2364 8170028d ths
                        dc->delayed_branch--;
2365 8170028d ths
                        if (dc->delayed_branch == 0)
2366 8170028d ths
                        {
2367 8170028d ths
                                if (dc->bcc == CC_A) {
2368 8170028d ths
                                        gen_op_jmp ();
2369 8170028d ths
                                        dc->is_jmp = DISAS_UPDATE;
2370 8170028d ths
                                }
2371 8170028d ths
                                else {
2372 8170028d ths
                                        /* Conditional jmp.  */
2373 8170028d ths
                                        gen_op_cc_jmp (dc->delayed_pc, dc->pc);
2374 8170028d ths
                                        dc->is_jmp = DISAS_UPDATE;
2375 8170028d ths
                                }
2376 8170028d ths
                        }
2377 8170028d ths
                }
2378 8170028d ths
2379 8170028d ths
                if (env->singlestep_enabled)
2380 8170028d ths
                        break;
2381 8170028d ths
        } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end
2382 8170028d ths
                 && dc->pc < next_page_start);
2383 8170028d ths
2384 8170028d ths
        if (!dc->is_jmp) {
2385 8170028d ths
                gen_op_movl_T0_im((long)dc->pc);
2386 8170028d ths
                gen_op_movl_pc_T0();
2387 8170028d ths
        }
2388 8170028d ths
2389 8170028d ths
        cris_evaluate_flags (dc);
2390 8170028d ths
  done:
2391 8170028d ths
        if (__builtin_expect(env->singlestep_enabled, 0)) {
2392 8170028d ths
                gen_op_debug();
2393 8170028d ths
        } else {
2394 8170028d ths
                switch(dc->is_jmp) {
2395 8170028d ths
                        case DISAS_NEXT:
2396 8170028d ths
                                gen_goto_tb(dc, 1, dc->pc);
2397 8170028d ths
                                break;
2398 8170028d ths
                        default:
2399 8170028d ths
                        case DISAS_JUMP:
2400 8170028d ths
                        case DISAS_UPDATE:
2401 8170028d ths
                                /* indicate that the hash table must be used
2402 8170028d ths
                                   to find the next TB */
2403 8170028d ths
                                /* T0 is used to index the jmp tables.  */
2404 8170028d ths
                                gen_op_movl_T0_0();
2405 8170028d ths
                                gen_op_exit_tb();
2406 8170028d ths
                                break;
2407 8170028d ths
                        case DISAS_TB_JUMP:
2408 8170028d ths
                                /* nothing more to generate */
2409 8170028d ths
                                break;
2410 8170028d ths
                }
2411 8170028d ths
        }
2412 8170028d ths
        *gen_opc_ptr = INDEX_op_end;
2413 8170028d ths
        if (search_pc) {
2414 8170028d ths
                j = gen_opc_ptr - gen_opc_buf;
2415 8170028d ths
                lj++;
2416 8170028d ths
                while (lj <= j)
2417 8170028d ths
                        gen_opc_instr_start[lj++] = 0;
2418 8170028d ths
        } else {
2419 8170028d ths
                tb->size = dc->pc - pc_start;
2420 8170028d ths
        }
2421 8170028d ths
2422 8170028d ths
#ifdef DEBUG_DISAS
2423 8170028d ths
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2424 8170028d ths
                fprintf(logfile, "--------------\n");
2425 8170028d ths
                fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2426 8170028d ths
                target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0);
2427 8170028d ths
                fprintf(logfile, "\n");
2428 8170028d ths
                if (loglevel & CPU_LOG_TB_OP) {
2429 8170028d ths
                        fprintf(logfile, "OP:\n");
2430 8170028d ths
                        dump_ops(gen_opc_buf, gen_opparam_buf);
2431 8170028d ths
                        fprintf(logfile, "\n");
2432 8170028d ths
                }
2433 8170028d ths
        }
2434 8170028d ths
#endif
2435 8170028d ths
        return 0;
2436 8170028d ths
}
2437 8170028d ths
2438 8170028d ths
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2439 8170028d ths
{
2440 8170028d ths
    return gen_intermediate_code_internal(env, tb, 0);
2441 8170028d ths
}
2442 8170028d ths
2443 8170028d ths
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2444 8170028d ths
{
2445 8170028d ths
    return gen_intermediate_code_internal(env, tb, 1);
2446 8170028d ths
}
2447 8170028d ths
2448 8170028d ths
void cpu_dump_state (CPUState *env, FILE *f,
2449 8170028d ths
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2450 8170028d ths
                     int flags)
2451 8170028d ths
{
2452 8170028d ths
        int i;
2453 8170028d ths
        uint32_t srs;
2454 8170028d ths
2455 8170028d ths
        if (!env || !f)
2456 8170028d ths
                return;
2457 8170028d ths
2458 8170028d ths
        cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
2459 8170028d ths
                    "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n"
2460 8170028d ths
                    "debug=%x %x %x\n",
2461 8170028d ths
                    env->pc, env->pregs[SR_CCS], env->btaken, env->btarget,
2462 8170028d ths
                    env->cc_op,
2463 8170028d ths
                    env->cc_src, env->cc_dest, env->cc_result, env->cc_mask,
2464 8170028d ths
                    env->debug1, env->debug2, env->debug3);
2465 8170028d ths
2466 8170028d ths
        for (i = 0; i < 16; i++) {
2467 8170028d ths
                cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
2468 8170028d ths
                if ((i + 1) % 4 == 0)
2469 8170028d ths
                        cpu_fprintf(f, "\n");
2470 8170028d ths
        }
2471 8170028d ths
        cpu_fprintf(f, "\nspecial regs:\n");
2472 8170028d ths
        for (i = 0; i < 16; i++) {
2473 8170028d ths
                cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]);
2474 8170028d ths
                if ((i + 1) % 4 == 0)
2475 8170028d ths
                        cpu_fprintf(f, "\n");
2476 8170028d ths
        }
2477 8170028d ths
        srs = env->pregs[SR_SRS];
2478 8170028d ths
        cpu_fprintf(f, "\nsupport function regs bank %d:\n", srs);
2479 8170028d ths
        if (srs < 256) {
2480 8170028d ths
                for (i = 0; i < 16; i++) {
2481 8170028d ths
                        cpu_fprintf(f, "s%2.2d=%8.8x ",
2482 8170028d ths
                                    i, env->sregs[srs][i]);
2483 8170028d ths
                        if ((i + 1) % 4 == 0)
2484 8170028d ths
                                cpu_fprintf(f, "\n");
2485 8170028d ths
                }
2486 8170028d ths
        }
2487 8170028d ths
        cpu_fprintf(f, "\n\n");
2488 8170028d ths
2489 8170028d ths
}
2490 8170028d ths
2491 8170028d ths
CPUCRISState *cpu_cris_init (void)
2492 8170028d ths
{
2493 8170028d ths
        CPUCRISState *env;
2494 8170028d ths
2495 8170028d ths
        env = qemu_mallocz(sizeof(CPUCRISState));
2496 8170028d ths
        if (!env)
2497 8170028d ths
                return NULL;
2498 8170028d ths
        cpu_exec_init(env);
2499 8170028d ths
        cpu_reset(env);
2500 8170028d ths
        return env;
2501 8170028d ths
}
2502 8170028d ths
2503 8170028d ths
void cpu_reset (CPUCRISState *env)
2504 8170028d ths
{
2505 8170028d ths
        memset(env, 0, offsetof(CPUCRISState, breakpoints));
2506 8170028d ths
        tlb_flush(env, 1);
2507 8170028d ths
}