|
1 /* |
|
2 * CRIS emulation for qemu: main translation routines. |
|
3 * |
|
4 * Copyright (c) 2008 AXIS Communications AB |
|
5 * Written by Edgar E. Iglesias. |
|
6 * |
|
7 * This library is free software; you can redistribute it and/or |
|
8 * modify it under the terms of the GNU Lesser General Public |
|
9 * License as published by the Free Software Foundation; either |
|
10 * version 2 of the License, or (at your option) any later version. |
|
11 * |
|
12 * This library is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 * Lesser General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU Lesser General Public |
|
18 * License along with this library; if not, write to the Free Software |
|
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
20 */ |
|
21 |
|
22 /* |
|
23 * FIXME: |
|
24 * The condition code translation is in need of attention. |
|
25 */ |
|
26 |
|
27 #include <stdarg.h> |
|
28 #include <stdlib.h> |
|
29 #include <stdio.h> |
|
30 #include <string.h> |
|
31 #include <inttypes.h> |
|
32 #include <assert.h> |
|
33 |
|
34 #include "cpu.h" |
|
35 #include "exec-all.h" |
|
36 #include "disas.h" |
|
37 #include "tcg-op.h" |
|
38 #include "helper.h" |
|
39 #include "crisv32-decode.h" |
|
40 #include "qemu-common.h" |
|
41 |
|
42 #define GEN_HELPER 1 |
|
43 #include "helper.h" |
|
44 |
|
45 #define DISAS_CRIS 0 |
|
46 #if DISAS_CRIS |
|
47 #define DIS(x) if (loglevel & CPU_LOG_TB_IN_ASM) x |
|
48 #else |
|
49 #define DIS(x) |
|
50 #endif |
|
51 |
|
52 #define D(x) |
|
53 #define BUG() (gen_BUG(dc, __FILE__, __LINE__)) |
|
54 #define BUG_ON(x) ({if (x) BUG();}) |
|
55 |
|
56 #define DISAS_SWI 5 |
|
57 |
|
58 /* Used by the decoder. */ |
|
59 #define EXTRACT_FIELD(src, start, end) \ |
|
60 (((src) >> start) & ((1 << (end - start + 1)) - 1)) |
|
61 |
|
62 #define CC_MASK_NZ 0xc |
|
63 #define CC_MASK_NZV 0xe |
|
64 #define CC_MASK_NZVC 0xf |
|
65 #define CC_MASK_RNZV 0x10e |
|
66 |
|
67 static TCGv_ptr cpu_env; |
|
68 static TCGv cpu_R[16]; |
|
69 static TCGv cpu_PR[16]; |
|
70 static TCGv cc_x; |
|
71 static TCGv cc_src; |
|
72 static TCGv cc_dest; |
|
73 static TCGv cc_result; |
|
74 static TCGv cc_op; |
|
75 static TCGv cc_size; |
|
76 static TCGv cc_mask; |
|
77 |
|
78 static TCGv env_btaken; |
|
79 static TCGv env_btarget; |
|
80 static TCGv env_pc; |
|
81 |
|
82 #include "gen-icount.h" |
|
83 |
|
84 /* This is the state at translation time. */ |
|
85 typedef struct DisasContext { |
|
86 CPUState *env; |
|
87 target_ulong pc, ppc; |
|
88 |
|
89 /* Decoder. */ |
|
90 uint32_t ir; |
|
91 uint32_t opcode; |
|
92 unsigned int op1; |
|
93 unsigned int op2; |
|
94 unsigned int zsize, zzsize; |
|
95 unsigned int mode; |
|
96 unsigned int postinc; |
|
97 |
|
98 int update_cc; |
|
99 int cc_op; |
|
100 int cc_size; |
|
101 uint32_t cc_mask; |
|
102 |
|
103 int cc_size_uptodate; /* -1 invalid or last written value. */ |
|
104 |
|
105 int cc_x_uptodate; /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate. */ |
|
106 int flags_uptodate; /* Wether or not $ccs is uptodate. */ |
|
107 int flagx_known; /* Wether or not flags_x has the x flag known at |
|
108 translation time. */ |
|
109 int flags_x; |
|
110 |
|
111 int clear_x; /* Clear x after this insn? */ |
|
112 int cpustate_changed; |
|
113 unsigned int tb_flags; /* tb dependent flags. */ |
|
114 int is_jmp; |
|
115 |
|
116 #define JMP_NOJMP 0 |
|
117 #define JMP_DIRECT 1 |
|
118 #define JMP_INDIRECT 2 |
|
119 int jmp; /* 0=nojmp, 1=direct, 2=indirect. */ |
|
120 uint32_t jmp_pc; |
|
121 |
|
122 int delayed_branch; |
|
123 |
|
124 struct TranslationBlock *tb; |
|
125 int singlestep_enabled; |
|
126 } DisasContext; |
|
127 |
|
128 static void gen_BUG(DisasContext *dc, const char *file, int line) |
|
129 { |
|
130 printf ("BUG: pc=%x %s %d\n", dc->pc, file, line); |
|
131 fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line); |
|
132 cpu_abort(dc->env, "%s:%d\n", file, line); |
|
133 } |
|
134 |
|
135 static const char *regnames[] = |
|
136 { |
|
137 "$r0", "$r1", "$r2", "$r3", |
|
138 "$r4", "$r5", "$r6", "$r7", |
|
139 "$r8", "$r9", "$r10", "$r11", |
|
140 "$r12", "$r13", "$sp", "$acr", |
|
141 }; |
|
142 static const char *pregnames[] = |
|
143 { |
|
144 "$bz", "$vr", "$pid", "$srs", |
|
145 "$wz", "$exs", "$eda", "$mof", |
|
146 "$dz", "$ebp", "$erp", "$srp", |
|
147 "$nrp", "$ccs", "$usp", "$spc", |
|
148 }; |
|
149 |
|
150 /* We need this table to handle preg-moves with implicit width. */ |
|
151 static int preg_sizes[] = { |
|
152 1, /* bz. */ |
|
153 1, /* vr. */ |
|
154 4, /* pid. */ |
|
155 1, /* srs. */ |
|
156 2, /* wz. */ |
|
157 4, 4, 4, |
|
158 4, 4, 4, 4, |
|
159 4, 4, 4, 4, |
|
160 }; |
|
161 |
|
162 #define t_gen_mov_TN_env(tn, member) \ |
|
163 _t_gen_mov_TN_env((tn), offsetof(CPUState, member)) |
|
164 #define t_gen_mov_env_TN(member, tn) \ |
|
165 _t_gen_mov_env_TN(offsetof(CPUState, member), (tn)) |
|
166 |
|
167 static inline void t_gen_mov_TN_reg(TCGv tn, int r) |
|
168 { |
|
169 if (r < 0 || r > 15) |
|
170 fprintf(stderr, "wrong register read $r%d\n", r); |
|
171 tcg_gen_mov_tl(tn, cpu_R[r]); |
|
172 } |
|
173 static inline void t_gen_mov_reg_TN(int r, TCGv tn) |
|
174 { |
|
175 if (r < 0 || r > 15) |
|
176 fprintf(stderr, "wrong register write $r%d\n", r); |
|
177 tcg_gen_mov_tl(cpu_R[r], tn); |
|
178 } |
|
179 |
|
180 static inline void _t_gen_mov_TN_env(TCGv tn, int offset) |
|
181 { |
|
182 if (offset > sizeof (CPUState)) |
|
183 fprintf(stderr, "wrong load from env from off=%d\n", offset); |
|
184 tcg_gen_ld_tl(tn, cpu_env, offset); |
|
185 } |
|
186 static inline void _t_gen_mov_env_TN(int offset, TCGv tn) |
|
187 { |
|
188 if (offset > sizeof (CPUState)) |
|
189 fprintf(stderr, "wrong store to env at off=%d\n", offset); |
|
190 tcg_gen_st_tl(tn, cpu_env, offset); |
|
191 } |
|
192 |
|
193 static inline void t_gen_mov_TN_preg(TCGv tn, int r) |
|
194 { |
|
195 if (r < 0 || r > 15) |
|
196 fprintf(stderr, "wrong register read $p%d\n", r); |
|
197 if (r == PR_BZ || r == PR_WZ || r == PR_DZ) |
|
198 tcg_gen_mov_tl(tn, tcg_const_tl(0)); |
|
199 else if (r == PR_VR) |
|
200 tcg_gen_mov_tl(tn, tcg_const_tl(32)); |
|
201 else if (r == PR_EDA) { |
|
202 printf("read from EDA!\n"); |
|
203 tcg_gen_mov_tl(tn, cpu_PR[r]); |
|
204 } |
|
205 else |
|
206 tcg_gen_mov_tl(tn, cpu_PR[r]); |
|
207 } |
|
208 static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) |
|
209 { |
|
210 if (r < 0 || r > 15) |
|
211 fprintf(stderr, "wrong register write $p%d\n", r); |
|
212 if (r == PR_BZ || r == PR_WZ || r == PR_DZ) |
|
213 return; |
|
214 else if (r == PR_SRS) |
|
215 tcg_gen_andi_tl(cpu_PR[r], tn, 3); |
|
216 else { |
|
217 if (r == PR_PID) |
|
218 gen_helper_tlb_flush_pid(tn); |
|
219 if (dc->tb_flags & S_FLAG && r == PR_SPC) |
|
220 gen_helper_spc_write(tn); |
|
221 else if (r == PR_CCS) |
|
222 dc->cpustate_changed = 1; |
|
223 tcg_gen_mov_tl(cpu_PR[r], tn); |
|
224 } |
|
225 } |
|
226 |
|
227 static inline void t_gen_raise_exception(uint32_t index) |
|
228 { |
|
229 TCGv_i32 tmp = tcg_const_i32(index); |
|
230 gen_helper_raise_exception(tmp); |
|
231 tcg_temp_free_i32(tmp); |
|
232 } |
|
233 |
|
234 static void t_gen_lsl(TCGv d, TCGv a, TCGv b) |
|
235 { |
|
236 TCGv t0, t_31; |
|
237 |
|
238 t0 = tcg_temp_new(); |
|
239 t_31 = tcg_const_tl(31); |
|
240 tcg_gen_shl_tl(d, a, b); |
|
241 |
|
242 tcg_gen_sub_tl(t0, t_31, b); |
|
243 tcg_gen_sar_tl(t0, t0, t_31); |
|
244 tcg_gen_and_tl(t0, t0, d); |
|
245 tcg_gen_xor_tl(d, d, t0); |
|
246 tcg_temp_free(t0); |
|
247 tcg_temp_free(t_31); |
|
248 } |
|
249 |
|
250 static void t_gen_lsr(TCGv d, TCGv a, TCGv b) |
|
251 { |
|
252 TCGv t0, t_31; |
|
253 |
|
254 t0 = tcg_temp_new(); |
|
255 t_31 = tcg_temp_new(); |
|
256 tcg_gen_shr_tl(d, a, b); |
|
257 |
|
258 tcg_gen_movi_tl(t_31, 31); |
|
259 tcg_gen_sub_tl(t0, t_31, b); |
|
260 tcg_gen_sar_tl(t0, t0, t_31); |
|
261 tcg_gen_and_tl(t0, t0, d); |
|
262 tcg_gen_xor_tl(d, d, t0); |
|
263 tcg_temp_free(t0); |
|
264 tcg_temp_free(t_31); |
|
265 } |
|
266 |
|
267 static void t_gen_asr(TCGv d, TCGv a, TCGv b) |
|
268 { |
|
269 TCGv t0, t_31; |
|
270 |
|
271 t0 = tcg_temp_new(); |
|
272 t_31 = tcg_temp_new(); |
|
273 tcg_gen_sar_tl(d, a, b); |
|
274 |
|
275 tcg_gen_movi_tl(t_31, 31); |
|
276 tcg_gen_sub_tl(t0, t_31, b); |
|
277 tcg_gen_sar_tl(t0, t0, t_31); |
|
278 tcg_gen_or_tl(d, d, t0); |
|
279 tcg_temp_free(t0); |
|
280 tcg_temp_free(t_31); |
|
281 } |
|
282 |
|
283 /* 64-bit signed mul, lower result in d and upper in d2. */ |
|
284 static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b) |
|
285 { |
|
286 TCGv_i64 t0, t1; |
|
287 |
|
288 t0 = tcg_temp_new_i64(); |
|
289 t1 = tcg_temp_new_i64(); |
|
290 |
|
291 tcg_gen_ext_i32_i64(t0, a); |
|
292 tcg_gen_ext_i32_i64(t1, b); |
|
293 tcg_gen_mul_i64(t0, t0, t1); |
|
294 |
|
295 tcg_gen_trunc_i64_i32(d, t0); |
|
296 tcg_gen_shri_i64(t0, t0, 32); |
|
297 tcg_gen_trunc_i64_i32(d2, t0); |
|
298 |
|
299 tcg_temp_free_i64(t0); |
|
300 tcg_temp_free_i64(t1); |
|
301 } |
|
302 |
|
303 /* 64-bit unsigned muls, lower result in d and upper in d2. */ |
|
304 static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b) |
|
305 { |
|
306 TCGv_i64 t0, t1; |
|
307 |
|
308 t0 = tcg_temp_new_i64(); |
|
309 t1 = tcg_temp_new_i64(); |
|
310 |
|
311 tcg_gen_extu_i32_i64(t0, a); |
|
312 tcg_gen_extu_i32_i64(t1, b); |
|
313 tcg_gen_mul_i64(t0, t0, t1); |
|
314 |
|
315 tcg_gen_trunc_i64_i32(d, t0); |
|
316 tcg_gen_shri_i64(t0, t0, 32); |
|
317 tcg_gen_trunc_i64_i32(d2, t0); |
|
318 |
|
319 tcg_temp_free_i64(t0); |
|
320 tcg_temp_free_i64(t1); |
|
321 } |
|
322 |
|
323 /* 32bit branch-free binary search for counting leading zeros. */ |
|
324 static void t_gen_lz_i32(TCGv d, TCGv x) |
|
325 { |
|
326 TCGv_i32 y, m, n; |
|
327 |
|
328 y = tcg_temp_new_i32(); |
|
329 m = tcg_temp_new_i32(); |
|
330 n = tcg_temp_new_i32(); |
|
331 |
|
332 /* y = -(x >> 16) */ |
|
333 tcg_gen_shri_i32(y, x, 16); |
|
334 tcg_gen_neg_i32(y, y); |
|
335 |
|
336 /* m = (y >> 16) & 16 */ |
|
337 tcg_gen_sari_i32(m, y, 16); |
|
338 tcg_gen_andi_i32(m, m, 16); |
|
339 |
|
340 /* n = 16 - m */ |
|
341 tcg_gen_sub_i32(n, tcg_const_i32(16), m); |
|
342 /* x = x >> m */ |
|
343 tcg_gen_shr_i32(x, x, m); |
|
344 |
|
345 /* y = x - 0x100 */ |
|
346 tcg_gen_subi_i32(y, x, 0x100); |
|
347 /* m = (y >> 16) & 8 */ |
|
348 tcg_gen_sari_i32(m, y, 16); |
|
349 tcg_gen_andi_i32(m, m, 8); |
|
350 /* n = n + m */ |
|
351 tcg_gen_add_i32(n, n, m); |
|
352 /* x = x << m */ |
|
353 tcg_gen_shl_i32(x, x, m); |
|
354 |
|
355 /* y = x - 0x1000 */ |
|
356 tcg_gen_subi_i32(y, x, 0x1000); |
|
357 /* m = (y >> 16) & 4 */ |
|
358 tcg_gen_sari_i32(m, y, 16); |
|
359 tcg_gen_andi_i32(m, m, 4); |
|
360 /* n = n + m */ |
|
361 tcg_gen_add_i32(n, n, m); |
|
362 /* x = x << m */ |
|
363 tcg_gen_shl_i32(x, x, m); |
|
364 |
|
365 /* y = x - 0x4000 */ |
|
366 tcg_gen_subi_i32(y, x, 0x4000); |
|
367 /* m = (y >> 16) & 2 */ |
|
368 tcg_gen_sari_i32(m, y, 16); |
|
369 tcg_gen_andi_i32(m, m, 2); |
|
370 /* n = n + m */ |
|
371 tcg_gen_add_i32(n, n, m); |
|
372 /* x = x << m */ |
|
373 tcg_gen_shl_i32(x, x, m); |
|
374 |
|
375 /* y = x >> 14 */ |
|
376 tcg_gen_shri_i32(y, x, 14); |
|
377 /* m = y & ~(y >> 1) */ |
|
378 tcg_gen_sari_i32(m, y, 1); |
|
379 tcg_gen_not_i32(m, m); |
|
380 tcg_gen_and_i32(m, m, y); |
|
381 |
|
382 /* d = n + 2 - m */ |
|
383 tcg_gen_addi_i32(d, n, 2); |
|
384 tcg_gen_sub_i32(d, d, m); |
|
385 |
|
386 tcg_temp_free(y); |
|
387 tcg_temp_free(m); |
|
388 tcg_temp_free(n); |
|
389 } |
|
390 |
|
391 static void t_gen_btst(TCGv d, TCGv a, TCGv b) |
|
392 { |
|
393 TCGv sbit; |
|
394 TCGv bset; |
|
395 TCGv t0; |
|
396 int l1; |
|
397 |
|
398 /* des ref: |
|
399 The N flag is set according to the selected bit in the dest reg. |
|
400 The Z flag is set if the selected bit and all bits to the right are |
|
401 zero. |
|
402 The X flag is cleared. |
|
403 Other flags are left untouched. |
|
404 The destination reg is not affected. |
|
405 |
|
406 unsigned int fz, sbit, bset, mask, masked_t0; |
|
407 |
|
408 sbit = T1 & 31; |
|
409 bset = !!(T0 & (1 << sbit)); |
|
410 mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1; |
|
411 masked_t0 = T0 & mask; |
|
412 fz = !(masked_t0 | bset); |
|
413 |
|
414 // Clear the X, N and Z flags. |
|
415 T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG); |
|
416 // Set the N and Z flags accordingly. |
|
417 T0 |= (bset << 3) | (fz << 2); |
|
418 */ |
|
419 |
|
420 l1 = gen_new_label(); |
|
421 sbit = tcg_temp_new(); |
|
422 bset = tcg_temp_new(); |
|
423 t0 = tcg_temp_new(); |
|
424 |
|
425 /* Compute bset and sbit. */ |
|
426 tcg_gen_andi_tl(sbit, b, 31); |
|
427 tcg_gen_shl_tl(t0, tcg_const_tl(1), sbit); |
|
428 tcg_gen_and_tl(bset, a, t0); |
|
429 tcg_gen_shr_tl(bset, bset, sbit); |
|
430 /* Displace to N_FLAG. */ |
|
431 tcg_gen_shli_tl(bset, bset, 3); |
|
432 |
|
433 tcg_gen_shl_tl(sbit, tcg_const_tl(2), sbit); |
|
434 tcg_gen_subi_tl(sbit, sbit, 1); |
|
435 tcg_gen_and_tl(sbit, a, sbit); |
|
436 |
|
437 tcg_gen_andi_tl(d, cpu_PR[PR_CCS], ~(X_FLAG | N_FLAG | Z_FLAG)); |
|
438 /* or in the N_FLAG. */ |
|
439 tcg_gen_or_tl(d, d, bset); |
|
440 tcg_gen_brcondi_tl(TCG_COND_NE, sbit, 0, l1); |
|
441 /* or in the Z_FLAG. */ |
|
442 tcg_gen_ori_tl(d, d, Z_FLAG); |
|
443 gen_set_label(l1); |
|
444 |
|
445 tcg_temp_free(sbit); |
|
446 tcg_temp_free(bset); |
|
447 } |
|
448 |
|
449 static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b) |
|
450 { |
|
451 int l1; |
|
452 |
|
453 l1 = gen_new_label(); |
|
454 |
|
455 /* |
|
456 * d <<= 1 |
|
457 * if (d >= s) |
|
458 * d -= s; |
|
459 */ |
|
460 tcg_gen_shli_tl(d, a, 1); |
|
461 tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1); |
|
462 tcg_gen_sub_tl(d, d, b); |
|
463 gen_set_label(l1); |
|
464 } |
|
465 |
|
466 /* Extended arithmetics on CRIS. */ |
|
467 static inline void t_gen_add_flag(TCGv d, int flag) |
|
468 { |
|
469 TCGv c; |
|
470 |
|
471 c = tcg_temp_new(); |
|
472 t_gen_mov_TN_preg(c, PR_CCS); |
|
473 /* Propagate carry into d. */ |
|
474 tcg_gen_andi_tl(c, c, 1 << flag); |
|
475 if (flag) |
|
476 tcg_gen_shri_tl(c, c, flag); |
|
477 tcg_gen_add_tl(d, d, c); |
|
478 tcg_temp_free(c); |
|
479 } |
|
480 |
|
481 static inline void t_gen_addx_carry(DisasContext *dc, TCGv d) |
|
482 { |
|
483 if (dc->flagx_known) { |
|
484 if (dc->flags_x) { |
|
485 TCGv c; |
|
486 |
|
487 c = tcg_temp_new(); |
|
488 t_gen_mov_TN_preg(c, PR_CCS); |
|
489 /* C flag is already at bit 0. */ |
|
490 tcg_gen_andi_tl(c, c, C_FLAG); |
|
491 tcg_gen_add_tl(d, d, c); |
|
492 tcg_temp_free(c); |
|
493 } |
|
494 } else { |
|
495 TCGv x, c; |
|
496 |
|
497 x = tcg_temp_new(); |
|
498 c = tcg_temp_new(); |
|
499 t_gen_mov_TN_preg(x, PR_CCS); |
|
500 tcg_gen_mov_tl(c, x); |
|
501 |
|
502 /* Propagate carry into d if X is set. Branch free. */ |
|
503 tcg_gen_andi_tl(c, c, C_FLAG); |
|
504 tcg_gen_andi_tl(x, x, X_FLAG); |
|
505 tcg_gen_shri_tl(x, x, 4); |
|
506 |
|
507 tcg_gen_and_tl(x, x, c); |
|
508 tcg_gen_add_tl(d, d, x); |
|
509 tcg_temp_free(x); |
|
510 tcg_temp_free(c); |
|
511 } |
|
512 } |
|
513 |
|
514 static inline void t_gen_subx_carry(DisasContext *dc, TCGv d) |
|
515 { |
|
516 if (dc->flagx_known) { |
|
517 if (dc->flags_x) { |
|
518 TCGv c; |
|
519 |
|
520 c = tcg_temp_new(); |
|
521 t_gen_mov_TN_preg(c, PR_CCS); |
|
522 /* C flag is already at bit 0. */ |
|
523 tcg_gen_andi_tl(c, c, C_FLAG); |
|
524 tcg_gen_sub_tl(d, d, c); |
|
525 tcg_temp_free(c); |
|
526 } |
|
527 } else { |
|
528 TCGv x, c; |
|
529 |
|
530 x = tcg_temp_new(); |
|
531 c = tcg_temp_new(); |
|
532 t_gen_mov_TN_preg(x, PR_CCS); |
|
533 tcg_gen_mov_tl(c, x); |
|
534 |
|
535 /* Propagate carry into d if X is set. Branch free. */ |
|
536 tcg_gen_andi_tl(c, c, C_FLAG); |
|
537 tcg_gen_andi_tl(x, x, X_FLAG); |
|
538 tcg_gen_shri_tl(x, x, 4); |
|
539 |
|
540 tcg_gen_and_tl(x, x, c); |
|
541 tcg_gen_sub_tl(d, d, x); |
|
542 tcg_temp_free(x); |
|
543 tcg_temp_free(c); |
|
544 } |
|
545 } |
|
546 |
|
547 /* Swap the two bytes within each half word of the s operand. |
|
548 T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff) */ |
|
549 static inline void t_gen_swapb(TCGv d, TCGv s) |
|
550 { |
|
551 TCGv t, org_s; |
|
552 |
|
553 t = tcg_temp_new(); |
|
554 org_s = tcg_temp_new(); |
|
555 |
|
556 /* d and s may refer to the same object. */ |
|
557 tcg_gen_mov_tl(org_s, s); |
|
558 tcg_gen_shli_tl(t, org_s, 8); |
|
559 tcg_gen_andi_tl(d, t, 0xff00ff00); |
|
560 tcg_gen_shri_tl(t, org_s, 8); |
|
561 tcg_gen_andi_tl(t, t, 0x00ff00ff); |
|
562 tcg_gen_or_tl(d, d, t); |
|
563 tcg_temp_free(t); |
|
564 tcg_temp_free(org_s); |
|
565 } |
|
566 |
|
567 /* Swap the halfwords of the s operand. */ |
|
568 static inline void t_gen_swapw(TCGv d, TCGv s) |
|
569 { |
|
570 TCGv t; |
|
571 /* d and s refer the same object. */ |
|
572 t = tcg_temp_new(); |
|
573 tcg_gen_mov_tl(t, s); |
|
574 tcg_gen_shli_tl(d, t, 16); |
|
575 tcg_gen_shri_tl(t, t, 16); |
|
576 tcg_gen_or_tl(d, d, t); |
|
577 tcg_temp_free(t); |
|
578 } |
|
579 |
|
580 /* Reverse the within each byte. |
|
581 T0 = (((T0 << 7) & 0x80808080) | |
|
582 ((T0 << 5) & 0x40404040) | |
|
583 ((T0 << 3) & 0x20202020) | |
|
584 ((T0 << 1) & 0x10101010) | |
|
585 ((T0 >> 1) & 0x08080808) | |
|
586 ((T0 >> 3) & 0x04040404) | |
|
587 ((T0 >> 5) & 0x02020202) | |
|
588 ((T0 >> 7) & 0x01010101)); |
|
589 */ |
|
590 static inline void t_gen_swapr(TCGv d, TCGv s) |
|
591 { |
|
592 struct { |
|
593 int shift; /* LSL when positive, LSR when negative. */ |
|
594 uint32_t mask; |
|
595 } bitrev [] = { |
|
596 {7, 0x80808080}, |
|
597 {5, 0x40404040}, |
|
598 {3, 0x20202020}, |
|
599 {1, 0x10101010}, |
|
600 {-1, 0x08080808}, |
|
601 {-3, 0x04040404}, |
|
602 {-5, 0x02020202}, |
|
603 {-7, 0x01010101} |
|
604 }; |
|
605 int i; |
|
606 TCGv t, org_s; |
|
607 |
|
608 /* d and s refer the same object. */ |
|
609 t = tcg_temp_new(); |
|
610 org_s = tcg_temp_new(); |
|
611 tcg_gen_mov_tl(org_s, s); |
|
612 |
|
613 tcg_gen_shli_tl(t, org_s, bitrev[0].shift); |
|
614 tcg_gen_andi_tl(d, t, bitrev[0].mask); |
|
615 for (i = 1; i < ARRAY_SIZE(bitrev); i++) { |
|
616 if (bitrev[i].shift >= 0) { |
|
617 tcg_gen_shli_tl(t, org_s, bitrev[i].shift); |
|
618 } else { |
|
619 tcg_gen_shri_tl(t, org_s, -bitrev[i].shift); |
|
620 } |
|
621 tcg_gen_andi_tl(t, t, bitrev[i].mask); |
|
622 tcg_gen_or_tl(d, d, t); |
|
623 } |
|
624 tcg_temp_free(t); |
|
625 tcg_temp_free(org_s); |
|
626 } |
|
627 |
|
628 static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false) |
|
629 { |
|
630 TCGv btaken; |
|
631 int l1; |
|
632 |
|
633 l1 = gen_new_label(); |
|
634 btaken = tcg_temp_new(); |
|
635 |
|
636 /* Conditional jmp. */ |
|
637 tcg_gen_mov_tl(btaken, env_btaken); |
|
638 tcg_gen_mov_tl(env_pc, pc_false); |
|
639 tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1); |
|
640 tcg_gen_mov_tl(env_pc, pc_true); |
|
641 gen_set_label(l1); |
|
642 |
|
643 tcg_temp_free(btaken); |
|
644 } |
|
645 |
|
646 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) |
|
647 { |
|
648 TranslationBlock *tb; |
|
649 tb = dc->tb; |
|
650 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { |
|
651 tcg_gen_goto_tb(n); |
|
652 tcg_gen_movi_tl(env_pc, dest); |
|
653 tcg_gen_exit_tb((long)tb + n); |
|
654 } else { |
|
655 tcg_gen_movi_tl(env_pc, dest); |
|
656 tcg_gen_exit_tb(0); |
|
657 } |
|
658 } |
|
659 |
|
660 /* Sign extend at translation time. */ |
|
661 static int sign_extend(unsigned int val, unsigned int width) |
|
662 { |
|
663 int sval; |
|
664 |
|
665 /* LSL. */ |
|
666 val <<= 31 - width; |
|
667 sval = val; |
|
668 /* ASR. */ |
|
669 sval >>= 31 - width; |
|
670 return sval; |
|
671 } |
|
672 |
|
673 static inline void cris_clear_x_flag(DisasContext *dc) |
|
674 { |
|
675 if (dc->flagx_known && dc->flags_x) |
|
676 dc->flags_uptodate = 0; |
|
677 |
|
678 dc->flagx_known = 1; |
|
679 dc->flags_x = 0; |
|
680 } |
|
681 |
|
682 static void cris_flush_cc_state(DisasContext *dc) |
|
683 { |
|
684 if (dc->cc_size_uptodate != dc->cc_size) { |
|
685 tcg_gen_movi_tl(cc_size, dc->cc_size); |
|
686 dc->cc_size_uptodate = dc->cc_size; |
|
687 } |
|
688 tcg_gen_movi_tl(cc_op, dc->cc_op); |
|
689 tcg_gen_movi_tl(cc_mask, dc->cc_mask); |
|
690 } |
|
691 |
|
692 static void cris_evaluate_flags(DisasContext *dc) |
|
693 { |
|
694 if (!dc->flags_uptodate) { |
|
695 cris_flush_cc_state(dc); |
|
696 |
|
697 switch (dc->cc_op) |
|
698 { |
|
699 case CC_OP_MCP: |
|
700 gen_helper_evaluate_flags_mcp(); |
|
701 break; |
|
702 case CC_OP_MULS: |
|
703 gen_helper_evaluate_flags_muls(); |
|
704 break; |
|
705 case CC_OP_MULU: |
|
706 gen_helper_evaluate_flags_mulu(); |
|
707 break; |
|
708 case CC_OP_MOVE: |
|
709 case CC_OP_AND: |
|
710 case CC_OP_OR: |
|
711 case CC_OP_XOR: |
|
712 case CC_OP_ASR: |
|
713 case CC_OP_LSR: |
|
714 case CC_OP_LSL: |
|
715 switch (dc->cc_size) |
|
716 { |
|
717 case 4: |
|
718 gen_helper_evaluate_flags_move_4(); |
|
719 break; |
|
720 case 2: |
|
721 gen_helper_evaluate_flags_move_2(); |
|
722 break; |
|
723 default: |
|
724 gen_helper_evaluate_flags(); |
|
725 break; |
|
726 } |
|
727 break; |
|
728 case CC_OP_FLAGS: |
|
729 /* live. */ |
|
730 break; |
|
731 default: |
|
732 { |
|
733 switch (dc->cc_size) |
|
734 { |
|
735 case 4: |
|
736 gen_helper_evaluate_flags_alu_4(); |
|
737 break; |
|
738 default: |
|
739 gen_helper_evaluate_flags(); |
|
740 break; |
|
741 } |
|
742 } |
|
743 break; |
|
744 } |
|
745 if (dc->flagx_known) { |
|
746 if (dc->flags_x) |
|
747 tcg_gen_ori_tl(cpu_PR[PR_CCS], |
|
748 cpu_PR[PR_CCS], X_FLAG); |
|
749 else |
|
750 tcg_gen_andi_tl(cpu_PR[PR_CCS], |
|
751 cpu_PR[PR_CCS], ~X_FLAG); |
|
752 } |
|
753 |
|
754 dc->flags_uptodate = 1; |
|
755 } |
|
756 } |
|
757 |
|
758 static void cris_cc_mask(DisasContext *dc, unsigned int mask) |
|
759 { |
|
760 uint32_t ovl; |
|
761 |
|
762 if (!mask) { |
|
763 dc->update_cc = 0; |
|
764 return; |
|
765 } |
|
766 |
|
767 /* Check if we need to evaluate the condition codes due to |
|
768 CC overlaying. */ |
|
769 ovl = (dc->cc_mask ^ mask) & ~mask; |
|
770 if (ovl) { |
|
771 /* TODO: optimize this case. It trigs all the time. */ |
|
772 cris_evaluate_flags (dc); |
|
773 } |
|
774 dc->cc_mask = mask; |
|
775 dc->update_cc = 1; |
|
776 } |
|
777 |
|
778 static void cris_update_cc_op(DisasContext *dc, int op, int size) |
|
779 { |
|
780 dc->cc_op = op; |
|
781 dc->cc_size = size; |
|
782 dc->flags_uptodate = 0; |
|
783 } |
|
784 |
|
785 static inline void cris_update_cc_x(DisasContext *dc) |
|
786 { |
|
787 /* Save the x flag state at the time of the cc snapshot. */ |
|
788 if (dc->flagx_known) { |
|
789 if (dc->cc_x_uptodate == (2 | dc->flags_x)) |
|
790 return; |
|
791 tcg_gen_movi_tl(cc_x, dc->flags_x); |
|
792 dc->cc_x_uptodate = 2 | dc->flags_x; |
|
793 } |
|
794 else { |
|
795 tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG); |
|
796 dc->cc_x_uptodate = 1; |
|
797 } |
|
798 } |
|
799 |
|
800 /* Update cc prior to executing ALU op. Needs source operands untouched. */ |
|
801 static void cris_pre_alu_update_cc(DisasContext *dc, int op, |
|
802 TCGv dst, TCGv src, int size) |
|
803 { |
|
804 if (dc->update_cc) { |
|
805 cris_update_cc_op(dc, op, size); |
|
806 tcg_gen_mov_tl(cc_src, src); |
|
807 |
|
808 if (op != CC_OP_MOVE |
|
809 && op != CC_OP_AND |
|
810 && op != CC_OP_OR |
|
811 && op != CC_OP_XOR |
|
812 && op != CC_OP_ASR |
|
813 && op != CC_OP_LSR |
|
814 && op != CC_OP_LSL) |
|
815 tcg_gen_mov_tl(cc_dest, dst); |
|
816 |
|
817 cris_update_cc_x(dc); |
|
818 } |
|
819 } |
|
820 |
|
821 /* Update cc after executing ALU op. needs the result. */ |
|
822 static inline void cris_update_result(DisasContext *dc, TCGv res) |
|
823 { |
|
824 if (dc->update_cc) { |
|
825 if (dc->cc_size == 4 && |
|
826 (dc->cc_op == CC_OP_SUB |
|
827 || dc->cc_op == CC_OP_ADD)) |
|
828 return; |
|
829 tcg_gen_mov_tl(cc_result, res); |
|
830 } |
|
831 } |
|
832 |
|
833 /* Returns one if the write back stage should execute. */ |
|
834 static void cris_alu_op_exec(DisasContext *dc, int op, |
|
835 TCGv dst, TCGv a, TCGv b, int size) |
|
836 { |
|
837 /* Emit the ALU insns. */ |
|
838 switch (op) |
|
839 { |
|
840 case CC_OP_ADD: |
|
841 tcg_gen_add_tl(dst, a, b); |
|
842 /* Extended arithmetics. */ |
|
843 t_gen_addx_carry(dc, dst); |
|
844 break; |
|
845 case CC_OP_ADDC: |
|
846 tcg_gen_add_tl(dst, a, b); |
|
847 t_gen_add_flag(dst, 0); /* C_FLAG. */ |
|
848 break; |
|
849 case CC_OP_MCP: |
|
850 tcg_gen_add_tl(dst, a, b); |
|
851 t_gen_add_flag(dst, 8); /* R_FLAG. */ |
|
852 break; |
|
853 case CC_OP_SUB: |
|
854 tcg_gen_sub_tl(dst, a, b); |
|
855 /* Extended arithmetics. */ |
|
856 t_gen_subx_carry(dc, dst); |
|
857 break; |
|
858 case CC_OP_MOVE: |
|
859 tcg_gen_mov_tl(dst, b); |
|
860 break; |
|
861 case CC_OP_OR: |
|
862 tcg_gen_or_tl(dst, a, b); |
|
863 break; |
|
864 case CC_OP_AND: |
|
865 tcg_gen_and_tl(dst, a, b); |
|
866 break; |
|
867 case CC_OP_XOR: |
|
868 tcg_gen_xor_tl(dst, a, b); |
|
869 break; |
|
870 case CC_OP_LSL: |
|
871 t_gen_lsl(dst, a, b); |
|
872 break; |
|
873 case CC_OP_LSR: |
|
874 t_gen_lsr(dst, a, b); |
|
875 break; |
|
876 case CC_OP_ASR: |
|
877 t_gen_asr(dst, a, b); |
|
878 break; |
|
879 case CC_OP_NEG: |
|
880 tcg_gen_neg_tl(dst, b); |
|
881 /* Extended arithmetics. */ |
|
882 t_gen_subx_carry(dc, dst); |
|
883 break; |
|
884 case CC_OP_LZ: |
|
885 t_gen_lz_i32(dst, b); |
|
886 break; |
|
887 case CC_OP_BTST: |
|
888 t_gen_btst(dst, a, b); |
|
889 break; |
|
890 case CC_OP_MULS: |
|
891 t_gen_muls(dst, cpu_PR[PR_MOF], a, b); |
|
892 break; |
|
893 case CC_OP_MULU: |
|
894 t_gen_mulu(dst, cpu_PR[PR_MOF], a, b); |
|
895 break; |
|
896 case CC_OP_DSTEP: |
|
897 t_gen_cris_dstep(dst, a, b); |
|
898 break; |
|
899 case CC_OP_BOUND: |
|
900 { |
|
901 int l1; |
|
902 l1 = gen_new_label(); |
|
903 tcg_gen_mov_tl(dst, a); |
|
904 tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1); |
|
905 tcg_gen_mov_tl(dst, b); |
|
906 gen_set_label(l1); |
|
907 } |
|
908 break; |
|
909 case CC_OP_CMP: |
|
910 tcg_gen_sub_tl(dst, a, b); |
|
911 /* Extended arithmetics. */ |
|
912 t_gen_subx_carry(dc, dst); |
|
913 break; |
|
914 default: |
|
915 fprintf (logfile, "illegal ALU op.\n"); |
|
916 BUG(); |
|
917 break; |
|
918 } |
|
919 |
|
920 if (size == 1) |
|
921 tcg_gen_andi_tl(dst, dst, 0xff); |
|
922 else if (size == 2) |
|
923 tcg_gen_andi_tl(dst, dst, 0xffff); |
|
924 } |
|
925 |
|
926 static void cris_alu(DisasContext *dc, int op, |
|
927 TCGv d, TCGv op_a, TCGv op_b, int size) |
|
928 { |
|
929 TCGv tmp; |
|
930 int writeback; |
|
931 |
|
932 writeback = 1; |
|
933 |
|
934 if (op == CC_OP_BOUND || op == CC_OP_BTST) |
|
935 tmp = tcg_temp_local_new(); |
|
936 |
|
937 if (op == CC_OP_CMP) { |
|
938 tmp = tcg_temp_new(); |
|
939 writeback = 0; |
|
940 } else if (size == 4) { |
|
941 tmp = d; |
|
942 writeback = 0; |
|
943 } else |
|
944 tmp = tcg_temp_new(); |
|
945 |
|
946 |
|
947 cris_pre_alu_update_cc(dc, op, op_a, op_b, size); |
|
948 cris_alu_op_exec(dc, op, tmp, op_a, op_b, size); |
|
949 cris_update_result(dc, tmp); |
|
950 |
|
951 /* Writeback. */ |
|
952 if (writeback) { |
|
953 if (size == 1) |
|
954 tcg_gen_andi_tl(d, d, ~0xff); |
|
955 else |
|
956 tcg_gen_andi_tl(d, d, ~0xffff); |
|
957 tcg_gen_or_tl(d, d, tmp); |
|
958 } |
|
959 if (!TCGV_EQUAL(tmp, d)) |
|
960 tcg_temp_free(tmp); |
|
961 } |
|
962 |
|
963 static int arith_cc(DisasContext *dc) |
|
964 { |
|
965 if (dc->update_cc) { |
|
966 switch (dc->cc_op) { |
|
967 case CC_OP_ADDC: return 1; |
|
968 case CC_OP_ADD: return 1; |
|
969 case CC_OP_SUB: return 1; |
|
970 case CC_OP_DSTEP: return 1; |
|
971 case CC_OP_LSL: return 1; |
|
972 case CC_OP_LSR: return 1; |
|
973 case CC_OP_ASR: return 1; |
|
974 case CC_OP_CMP: return 1; |
|
975 case CC_OP_NEG: return 1; |
|
976 case CC_OP_OR: return 1; |
|
977 case CC_OP_XOR: return 1; |
|
978 case CC_OP_MULU: return 1; |
|
979 case CC_OP_MULS: return 1; |
|
980 default: |
|
981 return 0; |
|
982 } |
|
983 } |
|
984 return 0; |
|
985 } |
|
986 |
|
987 static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond) |
|
988 { |
|
989 int arith_opt, move_opt; |
|
990 |
|
991 /* TODO: optimize more condition codes. */ |
|
992 |
|
993 /* |
|
994 * If the flags are live, we've gotta look into the bits of CCS. |
|
995 * Otherwise, if we just did an arithmetic operation we try to |
|
996 * evaluate the condition code faster. |
|
997 * |
|
998 * When this function is done, T0 should be non-zero if the condition |
|
999 * code is true. |
|
1000 */ |
|
1001 arith_opt = arith_cc(dc) && !dc->flags_uptodate; |
|
1002 move_opt = (dc->cc_op == CC_OP_MOVE) && dc->flags_uptodate; |
|
1003 switch (cond) { |
|
1004 case CC_EQ: |
|
1005 if (arith_opt || move_opt) { |
|
1006 /* If cc_result is zero, T0 should be |
|
1007 non-zero otherwise T0 should be zero. */ |
|
1008 int l1; |
|
1009 l1 = gen_new_label(); |
|
1010 tcg_gen_movi_tl(cc, 0); |
|
1011 tcg_gen_brcondi_tl(TCG_COND_NE, cc_result, |
|
1012 0, l1); |
|
1013 tcg_gen_movi_tl(cc, 1); |
|
1014 gen_set_label(l1); |
|
1015 } |
|
1016 else { |
|
1017 cris_evaluate_flags(dc); |
|
1018 tcg_gen_andi_tl(cc, |
|
1019 cpu_PR[PR_CCS], Z_FLAG); |
|
1020 } |
|
1021 break; |
|
1022 case CC_NE: |
|
1023 if (arith_opt || move_opt) |
|
1024 tcg_gen_mov_tl(cc, cc_result); |
|
1025 else { |
|
1026 cris_evaluate_flags(dc); |
|
1027 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], |
|
1028 Z_FLAG); |
|
1029 tcg_gen_andi_tl(cc, cc, Z_FLAG); |
|
1030 } |
|
1031 break; |
|
1032 case CC_CS: |
|
1033 cris_evaluate_flags(dc); |
|
1034 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG); |
|
1035 break; |
|
1036 case CC_CC: |
|
1037 cris_evaluate_flags(dc); |
|
1038 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG); |
|
1039 tcg_gen_andi_tl(cc, cc, C_FLAG); |
|
1040 break; |
|
1041 case CC_VS: |
|
1042 cris_evaluate_flags(dc); |
|
1043 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG); |
|
1044 break; |
|
1045 case CC_VC: |
|
1046 cris_evaluate_flags(dc); |
|
1047 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], |
|
1048 V_FLAG); |
|
1049 tcg_gen_andi_tl(cc, cc, V_FLAG); |
|
1050 break; |
|
1051 case CC_PL: |
|
1052 if (arith_opt || move_opt) { |
|
1053 int bits = 31; |
|
1054 |
|
1055 if (dc->cc_size == 1) |
|
1056 bits = 7; |
|
1057 else if (dc->cc_size == 2) |
|
1058 bits = 15; |
|
1059 |
|
1060 tcg_gen_shri_tl(cc, cc_result, bits); |
|
1061 tcg_gen_xori_tl(cc, cc, 1); |
|
1062 } else { |
|
1063 cris_evaluate_flags(dc); |
|
1064 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], |
|
1065 N_FLAG); |
|
1066 tcg_gen_andi_tl(cc, cc, N_FLAG); |
|
1067 } |
|
1068 break; |
|
1069 case CC_MI: |
|
1070 if (arith_opt || move_opt) { |
|
1071 int bits = 31; |
|
1072 |
|
1073 if (dc->cc_size == 1) |
|
1074 bits = 7; |
|
1075 else if (dc->cc_size == 2) |
|
1076 bits = 15; |
|
1077 |
|
1078 tcg_gen_shri_tl(cc, cc_result, 31); |
|
1079 } |
|
1080 else { |
|
1081 cris_evaluate_flags(dc); |
|
1082 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], |
|
1083 N_FLAG); |
|
1084 } |
|
1085 break; |
|
1086 case CC_LS: |
|
1087 cris_evaluate_flags(dc); |
|
1088 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], |
|
1089 C_FLAG | Z_FLAG); |
|
1090 break; |
|
1091 case CC_HI: |
|
1092 cris_evaluate_flags(dc); |
|
1093 { |
|
1094 TCGv tmp; |
|
1095 |
|
1096 tmp = tcg_temp_new(); |
|
1097 tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS], |
|
1098 C_FLAG | Z_FLAG); |
|
1099 /* Overlay the C flag on top of the Z. */ |
|
1100 tcg_gen_shli_tl(cc, tmp, 2); |
|
1101 tcg_gen_and_tl(cc, tmp, cc); |
|
1102 tcg_gen_andi_tl(cc, cc, Z_FLAG); |
|
1103 |
|
1104 tcg_temp_free(tmp); |
|
1105 } |
|
1106 break; |
|
1107 case CC_GE: |
|
1108 cris_evaluate_flags(dc); |
|
1109 /* Overlay the V flag on top of the N. */ |
|
1110 tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2); |
|
1111 tcg_gen_xor_tl(cc, |
|
1112 cpu_PR[PR_CCS], cc); |
|
1113 tcg_gen_andi_tl(cc, cc, N_FLAG); |
|
1114 tcg_gen_xori_tl(cc, cc, N_FLAG); |
|
1115 break; |
|
1116 case CC_LT: |
|
1117 cris_evaluate_flags(dc); |
|
1118 /* Overlay the V flag on top of the N. */ |
|
1119 tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2); |
|
1120 tcg_gen_xor_tl(cc, |
|
1121 cpu_PR[PR_CCS], cc); |
|
1122 tcg_gen_andi_tl(cc, cc, N_FLAG); |
|
1123 break; |
|
1124 case CC_GT: |
|
1125 cris_evaluate_flags(dc); |
|
1126 { |
|
1127 TCGv n, z; |
|
1128 |
|
1129 n = tcg_temp_new(); |
|
1130 z = tcg_temp_new(); |
|
1131 |
|
1132 /* To avoid a shift we overlay everything on |
|
1133 the V flag. */ |
|
1134 tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2); |
|
1135 tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1); |
|
1136 /* invert Z. */ |
|
1137 tcg_gen_xori_tl(z, z, 2); |
|
1138 |
|
1139 tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); |
|
1140 tcg_gen_xori_tl(n, n, 2); |
|
1141 tcg_gen_and_tl(cc, z, n); |
|
1142 tcg_gen_andi_tl(cc, cc, 2); |
|
1143 |
|
1144 tcg_temp_free(n); |
|
1145 tcg_temp_free(z); |
|
1146 } |
|
1147 break; |
|
1148 case CC_LE: |
|
1149 cris_evaluate_flags(dc); |
|
1150 { |
|
1151 TCGv n, z; |
|
1152 |
|
1153 n = tcg_temp_new(); |
|
1154 z = tcg_temp_new(); |
|
1155 |
|
1156 /* To avoid a shift we overlay everything on |
|
1157 the V flag. */ |
|
1158 tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2); |
|
1159 tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1); |
|
1160 |
|
1161 tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); |
|
1162 tcg_gen_or_tl(cc, z, n); |
|
1163 tcg_gen_andi_tl(cc, cc, 2); |
|
1164 |
|
1165 tcg_temp_free(n); |
|
1166 tcg_temp_free(z); |
|
1167 } |
|
1168 break; |
|
1169 case CC_P: |
|
1170 cris_evaluate_flags(dc); |
|
1171 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], P_FLAG); |
|
1172 break; |
|
1173 case CC_A: |
|
1174 tcg_gen_movi_tl(cc, 1); |
|
1175 break; |
|
1176 default: |
|
1177 BUG(); |
|
1178 break; |
|
1179 }; |
|
1180 } |
|
1181 |
|
1182 static void cris_store_direct_jmp(DisasContext *dc) |
|
1183 { |
|
1184 /* Store the direct jmp state into the cpu-state. */ |
|
1185 if (dc->jmp == JMP_DIRECT) { |
|
1186 tcg_gen_movi_tl(env_btarget, dc->jmp_pc); |
|
1187 tcg_gen_movi_tl(env_btaken, 1); |
|
1188 } |
|
1189 } |
|
1190 |
|
1191 static void cris_prepare_cc_branch (DisasContext *dc, |
|
1192 int offset, int cond) |
|
1193 { |
|
1194 /* This helps us re-schedule the micro-code to insns in delay-slots |
|
1195 before the actual jump. */ |
|
1196 dc->delayed_branch = 2; |
|
1197 dc->jmp_pc = dc->pc + offset; |
|
1198 |
|
1199 if (cond != CC_A) |
|
1200 { |
|
1201 dc->jmp = JMP_INDIRECT; |
|
1202 gen_tst_cc (dc, env_btaken, cond); |
|
1203 tcg_gen_movi_tl(env_btarget, dc->jmp_pc); |
|
1204 } else { |
|
1205 /* Allow chaining. */ |
|
1206 dc->jmp = JMP_DIRECT; |
|
1207 } |
|
1208 } |
|
1209 |
|
1210 |
|
1211 /* jumps, when the dest is in a live reg for example. Direct should be set |
|
1212 when the dest addr is constant to allow tb chaining. */ |
|
1213 static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type) |
|
1214 { |
|
1215 /* This helps us re-schedule the micro-code to insns in delay-slots |
|
1216 before the actual jump. */ |
|
1217 dc->delayed_branch = 2; |
|
1218 dc->jmp = type; |
|
1219 if (type == JMP_INDIRECT) |
|
1220 tcg_gen_movi_tl(env_btaken, 1); |
|
1221 } |
|
1222 |
|
1223 static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr) |
|
1224 { |
|
1225 int mem_index = cpu_mmu_index(dc->env); |
|
1226 |
|
1227 /* If we get a fault on a delayslot we must keep the jmp state in |
|
1228 the cpu-state to be able to re-execute the jmp. */ |
|
1229 if (dc->delayed_branch == 1) |
|
1230 cris_store_direct_jmp(dc); |
|
1231 |
|
1232 tcg_gen_qemu_ld64(dst, addr, mem_index); |
|
1233 } |
|
1234 |
|
1235 static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
|
1236 unsigned int size, int sign) |
|
1237 { |
|
1238 int mem_index = cpu_mmu_index(dc->env); |
|
1239 |
|
1240 /* If we get a fault on a delayslot we must keep the jmp state in |
|
1241 the cpu-state to be able to re-execute the jmp. */ |
|
1242 if (dc->delayed_branch == 1) |
|
1243 cris_store_direct_jmp(dc); |
|
1244 |
|
1245 if (size == 1) { |
|
1246 if (sign) |
|
1247 tcg_gen_qemu_ld8s(dst, addr, mem_index); |
|
1248 else |
|
1249 tcg_gen_qemu_ld8u(dst, addr, mem_index); |
|
1250 } |
|
1251 else if (size == 2) { |
|
1252 if (sign) |
|
1253 tcg_gen_qemu_ld16s(dst, addr, mem_index); |
|
1254 else |
|
1255 tcg_gen_qemu_ld16u(dst, addr, mem_index); |
|
1256 } |
|
1257 else if (size == 4) { |
|
1258 tcg_gen_qemu_ld32u(dst, addr, mem_index); |
|
1259 } |
|
1260 else { |
|
1261 abort(); |
|
1262 } |
|
1263 } |
|
1264 |
|
1265 static void gen_store (DisasContext *dc, TCGv addr, TCGv val, |
|
1266 unsigned int size) |
|
1267 { |
|
1268 int mem_index = cpu_mmu_index(dc->env); |
|
1269 |
|
1270 /* If we get a fault on a delayslot we must keep the jmp state in |
|
1271 the cpu-state to be able to re-execute the jmp. */ |
|
1272 if (dc->delayed_branch == 1) |
|
1273 cris_store_direct_jmp(dc); |
|
1274 |
|
1275 |
|
1276 /* Conditional writes. We only support the kind were X and P are known |
|
1277 at translation time. */ |
|
1278 if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) { |
|
1279 dc->postinc = 0; |
|
1280 cris_evaluate_flags(dc); |
|
1281 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG); |
|
1282 return; |
|
1283 } |
|
1284 |
|
1285 if (size == 1) |
|
1286 tcg_gen_qemu_st8(val, addr, mem_index); |
|
1287 else if (size == 2) |
|
1288 tcg_gen_qemu_st16(val, addr, mem_index); |
|
1289 else |
|
1290 tcg_gen_qemu_st32(val, addr, mem_index); |
|
1291 |
|
1292 if (dc->flagx_known && dc->flags_x) { |
|
1293 cris_evaluate_flags(dc); |
|
1294 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG); |
|
1295 } |
|
1296 } |
|
1297 |
|
1298 static inline void t_gen_sext(TCGv d, TCGv s, int size) |
|
1299 { |
|
1300 if (size == 1) |
|
1301 tcg_gen_ext8s_i32(d, s); |
|
1302 else if (size == 2) |
|
1303 tcg_gen_ext16s_i32(d, s); |
|
1304 else if(!TCGV_EQUAL(d, s)) |
|
1305 tcg_gen_mov_tl(d, s); |
|
1306 } |
|
1307 |
|
1308 static inline void t_gen_zext(TCGv d, TCGv s, int size) |
|
1309 { |
|
1310 if (size == 1) |
|
1311 tcg_gen_ext8u_i32(d, s); |
|
1312 else if (size == 2) |
|
1313 tcg_gen_ext16u_i32(d, s); |
|
1314 else if (!TCGV_EQUAL(d, s)) |
|
1315 tcg_gen_mov_tl(d, s); |
|
1316 } |
|
1317 |
|
1318 #if DISAS_CRIS |
|
1319 static char memsize_char(int size) |
|
1320 { |
|
1321 switch (size) |
|
1322 { |
|
1323 case 1: return 'b'; break; |
|
1324 case 2: return 'w'; break; |
|
1325 case 4: return 'd'; break; |
|
1326 default: |
|
1327 return 'x'; |
|
1328 break; |
|
1329 } |
|
1330 } |
|
1331 #endif |
|
1332 |
|
1333 static inline unsigned int memsize_z(DisasContext *dc) |
|
1334 { |
|
1335 return dc->zsize + 1; |
|
1336 } |
|
1337 |
|
1338 static inline unsigned int memsize_zz(DisasContext *dc) |
|
1339 { |
|
1340 switch (dc->zzsize) |
|
1341 { |
|
1342 case 0: return 1; |
|
1343 case 1: return 2; |
|
1344 default: |
|
1345 return 4; |
|
1346 } |
|
1347 } |
|
1348 |
|
1349 static inline void do_postinc (DisasContext *dc, int size) |
|
1350 { |
|
1351 if (dc->postinc) |
|
1352 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size); |
|
1353 } |
|
1354 |
|
1355 static inline void dec_prep_move_r(DisasContext *dc, int rs, int rd, |
|
1356 int size, int s_ext, TCGv dst) |
|
1357 { |
|
1358 if (s_ext) |
|
1359 t_gen_sext(dst, cpu_R[rs], size); |
|
1360 else |
|
1361 t_gen_zext(dst, cpu_R[rs], size); |
|
1362 } |
|
1363 |
|
1364 /* Prepare T0 and T1 for a register alu operation. |
|
1365 s_ext decides if the operand1 should be sign-extended or zero-extended when |
|
1366 needed. */ |
|
1367 static void dec_prep_alu_r(DisasContext *dc, int rs, int rd, |
|
1368 int size, int s_ext, TCGv dst, TCGv src) |
|
1369 { |
|
1370 dec_prep_move_r(dc, rs, rd, size, s_ext, src); |
|
1371 |
|
1372 if (s_ext) |
|
1373 t_gen_sext(dst, cpu_R[rd], size); |
|
1374 else |
|
1375 t_gen_zext(dst, cpu_R[rd], size); |
|
1376 } |
|
1377 |
|
1378 static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize, |
|
1379 TCGv dst) |
|
1380 { |
|
1381 unsigned int rs, rd; |
|
1382 uint32_t imm; |
|
1383 int is_imm; |
|
1384 int insn_len = 2; |
|
1385 |
|
1386 rs = dc->op1; |
|
1387 rd = dc->op2; |
|
1388 is_imm = rs == 15 && dc->postinc; |
|
1389 |
|
1390 /* Load [$rs] onto T1. */ |
|
1391 if (is_imm) { |
|
1392 insn_len = 2 + memsize; |
|
1393 if (memsize == 1) |
|
1394 insn_len++; |
|
1395 |
|
1396 if (memsize != 4) { |
|
1397 if (s_ext) { |
|
1398 if (memsize == 1) |
|
1399 imm = ldsb_code(dc->pc + 2); |
|
1400 else |
|
1401 imm = ldsw_code(dc->pc + 2); |
|
1402 } else { |
|
1403 if (memsize == 1) |
|
1404 imm = ldub_code(dc->pc + 2); |
|
1405 else |
|
1406 imm = lduw_code(dc->pc + 2); |
|
1407 } |
|
1408 } else |
|
1409 imm = ldl_code(dc->pc + 2); |
|
1410 |
|
1411 tcg_gen_movi_tl(dst, imm); |
|
1412 dc->postinc = 0; |
|
1413 } else { |
|
1414 cris_flush_cc_state(dc); |
|
1415 gen_load(dc, dst, cpu_R[rs], memsize, 0); |
|
1416 if (s_ext) |
|
1417 t_gen_sext(dst, dst, memsize); |
|
1418 else |
|
1419 t_gen_zext(dst, dst, memsize); |
|
1420 } |
|
1421 return insn_len; |
|
1422 } |
|
1423 |
|
1424 /* Prepare T0 and T1 for a memory + alu operation. |
|
1425 s_ext decides if the operand1 should be sign-extended or zero-extended when |
|
1426 needed. */ |
|
1427 static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize, |
|
1428 TCGv dst, TCGv src) |
|
1429 { |
|
1430 int insn_len; |
|
1431 |
|
1432 insn_len = dec_prep_move_m(dc, s_ext, memsize, src); |
|
1433 tcg_gen_mov_tl(dst, cpu_R[dc->op2]); |
|
1434 return insn_len; |
|
1435 } |
|
1436 |
|
1437 #if DISAS_CRIS |
|
1438 static const char *cc_name(int cc) |
|
1439 { |
|
1440 static const char *cc_names[16] = { |
|
1441 "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", |
|
1442 "ls", "hi", "ge", "lt", "gt", "le", "a", "p" |
|
1443 }; |
|
1444 assert(cc < 16); |
|
1445 return cc_names[cc]; |
|
1446 } |
|
1447 #endif |
|
1448 |
|
1449 /* Start of insn decoders. */ |
|
1450 |
|
1451 static unsigned int dec_bccq(DisasContext *dc) |
|
1452 { |
|
1453 int32_t offset; |
|
1454 int sign; |
|
1455 uint32_t cond = dc->op2; |
|
1456 int tmp; |
|
1457 |
|
1458 offset = EXTRACT_FIELD (dc->ir, 1, 7); |
|
1459 sign = EXTRACT_FIELD(dc->ir, 0, 0); |
|
1460 |
|
1461 offset *= 2; |
|
1462 offset |= sign << 8; |
|
1463 tmp = offset; |
|
1464 offset = sign_extend(offset, 8); |
|
1465 |
|
1466 DIS(fprintf (logfile, "b%s %x\n", cc_name(cond), dc->pc + offset)); |
|
1467 |
|
1468 /* op2 holds the condition-code. */ |
|
1469 cris_cc_mask(dc, 0); |
|
1470 cris_prepare_cc_branch (dc, offset, cond); |
|
1471 return 2; |
|
1472 } |
|
1473 static unsigned int dec_addoq(DisasContext *dc) |
|
1474 { |
|
1475 int32_t imm; |
|
1476 |
|
1477 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7); |
|
1478 imm = sign_extend(dc->op1, 7); |
|
1479 |
|
1480 DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2)); |
|
1481 cris_cc_mask(dc, 0); |
|
1482 /* Fetch register operand, */ |
|
1483 tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm); |
|
1484 |
|
1485 return 2; |
|
1486 } |
|
1487 static unsigned int dec_addq(DisasContext *dc) |
|
1488 { |
|
1489 DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2)); |
|
1490 |
|
1491 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
|
1492 |
|
1493 cris_cc_mask(dc, CC_MASK_NZVC); |
|
1494 |
|
1495 cris_alu(dc, CC_OP_ADD, |
|
1496 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); |
|
1497 return 2; |
|
1498 } |
|
1499 static unsigned int dec_moveq(DisasContext *dc) |
|
1500 { |
|
1501 uint32_t imm; |
|
1502 |
|
1503 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
|
1504 imm = sign_extend(dc->op1, 5); |
|
1505 DIS(fprintf (logfile, "moveq %d, $r%u\n", imm, dc->op2)); |
|
1506 |
|
1507 tcg_gen_mov_tl(cpu_R[dc->op2], tcg_const_tl(imm)); |
|
1508 return 2; |
|
1509 } |
|
1510 static unsigned int dec_subq(DisasContext *dc) |
|
1511 { |
|
1512 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
|
1513 |
|
1514 DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2)); |
|
1515 |
|
1516 cris_cc_mask(dc, CC_MASK_NZVC); |
|
1517 cris_alu(dc, CC_OP_SUB, |
|
1518 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); |
|
1519 return 2; |
|
1520 } |
|
1521 static unsigned int dec_cmpq(DisasContext *dc) |
|
1522 { |
|
1523 uint32_t imm; |
|
1524 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
|
1525 imm = sign_extend(dc->op1, 5); |
|
1526 |
|
1527 DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2)); |
|
1528 cris_cc_mask(dc, CC_MASK_NZVC); |
|
1529 |
|
1530 cris_alu(dc, CC_OP_CMP, |
|
1531 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4); |
|
1532 return 2; |
|
1533 } |
|
1534 static unsigned int dec_andq(DisasContext *dc) |
|
1535 { |
|
1536 uint32_t imm; |
|
1537 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
|
1538 imm = sign_extend(dc->op1, 5); |
|
1539 |
|
1540 DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2)); |
|
1541 cris_cc_mask(dc, CC_MASK_NZ); |
|
1542 |
|
1543 cris_alu(dc, CC_OP_AND, |
|
1544 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4); |
|
1545 return 2; |
|
1546 } |
|
1547 static unsigned int dec_orq(DisasContext *dc) |
|
1548 { |
|
1549 uint32_t imm; |
|
1550 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); |
|
1551 imm = sign_extend(dc->op1, 5); |
|
1552 DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2)); |
|
1553 cris_cc_mask(dc, CC_MASK_NZ); |
|
1554 |
|
1555 cris_alu(dc, CC_OP_OR, |
|
1556 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4); |
|
1557 return 2; |
|
1558 } |
|
1559 static unsigned int dec_btstq(DisasContext *dc) |
|
1560 { |
|
1561 TCGv l0; |
|
1562 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
|
1563 DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2)); |
|
1564 |
|
1565 cris_cc_mask(dc, CC_MASK_NZ); |
|
1566 l0 = tcg_temp_local_new(); |
|
1567 cris_alu(dc, CC_OP_BTST, |
|
1568 l0, cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); |
|
1569 cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
|
1570 t_gen_mov_preg_TN(dc, PR_CCS, l0); |
|
1571 dc->flags_uptodate = 1; |
|
1572 tcg_temp_free(l0); |
|
1573 return 2; |
|
1574 } |
|
1575 static unsigned int dec_asrq(DisasContext *dc) |
|
1576 { |
|
1577 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
|
1578 DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2)); |
|
1579 cris_cc_mask(dc, CC_MASK_NZ); |
|
1580 |
|
1581 tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); |
|
1582 cris_alu(dc, CC_OP_MOVE, |
|
1583 cpu_R[dc->op2], |
|
1584 cpu_R[dc->op2], cpu_R[dc->op2], 4); |
|
1585 return 2; |
|
1586 } |
|
1587 static unsigned int dec_lslq(DisasContext *dc) |
|
1588 { |
|
1589 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
|
1590 DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2)); |
|
1591 |
|
1592 cris_cc_mask(dc, CC_MASK_NZ); |
|
1593 |
|
1594 tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); |
|
1595 |
|
1596 cris_alu(dc, CC_OP_MOVE, |
|
1597 cpu_R[dc->op2], |
|
1598 cpu_R[dc->op2], cpu_R[dc->op2], 4); |
|
1599 return 2; |
|
1600 } |
|
1601 static unsigned int dec_lsrq(DisasContext *dc) |
|
1602 { |
|
1603 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
|
1604 DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2)); |
|
1605 |
|
1606 cris_cc_mask(dc, CC_MASK_NZ); |
|
1607 |
|
1608 tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); |
|
1609 cris_alu(dc, CC_OP_MOVE, |
|
1610 cpu_R[dc->op2], |
|
1611 cpu_R[dc->op2], cpu_R[dc->op2], 4); |
|
1612 return 2; |
|
1613 } |
|
1614 |
|
1615 static unsigned int dec_move_r(DisasContext *dc) |
|
1616 { |
|
1617 int size = memsize_zz(dc); |
|
1618 |
|
1619 DIS(fprintf (logfile, "move.%c $r%u, $r%u\n", |
|
1620 memsize_char(size), dc->op1, dc->op2)); |
|
1621 |
|
1622 cris_cc_mask(dc, CC_MASK_NZ); |
|
1623 if (size == 4) { |
|
1624 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]); |
|
1625 cris_cc_mask(dc, CC_MASK_NZ); |
|
1626 cris_update_cc_op(dc, CC_OP_MOVE, 4); |
|
1627 cris_update_cc_x(dc); |
|
1628 cris_update_result(dc, cpu_R[dc->op2]); |
|
1629 } |
|
1630 else { |
|
1631 TCGv t0; |
|
1632 |
|
1633 t0 = tcg_temp_new(); |
|
1634 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0); |
|
1635 cris_alu(dc, CC_OP_MOVE, |
|
1636 cpu_R[dc->op2], |
|
1637 cpu_R[dc->op2], t0, size); |
|
1638 tcg_temp_free(t0); |
|
1639 } |
|
1640 return 2; |
|
1641 } |
|
1642 |
|
1643 static unsigned int dec_scc_r(DisasContext *dc) |
|
1644 { |
|
1645 int cond = dc->op2; |
|
1646 |
|
1647 DIS(fprintf (logfile, "s%s $r%u\n", |
|
1648 cc_name(cond), dc->op1)); |
|
1649 |
|
1650 if (cond != CC_A) |
|
1651 { |
|
1652 int l1; |
|
1653 |
|
1654 gen_tst_cc (dc, cpu_R[dc->op1], cond); |
|
1655 l1 = gen_new_label(); |
|
1656 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->op1], 0, l1); |
|
1657 tcg_gen_movi_tl(cpu_R[dc->op1], 1); |
|
1658 gen_set_label(l1); |
|
1659 } |
|
1660 else |
|
1661 tcg_gen_movi_tl(cpu_R[dc->op1], 1); |
|
1662 |
|
1663 cris_cc_mask(dc, 0); |
|
1664 return 2; |
|
1665 } |
|
1666 |
|
1667 static inline void cris_alu_alloc_temps(DisasContext *dc, int size, TCGv *t) |
|
1668 { |
|
1669 if (size == 4) { |
|
1670 t[0] = cpu_R[dc->op2]; |
|
1671 t[1] = cpu_R[dc->op1]; |
|
1672 } else { |
|
1673 t[0] = tcg_temp_new(); |
|
1674 t[1] = tcg_temp_new(); |
|
1675 } |
|
1676 } |
|
1677 |
|
1678 static inline void cris_alu_free_temps(DisasContext *dc, int size, TCGv *t) |
|
1679 { |
|
1680 if (size != 4) { |
|
1681 tcg_temp_free(t[0]); |
|
1682 tcg_temp_free(t[1]); |
|
1683 } |
|
1684 } |
|
1685 |
|
1686 static unsigned int dec_and_r(DisasContext *dc) |
|
1687 { |
|
1688 TCGv t[2]; |
|
1689 int size = memsize_zz(dc); |
|
1690 |
|
1691 DIS(fprintf (logfile, "and.%c $r%u, $r%u\n", |
|
1692 memsize_char(size), dc->op1, dc->op2)); |
|
1693 |
|
1694 cris_cc_mask(dc, CC_MASK_NZ); |
|
1695 |
|
1696 cris_alu_alloc_temps(dc, size, t); |
|
1697 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1698 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size); |
|
1699 cris_alu_free_temps(dc, size, t); |
|
1700 return 2; |
|
1701 } |
|
1702 |
|
1703 static unsigned int dec_lz_r(DisasContext *dc) |
|
1704 { |
|
1705 TCGv t0; |
|
1706 DIS(fprintf (logfile, "lz $r%u, $r%u\n", |
|
1707 dc->op1, dc->op2)); |
|
1708 cris_cc_mask(dc, CC_MASK_NZ); |
|
1709 t0 = tcg_temp_new(); |
|
1710 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0); |
|
1711 cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4); |
|
1712 tcg_temp_free(t0); |
|
1713 return 2; |
|
1714 } |
|
1715 |
|
1716 static unsigned int dec_lsl_r(DisasContext *dc) |
|
1717 { |
|
1718 TCGv t[2]; |
|
1719 int size = memsize_zz(dc); |
|
1720 |
|
1721 DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n", |
|
1722 memsize_char(size), dc->op1, dc->op2)); |
|
1723 |
|
1724 cris_cc_mask(dc, CC_MASK_NZ); |
|
1725 cris_alu_alloc_temps(dc, size, t); |
|
1726 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1727 tcg_gen_andi_tl(t[1], t[1], 63); |
|
1728 cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size); |
|
1729 cris_alu_alloc_temps(dc, size, t); |
|
1730 return 2; |
|
1731 } |
|
1732 |
|
1733 static unsigned int dec_lsr_r(DisasContext *dc) |
|
1734 { |
|
1735 TCGv t[2]; |
|
1736 int size = memsize_zz(dc); |
|
1737 |
|
1738 DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n", |
|
1739 memsize_char(size), dc->op1, dc->op2)); |
|
1740 |
|
1741 cris_cc_mask(dc, CC_MASK_NZ); |
|
1742 cris_alu_alloc_temps(dc, size, t); |
|
1743 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1744 tcg_gen_andi_tl(t[1], t[1], 63); |
|
1745 cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size); |
|
1746 cris_alu_free_temps(dc, size, t); |
|
1747 return 2; |
|
1748 } |
|
1749 |
|
1750 static unsigned int dec_asr_r(DisasContext *dc) |
|
1751 { |
|
1752 TCGv t[2]; |
|
1753 int size = memsize_zz(dc); |
|
1754 |
|
1755 DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n", |
|
1756 memsize_char(size), dc->op1, dc->op2)); |
|
1757 |
|
1758 cris_cc_mask(dc, CC_MASK_NZ); |
|
1759 cris_alu_alloc_temps(dc, size, t); |
|
1760 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]); |
|
1761 tcg_gen_andi_tl(t[1], t[1], 63); |
|
1762 cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size); |
|
1763 cris_alu_free_temps(dc, size, t); |
|
1764 return 2; |
|
1765 } |
|
1766 |
|
1767 static unsigned int dec_muls_r(DisasContext *dc) |
|
1768 { |
|
1769 TCGv t[2]; |
|
1770 int size = memsize_zz(dc); |
|
1771 |
|
1772 DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n", |
|
1773 memsize_char(size), dc->op1, dc->op2)); |
|
1774 cris_cc_mask(dc, CC_MASK_NZV); |
|
1775 cris_alu_alloc_temps(dc, size, t); |
|
1776 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]); |
|
1777 |
|
1778 cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4); |
|
1779 cris_alu_free_temps(dc, size, t); |
|
1780 return 2; |
|
1781 } |
|
1782 |
|
1783 static unsigned int dec_mulu_r(DisasContext *dc) |
|
1784 { |
|
1785 TCGv t[2]; |
|
1786 int size = memsize_zz(dc); |
|
1787 |
|
1788 DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n", |
|
1789 memsize_char(size), dc->op1, dc->op2)); |
|
1790 cris_cc_mask(dc, CC_MASK_NZV); |
|
1791 cris_alu_alloc_temps(dc, size, t); |
|
1792 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1793 |
|
1794 cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4); |
|
1795 cris_alu_alloc_temps(dc, size, t); |
|
1796 return 2; |
|
1797 } |
|
1798 |
|
1799 |
|
1800 static unsigned int dec_dstep_r(DisasContext *dc) |
|
1801 { |
|
1802 DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2)); |
|
1803 cris_cc_mask(dc, CC_MASK_NZ); |
|
1804 cris_alu(dc, CC_OP_DSTEP, |
|
1805 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4); |
|
1806 return 2; |
|
1807 } |
|
1808 |
|
1809 static unsigned int dec_xor_r(DisasContext *dc) |
|
1810 { |
|
1811 TCGv t[2]; |
|
1812 int size = memsize_zz(dc); |
|
1813 DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n", |
|
1814 memsize_char(size), dc->op1, dc->op2)); |
|
1815 BUG_ON(size != 4); /* xor is dword. */ |
|
1816 cris_cc_mask(dc, CC_MASK_NZ); |
|
1817 cris_alu_alloc_temps(dc, size, t); |
|
1818 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1819 |
|
1820 cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4); |
|
1821 cris_alu_free_temps(dc, size, t); |
|
1822 return 2; |
|
1823 } |
|
1824 |
|
1825 static unsigned int dec_bound_r(DisasContext *dc) |
|
1826 { |
|
1827 TCGv l0; |
|
1828 int size = memsize_zz(dc); |
|
1829 DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n", |
|
1830 memsize_char(size), dc->op1, dc->op2)); |
|
1831 cris_cc_mask(dc, CC_MASK_NZ); |
|
1832 l0 = tcg_temp_local_new(); |
|
1833 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0); |
|
1834 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4); |
|
1835 tcg_temp_free(l0); |
|
1836 return 2; |
|
1837 } |
|
1838 |
|
1839 static unsigned int dec_cmp_r(DisasContext *dc) |
|
1840 { |
|
1841 TCGv t[2]; |
|
1842 int size = memsize_zz(dc); |
|
1843 DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n", |
|
1844 memsize_char(size), dc->op1, dc->op2)); |
|
1845 cris_cc_mask(dc, CC_MASK_NZVC); |
|
1846 cris_alu_alloc_temps(dc, size, t); |
|
1847 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1848 |
|
1849 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size); |
|
1850 cris_alu_free_temps(dc, size, t); |
|
1851 return 2; |
|
1852 } |
|
1853 |
|
1854 static unsigned int dec_abs_r(DisasContext *dc) |
|
1855 { |
|
1856 TCGv t0; |
|
1857 |
|
1858 DIS(fprintf (logfile, "abs $r%u, $r%u\n", |
|
1859 dc->op1, dc->op2)); |
|
1860 cris_cc_mask(dc, CC_MASK_NZ); |
|
1861 |
|
1862 t0 = tcg_temp_new(); |
|
1863 tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31); |
|
1864 tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0); |
|
1865 tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0); |
|
1866 tcg_temp_free(t0); |
|
1867 |
|
1868 cris_alu(dc, CC_OP_MOVE, |
|
1869 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4); |
|
1870 return 2; |
|
1871 } |
|
1872 |
|
1873 static unsigned int dec_add_r(DisasContext *dc) |
|
1874 { |
|
1875 TCGv t[2]; |
|
1876 int size = memsize_zz(dc); |
|
1877 DIS(fprintf (logfile, "add.%c $r%u, $r%u\n", |
|
1878 memsize_char(size), dc->op1, dc->op2)); |
|
1879 cris_cc_mask(dc, CC_MASK_NZVC); |
|
1880 cris_alu_alloc_temps(dc, size, t); |
|
1881 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1882 |
|
1883 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size); |
|
1884 cris_alu_free_temps(dc, size, t); |
|
1885 return 2; |
|
1886 } |
|
1887 |
|
1888 static unsigned int dec_addc_r(DisasContext *dc) |
|
1889 { |
|
1890 DIS(fprintf (logfile, "addc $r%u, $r%u\n", |
|
1891 dc->op1, dc->op2)); |
|
1892 cris_evaluate_flags(dc); |
|
1893 cris_cc_mask(dc, CC_MASK_NZVC); |
|
1894 cris_alu(dc, CC_OP_ADDC, |
|
1895 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4); |
|
1896 return 2; |
|
1897 } |
|
1898 |
|
1899 static unsigned int dec_mcp_r(DisasContext *dc) |
|
1900 { |
|
1901 DIS(fprintf (logfile, "mcp $p%u, $r%u\n", |
|
1902 dc->op2, dc->op1)); |
|
1903 cris_evaluate_flags(dc); |
|
1904 cris_cc_mask(dc, CC_MASK_RNZV); |
|
1905 cris_alu(dc, CC_OP_MCP, |
|
1906 cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4); |
|
1907 return 2; |
|
1908 } |
|
1909 |
|
1910 #if DISAS_CRIS |
|
1911 static char * swapmode_name(int mode, char *modename) { |
|
1912 int i = 0; |
|
1913 if (mode & 8) |
|
1914 modename[i++] = 'n'; |
|
1915 if (mode & 4) |
|
1916 modename[i++] = 'w'; |
|
1917 if (mode & 2) |
|
1918 modename[i++] = 'b'; |
|
1919 if (mode & 1) |
|
1920 modename[i++] = 'r'; |
|
1921 modename[i++] = 0; |
|
1922 return modename; |
|
1923 } |
|
1924 #endif |
|
1925 |
|
1926 static unsigned int dec_swap_r(DisasContext *dc) |
|
1927 { |
|
1928 TCGv t0; |
|
1929 #if DISAS_CRIS |
|
1930 char modename[4]; |
|
1931 #endif |
|
1932 DIS(fprintf (logfile, "swap%s $r%u\n", |
|
1933 swapmode_name(dc->op2, modename), dc->op1)); |
|
1934 |
|
1935 cris_cc_mask(dc, CC_MASK_NZ); |
|
1936 t0 = tcg_temp_new(); |
|
1937 t_gen_mov_TN_reg(t0, dc->op1); |
|
1938 if (dc->op2 & 8) |
|
1939 tcg_gen_not_tl(t0, t0); |
|
1940 if (dc->op2 & 4) |
|
1941 t_gen_swapw(t0, t0); |
|
1942 if (dc->op2 & 2) |
|
1943 t_gen_swapb(t0, t0); |
|
1944 if (dc->op2 & 1) |
|
1945 t_gen_swapr(t0, t0); |
|
1946 cris_alu(dc, CC_OP_MOVE, |
|
1947 cpu_R[dc->op1], cpu_R[dc->op1], t0, 4); |
|
1948 tcg_temp_free(t0); |
|
1949 return 2; |
|
1950 } |
|
1951 |
|
1952 static unsigned int dec_or_r(DisasContext *dc) |
|
1953 { |
|
1954 TCGv t[2]; |
|
1955 int size = memsize_zz(dc); |
|
1956 DIS(fprintf (logfile, "or.%c $r%u, $r%u\n", |
|
1957 memsize_char(size), dc->op1, dc->op2)); |
|
1958 cris_cc_mask(dc, CC_MASK_NZ); |
|
1959 cris_alu_alloc_temps(dc, size, t); |
|
1960 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
1961 cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size); |
|
1962 cris_alu_free_temps(dc, size, t); |
|
1963 return 2; |
|
1964 } |
|
1965 |
|
1966 static unsigned int dec_addi_r(DisasContext *dc) |
|
1967 { |
|
1968 TCGv t0; |
|
1969 DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n", |
|
1970 memsize_char(memsize_zz(dc)), dc->op2, dc->op1)); |
|
1971 cris_cc_mask(dc, 0); |
|
1972 t0 = tcg_temp_new(); |
|
1973 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize)); |
|
1974 tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0); |
|
1975 tcg_temp_free(t0); |
|
1976 return 2; |
|
1977 } |
|
1978 |
|
1979 static unsigned int dec_addi_acr(DisasContext *dc) |
|
1980 { |
|
1981 TCGv t0; |
|
1982 DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n", |
|
1983 memsize_char(memsize_zz(dc)), dc->op2, dc->op1)); |
|
1984 cris_cc_mask(dc, 0); |
|
1985 t0 = tcg_temp_new(); |
|
1986 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize)); |
|
1987 tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0); |
|
1988 tcg_temp_free(t0); |
|
1989 return 2; |
|
1990 } |
|
1991 |
|
1992 static unsigned int dec_neg_r(DisasContext *dc) |
|
1993 { |
|
1994 TCGv t[2]; |
|
1995 int size = memsize_zz(dc); |
|
1996 DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n", |
|
1997 memsize_char(size), dc->op1, dc->op2)); |
|
1998 cris_cc_mask(dc, CC_MASK_NZVC); |
|
1999 cris_alu_alloc_temps(dc, size, t); |
|
2000 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
2001 |
|
2002 cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size); |
|
2003 cris_alu_free_temps(dc, size, t); |
|
2004 return 2; |
|
2005 } |
|
2006 |
|
2007 static unsigned int dec_btst_r(DisasContext *dc) |
|
2008 { |
|
2009 TCGv l0; |
|
2010 DIS(fprintf (logfile, "btst $r%u, $r%u\n", |
|
2011 dc->op1, dc->op2)); |
|
2012 cris_cc_mask(dc, CC_MASK_NZ); |
|
2013 |
|
2014 l0 = tcg_temp_local_new(); |
|
2015 cris_alu(dc, CC_OP_BTST, l0, cpu_R[dc->op2], cpu_R[dc->op1], 4); |
|
2016 cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
|
2017 t_gen_mov_preg_TN(dc, PR_CCS, l0); |
|
2018 dc->flags_uptodate = 1; |
|
2019 tcg_temp_free(l0); |
|
2020 return 2; |
|
2021 } |
|
2022 |
|
2023 static unsigned int dec_sub_r(DisasContext *dc) |
|
2024 { |
|
2025 TCGv t[2]; |
|
2026 int size = memsize_zz(dc); |
|
2027 DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n", |
|
2028 memsize_char(size), dc->op1, dc->op2)); |
|
2029 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2030 cris_alu_alloc_temps(dc, size, t); |
|
2031 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]); |
|
2032 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size); |
|
2033 cris_alu_free_temps(dc, size, t); |
|
2034 return 2; |
|
2035 } |
|
2036 |
|
2037 /* Zero extension. From size to dword. */ |
|
2038 static unsigned int dec_movu_r(DisasContext *dc) |
|
2039 { |
|
2040 TCGv t0; |
|
2041 int size = memsize_z(dc); |
|
2042 DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n", |
|
2043 memsize_char(size), |
|
2044 dc->op1, dc->op2)); |
|
2045 |
|
2046 cris_cc_mask(dc, CC_MASK_NZ); |
|
2047 t0 = tcg_temp_new(); |
|
2048 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0); |
|
2049 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4); |
|
2050 tcg_temp_free(t0); |
|
2051 return 2; |
|
2052 } |
|
2053 |
|
2054 /* Sign extension. From size to dword. */ |
|
2055 static unsigned int dec_movs_r(DisasContext *dc) |
|
2056 { |
|
2057 TCGv t0; |
|
2058 int size = memsize_z(dc); |
|
2059 DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n", |
|
2060 memsize_char(size), |
|
2061 dc->op1, dc->op2)); |
|
2062 |
|
2063 cris_cc_mask(dc, CC_MASK_NZ); |
|
2064 t0 = tcg_temp_new(); |
|
2065 /* Size can only be qi or hi. */ |
|
2066 t_gen_sext(t0, cpu_R[dc->op1], size); |
|
2067 cris_alu(dc, CC_OP_MOVE, |
|
2068 cpu_R[dc->op2], cpu_R[dc->op1], t0, 4); |
|
2069 tcg_temp_free(t0); |
|
2070 return 2; |
|
2071 } |
|
2072 |
|
2073 /* zero extension. From size to dword. */ |
|
2074 static unsigned int dec_addu_r(DisasContext *dc) |
|
2075 { |
|
2076 TCGv t0; |
|
2077 int size = memsize_z(dc); |
|
2078 DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n", |
|
2079 memsize_char(size), |
|
2080 dc->op1, dc->op2)); |
|
2081 |
|
2082 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2083 t0 = tcg_temp_new(); |
|
2084 /* Size can only be qi or hi. */ |
|
2085 t_gen_zext(t0, cpu_R[dc->op1], size); |
|
2086 cris_alu(dc, CC_OP_ADD, |
|
2087 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4); |
|
2088 tcg_temp_free(t0); |
|
2089 return 2; |
|
2090 } |
|
2091 |
|
2092 /* Sign extension. From size to dword. */ |
|
2093 static unsigned int dec_adds_r(DisasContext *dc) |
|
2094 { |
|
2095 TCGv t0; |
|
2096 int size = memsize_z(dc); |
|
2097 DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n", |
|
2098 memsize_char(size), |
|
2099 dc->op1, dc->op2)); |
|
2100 |
|
2101 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2102 t0 = tcg_temp_new(); |
|
2103 /* Size can only be qi or hi. */ |
|
2104 t_gen_sext(t0, cpu_R[dc->op1], size); |
|
2105 cris_alu(dc, CC_OP_ADD, |
|
2106 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4); |
|
2107 tcg_temp_free(t0); |
|
2108 return 2; |
|
2109 } |
|
2110 |
|
2111 /* Zero extension. From size to dword. */ |
|
2112 static unsigned int dec_subu_r(DisasContext *dc) |
|
2113 { |
|
2114 TCGv t0; |
|
2115 int size = memsize_z(dc); |
|
2116 DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n", |
|
2117 memsize_char(size), |
|
2118 dc->op1, dc->op2)); |
|
2119 |
|
2120 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2121 t0 = tcg_temp_new(); |
|
2122 /* Size can only be qi or hi. */ |
|
2123 t_gen_zext(t0, cpu_R[dc->op1], size); |
|
2124 cris_alu(dc, CC_OP_SUB, |
|
2125 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4); |
|
2126 tcg_temp_free(t0); |
|
2127 return 2; |
|
2128 } |
|
2129 |
|
2130 /* Sign extension. From size to dword. */ |
|
2131 static unsigned int dec_subs_r(DisasContext *dc) |
|
2132 { |
|
2133 TCGv t0; |
|
2134 int size = memsize_z(dc); |
|
2135 DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n", |
|
2136 memsize_char(size), |
|
2137 dc->op1, dc->op2)); |
|
2138 |
|
2139 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2140 t0 = tcg_temp_new(); |
|
2141 /* Size can only be qi or hi. */ |
|
2142 t_gen_sext(t0, cpu_R[dc->op1], size); |
|
2143 cris_alu(dc, CC_OP_SUB, |
|
2144 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4); |
|
2145 tcg_temp_free(t0); |
|
2146 return 2; |
|
2147 } |
|
2148 |
|
2149 static unsigned int dec_setclrf(DisasContext *dc) |
|
2150 { |
|
2151 uint32_t flags; |
|
2152 int set = (~dc->opcode >> 2) & 1; |
|
2153 |
|
2154 |
|
2155 flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4) |
|
2156 | EXTRACT_FIELD(dc->ir, 0, 3); |
|
2157 if (set && flags == 0) { |
|
2158 DIS(fprintf (logfile, "nop\n")); |
|
2159 return 2; |
|
2160 } else if (!set && (flags & 0x20)) { |
|
2161 DIS(fprintf (logfile, "di\n")); |
|
2162 } |
|
2163 else { |
|
2164 DIS(fprintf (logfile, "%sf %x\n", |
|
2165 set ? "set" : "clr", |
|
2166 flags)); |
|
2167 } |
|
2168 |
|
2169 /* User space is not allowed to touch these. Silently ignore. */ |
|
2170 if (dc->tb_flags & U_FLAG) { |
|
2171 flags &= ~(S_FLAG | I_FLAG | U_FLAG); |
|
2172 } |
|
2173 |
|
2174 if (flags & X_FLAG) { |
|
2175 dc->flagx_known = 1; |
|
2176 if (set) |
|
2177 dc->flags_x = X_FLAG; |
|
2178 else |
|
2179 dc->flags_x = 0; |
|
2180 } |
|
2181 |
|
2182 /* Break the TB if the P flag changes. */ |
|
2183 if (flags & P_FLAG) { |
|
2184 if ((set && !(dc->tb_flags & P_FLAG)) |
|
2185 || (!set && (dc->tb_flags & P_FLAG))) { |
|
2186 tcg_gen_movi_tl(env_pc, dc->pc + 2); |
|
2187 dc->is_jmp = DISAS_UPDATE; |
|
2188 dc->cpustate_changed = 1; |
|
2189 } |
|
2190 } |
|
2191 if (flags & S_FLAG) { |
|
2192 dc->cpustate_changed = 1; |
|
2193 } |
|
2194 |
|
2195 |
|
2196 /* Simply decode the flags. */ |
|
2197 cris_evaluate_flags (dc); |
|
2198 cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
|
2199 cris_update_cc_x(dc); |
|
2200 tcg_gen_movi_tl(cc_op, dc->cc_op); |
|
2201 |
|
2202 if (set) { |
|
2203 if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) { |
|
2204 /* Enter user mode. */ |
|
2205 t_gen_mov_env_TN(ksp, cpu_R[R_SP]); |
|
2206 tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]); |
|
2207 dc->cpustate_changed = 1; |
|
2208 } |
|
2209 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags); |
|
2210 } |
|
2211 else |
|
2212 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags); |
|
2213 |
|
2214 dc->flags_uptodate = 1; |
|
2215 dc->clear_x = 0; |
|
2216 return 2; |
|
2217 } |
|
2218 |
|
2219 static unsigned int dec_move_rs(DisasContext *dc) |
|
2220 { |
|
2221 DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2)); |
|
2222 cris_cc_mask(dc, 0); |
|
2223 gen_helper_movl_sreg_reg(tcg_const_tl(dc->op2), tcg_const_tl(dc->op1)); |
|
2224 return 2; |
|
2225 } |
|
2226 static unsigned int dec_move_sr(DisasContext *dc) |
|
2227 { |
|
2228 DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op2, dc->op1)); |
|
2229 cris_cc_mask(dc, 0); |
|
2230 gen_helper_movl_reg_sreg(tcg_const_tl(dc->op1), tcg_const_tl(dc->op2)); |
|
2231 return 2; |
|
2232 } |
|
2233 |
|
2234 static unsigned int dec_move_rp(DisasContext *dc) |
|
2235 { |
|
2236 TCGv t[2]; |
|
2237 DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2)); |
|
2238 cris_cc_mask(dc, 0); |
|
2239 |
|
2240 t[0] = tcg_temp_new(); |
|
2241 if (dc->op2 == PR_CCS) { |
|
2242 cris_evaluate_flags(dc); |
|
2243 t_gen_mov_TN_reg(t[0], dc->op1); |
|
2244 if (dc->tb_flags & U_FLAG) { |
|
2245 t[1] = tcg_temp_new(); |
|
2246 /* User space is not allowed to touch all flags. */ |
|
2247 tcg_gen_andi_tl(t[0], t[0], 0x39f); |
|
2248 tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f); |
|
2249 tcg_gen_or_tl(t[0], t[1], t[0]); |
|
2250 tcg_temp_free(t[1]); |
|
2251 } |
|
2252 } |
|
2253 else |
|
2254 t_gen_mov_TN_reg(t[0], dc->op1); |
|
2255 |
|
2256 t_gen_mov_preg_TN(dc, dc->op2, t[0]); |
|
2257 if (dc->op2 == PR_CCS) { |
|
2258 cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
|
2259 dc->flags_uptodate = 1; |
|
2260 } |
|
2261 tcg_temp_free(t[0]); |
|
2262 return 2; |
|
2263 } |
|
2264 static unsigned int dec_move_pr(DisasContext *dc) |
|
2265 { |
|
2266 TCGv t0; |
|
2267 DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2)); |
|
2268 cris_cc_mask(dc, 0); |
|
2269 |
|
2270 if (dc->op2 == PR_CCS) |
|
2271 cris_evaluate_flags(dc); |
|
2272 |
|
2273 t0 = tcg_temp_new(); |
|
2274 t_gen_mov_TN_preg(t0, dc->op2); |
|
2275 cris_alu(dc, CC_OP_MOVE, |
|
2276 cpu_R[dc->op1], cpu_R[dc->op1], t0, preg_sizes[dc->op2]); |
|
2277 tcg_temp_free(t0); |
|
2278 return 2; |
|
2279 } |
|
2280 |
|
2281 static unsigned int dec_move_mr(DisasContext *dc) |
|
2282 { |
|
2283 int memsize = memsize_zz(dc); |
|
2284 int insn_len; |
|
2285 DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n", |
|
2286 memsize_char(memsize), |
|
2287 dc->op1, dc->postinc ? "+]" : "]", |
|
2288 dc->op2)); |
|
2289 |
|
2290 if (memsize == 4) { |
|
2291 insn_len = dec_prep_move_m(dc, 0, 4, cpu_R[dc->op2]); |
|
2292 cris_cc_mask(dc, CC_MASK_NZ); |
|
2293 cris_update_cc_op(dc, CC_OP_MOVE, 4); |
|
2294 cris_update_cc_x(dc); |
|
2295 cris_update_result(dc, cpu_R[dc->op2]); |
|
2296 } |
|
2297 else { |
|
2298 TCGv t0; |
|
2299 |
|
2300 t0 = tcg_temp_new(); |
|
2301 insn_len = dec_prep_move_m(dc, 0, memsize, t0); |
|
2302 cris_cc_mask(dc, CC_MASK_NZ); |
|
2303 cris_alu(dc, CC_OP_MOVE, |
|
2304 cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize); |
|
2305 tcg_temp_free(t0); |
|
2306 } |
|
2307 do_postinc(dc, memsize); |
|
2308 return insn_len; |
|
2309 } |
|
2310 |
|
2311 static inline void cris_alu_m_alloc_temps(TCGv *t) |
|
2312 { |
|
2313 t[0] = tcg_temp_new(); |
|
2314 t[1] = tcg_temp_new(); |
|
2315 } |
|
2316 |
|
2317 static inline void cris_alu_m_free_temps(TCGv *t) |
|
2318 { |
|
2319 tcg_temp_free(t[0]); |
|
2320 tcg_temp_free(t[1]); |
|
2321 } |
|
2322 |
|
2323 static unsigned int dec_movs_m(DisasContext *dc) |
|
2324 { |
|
2325 TCGv t[2]; |
|
2326 int memsize = memsize_z(dc); |
|
2327 int insn_len; |
|
2328 DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n", |
|
2329 memsize_char(memsize), |
|
2330 dc->op1, dc->postinc ? "+]" : "]", |
|
2331 dc->op2)); |
|
2332 |
|
2333 cris_alu_m_alloc_temps(t); |
|
2334 /* sign extend. */ |
|
2335 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); |
|
2336 cris_cc_mask(dc, CC_MASK_NZ); |
|
2337 cris_alu(dc, CC_OP_MOVE, |
|
2338 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
|
2339 do_postinc(dc, memsize); |
|
2340 cris_alu_m_free_temps(t); |
|
2341 return insn_len; |
|
2342 } |
|
2343 |
|
2344 static unsigned int dec_addu_m(DisasContext *dc) |
|
2345 { |
|
2346 TCGv t[2]; |
|
2347 int memsize = memsize_z(dc); |
|
2348 int insn_len; |
|
2349 DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n", |
|
2350 memsize_char(memsize), |
|
2351 dc->op1, dc->postinc ? "+]" : "]", |
|
2352 dc->op2)); |
|
2353 |
|
2354 cris_alu_m_alloc_temps(t); |
|
2355 /* sign extend. */ |
|
2356 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2357 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2358 cris_alu(dc, CC_OP_ADD, |
|
2359 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
|
2360 do_postinc(dc, memsize); |
|
2361 cris_alu_m_free_temps(t); |
|
2362 return insn_len; |
|
2363 } |
|
2364 |
|
2365 static unsigned int dec_adds_m(DisasContext *dc) |
|
2366 { |
|
2367 TCGv t[2]; |
|
2368 int memsize = memsize_z(dc); |
|
2369 int insn_len; |
|
2370 DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n", |
|
2371 memsize_char(memsize), |
|
2372 dc->op1, dc->postinc ? "+]" : "]", |
|
2373 dc->op2)); |
|
2374 |
|
2375 cris_alu_m_alloc_temps(t); |
|
2376 /* sign extend. */ |
|
2377 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); |
|
2378 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2379 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
|
2380 do_postinc(dc, memsize); |
|
2381 cris_alu_m_free_temps(t); |
|
2382 return insn_len; |
|
2383 } |
|
2384 |
|
2385 static unsigned int dec_subu_m(DisasContext *dc) |
|
2386 { |
|
2387 TCGv t[2]; |
|
2388 int memsize = memsize_z(dc); |
|
2389 int insn_len; |
|
2390 DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n", |
|
2391 memsize_char(memsize), |
|
2392 dc->op1, dc->postinc ? "+]" : "]", |
|
2393 dc->op2)); |
|
2394 |
|
2395 cris_alu_m_alloc_temps(t); |
|
2396 /* sign extend. */ |
|
2397 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2398 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2399 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
|
2400 do_postinc(dc, memsize); |
|
2401 cris_alu_m_free_temps(t); |
|
2402 return insn_len; |
|
2403 } |
|
2404 |
|
2405 static unsigned int dec_subs_m(DisasContext *dc) |
|
2406 { |
|
2407 TCGv t[2]; |
|
2408 int memsize = memsize_z(dc); |
|
2409 int insn_len; |
|
2410 DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n", |
|
2411 memsize_char(memsize), |
|
2412 dc->op1, dc->postinc ? "+]" : "]", |
|
2413 dc->op2)); |
|
2414 |
|
2415 cris_alu_m_alloc_temps(t); |
|
2416 /* sign extend. */ |
|
2417 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); |
|
2418 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2419 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
|
2420 do_postinc(dc, memsize); |
|
2421 cris_alu_m_free_temps(t); |
|
2422 return insn_len; |
|
2423 } |
|
2424 |
|
2425 static unsigned int dec_movu_m(DisasContext *dc) |
|
2426 { |
|
2427 TCGv t[2]; |
|
2428 int memsize = memsize_z(dc); |
|
2429 int insn_len; |
|
2430 |
|
2431 DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n", |
|
2432 memsize_char(memsize), |
|
2433 dc->op1, dc->postinc ? "+]" : "]", |
|
2434 dc->op2)); |
|
2435 |
|
2436 cris_alu_m_alloc_temps(t); |
|
2437 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2438 cris_cc_mask(dc, CC_MASK_NZ); |
|
2439 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
|
2440 do_postinc(dc, memsize); |
|
2441 cris_alu_m_free_temps(t); |
|
2442 return insn_len; |
|
2443 } |
|
2444 |
|
2445 static unsigned int dec_cmpu_m(DisasContext *dc) |
|
2446 { |
|
2447 TCGv t[2]; |
|
2448 int memsize = memsize_z(dc); |
|
2449 int insn_len; |
|
2450 DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n", |
|
2451 memsize_char(memsize), |
|
2452 dc->op1, dc->postinc ? "+]" : "]", |
|
2453 dc->op2)); |
|
2454 |
|
2455 cris_alu_m_alloc_temps(t); |
|
2456 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2457 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2458 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4); |
|
2459 do_postinc(dc, memsize); |
|
2460 cris_alu_m_free_temps(t); |
|
2461 return insn_len; |
|
2462 } |
|
2463 |
|
2464 static unsigned int dec_cmps_m(DisasContext *dc) |
|
2465 { |
|
2466 TCGv t[2]; |
|
2467 int memsize = memsize_z(dc); |
|
2468 int insn_len; |
|
2469 DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n", |
|
2470 memsize_char(memsize), |
|
2471 dc->op1, dc->postinc ? "+]" : "]", |
|
2472 dc->op2)); |
|
2473 |
|
2474 cris_alu_m_alloc_temps(t); |
|
2475 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); |
|
2476 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2477 cris_alu(dc, CC_OP_CMP, |
|
2478 cpu_R[dc->op2], cpu_R[dc->op2], t[1], |
|
2479 memsize_zz(dc)); |
|
2480 do_postinc(dc, memsize); |
|
2481 cris_alu_m_free_temps(t); |
|
2482 return insn_len; |
|
2483 } |
|
2484 |
|
2485 static unsigned int dec_cmp_m(DisasContext *dc) |
|
2486 { |
|
2487 TCGv t[2]; |
|
2488 int memsize = memsize_zz(dc); |
|
2489 int insn_len; |
|
2490 DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n", |
|
2491 memsize_char(memsize), |
|
2492 dc->op1, dc->postinc ? "+]" : "]", |
|
2493 dc->op2)); |
|
2494 |
|
2495 cris_alu_m_alloc_temps(t); |
|
2496 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2497 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2498 cris_alu(dc, CC_OP_CMP, |
|
2499 cpu_R[dc->op2], cpu_R[dc->op2], t[1], |
|
2500 memsize_zz(dc)); |
|
2501 do_postinc(dc, memsize); |
|
2502 cris_alu_m_free_temps(t); |
|
2503 return insn_len; |
|
2504 } |
|
2505 |
|
2506 static unsigned int dec_test_m(DisasContext *dc) |
|
2507 { |
|
2508 TCGv t[2]; |
|
2509 int memsize = memsize_zz(dc); |
|
2510 int insn_len; |
|
2511 DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n", |
|
2512 memsize_char(memsize), |
|
2513 dc->op1, dc->postinc ? "+]" : "]", |
|
2514 dc->op2)); |
|
2515 |
|
2516 cris_evaluate_flags(dc); |
|
2517 |
|
2518 cris_alu_m_alloc_temps(t); |
|
2519 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2520 cris_cc_mask(dc, CC_MASK_NZ); |
|
2521 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3); |
|
2522 |
|
2523 cris_alu(dc, CC_OP_CMP, |
|
2524 cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc)); |
|
2525 do_postinc(dc, memsize); |
|
2526 cris_alu_m_free_temps(t); |
|
2527 return insn_len; |
|
2528 } |
|
2529 |
|
2530 static unsigned int dec_and_m(DisasContext *dc) |
|
2531 { |
|
2532 TCGv t[2]; |
|
2533 int memsize = memsize_zz(dc); |
|
2534 int insn_len; |
|
2535 DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n", |
|
2536 memsize_char(memsize), |
|
2537 dc->op1, dc->postinc ? "+]" : "]", |
|
2538 dc->op2)); |
|
2539 |
|
2540 cris_alu_m_alloc_temps(t); |
|
2541 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2542 cris_cc_mask(dc, CC_MASK_NZ); |
|
2543 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); |
|
2544 do_postinc(dc, memsize); |
|
2545 cris_alu_m_free_temps(t); |
|
2546 return insn_len; |
|
2547 } |
|
2548 |
|
2549 static unsigned int dec_add_m(DisasContext *dc) |
|
2550 { |
|
2551 TCGv t[2]; |
|
2552 int memsize = memsize_zz(dc); |
|
2553 int insn_len; |
|
2554 DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n", |
|
2555 memsize_char(memsize), |
|
2556 dc->op1, dc->postinc ? "+]" : "]", |
|
2557 dc->op2)); |
|
2558 |
|
2559 cris_alu_m_alloc_temps(t); |
|
2560 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2561 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2562 cris_alu(dc, CC_OP_ADD, |
|
2563 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); |
|
2564 do_postinc(dc, memsize); |
|
2565 cris_alu_m_free_temps(t); |
|
2566 return insn_len; |
|
2567 } |
|
2568 |
|
2569 static unsigned int dec_addo_m(DisasContext *dc) |
|
2570 { |
|
2571 TCGv t[2]; |
|
2572 int memsize = memsize_zz(dc); |
|
2573 int insn_len; |
|
2574 DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n", |
|
2575 memsize_char(memsize), |
|
2576 dc->op1, dc->postinc ? "+]" : "]", |
|
2577 dc->op2)); |
|
2578 |
|
2579 cris_alu_m_alloc_temps(t); |
|
2580 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]); |
|
2581 cris_cc_mask(dc, 0); |
|
2582 cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4); |
|
2583 do_postinc(dc, memsize); |
|
2584 cris_alu_m_free_temps(t); |
|
2585 return insn_len; |
|
2586 } |
|
2587 |
|
2588 static unsigned int dec_bound_m(DisasContext *dc) |
|
2589 { |
|
2590 TCGv l[2]; |
|
2591 int memsize = memsize_zz(dc); |
|
2592 int insn_len; |
|
2593 DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n", |
|
2594 memsize_char(memsize), |
|
2595 dc->op1, dc->postinc ? "+]" : "]", |
|
2596 dc->op2)); |
|
2597 |
|
2598 l[0] = tcg_temp_local_new(); |
|
2599 l[1] = tcg_temp_local_new(); |
|
2600 insn_len = dec_prep_alu_m(dc, 0, memsize, l[0], l[1]); |
|
2601 cris_cc_mask(dc, CC_MASK_NZ); |
|
2602 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4); |
|
2603 do_postinc(dc, memsize); |
|
2604 tcg_temp_free(l[0]); |
|
2605 tcg_temp_free(l[1]); |
|
2606 return insn_len; |
|
2607 } |
|
2608 |
|
2609 static unsigned int dec_addc_mr(DisasContext *dc) |
|
2610 { |
|
2611 TCGv t[2]; |
|
2612 int insn_len = 2; |
|
2613 DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n", |
|
2614 dc->op1, dc->postinc ? "+]" : "]", |
|
2615 dc->op2)); |
|
2616 |
|
2617 cris_evaluate_flags(dc); |
|
2618 cris_alu_m_alloc_temps(t); |
|
2619 insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]); |
|
2620 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2621 cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4); |
|
2622 do_postinc(dc, 4); |
|
2623 cris_alu_m_free_temps(t); |
|
2624 return insn_len; |
|
2625 } |
|
2626 |
|
2627 static unsigned int dec_sub_m(DisasContext *dc) |
|
2628 { |
|
2629 TCGv t[2]; |
|
2630 int memsize = memsize_zz(dc); |
|
2631 int insn_len; |
|
2632 DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n", |
|
2633 memsize_char(memsize), |
|
2634 dc->op1, dc->postinc ? "+]" : "]", |
|
2635 dc->op2, dc->ir, dc->zzsize)); |
|
2636 |
|
2637 cris_alu_m_alloc_temps(t); |
|
2638 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2639 cris_cc_mask(dc, CC_MASK_NZVC); |
|
2640 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize); |
|
2641 do_postinc(dc, memsize); |
|
2642 cris_alu_m_free_temps(t); |
|
2643 return insn_len; |
|
2644 } |
|
2645 |
|
2646 static unsigned int dec_or_m(DisasContext *dc) |
|
2647 { |
|
2648 TCGv t[2]; |
|
2649 int memsize = memsize_zz(dc); |
|
2650 int insn_len; |
|
2651 DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n", |
|
2652 memsize_char(memsize), |
|
2653 dc->op1, dc->postinc ? "+]" : "]", |
|
2654 dc->op2, dc->pc)); |
|
2655 |
|
2656 cris_alu_m_alloc_temps(t); |
|
2657 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2658 cris_cc_mask(dc, CC_MASK_NZ); |
|
2659 cris_alu(dc, CC_OP_OR, |
|
2660 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc)); |
|
2661 do_postinc(dc, memsize); |
|
2662 cris_alu_m_free_temps(t); |
|
2663 return insn_len; |
|
2664 } |
|
2665 |
|
2666 static unsigned int dec_move_mp(DisasContext *dc) |
|
2667 { |
|
2668 TCGv t[2]; |
|
2669 int memsize = memsize_zz(dc); |
|
2670 int insn_len = 2; |
|
2671 |
|
2672 DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n", |
|
2673 memsize_char(memsize), |
|
2674 dc->op1, |
|
2675 dc->postinc ? "+]" : "]", |
|
2676 dc->op2)); |
|
2677 |
|
2678 cris_alu_m_alloc_temps(t); |
|
2679 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]); |
|
2680 cris_cc_mask(dc, 0); |
|
2681 if (dc->op2 == PR_CCS) { |
|
2682 cris_evaluate_flags(dc); |
|
2683 if (dc->tb_flags & U_FLAG) { |
|
2684 /* User space is not allowed to touch all flags. */ |
|
2685 tcg_gen_andi_tl(t[1], t[1], 0x39f); |
|
2686 tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f); |
|
2687 tcg_gen_or_tl(t[1], t[0], t[1]); |
|
2688 } |
|
2689 } |
|
2690 |
|
2691 t_gen_mov_preg_TN(dc, dc->op2, t[1]); |
|
2692 |
|
2693 do_postinc(dc, memsize); |
|
2694 cris_alu_m_free_temps(t); |
|
2695 return insn_len; |
|
2696 } |
|
2697 |
|
2698 static unsigned int dec_move_pm(DisasContext *dc) |
|
2699 { |
|
2700 TCGv t0; |
|
2701 int memsize; |
|
2702 |
|
2703 memsize = preg_sizes[dc->op2]; |
|
2704 |
|
2705 DIS(fprintf (logfile, "move.%c $p%u, [$r%u%s\n", |
|
2706 memsize_char(memsize), |
|
2707 dc->op2, dc->op1, dc->postinc ? "+]" : "]")); |
|
2708 |
|
2709 /* prepare store. Address in T0, value in T1. */ |
|
2710 if (dc->op2 == PR_CCS) |
|
2711 cris_evaluate_flags(dc); |
|
2712 t0 = tcg_temp_new(); |
|
2713 t_gen_mov_TN_preg(t0, dc->op2); |
|
2714 cris_flush_cc_state(dc); |
|
2715 gen_store(dc, cpu_R[dc->op1], t0, memsize); |
|
2716 tcg_temp_free(t0); |
|
2717 |
|
2718 cris_cc_mask(dc, 0); |
|
2719 if (dc->postinc) |
|
2720 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize); |
|
2721 return 2; |
|
2722 } |
|
2723 |
|
2724 static unsigned int dec_movem_mr(DisasContext *dc) |
|
2725 { |
|
2726 TCGv_i64 tmp[16]; |
|
2727 TCGv tmp32; |
|
2728 TCGv addr; |
|
2729 int i; |
|
2730 int nr = dc->op2 + 1; |
|
2731 |
|
2732 DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1, |
|
2733 dc->postinc ? "+]" : "]", dc->op2)); |
|
2734 |
|
2735 addr = tcg_temp_new(); |
|
2736 /* There are probably better ways of doing this. */ |
|
2737 cris_flush_cc_state(dc); |
|
2738 for (i = 0; i < (nr >> 1); i++) { |
|
2739 tmp[i] = tcg_temp_new_i64(); |
|
2740 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8); |
|
2741 gen_load64(dc, tmp[i], addr); |
|
2742 } |
|
2743 if (nr & 1) { |
|
2744 tmp32 = tcg_temp_new_i32(); |
|
2745 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8); |
|
2746 gen_load(dc, tmp32, addr, 4, 0); |
|
2747 } |
|
2748 tcg_temp_free(addr); |
|
2749 |
|
2750 for (i = 0; i < (nr >> 1); i++) { |
|
2751 tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]); |
|
2752 tcg_gen_shri_i64(tmp[i], tmp[i], 32); |
|
2753 tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]); |
|
2754 tcg_temp_free_i64(tmp[i]); |
|
2755 } |
|
2756 if (nr & 1) { |
|
2757 tcg_gen_mov_tl(cpu_R[dc->op2], tmp32); |
|
2758 tcg_temp_free(tmp32); |
|
2759 } |
|
2760 |
|
2761 /* writeback the updated pointer value. */ |
|
2762 if (dc->postinc) |
|
2763 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4); |
|
2764 |
|
2765 /* gen_load might want to evaluate the previous insns flags. */ |
|
2766 cris_cc_mask(dc, 0); |
|
2767 return 2; |
|
2768 } |
|
2769 |
|
2770 static unsigned int dec_movem_rm(DisasContext *dc) |
|
2771 { |
|
2772 TCGv tmp; |
|
2773 TCGv addr; |
|
2774 int i; |
|
2775 |
|
2776 DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1, |
|
2777 dc->postinc ? "+]" : "]")); |
|
2778 |
|
2779 cris_flush_cc_state(dc); |
|
2780 |
|
2781 tmp = tcg_temp_new(); |
|
2782 addr = tcg_temp_new(); |
|
2783 tcg_gen_movi_tl(tmp, 4); |
|
2784 tcg_gen_mov_tl(addr, cpu_R[dc->op1]); |
|
2785 for (i = 0; i <= dc->op2; i++) { |
|
2786 /* Displace addr. */ |
|
2787 /* Perform the store. */ |
|
2788 gen_store(dc, addr, cpu_R[i], 4); |
|
2789 tcg_gen_add_tl(addr, addr, tmp); |
|
2790 } |
|
2791 if (dc->postinc) |
|
2792 tcg_gen_mov_tl(cpu_R[dc->op1], addr); |
|
2793 cris_cc_mask(dc, 0); |
|
2794 tcg_temp_free(tmp); |
|
2795 tcg_temp_free(addr); |
|
2796 return 2; |
|
2797 } |
|
2798 |
|
2799 static unsigned int dec_move_rm(DisasContext *dc) |
|
2800 { |
|
2801 int memsize; |
|
2802 |
|
2803 memsize = memsize_zz(dc); |
|
2804 |
|
2805 DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n", |
|
2806 memsize, dc->op2, dc->op1)); |
|
2807 |
|
2808 /* prepare store. */ |
|
2809 cris_flush_cc_state(dc); |
|
2810 gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize); |
|
2811 |
|
2812 if (dc->postinc) |
|
2813 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize); |
|
2814 cris_cc_mask(dc, 0); |
|
2815 return 2; |
|
2816 } |
|
2817 |
|
2818 static unsigned int dec_lapcq(DisasContext *dc) |
|
2819 { |
|
2820 DIS(fprintf (logfile, "lapcq %x, $r%u\n", |
|
2821 dc->pc + dc->op1*2, dc->op2)); |
|
2822 cris_cc_mask(dc, 0); |
|
2823 tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2); |
|
2824 return 2; |
|
2825 } |
|
2826 |
|
2827 static unsigned int dec_lapc_im(DisasContext *dc) |
|
2828 { |
|
2829 unsigned int rd; |
|
2830 int32_t imm; |
|
2831 int32_t pc; |
|
2832 |
|
2833 rd = dc->op2; |
|
2834 |
|
2835 cris_cc_mask(dc, 0); |
|
2836 imm = ldl_code(dc->pc + 2); |
|
2837 DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2)); |
|
2838 |
|
2839 pc = dc->pc; |
|
2840 pc += imm; |
|
2841 t_gen_mov_reg_TN(rd, tcg_const_tl(pc)); |
|
2842 return 6; |
|
2843 } |
|
2844 |
|
2845 /* Jump to special reg. */ |
|
2846 static unsigned int dec_jump_p(DisasContext *dc) |
|
2847 { |
|
2848 DIS(fprintf (logfile, "jump $p%u\n", dc->op2)); |
|
2849 |
|
2850 if (dc->op2 == PR_CCS) |
|
2851 cris_evaluate_flags(dc); |
|
2852 t_gen_mov_TN_preg(env_btarget, dc->op2); |
|
2853 /* rete will often have low bit set to indicate delayslot. */ |
|
2854 tcg_gen_andi_tl(env_btarget, env_btarget, ~1); |
|
2855 cris_cc_mask(dc, 0); |
|
2856 cris_prepare_jmp(dc, JMP_INDIRECT); |
|
2857 return 2; |
|
2858 } |
|
2859 |
|
2860 /* Jump and save. */ |
|
2861 static unsigned int dec_jas_r(DisasContext *dc) |
|
2862 { |
|
2863 DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2)); |
|
2864 cris_cc_mask(dc, 0); |
|
2865 /* Store the return address in Pd. */ |
|
2866 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]); |
|
2867 if (dc->op2 > 15) |
|
2868 abort(); |
|
2869 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4)); |
|
2870 |
|
2871 cris_prepare_jmp(dc, JMP_INDIRECT); |
|
2872 return 2; |
|
2873 } |
|
2874 |
|
2875 static unsigned int dec_jas_im(DisasContext *dc) |
|
2876 { |
|
2877 uint32_t imm; |
|
2878 |
|
2879 imm = ldl_code(dc->pc + 2); |
|
2880 |
|
2881 DIS(fprintf (logfile, "jas 0x%x\n", imm)); |
|
2882 cris_cc_mask(dc, 0); |
|
2883 /* Store the return address in Pd. */ |
|
2884 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8)); |
|
2885 |
|
2886 dc->jmp_pc = imm; |
|
2887 cris_prepare_jmp(dc, JMP_DIRECT); |
|
2888 return 6; |
|
2889 } |
|
2890 |
|
2891 static unsigned int dec_jasc_im(DisasContext *dc) |
|
2892 { |
|
2893 uint32_t imm; |
|
2894 |
|
2895 imm = ldl_code(dc->pc + 2); |
|
2896 |
|
2897 DIS(fprintf (logfile, "jasc 0x%x\n", imm)); |
|
2898 cris_cc_mask(dc, 0); |
|
2899 /* Store the return address in Pd. */ |
|
2900 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4)); |
|
2901 |
|
2902 dc->jmp_pc = imm; |
|
2903 cris_prepare_jmp(dc, JMP_DIRECT); |
|
2904 return 6; |
|
2905 } |
|
2906 |
|
2907 static unsigned int dec_jasc_r(DisasContext *dc) |
|
2908 { |
|
2909 DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2)); |
|
2910 cris_cc_mask(dc, 0); |
|
2911 /* Store the return address in Pd. */ |
|
2912 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]); |
|
2913 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4)); |
|
2914 cris_prepare_jmp(dc, JMP_INDIRECT); |
|
2915 return 2; |
|
2916 } |
|
2917 |
|
2918 static unsigned int dec_bcc_im(DisasContext *dc) |
|
2919 { |
|
2920 int32_t offset; |
|
2921 uint32_t cond = dc->op2; |
|
2922 |
|
2923 offset = ldsw_code(dc->pc + 2); |
|
2924 |
|
2925 DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n", |
|
2926 cc_name(cond), offset, |
|
2927 dc->pc, dc->pc + offset)); |
|
2928 |
|
2929 cris_cc_mask(dc, 0); |
|
2930 /* op2 holds the condition-code. */ |
|
2931 cris_prepare_cc_branch (dc, offset, cond); |
|
2932 return 4; |
|
2933 } |
|
2934 |
|
2935 static unsigned int dec_bas_im(DisasContext *dc) |
|
2936 { |
|
2937 int32_t simm; |
|
2938 |
|
2939 |
|
2940 simm = ldl_code(dc->pc + 2); |
|
2941 |
|
2942 DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2)); |
|
2943 cris_cc_mask(dc, 0); |
|
2944 /* Store the return address in Pd. */ |
|
2945 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8)); |
|
2946 |
|
2947 dc->jmp_pc = dc->pc + simm; |
|
2948 cris_prepare_jmp(dc, JMP_DIRECT); |
|
2949 return 6; |
|
2950 } |
|
2951 |
|
2952 static unsigned int dec_basc_im(DisasContext *dc) |
|
2953 { |
|
2954 int32_t simm; |
|
2955 simm = ldl_code(dc->pc + 2); |
|
2956 |
|
2957 DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2)); |
|
2958 cris_cc_mask(dc, 0); |
|
2959 /* Store the return address in Pd. */ |
|
2960 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12)); |
|
2961 |
|
2962 dc->jmp_pc = dc->pc + simm; |
|
2963 cris_prepare_jmp(dc, JMP_DIRECT); |
|
2964 return 6; |
|
2965 } |
|
2966 |
|
2967 static unsigned int dec_rfe_etc(DisasContext *dc) |
|
2968 { |
|
2969 cris_cc_mask(dc, 0); |
|
2970 |
|
2971 if (dc->op2 == 15) /* ignore halt. */ |
|
2972 return 2; |
|
2973 |
|
2974 switch (dc->op2 & 7) { |
|
2975 case 2: |
|
2976 /* rfe. */ |
|
2977 DIS(fprintf(logfile, "rfe\n")); |
|
2978 cris_evaluate_flags(dc); |
|
2979 gen_helper_rfe(); |
|
2980 dc->is_jmp = DISAS_UPDATE; |
|
2981 break; |
|
2982 case 5: |
|
2983 /* rfn. */ |
|
2984 DIS(fprintf(logfile, "rfn\n")); |
|
2985 cris_evaluate_flags(dc); |
|
2986 gen_helper_rfn(); |
|
2987 dc->is_jmp = DISAS_UPDATE; |
|
2988 break; |
|
2989 case 6: |
|
2990 DIS(fprintf(logfile, "break %d\n", dc->op1)); |
|
2991 cris_evaluate_flags (dc); |
|
2992 /* break. */ |
|
2993 tcg_gen_movi_tl(env_pc, dc->pc + 2); |
|
2994 |
|
2995 /* Breaks start at 16 in the exception vector. */ |
|
2996 t_gen_mov_env_TN(trap_vector, |
|
2997 tcg_const_tl(dc->op1 + 16)); |
|
2998 t_gen_raise_exception(EXCP_BREAK); |
|
2999 dc->is_jmp = DISAS_UPDATE; |
|
3000 break; |
|
3001 default: |
|
3002 printf ("op2=%x\n", dc->op2); |
|
3003 BUG(); |
|
3004 break; |
|
3005 |
|
3006 } |
|
3007 return 2; |
|
3008 } |
|
3009 |
|
3010 static unsigned int dec_ftag_fidx_d_m(DisasContext *dc) |
|
3011 { |
|
3012 return 2; |
|
3013 } |
|
3014 |
|
3015 static unsigned int dec_ftag_fidx_i_m(DisasContext *dc) |
|
3016 { |
|
3017 return 2; |
|
3018 } |
|
3019 |
|
3020 static unsigned int dec_null(DisasContext *dc) |
|
3021 { |
|
3022 printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n", |
|
3023 dc->pc, dc->opcode, dc->op1, dc->op2); |
|
3024 fflush(NULL); |
|
3025 BUG(); |
|
3026 return 2; |
|
3027 } |
|
3028 |
|
3029 static struct decoder_info { |
|
3030 struct { |
|
3031 uint32_t bits; |
|
3032 uint32_t mask; |
|
3033 }; |
|
3034 unsigned int (*dec)(DisasContext *dc); |
|
3035 } decinfo[] = { |
|
3036 /* Order matters here. */ |
|
3037 {DEC_MOVEQ, dec_moveq}, |
|
3038 {DEC_BTSTQ, dec_btstq}, |
|
3039 {DEC_CMPQ, dec_cmpq}, |
|
3040 {DEC_ADDOQ, dec_addoq}, |
|
3041 {DEC_ADDQ, dec_addq}, |
|
3042 {DEC_SUBQ, dec_subq}, |
|
3043 {DEC_ANDQ, dec_andq}, |
|
3044 {DEC_ORQ, dec_orq}, |
|
3045 {DEC_ASRQ, dec_asrq}, |
|
3046 {DEC_LSLQ, dec_lslq}, |
|
3047 {DEC_LSRQ, dec_lsrq}, |
|
3048 {DEC_BCCQ, dec_bccq}, |
|
3049 |
|
3050 {DEC_BCC_IM, dec_bcc_im}, |
|
3051 {DEC_JAS_IM, dec_jas_im}, |
|
3052 {DEC_JAS_R, dec_jas_r}, |
|
3053 {DEC_JASC_IM, dec_jasc_im}, |
|
3054 {DEC_JASC_R, dec_jasc_r}, |
|
3055 {DEC_BAS_IM, dec_bas_im}, |
|
3056 {DEC_BASC_IM, dec_basc_im}, |
|
3057 {DEC_JUMP_P, dec_jump_p}, |
|
3058 {DEC_LAPC_IM, dec_lapc_im}, |
|
3059 {DEC_LAPCQ, dec_lapcq}, |
|
3060 |
|
3061 {DEC_RFE_ETC, dec_rfe_etc}, |
|
3062 {DEC_ADDC_MR, dec_addc_mr}, |
|
3063 |
|
3064 {DEC_MOVE_MP, dec_move_mp}, |
|
3065 {DEC_MOVE_PM, dec_move_pm}, |
|
3066 {DEC_MOVEM_MR, dec_movem_mr}, |
|
3067 {DEC_MOVEM_RM, dec_movem_rm}, |
|
3068 {DEC_MOVE_PR, dec_move_pr}, |
|
3069 {DEC_SCC_R, dec_scc_r}, |
|
3070 {DEC_SETF, dec_setclrf}, |
|
3071 {DEC_CLEARF, dec_setclrf}, |
|
3072 |
|
3073 {DEC_MOVE_SR, dec_move_sr}, |
|
3074 {DEC_MOVE_RP, dec_move_rp}, |
|
3075 {DEC_SWAP_R, dec_swap_r}, |
|
3076 {DEC_ABS_R, dec_abs_r}, |
|
3077 {DEC_LZ_R, dec_lz_r}, |
|
3078 {DEC_MOVE_RS, dec_move_rs}, |
|
3079 {DEC_BTST_R, dec_btst_r}, |
|
3080 {DEC_ADDC_R, dec_addc_r}, |
|
3081 |
|
3082 {DEC_DSTEP_R, dec_dstep_r}, |
|
3083 {DEC_XOR_R, dec_xor_r}, |
|
3084 {DEC_MCP_R, dec_mcp_r}, |
|
3085 {DEC_CMP_R, dec_cmp_r}, |
|
3086 |
|
3087 {DEC_ADDI_R, dec_addi_r}, |
|
3088 {DEC_ADDI_ACR, dec_addi_acr}, |
|
3089 |
|
3090 {DEC_ADD_R, dec_add_r}, |
|
3091 {DEC_SUB_R, dec_sub_r}, |
|
3092 |
|
3093 {DEC_ADDU_R, dec_addu_r}, |
|
3094 {DEC_ADDS_R, dec_adds_r}, |
|
3095 {DEC_SUBU_R, dec_subu_r}, |
|
3096 {DEC_SUBS_R, dec_subs_r}, |
|
3097 {DEC_LSL_R, dec_lsl_r}, |
|
3098 |
|
3099 {DEC_AND_R, dec_and_r}, |
|
3100 {DEC_OR_R, dec_or_r}, |
|
3101 {DEC_BOUND_R, dec_bound_r}, |
|
3102 {DEC_ASR_R, dec_asr_r}, |
|
3103 {DEC_LSR_R, dec_lsr_r}, |
|
3104 |
|
3105 {DEC_MOVU_R, dec_movu_r}, |
|
3106 {DEC_MOVS_R, dec_movs_r}, |
|
3107 {DEC_NEG_R, dec_neg_r}, |
|
3108 {DEC_MOVE_R, dec_move_r}, |
|
3109 |
|
3110 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m}, |
|
3111 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m}, |
|
3112 |
|
3113 {DEC_MULS_R, dec_muls_r}, |
|
3114 {DEC_MULU_R, dec_mulu_r}, |
|
3115 |
|
3116 {DEC_ADDU_M, dec_addu_m}, |
|
3117 {DEC_ADDS_M, dec_adds_m}, |
|
3118 {DEC_SUBU_M, dec_subu_m}, |
|
3119 {DEC_SUBS_M, dec_subs_m}, |
|
3120 |
|
3121 {DEC_CMPU_M, dec_cmpu_m}, |
|
3122 {DEC_CMPS_M, dec_cmps_m}, |
|
3123 {DEC_MOVU_M, dec_movu_m}, |
|
3124 {DEC_MOVS_M, dec_movs_m}, |
|
3125 |
|
3126 {DEC_CMP_M, dec_cmp_m}, |
|
3127 {DEC_ADDO_M, dec_addo_m}, |
|
3128 {DEC_BOUND_M, dec_bound_m}, |
|
3129 {DEC_ADD_M, dec_add_m}, |
|
3130 {DEC_SUB_M, dec_sub_m}, |
|
3131 {DEC_AND_M, dec_and_m}, |
|
3132 {DEC_OR_M, dec_or_m}, |
|
3133 {DEC_MOVE_RM, dec_move_rm}, |
|
3134 {DEC_TEST_M, dec_test_m}, |
|
3135 {DEC_MOVE_MR, dec_move_mr}, |
|
3136 |
|
3137 {{0, 0}, dec_null} |
|
3138 }; |
|
3139 |
|
3140 static inline unsigned int |
|
3141 cris_decoder(DisasContext *dc) |
|
3142 { |
|
3143 unsigned int insn_len = 2; |
|
3144 int i; |
|
3145 |
|
3146 if (unlikely(loglevel & CPU_LOG_TB_OP)) |
|
3147 tcg_gen_debug_insn_start(dc->pc); |
|
3148 |
|
3149 /* Load a halfword onto the instruction register. */ |
|
3150 dc->ir = lduw_code(dc->pc); |
|
3151 |
|
3152 /* Now decode it. */ |
|
3153 dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11); |
|
3154 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3); |
|
3155 dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15); |
|
3156 dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4); |
|
3157 dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5); |
|
3158 dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10); |
|
3159 |
|
3160 /* Large switch for all insns. */ |
|
3161 for (i = 0; i < ARRAY_SIZE(decinfo); i++) { |
|
3162 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) |
|
3163 { |
|
3164 insn_len = decinfo[i].dec(dc); |
|
3165 break; |
|
3166 } |
|
3167 } |
|
3168 |
|
3169 #if !defined(CONFIG_USER_ONLY) |
|
3170 /* Single-stepping ? */ |
|
3171 if (dc->tb_flags & S_FLAG) { |
|
3172 int l1; |
|
3173 |
|
3174 l1 = gen_new_label(); |
|
3175 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1); |
|
3176 /* We treat SPC as a break with an odd trap vector. */ |
|
3177 cris_evaluate_flags (dc); |
|
3178 t_gen_mov_env_TN(trap_vector, tcg_const_tl(3)); |
|
3179 tcg_gen_movi_tl(env_pc, dc->pc + insn_len); |
|
3180 tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len); |
|
3181 t_gen_raise_exception(EXCP_BREAK); |
|
3182 gen_set_label(l1); |
|
3183 } |
|
3184 #endif |
|
3185 return insn_len; |
|
3186 } |
|
3187 |
|
3188 static void check_breakpoint(CPUState *env, DisasContext *dc) |
|
3189 { |
|
3190 CPUBreakpoint *bp; |
|
3191 |
|
3192 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { |
|
3193 TAILQ_FOREACH(bp, &env->breakpoints, entry) { |
|
3194 if (bp->pc == dc->pc) { |
|
3195 cris_evaluate_flags (dc); |
|
3196 tcg_gen_movi_tl(env_pc, dc->pc); |
|
3197 t_gen_raise_exception(EXCP_DEBUG); |
|
3198 dc->is_jmp = DISAS_UPDATE; |
|
3199 } |
|
3200 } |
|
3201 } |
|
3202 } |
|
3203 |
|
3204 |
|
3205 /* |
|
3206 * Delay slots on QEMU/CRIS. |
|
3207 * |
|
3208 * If an exception hits on a delayslot, the core will let ERP (the Exception |
|
3209 * Return Pointer) point to the branch (the previous) insn and set the lsb to |
|
3210 * to give SW a hint that the exception actually hit on the dslot. |
|
3211 * |
|
3212 * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by |
|
3213 * the core and any jmp to an odd addresses will mask off that lsb. It is |
|
3214 * simply there to let sw know there was an exception on a dslot. |
|
3215 * |
|
3216 * When the software returns from an exception, the branch will re-execute. |
|
3217 * On QEMU care needs to be taken when a branch+delayslot sequence is broken |
|
3218 * and the branch and delayslot dont share pages. |
|
3219 * |
|
3220 * The TB contaning the branch insn will set up env->btarget and evaluate |
|
3221 * env->btaken. When the translation loop exits we will note that the branch |
|
3222 * sequence is broken and let env->dslot be the size of the branch insn (those |
|
3223 * vary in length). |
|
3224 * |
|
3225 * The TB contaning the delayslot will have the PC of its real insn (i.e no lsb |
|
3226 * set). It will also expect to have env->dslot setup with the size of the |
|
3227 * delay slot so that env->pc - env->dslot point to the branch insn. This TB |
|
3228 * will execute the dslot and take the branch, either to btarget or just one |
|
3229 * insn ahead. |
|
3230 * |
|
3231 * When exceptions occur, we check for env->dslot in do_interrupt to detect |
|
3232 * broken branch sequences and setup $erp accordingly (i.e let it point to the |
|
3233 * branch and set lsb). Then env->dslot gets cleared so that the exception |
|
3234 * handler can enter. When returning from exceptions (jump $erp) the lsb gets |
|
3235 * masked off and we will reexecute the branch insn. |
|
3236 * |
|
3237 */ |
|
3238 |
|
3239 /* generate intermediate code for basic block 'tb'. */ |
|
3240 static void |
|
3241 gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
|
3242 int search_pc) |
|
3243 { |
|
3244 uint16_t *gen_opc_end; |
|
3245 uint32_t pc_start; |
|
3246 unsigned int insn_len; |
|
3247 int j, lj; |
|
3248 struct DisasContext ctx; |
|
3249 struct DisasContext *dc = &ctx; |
|
3250 uint32_t next_page_start; |
|
3251 target_ulong npc; |
|
3252 int num_insns; |
|
3253 int max_insns; |
|
3254 |
|
3255 if (!logfile) |
|
3256 logfile = stderr; |
|
3257 |
|
3258 /* Odd PC indicates that branch is rexecuting due to exception in the |
|
3259 * delayslot, like in real hw. |
|
3260 */ |
|
3261 pc_start = tb->pc & ~1; |
|
3262 dc->env = env; |
|
3263 dc->tb = tb; |
|
3264 |
|
3265 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
|
3266 |
|
3267 dc->is_jmp = DISAS_NEXT; |
|
3268 dc->ppc = pc_start; |
|
3269 dc->pc = pc_start; |
|
3270 dc->singlestep_enabled = env->singlestep_enabled; |
|
3271 dc->flags_uptodate = 1; |
|
3272 dc->flagx_known = 1; |
|
3273 dc->flags_x = tb->flags & X_FLAG; |
|
3274 dc->cc_x_uptodate = 0; |
|
3275 dc->cc_mask = 0; |
|
3276 dc->update_cc = 0; |
|
3277 |
|
3278 cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
|
3279 dc->cc_size_uptodate = -1; |
|
3280 |
|
3281 /* Decode TB flags. */ |
|
3282 dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG); |
|
3283 dc->delayed_branch = !!(tb->flags & 7); |
|
3284 if (dc->delayed_branch) |
|
3285 dc->jmp = JMP_INDIRECT; |
|
3286 else |
|
3287 dc->jmp = JMP_NOJMP; |
|
3288 |
|
3289 dc->cpustate_changed = 0; |
|
3290 |
|
3291 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
3292 fprintf(logfile, |
|
3293 "srch=%d pc=%x %x flg=%llx bt=%x ds=%u ccs=%x\n" |
|
3294 "pid=%x usp=%x\n" |
|
3295 "%x.%x.%x.%x\n" |
|
3296 "%x.%x.%x.%x\n" |
|
3297 "%x.%x.%x.%x\n" |
|
3298 "%x.%x.%x.%x\n", |
|
3299 search_pc, dc->pc, dc->ppc, |
|
3300 (unsigned long long)tb->flags, |
|
3301 env->btarget, (unsigned)tb->flags & 7, |
|
3302 env->pregs[PR_CCS], |
|
3303 env->pregs[PR_PID], env->pregs[PR_USP], |
|
3304 env->regs[0], env->regs[1], env->regs[2], env->regs[3], |
|
3305 env->regs[4], env->regs[5], env->regs[6], env->regs[7], |
|
3306 env->regs[8], env->regs[9], |
|
3307 env->regs[10], env->regs[11], |
|
3308 env->regs[12], env->regs[13], |
|
3309 env->regs[14], env->regs[15]); |
|
3310 fprintf(logfile, "--------------\n"); |
|
3311 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
|
3312 } |
|
3313 |
|
3314 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; |
|
3315 lj = -1; |
|
3316 num_insns = 0; |
|
3317 max_insns = tb->cflags & CF_COUNT_MASK; |
|
3318 if (max_insns == 0) |
|
3319 max_insns = CF_COUNT_MASK; |
|
3320 |
|
3321 gen_icount_start(); |
|
3322 do |
|
3323 { |
|
3324 check_breakpoint(env, dc); |
|
3325 |
|
3326 if (search_pc) { |
|
3327 j = gen_opc_ptr - gen_opc_buf; |
|
3328 if (lj < j) { |
|
3329 lj++; |
|
3330 while (lj < j) |
|
3331 gen_opc_instr_start[lj++] = 0; |
|
3332 } |
|
3333 if (dc->delayed_branch == 1) |
|
3334 gen_opc_pc[lj] = dc->ppc | 1; |
|
3335 else |
|
3336 gen_opc_pc[lj] = dc->pc; |
|
3337 gen_opc_instr_start[lj] = 1; |
|
3338 gen_opc_icount[lj] = num_insns; |
|
3339 } |
|
3340 |
|
3341 /* Pretty disas. */ |
|
3342 DIS(fprintf(logfile, "%8.8x:\t", dc->pc)); |
|
3343 |
|
3344 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) |
|
3345 gen_io_start(); |
|
3346 dc->clear_x = 1; |
|
3347 |
|
3348 insn_len = cris_decoder(dc); |
|
3349 dc->ppc = dc->pc; |
|
3350 dc->pc += insn_len; |
|
3351 if (dc->clear_x) |
|
3352 cris_clear_x_flag(dc); |
|
3353 |
|
3354 num_insns++; |
|
3355 /* Check for delayed branches here. If we do it before |
|
3356 actually generating any host code, the simulator will just |
|
3357 loop doing nothing for on this program location. */ |
|
3358 if (dc->delayed_branch) { |
|
3359 dc->delayed_branch--; |
|
3360 if (dc->delayed_branch == 0) |
|
3361 { |
|
3362 if (tb->flags & 7) |
|
3363 t_gen_mov_env_TN(dslot, |
|
3364 tcg_const_tl(0)); |
|
3365 if (dc->jmp == JMP_DIRECT) { |
|
3366 dc->is_jmp = DISAS_NEXT; |
|
3367 } else { |
|
3368 t_gen_cc_jmp(env_btarget, |
|
3369 tcg_const_tl(dc->pc)); |
|
3370 dc->is_jmp = DISAS_JUMP; |
|
3371 } |
|
3372 break; |
|
3373 } |
|
3374 } |
|
3375 |
|
3376 /* If we are rexecuting a branch due to exceptions on |
|
3377 delay slots dont break. */ |
|
3378 if (!(tb->pc & 1) && env->singlestep_enabled) |
|
3379 break; |
|
3380 } while (!dc->is_jmp && !dc->cpustate_changed |
|
3381 && gen_opc_ptr < gen_opc_end |
|
3382 && (dc->pc < next_page_start) |
|
3383 && num_insns < max_insns); |
|
3384 |
|
3385 npc = dc->pc; |
|
3386 if (dc->jmp == JMP_DIRECT && !dc->delayed_branch) |
|
3387 npc = dc->jmp_pc; |
|
3388 |
|
3389 if (tb->cflags & CF_LAST_IO) |
|
3390 gen_io_end(); |
|
3391 /* Force an update if the per-tb cpu state has changed. */ |
|
3392 if (dc->is_jmp == DISAS_NEXT |
|
3393 && (dc->cpustate_changed || !dc->flagx_known |
|
3394 || (dc->flags_x != (tb->flags & X_FLAG)))) { |
|
3395 dc->is_jmp = DISAS_UPDATE; |
|
3396 tcg_gen_movi_tl(env_pc, npc); |
|
3397 } |
|
3398 /* Broken branch+delayslot sequence. */ |
|
3399 if (dc->delayed_branch == 1) { |
|
3400 /* Set env->dslot to the size of the branch insn. */ |
|
3401 t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc)); |
|
3402 cris_store_direct_jmp(dc); |
|
3403 } |
|
3404 |
|
3405 cris_evaluate_flags (dc); |
|
3406 |
|
3407 if (unlikely(env->singlestep_enabled)) { |
|
3408 if (dc->is_jmp == DISAS_NEXT) |
|
3409 tcg_gen_movi_tl(env_pc, npc); |
|
3410 t_gen_raise_exception(EXCP_DEBUG); |
|
3411 } else { |
|
3412 switch(dc->is_jmp) { |
|
3413 case DISAS_NEXT: |
|
3414 gen_goto_tb(dc, 1, npc); |
|
3415 break; |
|
3416 default: |
|
3417 case DISAS_JUMP: |
|
3418 case DISAS_UPDATE: |
|
3419 /* indicate that the hash table must be used |
|
3420 to find the next TB */ |
|
3421 tcg_gen_exit_tb(0); |
|
3422 break; |
|
3423 case DISAS_SWI: |
|
3424 case DISAS_TB_JUMP: |
|
3425 /* nothing more to generate */ |
|
3426 break; |
|
3427 } |
|
3428 } |
|
3429 gen_icount_end(tb, num_insns); |
|
3430 *gen_opc_ptr = INDEX_op_end; |
|
3431 if (search_pc) { |
|
3432 j = gen_opc_ptr - gen_opc_buf; |
|
3433 lj++; |
|
3434 while (lj <= j) |
|
3435 gen_opc_instr_start[lj++] = 0; |
|
3436 } else { |
|
3437 tb->size = dc->pc - pc_start; |
|
3438 tb->icount = num_insns; |
|
3439 } |
|
3440 |
|
3441 #ifdef DEBUG_DISAS |
|
3442 #if !DISAS_CRIS |
|
3443 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
3444 target_disas(logfile, pc_start, dc->pc - pc_start, 0); |
|
3445 fprintf(logfile, "\nisize=%d osize=%zd\n", |
|
3446 dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); |
|
3447 } |
|
3448 #endif |
|
3449 #endif |
|
3450 } |
|
3451 |
|
3452 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) |
|
3453 { |
|
3454 gen_intermediate_code_internal(env, tb, 0); |
|
3455 } |
|
3456 |
|
3457 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) |
|
3458 { |
|
3459 gen_intermediate_code_internal(env, tb, 1); |
|
3460 } |
|
3461 |
|
3462 void cpu_dump_state (CPUState *env, FILE *f, |
|
3463 int (*cpu_fprintf)(FILE *f, const char *fmt, ...), |
|
3464 int flags) |
|
3465 { |
|
3466 int i; |
|
3467 uint32_t srs; |
|
3468 |
|
3469 if (!env || !f) |
|
3470 return; |
|
3471 |
|
3472 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n" |
|
3473 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n", |
|
3474 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget, |
|
3475 env->cc_op, |
|
3476 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask); |
|
3477 |
|
3478 |
|
3479 for (i = 0; i < 16; i++) { |
|
3480 cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); |
|
3481 if ((i + 1) % 4 == 0) |
|
3482 cpu_fprintf(f, "\n"); |
|
3483 } |
|
3484 cpu_fprintf(f, "\nspecial regs:\n"); |
|
3485 for (i = 0; i < 16; i++) { |
|
3486 cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]); |
|
3487 if ((i + 1) % 4 == 0) |
|
3488 cpu_fprintf(f, "\n"); |
|
3489 } |
|
3490 srs = env->pregs[PR_SRS]; |
|
3491 cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs); |
|
3492 if (srs < 256) { |
|
3493 for (i = 0; i < 16; i++) { |
|
3494 cpu_fprintf(f, "s%2.2d=%8.8x ", |
|
3495 i, env->sregs[srs][i]); |
|
3496 if ((i + 1) % 4 == 0) |
|
3497 cpu_fprintf(f, "\n"); |
|
3498 } |
|
3499 } |
|
3500 cpu_fprintf(f, "\n\n"); |
|
3501 |
|
3502 } |
|
3503 |
|
3504 CPUCRISState *cpu_cris_init (const char *cpu_model) |
|
3505 { |
|
3506 CPUCRISState *env; |
|
3507 static int tcg_initialized = 0; |
|
3508 int i; |
|
3509 |
|
3510 env = qemu_mallocz(sizeof(CPUCRISState)); |
|
3511 if (!env) |
|
3512 return NULL; |
|
3513 |
|
3514 cpu_exec_init(env); |
|
3515 cpu_reset(env); |
|
3516 |
|
3517 if (tcg_initialized) |
|
3518 return env; |
|
3519 |
|
3520 tcg_initialized = 1; |
|
3521 |
|
3522 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); |
|
3523 cc_x = tcg_global_mem_new(TCG_AREG0, |
|
3524 offsetof(CPUState, cc_x), "cc_x"); |
|
3525 cc_src = tcg_global_mem_new(TCG_AREG0, |
|
3526 offsetof(CPUState, cc_src), "cc_src"); |
|
3527 cc_dest = tcg_global_mem_new(TCG_AREG0, |
|
3528 offsetof(CPUState, cc_dest), |
|
3529 "cc_dest"); |
|
3530 cc_result = tcg_global_mem_new(TCG_AREG0, |
|
3531 offsetof(CPUState, cc_result), |
|
3532 "cc_result"); |
|
3533 cc_op = tcg_global_mem_new(TCG_AREG0, |
|
3534 offsetof(CPUState, cc_op), "cc_op"); |
|
3535 cc_size = tcg_global_mem_new(TCG_AREG0, |
|
3536 offsetof(CPUState, cc_size), |
|
3537 "cc_size"); |
|
3538 cc_mask = tcg_global_mem_new(TCG_AREG0, |
|
3539 offsetof(CPUState, cc_mask), |
|
3540 "cc_mask"); |
|
3541 |
|
3542 env_pc = tcg_global_mem_new(TCG_AREG0, |
|
3543 offsetof(CPUState, pc), |
|
3544 "pc"); |
|
3545 env_btarget = tcg_global_mem_new(TCG_AREG0, |
|
3546 offsetof(CPUState, btarget), |
|
3547 "btarget"); |
|
3548 env_btaken = tcg_global_mem_new(TCG_AREG0, |
|
3549 offsetof(CPUState, btaken), |
|
3550 "btaken"); |
|
3551 for (i = 0; i < 16; i++) { |
|
3552 cpu_R[i] = tcg_global_mem_new(TCG_AREG0, |
|
3553 offsetof(CPUState, regs[i]), |
|
3554 regnames[i]); |
|
3555 } |
|
3556 for (i = 0; i < 16; i++) { |
|
3557 cpu_PR[i] = tcg_global_mem_new(TCG_AREG0, |
|
3558 offsetof(CPUState, pregs[i]), |
|
3559 pregnames[i]); |
|
3560 } |
|
3561 |
|
3562 #define GEN_HELPER 2 |
|
3563 #include "helper.h" |
|
3564 |
|
3565 return env; |
|
3566 } |
|
3567 |
|
3568 void cpu_reset (CPUCRISState *env) |
|
3569 { |
|
3570 memset(env, 0, offsetof(CPUCRISState, breakpoints)); |
|
3571 tlb_flush(env, 1); |
|
3572 |
|
3573 env->pregs[PR_VR] = 32; |
|
3574 #if defined(CONFIG_USER_ONLY) |
|
3575 /* start in user mode with interrupts enabled. */ |
|
3576 env->pregs[PR_CCS] |= U_FLAG | I_FLAG; |
|
3577 #else |
|
3578 env->pregs[PR_CCS] = 0; |
|
3579 #endif |
|
3580 } |
|
3581 |
|
3582 void gen_pc_load(CPUState *env, struct TranslationBlock *tb, |
|
3583 unsigned long searched_pc, int pc_pos, void *puc) |
|
3584 { |
|
3585 env->pc = gen_opc_pc[pc_pos]; |
|
3586 } |