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