]> git.proxmox.com Git - mirror_qemu.git/blob - tcg/tci.c
tcg/tci: Change encoding to uint32_t units
[mirror_qemu.git] / tcg / tci.c
1 /*
2 * Tiny Code Interpreter for QEMU
3 *
4 * Copyright (c) 2009, 2011, 2016 Stefan Weil
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "qemu/osdep.h"
21 #include "qemu-common.h"
22 #include "tcg/tcg.h" /* MAX_OPC_PARAM_IARGS */
23 #include "exec/cpu_ldst.h"
24 #include "tcg/tcg-op.h"
25 #include "qemu/compiler.h"
26 #include <ffi.h>
27
28
29 /*
30 * Enable TCI assertions only when debugging TCG (and without NDEBUG defined).
31 * Without assertions, the interpreter runs much faster.
32 */
33 #if defined(CONFIG_DEBUG_TCG)
34 # define tci_assert(cond) assert(cond)
35 #else
36 # define tci_assert(cond) ((void)(cond))
37 #endif
38
39 __thread uintptr_t tci_tb_ptr;
40
41 static void tci_write_reg64(tcg_target_ulong *regs, uint32_t high_index,
42 uint32_t low_index, uint64_t value)
43 {
44 regs[low_index] = value;
45 regs[high_index] = value >> 32;
46 }
47
48 /* Create a 64 bit value from two 32 bit values. */
49 static uint64_t tci_uint64(uint32_t high, uint32_t low)
50 {
51 return ((uint64_t)high << 32) + low;
52 }
53
54 /*
55 * Load sets of arguments all at once. The naming convention is:
56 * tci_args_<arguments>
57 * where arguments is a sequence of
58 *
59 * b = immediate (bit position)
60 * c = condition (TCGCond)
61 * i = immediate (uint32_t)
62 * I = immediate (tcg_target_ulong)
63 * l = label or pointer
64 * m = immediate (TCGMemOpIdx)
65 * n = immediate (call return length)
66 * r = register
67 * s = signed ldst offset
68 */
69
70 static void tci_args_l(uint32_t insn, const void *tb_ptr, void **l0)
71 {
72 int diff = sextract32(insn, 12, 20);
73 *l0 = diff ? (void *)tb_ptr + diff : NULL;
74 }
75
76 static void tci_args_nl(uint32_t insn, const void *tb_ptr,
77 uint8_t *n0, void **l1)
78 {
79 *n0 = extract32(insn, 8, 4);
80 *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
81 }
82
83 static void tci_args_rl(uint32_t insn, const void *tb_ptr,
84 TCGReg *r0, void **l1)
85 {
86 *r0 = extract32(insn, 8, 4);
87 *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
88 }
89
90 static void tci_args_rr(uint32_t insn, TCGReg *r0, TCGReg *r1)
91 {
92 *r0 = extract32(insn, 8, 4);
93 *r1 = extract32(insn, 12, 4);
94 }
95
96 static void tci_args_ri(uint32_t insn, TCGReg *r0, tcg_target_ulong *i1)
97 {
98 *r0 = extract32(insn, 8, 4);
99 *i1 = sextract32(insn, 12, 20);
100 }
101
102 static void tci_args_rrm(uint32_t insn, TCGReg *r0,
103 TCGReg *r1, TCGMemOpIdx *m2)
104 {
105 *r0 = extract32(insn, 8, 4);
106 *r1 = extract32(insn, 12, 4);
107 *m2 = extract32(insn, 20, 12);
108 }
109
110 static void tci_args_rrr(uint32_t insn, TCGReg *r0, TCGReg *r1, TCGReg *r2)
111 {
112 *r0 = extract32(insn, 8, 4);
113 *r1 = extract32(insn, 12, 4);
114 *r2 = extract32(insn, 16, 4);
115 }
116
117 static void tci_args_rrs(uint32_t insn, TCGReg *r0, TCGReg *r1, int32_t *i2)
118 {
119 *r0 = extract32(insn, 8, 4);
120 *r1 = extract32(insn, 12, 4);
121 *i2 = sextract32(insn, 16, 16);
122 }
123
124 static void tci_args_rrrc(uint32_t insn,
125 TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGCond *c3)
126 {
127 *r0 = extract32(insn, 8, 4);
128 *r1 = extract32(insn, 12, 4);
129 *r2 = extract32(insn, 16, 4);
130 *c3 = extract32(insn, 20, 4);
131 }
132
133 static void tci_args_rrrm(uint32_t insn,
134 TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGMemOpIdx *m3)
135 {
136 *r0 = extract32(insn, 8, 4);
137 *r1 = extract32(insn, 12, 4);
138 *r2 = extract32(insn, 16, 4);
139 *m3 = extract32(insn, 20, 12);
140 }
141
142 static void tci_args_rrrbb(uint32_t insn, TCGReg *r0, TCGReg *r1,
143 TCGReg *r2, uint8_t *i3, uint8_t *i4)
144 {
145 *r0 = extract32(insn, 8, 4);
146 *r1 = extract32(insn, 12, 4);
147 *r2 = extract32(insn, 16, 4);
148 *i3 = extract32(insn, 20, 6);
149 *i4 = extract32(insn, 26, 6);
150 }
151
152 static void tci_args_rrrrr(uint32_t insn, TCGReg *r0, TCGReg *r1,
153 TCGReg *r2, TCGReg *r3, TCGReg *r4)
154 {
155 *r0 = extract32(insn, 8, 4);
156 *r1 = extract32(insn, 12, 4);
157 *r2 = extract32(insn, 16, 4);
158 *r3 = extract32(insn, 20, 4);
159 *r4 = extract32(insn, 24, 4);
160 }
161
162 #if TCG_TARGET_REG_BITS == 32
163 static void tci_args_rrrr(uint32_t insn,
164 TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGReg *r3)
165 {
166 *r0 = extract32(insn, 8, 4);
167 *r1 = extract32(insn, 12, 4);
168 *r2 = extract32(insn, 16, 4);
169 *r3 = extract32(insn, 20, 4);
170 }
171
172 static void tci_args_rrrrrc(uint32_t insn, TCGReg *r0, TCGReg *r1,
173 TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGCond *c5)
174 {
175 *r0 = extract32(insn, 8, 4);
176 *r1 = extract32(insn, 12, 4);
177 *r2 = extract32(insn, 16, 4);
178 *r3 = extract32(insn, 20, 4);
179 *r4 = extract32(insn, 24, 4);
180 *c5 = extract32(insn, 28, 4);
181 }
182
183 static void tci_args_rrrrrr(uint32_t insn, TCGReg *r0, TCGReg *r1,
184 TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGReg *r5)
185 {
186 *r0 = extract32(insn, 8, 4);
187 *r1 = extract32(insn, 12, 4);
188 *r2 = extract32(insn, 16, 4);
189 *r3 = extract32(insn, 20, 4);
190 *r4 = extract32(insn, 24, 4);
191 *r5 = extract32(insn, 28, 4);
192 }
193 #endif
194
195 static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition)
196 {
197 bool result = false;
198 int32_t i0 = u0;
199 int32_t i1 = u1;
200 switch (condition) {
201 case TCG_COND_EQ:
202 result = (u0 == u1);
203 break;
204 case TCG_COND_NE:
205 result = (u0 != u1);
206 break;
207 case TCG_COND_LT:
208 result = (i0 < i1);
209 break;
210 case TCG_COND_GE:
211 result = (i0 >= i1);
212 break;
213 case TCG_COND_LE:
214 result = (i0 <= i1);
215 break;
216 case TCG_COND_GT:
217 result = (i0 > i1);
218 break;
219 case TCG_COND_LTU:
220 result = (u0 < u1);
221 break;
222 case TCG_COND_GEU:
223 result = (u0 >= u1);
224 break;
225 case TCG_COND_LEU:
226 result = (u0 <= u1);
227 break;
228 case TCG_COND_GTU:
229 result = (u0 > u1);
230 break;
231 default:
232 g_assert_not_reached();
233 }
234 return result;
235 }
236
237 static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
238 {
239 bool result = false;
240 int64_t i0 = u0;
241 int64_t i1 = u1;
242 switch (condition) {
243 case TCG_COND_EQ:
244 result = (u0 == u1);
245 break;
246 case TCG_COND_NE:
247 result = (u0 != u1);
248 break;
249 case TCG_COND_LT:
250 result = (i0 < i1);
251 break;
252 case TCG_COND_GE:
253 result = (i0 >= i1);
254 break;
255 case TCG_COND_LE:
256 result = (i0 <= i1);
257 break;
258 case TCG_COND_GT:
259 result = (i0 > i1);
260 break;
261 case TCG_COND_LTU:
262 result = (u0 < u1);
263 break;
264 case TCG_COND_GEU:
265 result = (u0 >= u1);
266 break;
267 case TCG_COND_LEU:
268 result = (u0 <= u1);
269 break;
270 case TCG_COND_GTU:
271 result = (u0 > u1);
272 break;
273 default:
274 g_assert_not_reached();
275 }
276 return result;
277 }
278
279 #define qemu_ld_ub \
280 cpu_ldub_mmuidx_ra(env, taddr, get_mmuidx(oi), (uintptr_t)tb_ptr)
281 #define qemu_ld_leuw \
282 cpu_lduw_le_mmuidx_ra(env, taddr, get_mmuidx(oi), (uintptr_t)tb_ptr)
283 #define qemu_ld_leul \
284 cpu_ldl_le_mmuidx_ra(env, taddr, get_mmuidx(oi), (uintptr_t)tb_ptr)
285 #define qemu_ld_leq \
286 cpu_ldq_le_mmuidx_ra(env, taddr, get_mmuidx(oi), (uintptr_t)tb_ptr)
287 #define qemu_ld_beuw \
288 cpu_lduw_be_mmuidx_ra(env, taddr, get_mmuidx(oi), (uintptr_t)tb_ptr)
289 #define qemu_ld_beul \
290 cpu_ldl_be_mmuidx_ra(env, taddr, get_mmuidx(oi), (uintptr_t)tb_ptr)
291 #define qemu_ld_beq \
292 cpu_ldq_be_mmuidx_ra(env, taddr, get_mmuidx(oi), (uintptr_t)tb_ptr)
293 #define qemu_st_b(X) \
294 cpu_stb_mmuidx_ra(env, taddr, X, get_mmuidx(oi), (uintptr_t)tb_ptr)
295 #define qemu_st_lew(X) \
296 cpu_stw_le_mmuidx_ra(env, taddr, X, get_mmuidx(oi), (uintptr_t)tb_ptr)
297 #define qemu_st_lel(X) \
298 cpu_stl_le_mmuidx_ra(env, taddr, X, get_mmuidx(oi), (uintptr_t)tb_ptr)
299 #define qemu_st_leq(X) \
300 cpu_stq_le_mmuidx_ra(env, taddr, X, get_mmuidx(oi), (uintptr_t)tb_ptr)
301 #define qemu_st_bew(X) \
302 cpu_stw_be_mmuidx_ra(env, taddr, X, get_mmuidx(oi), (uintptr_t)tb_ptr)
303 #define qemu_st_bel(X) \
304 cpu_stl_be_mmuidx_ra(env, taddr, X, get_mmuidx(oi), (uintptr_t)tb_ptr)
305 #define qemu_st_beq(X) \
306 cpu_stq_be_mmuidx_ra(env, taddr, X, get_mmuidx(oi), (uintptr_t)tb_ptr)
307
308 #if TCG_TARGET_REG_BITS == 64
309 # define CASE_32_64(x) \
310 case glue(glue(INDEX_op_, x), _i64): \
311 case glue(glue(INDEX_op_, x), _i32):
312 # define CASE_64(x) \
313 case glue(glue(INDEX_op_, x), _i64):
314 #else
315 # define CASE_32_64(x) \
316 case glue(glue(INDEX_op_, x), _i32):
317 # define CASE_64(x)
318 #endif
319
320 /* Interpret pseudo code in tb. */
321 /*
322 * Disable CFI checks.
323 * One possible operation in the pseudo code is a call to binary code.
324 * Therefore, disable CFI checks in the interpreter function
325 */
326 uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
327 const void *v_tb_ptr)
328 {
329 const uint32_t *tb_ptr = v_tb_ptr;
330 tcg_target_ulong regs[TCG_TARGET_NB_REGS];
331 uint64_t stack[(TCG_STATIC_CALL_ARGS_SIZE + TCG_STATIC_FRAME_SIZE)
332 / sizeof(uint64_t)];
333 void *call_slots[TCG_STATIC_CALL_ARGS_SIZE / sizeof(uint64_t)];
334
335 regs[TCG_AREG0] = (tcg_target_ulong)env;
336 regs[TCG_REG_CALL_STACK] = (uintptr_t)stack;
337 /* Other call_slots entries initialized at first use (see below). */
338 call_slots[0] = NULL;
339 tci_assert(tb_ptr);
340
341 for (;;) {
342 uint32_t insn;
343 TCGOpcode opc;
344 TCGReg r0, r1, r2, r3, r4;
345 tcg_target_ulong t1;
346 TCGCond condition;
347 target_ulong taddr;
348 uint8_t pos, len;
349 uint32_t tmp32;
350 uint64_t tmp64;
351 #if TCG_TARGET_REG_BITS == 32
352 TCGReg r5;
353 uint64_t T1, T2;
354 #endif
355 TCGMemOpIdx oi;
356 int32_t ofs;
357 void *ptr;
358
359 insn = *tb_ptr++;
360 opc = extract32(insn, 0, 8);
361
362 switch (opc) {
363 case INDEX_op_call:
364 /*
365 * Set up the ffi_avalue array once, delayed until now
366 * because many TB's do not make any calls. In tcg_gen_callN,
367 * we arranged for every real argument to be "left-aligned"
368 * in each 64-bit slot.
369 */
370 if (unlikely(call_slots[0] == NULL)) {
371 for (int i = 0; i < ARRAY_SIZE(call_slots); ++i) {
372 call_slots[i] = &stack[i];
373 }
374 }
375
376 tci_args_nl(insn, tb_ptr, &len, &ptr);
377
378 /* Helper functions may need to access the "return address" */
379 tci_tb_ptr = (uintptr_t)tb_ptr;
380
381 {
382 void **pptr = ptr;
383 ffi_call(pptr[1], pptr[0], stack, call_slots);
384 }
385
386 /* Any result winds up "left-aligned" in the stack[0] slot. */
387 switch (len) {
388 case 0: /* void */
389 break;
390 case 1: /* uint32_t */
391 /*
392 * Note that libffi has an odd special case in that it will
393 * always widen an integral result to ffi_arg.
394 */
395 if (sizeof(ffi_arg) == 4) {
396 regs[TCG_REG_R0] = *(uint32_t *)stack;
397 break;
398 }
399 /* fall through */
400 case 2: /* uint64_t */
401 if (TCG_TARGET_REG_BITS == 32) {
402 tci_write_reg64(regs, TCG_REG_R1, TCG_REG_R0, stack[0]);
403 } else {
404 regs[TCG_REG_R0] = stack[0];
405 }
406 break;
407 default:
408 g_assert_not_reached();
409 }
410 break;
411
412 case INDEX_op_br:
413 tci_args_l(insn, tb_ptr, &ptr);
414 tb_ptr = ptr;
415 continue;
416 case INDEX_op_setcond_i32:
417 tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
418 regs[r0] = tci_compare32(regs[r1], regs[r2], condition);
419 break;
420 #if TCG_TARGET_REG_BITS == 32
421 case INDEX_op_setcond2_i32:
422 tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
423 T1 = tci_uint64(regs[r2], regs[r1]);
424 T2 = tci_uint64(regs[r4], regs[r3]);
425 regs[r0] = tci_compare64(T1, T2, condition);
426 break;
427 #elif TCG_TARGET_REG_BITS == 64
428 case INDEX_op_setcond_i64:
429 tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
430 regs[r0] = tci_compare64(regs[r1], regs[r2], condition);
431 break;
432 #endif
433 CASE_32_64(mov)
434 tci_args_rr(insn, &r0, &r1);
435 regs[r0] = regs[r1];
436 break;
437 case INDEX_op_tci_movi:
438 tci_args_ri(insn, &r0, &t1);
439 regs[r0] = t1;
440 break;
441 case INDEX_op_tci_movl:
442 tci_args_rl(insn, tb_ptr, &r0, &ptr);
443 regs[r0] = *(tcg_target_ulong *)ptr;
444 break;
445
446 /* Load/store operations (32 bit). */
447
448 CASE_32_64(ld8u)
449 tci_args_rrs(insn, &r0, &r1, &ofs);
450 ptr = (void *)(regs[r1] + ofs);
451 regs[r0] = *(uint8_t *)ptr;
452 break;
453 CASE_32_64(ld8s)
454 tci_args_rrs(insn, &r0, &r1, &ofs);
455 ptr = (void *)(regs[r1] + ofs);
456 regs[r0] = *(int8_t *)ptr;
457 break;
458 CASE_32_64(ld16u)
459 tci_args_rrs(insn, &r0, &r1, &ofs);
460 ptr = (void *)(regs[r1] + ofs);
461 regs[r0] = *(uint16_t *)ptr;
462 break;
463 CASE_32_64(ld16s)
464 tci_args_rrs(insn, &r0, &r1, &ofs);
465 ptr = (void *)(regs[r1] + ofs);
466 regs[r0] = *(int16_t *)ptr;
467 break;
468 case INDEX_op_ld_i32:
469 CASE_64(ld32u)
470 tci_args_rrs(insn, &r0, &r1, &ofs);
471 ptr = (void *)(regs[r1] + ofs);
472 regs[r0] = *(uint32_t *)ptr;
473 break;
474 CASE_32_64(st8)
475 tci_args_rrs(insn, &r0, &r1, &ofs);
476 ptr = (void *)(regs[r1] + ofs);
477 *(uint8_t *)ptr = regs[r0];
478 break;
479 CASE_32_64(st16)
480 tci_args_rrs(insn, &r0, &r1, &ofs);
481 ptr = (void *)(regs[r1] + ofs);
482 *(uint16_t *)ptr = regs[r0];
483 break;
484 case INDEX_op_st_i32:
485 CASE_64(st32)
486 tci_args_rrs(insn, &r0, &r1, &ofs);
487 ptr = (void *)(regs[r1] + ofs);
488 *(uint32_t *)ptr = regs[r0];
489 break;
490
491 /* Arithmetic operations (mixed 32/64 bit). */
492
493 CASE_32_64(add)
494 tci_args_rrr(insn, &r0, &r1, &r2);
495 regs[r0] = regs[r1] + regs[r2];
496 break;
497 CASE_32_64(sub)
498 tci_args_rrr(insn, &r0, &r1, &r2);
499 regs[r0] = regs[r1] - regs[r2];
500 break;
501 CASE_32_64(mul)
502 tci_args_rrr(insn, &r0, &r1, &r2);
503 regs[r0] = regs[r1] * regs[r2];
504 break;
505 CASE_32_64(and)
506 tci_args_rrr(insn, &r0, &r1, &r2);
507 regs[r0] = regs[r1] & regs[r2];
508 break;
509 CASE_32_64(or)
510 tci_args_rrr(insn, &r0, &r1, &r2);
511 regs[r0] = regs[r1] | regs[r2];
512 break;
513 CASE_32_64(xor)
514 tci_args_rrr(insn, &r0, &r1, &r2);
515 regs[r0] = regs[r1] ^ regs[r2];
516 break;
517
518 /* Arithmetic operations (32 bit). */
519
520 case INDEX_op_div_i32:
521 tci_args_rrr(insn, &r0, &r1, &r2);
522 regs[r0] = (int32_t)regs[r1] / (int32_t)regs[r2];
523 break;
524 case INDEX_op_divu_i32:
525 tci_args_rrr(insn, &r0, &r1, &r2);
526 regs[r0] = (uint32_t)regs[r1] / (uint32_t)regs[r2];
527 break;
528 case INDEX_op_rem_i32:
529 tci_args_rrr(insn, &r0, &r1, &r2);
530 regs[r0] = (int32_t)regs[r1] % (int32_t)regs[r2];
531 break;
532 case INDEX_op_remu_i32:
533 tci_args_rrr(insn, &r0, &r1, &r2);
534 regs[r0] = (uint32_t)regs[r1] % (uint32_t)regs[r2];
535 break;
536
537 /* Shift/rotate operations (32 bit). */
538
539 case INDEX_op_shl_i32:
540 tci_args_rrr(insn, &r0, &r1, &r2);
541 regs[r0] = (uint32_t)regs[r1] << (regs[r2] & 31);
542 break;
543 case INDEX_op_shr_i32:
544 tci_args_rrr(insn, &r0, &r1, &r2);
545 regs[r0] = (uint32_t)regs[r1] >> (regs[r2] & 31);
546 break;
547 case INDEX_op_sar_i32:
548 tci_args_rrr(insn, &r0, &r1, &r2);
549 regs[r0] = (int32_t)regs[r1] >> (regs[r2] & 31);
550 break;
551 #if TCG_TARGET_HAS_rot_i32
552 case INDEX_op_rotl_i32:
553 tci_args_rrr(insn, &r0, &r1, &r2);
554 regs[r0] = rol32(regs[r1], regs[r2] & 31);
555 break;
556 case INDEX_op_rotr_i32:
557 tci_args_rrr(insn, &r0, &r1, &r2);
558 regs[r0] = ror32(regs[r1], regs[r2] & 31);
559 break;
560 #endif
561 #if TCG_TARGET_HAS_deposit_i32
562 case INDEX_op_deposit_i32:
563 tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
564 regs[r0] = deposit32(regs[r1], pos, len, regs[r2]);
565 break;
566 #endif
567 case INDEX_op_brcond_i32:
568 tci_args_rl(insn, tb_ptr, &r0, &ptr);
569 if ((uint32_t)regs[r0]) {
570 tb_ptr = ptr;
571 }
572 break;
573 #if TCG_TARGET_REG_BITS == 32
574 case INDEX_op_add2_i32:
575 tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
576 T1 = tci_uint64(regs[r3], regs[r2]);
577 T2 = tci_uint64(regs[r5], regs[r4]);
578 tci_write_reg64(regs, r1, r0, T1 + T2);
579 break;
580 case INDEX_op_sub2_i32:
581 tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
582 T1 = tci_uint64(regs[r3], regs[r2]);
583 T2 = tci_uint64(regs[r5], regs[r4]);
584 tci_write_reg64(regs, r1, r0, T1 - T2);
585 break;
586 case INDEX_op_mulu2_i32:
587 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
588 tci_write_reg64(regs, r1, r0, (uint64_t)regs[r2] * regs[r3]);
589 break;
590 #endif /* TCG_TARGET_REG_BITS == 32 */
591 #if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64
592 CASE_32_64(ext8s)
593 tci_args_rr(insn, &r0, &r1);
594 regs[r0] = (int8_t)regs[r1];
595 break;
596 #endif
597 #if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64
598 CASE_32_64(ext16s)
599 tci_args_rr(insn, &r0, &r1);
600 regs[r0] = (int16_t)regs[r1];
601 break;
602 #endif
603 #if TCG_TARGET_HAS_ext8u_i32 || TCG_TARGET_HAS_ext8u_i64
604 CASE_32_64(ext8u)
605 tci_args_rr(insn, &r0, &r1);
606 regs[r0] = (uint8_t)regs[r1];
607 break;
608 #endif
609 #if TCG_TARGET_HAS_ext16u_i32 || TCG_TARGET_HAS_ext16u_i64
610 CASE_32_64(ext16u)
611 tci_args_rr(insn, &r0, &r1);
612 regs[r0] = (uint16_t)regs[r1];
613 break;
614 #endif
615 #if TCG_TARGET_HAS_bswap16_i32 || TCG_TARGET_HAS_bswap16_i64
616 CASE_32_64(bswap16)
617 tci_args_rr(insn, &r0, &r1);
618 regs[r0] = bswap16(regs[r1]);
619 break;
620 #endif
621 #if TCG_TARGET_HAS_bswap32_i32 || TCG_TARGET_HAS_bswap32_i64
622 CASE_32_64(bswap32)
623 tci_args_rr(insn, &r0, &r1);
624 regs[r0] = bswap32(regs[r1]);
625 break;
626 #endif
627 #if TCG_TARGET_HAS_not_i32 || TCG_TARGET_HAS_not_i64
628 CASE_32_64(not)
629 tci_args_rr(insn, &r0, &r1);
630 regs[r0] = ~regs[r1];
631 break;
632 #endif
633 #if TCG_TARGET_HAS_neg_i32 || TCG_TARGET_HAS_neg_i64
634 CASE_32_64(neg)
635 tci_args_rr(insn, &r0, &r1);
636 regs[r0] = -regs[r1];
637 break;
638 #endif
639 #if TCG_TARGET_REG_BITS == 64
640 /* Load/store operations (64 bit). */
641
642 case INDEX_op_ld32s_i64:
643 tci_args_rrs(insn, &r0, &r1, &ofs);
644 ptr = (void *)(regs[r1] + ofs);
645 regs[r0] = *(int32_t *)ptr;
646 break;
647 case INDEX_op_ld_i64:
648 tci_args_rrs(insn, &r0, &r1, &ofs);
649 ptr = (void *)(regs[r1] + ofs);
650 regs[r0] = *(uint64_t *)ptr;
651 break;
652 case INDEX_op_st_i64:
653 tci_args_rrs(insn, &r0, &r1, &ofs);
654 ptr = (void *)(regs[r1] + ofs);
655 *(uint64_t *)ptr = regs[r0];
656 break;
657
658 /* Arithmetic operations (64 bit). */
659
660 case INDEX_op_div_i64:
661 tci_args_rrr(insn, &r0, &r1, &r2);
662 regs[r0] = (int64_t)regs[r1] / (int64_t)regs[r2];
663 break;
664 case INDEX_op_divu_i64:
665 tci_args_rrr(insn, &r0, &r1, &r2);
666 regs[r0] = (uint64_t)regs[r1] / (uint64_t)regs[r2];
667 break;
668 case INDEX_op_rem_i64:
669 tci_args_rrr(insn, &r0, &r1, &r2);
670 regs[r0] = (int64_t)regs[r1] % (int64_t)regs[r2];
671 break;
672 case INDEX_op_remu_i64:
673 tci_args_rrr(insn, &r0, &r1, &r2);
674 regs[r0] = (uint64_t)regs[r1] % (uint64_t)regs[r2];
675 break;
676
677 /* Shift/rotate operations (64 bit). */
678
679 case INDEX_op_shl_i64:
680 tci_args_rrr(insn, &r0, &r1, &r2);
681 regs[r0] = regs[r1] << (regs[r2] & 63);
682 break;
683 case INDEX_op_shr_i64:
684 tci_args_rrr(insn, &r0, &r1, &r2);
685 regs[r0] = regs[r1] >> (regs[r2] & 63);
686 break;
687 case INDEX_op_sar_i64:
688 tci_args_rrr(insn, &r0, &r1, &r2);
689 regs[r0] = (int64_t)regs[r1] >> (regs[r2] & 63);
690 break;
691 #if TCG_TARGET_HAS_rot_i64
692 case INDEX_op_rotl_i64:
693 tci_args_rrr(insn, &r0, &r1, &r2);
694 regs[r0] = rol64(regs[r1], regs[r2] & 63);
695 break;
696 case INDEX_op_rotr_i64:
697 tci_args_rrr(insn, &r0, &r1, &r2);
698 regs[r0] = ror64(regs[r1], regs[r2] & 63);
699 break;
700 #endif
701 #if TCG_TARGET_HAS_deposit_i64
702 case INDEX_op_deposit_i64:
703 tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
704 regs[r0] = deposit64(regs[r1], pos, len, regs[r2]);
705 break;
706 #endif
707 case INDEX_op_brcond_i64:
708 tci_args_rl(insn, tb_ptr, &r0, &ptr);
709 if (regs[r0]) {
710 tb_ptr = ptr;
711 }
712 break;
713 case INDEX_op_ext32s_i64:
714 case INDEX_op_ext_i32_i64:
715 tci_args_rr(insn, &r0, &r1);
716 regs[r0] = (int32_t)regs[r1];
717 break;
718 case INDEX_op_ext32u_i64:
719 case INDEX_op_extu_i32_i64:
720 tci_args_rr(insn, &r0, &r1);
721 regs[r0] = (uint32_t)regs[r1];
722 break;
723 #if TCG_TARGET_HAS_bswap64_i64
724 case INDEX_op_bswap64_i64:
725 tci_args_rr(insn, &r0, &r1);
726 regs[r0] = bswap64(regs[r1]);
727 break;
728 #endif
729 #endif /* TCG_TARGET_REG_BITS == 64 */
730
731 /* QEMU specific operations. */
732
733 case INDEX_op_exit_tb:
734 tci_args_l(insn, tb_ptr, &ptr);
735 return (uintptr_t)ptr;
736
737 case INDEX_op_goto_tb:
738 tci_args_l(insn, tb_ptr, &ptr);
739 tb_ptr = *(void **)ptr;
740 break;
741
742 case INDEX_op_qemu_ld_i32:
743 if (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS) {
744 tci_args_rrm(insn, &r0, &r1, &oi);
745 taddr = regs[r1];
746 } else {
747 tci_args_rrrm(insn, &r0, &r1, &r2, &oi);
748 taddr = tci_uint64(regs[r2], regs[r1]);
749 }
750 switch (get_memop(oi) & (MO_BSWAP | MO_SSIZE)) {
751 case MO_UB:
752 tmp32 = qemu_ld_ub;
753 break;
754 case MO_SB:
755 tmp32 = (int8_t)qemu_ld_ub;
756 break;
757 case MO_LEUW:
758 tmp32 = qemu_ld_leuw;
759 break;
760 case MO_LESW:
761 tmp32 = (int16_t)qemu_ld_leuw;
762 break;
763 case MO_LEUL:
764 tmp32 = qemu_ld_leul;
765 break;
766 case MO_BEUW:
767 tmp32 = qemu_ld_beuw;
768 break;
769 case MO_BESW:
770 tmp32 = (int16_t)qemu_ld_beuw;
771 break;
772 case MO_BEUL:
773 tmp32 = qemu_ld_beul;
774 break;
775 default:
776 g_assert_not_reached();
777 }
778 regs[r0] = tmp32;
779 break;
780
781 case INDEX_op_qemu_ld_i64:
782 if (TCG_TARGET_REG_BITS == 64) {
783 tci_args_rrm(insn, &r0, &r1, &oi);
784 taddr = regs[r1];
785 } else if (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS) {
786 tci_args_rrrm(insn, &r0, &r1, &r2, &oi);
787 taddr = regs[r2];
788 } else {
789 tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
790 taddr = tci_uint64(regs[r3], regs[r2]);
791 oi = regs[r4];
792 }
793 switch (get_memop(oi) & (MO_BSWAP | MO_SSIZE)) {
794 case MO_UB:
795 tmp64 = qemu_ld_ub;
796 break;
797 case MO_SB:
798 tmp64 = (int8_t)qemu_ld_ub;
799 break;
800 case MO_LEUW:
801 tmp64 = qemu_ld_leuw;
802 break;
803 case MO_LESW:
804 tmp64 = (int16_t)qemu_ld_leuw;
805 break;
806 case MO_LEUL:
807 tmp64 = qemu_ld_leul;
808 break;
809 case MO_LESL:
810 tmp64 = (int32_t)qemu_ld_leul;
811 break;
812 case MO_LEQ:
813 tmp64 = qemu_ld_leq;
814 break;
815 case MO_BEUW:
816 tmp64 = qemu_ld_beuw;
817 break;
818 case MO_BESW:
819 tmp64 = (int16_t)qemu_ld_beuw;
820 break;
821 case MO_BEUL:
822 tmp64 = qemu_ld_beul;
823 break;
824 case MO_BESL:
825 tmp64 = (int32_t)qemu_ld_beul;
826 break;
827 case MO_BEQ:
828 tmp64 = qemu_ld_beq;
829 break;
830 default:
831 g_assert_not_reached();
832 }
833 if (TCG_TARGET_REG_BITS == 32) {
834 tci_write_reg64(regs, r1, r0, tmp64);
835 } else {
836 regs[r0] = tmp64;
837 }
838 break;
839
840 case INDEX_op_qemu_st_i32:
841 if (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS) {
842 tci_args_rrm(insn, &r0, &r1, &oi);
843 taddr = regs[r1];
844 } else {
845 tci_args_rrrm(insn, &r0, &r1, &r2, &oi);
846 taddr = tci_uint64(regs[r2], regs[r1]);
847 }
848 tmp32 = regs[r0];
849 switch (get_memop(oi) & (MO_BSWAP | MO_SIZE)) {
850 case MO_UB:
851 qemu_st_b(tmp32);
852 break;
853 case MO_LEUW:
854 qemu_st_lew(tmp32);
855 break;
856 case MO_LEUL:
857 qemu_st_lel(tmp32);
858 break;
859 case MO_BEUW:
860 qemu_st_bew(tmp32);
861 break;
862 case MO_BEUL:
863 qemu_st_bel(tmp32);
864 break;
865 default:
866 g_assert_not_reached();
867 }
868 break;
869
870 case INDEX_op_qemu_st_i64:
871 if (TCG_TARGET_REG_BITS == 64) {
872 tci_args_rrm(insn, &r0, &r1, &oi);
873 taddr = regs[r1];
874 tmp64 = regs[r0];
875 } else {
876 if (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS) {
877 tci_args_rrrm(insn, &r0, &r1, &r2, &oi);
878 taddr = regs[r2];
879 } else {
880 tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
881 taddr = tci_uint64(regs[r3], regs[r2]);
882 oi = regs[r4];
883 }
884 tmp64 = tci_uint64(regs[r1], regs[r0]);
885 }
886 switch (get_memop(oi) & (MO_BSWAP | MO_SIZE)) {
887 case MO_UB:
888 qemu_st_b(tmp64);
889 break;
890 case MO_LEUW:
891 qemu_st_lew(tmp64);
892 break;
893 case MO_LEUL:
894 qemu_st_lel(tmp64);
895 break;
896 case MO_LEQ:
897 qemu_st_leq(tmp64);
898 break;
899 case MO_BEUW:
900 qemu_st_bew(tmp64);
901 break;
902 case MO_BEUL:
903 qemu_st_bel(tmp64);
904 break;
905 case MO_BEQ:
906 qemu_st_beq(tmp64);
907 break;
908 default:
909 g_assert_not_reached();
910 }
911 break;
912
913 case INDEX_op_mb:
914 /* Ensure ordering for all kinds */
915 smp_mb();
916 break;
917 default:
918 g_assert_not_reached();
919 }
920 }
921 }
922
923 /*
924 * Disassembler that matches the interpreter
925 */
926
927 static const char *str_r(TCGReg r)
928 {
929 static const char regs[TCG_TARGET_NB_REGS][4] = {
930 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
931 "r8", "r9", "r10", "r11", "r12", "r13", "env", "sp"
932 };
933
934 QEMU_BUILD_BUG_ON(TCG_AREG0 != TCG_REG_R14);
935 QEMU_BUILD_BUG_ON(TCG_REG_CALL_STACK != TCG_REG_R15);
936
937 assert((unsigned)r < TCG_TARGET_NB_REGS);
938 return regs[r];
939 }
940
941 static const char *str_c(TCGCond c)
942 {
943 static const char cond[16][8] = {
944 [TCG_COND_NEVER] = "never",
945 [TCG_COND_ALWAYS] = "always",
946 [TCG_COND_EQ] = "eq",
947 [TCG_COND_NE] = "ne",
948 [TCG_COND_LT] = "lt",
949 [TCG_COND_GE] = "ge",
950 [TCG_COND_LE] = "le",
951 [TCG_COND_GT] = "gt",
952 [TCG_COND_LTU] = "ltu",
953 [TCG_COND_GEU] = "geu",
954 [TCG_COND_LEU] = "leu",
955 [TCG_COND_GTU] = "gtu",
956 };
957
958 assert((unsigned)c < ARRAY_SIZE(cond));
959 assert(cond[c][0] != 0);
960 return cond[c];
961 }
962
963 /* Disassemble TCI bytecode. */
964 int print_insn_tci(bfd_vma addr, disassemble_info *info)
965 {
966 const uint32_t *tb_ptr = (const void *)(uintptr_t)addr;
967 const TCGOpDef *def;
968 const char *op_name;
969 uint32_t insn;
970 TCGOpcode op;
971 TCGReg r0, r1, r2, r3, r4;
972 #if TCG_TARGET_REG_BITS == 32
973 TCGReg r5;
974 #endif
975 tcg_target_ulong i1;
976 int32_t s2;
977 TCGCond c;
978 TCGMemOpIdx oi;
979 uint8_t pos, len;
980 void *ptr;
981
982 /* TCI is always the host, so we don't need to load indirect. */
983 insn = *tb_ptr++;
984
985 info->fprintf_func(info->stream, "%08x ", insn);
986
987 op = extract32(insn, 0, 8);
988 def = &tcg_op_defs[op];
989 op_name = def->name;
990
991 switch (op) {
992 case INDEX_op_br:
993 case INDEX_op_exit_tb:
994 case INDEX_op_goto_tb:
995 tci_args_l(insn, tb_ptr, &ptr);
996 info->fprintf_func(info->stream, "%-12s %p", op_name, ptr);
997 break;
998
999 case INDEX_op_call:
1000 tci_args_nl(insn, tb_ptr, &len, &ptr);
1001 info->fprintf_func(info->stream, "%-12s %d, %p", op_name, len, ptr);
1002 break;
1003
1004 case INDEX_op_brcond_i32:
1005 case INDEX_op_brcond_i64:
1006 tci_args_rl(insn, tb_ptr, &r0, &ptr);
1007 info->fprintf_func(info->stream, "%-12s %s, 0, ne, %p",
1008 op_name, str_r(r0), ptr);
1009 break;
1010
1011 case INDEX_op_setcond_i32:
1012 case INDEX_op_setcond_i64:
1013 tci_args_rrrc(insn, &r0, &r1, &r2, &c);
1014 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
1015 op_name, str_r(r0), str_r(r1), str_r(r2), str_c(c));
1016 break;
1017
1018 case INDEX_op_tci_movi:
1019 tci_args_ri(insn, &r0, &i1);
1020 info->fprintf_func(info->stream, "%-12s %s, 0x%" TCG_PRIlx,
1021 op_name, str_r(r0), i1);
1022 break;
1023
1024 case INDEX_op_tci_movl:
1025 tci_args_rl(insn, tb_ptr, &r0, &ptr);
1026 info->fprintf_func(info->stream, "%-12s %s, %p",
1027 op_name, str_r(r0), ptr);
1028 break;
1029
1030 case INDEX_op_ld8u_i32:
1031 case INDEX_op_ld8u_i64:
1032 case INDEX_op_ld8s_i32:
1033 case INDEX_op_ld8s_i64:
1034 case INDEX_op_ld16u_i32:
1035 case INDEX_op_ld16u_i64:
1036 case INDEX_op_ld16s_i32:
1037 case INDEX_op_ld16s_i64:
1038 case INDEX_op_ld32u_i64:
1039 case INDEX_op_ld32s_i64:
1040 case INDEX_op_ld_i32:
1041 case INDEX_op_ld_i64:
1042 case INDEX_op_st8_i32:
1043 case INDEX_op_st8_i64:
1044 case INDEX_op_st16_i32:
1045 case INDEX_op_st16_i64:
1046 case INDEX_op_st32_i64:
1047 case INDEX_op_st_i32:
1048 case INDEX_op_st_i64:
1049 tci_args_rrs(insn, &r0, &r1, &s2);
1050 info->fprintf_func(info->stream, "%-12s %s, %s, %d",
1051 op_name, str_r(r0), str_r(r1), s2);
1052 break;
1053
1054 case INDEX_op_mov_i32:
1055 case INDEX_op_mov_i64:
1056 case INDEX_op_ext8s_i32:
1057 case INDEX_op_ext8s_i64:
1058 case INDEX_op_ext8u_i32:
1059 case INDEX_op_ext8u_i64:
1060 case INDEX_op_ext16s_i32:
1061 case INDEX_op_ext16s_i64:
1062 case INDEX_op_ext16u_i32:
1063 case INDEX_op_ext32s_i64:
1064 case INDEX_op_ext32u_i64:
1065 case INDEX_op_ext_i32_i64:
1066 case INDEX_op_extu_i32_i64:
1067 case INDEX_op_bswap16_i32:
1068 case INDEX_op_bswap16_i64:
1069 case INDEX_op_bswap32_i32:
1070 case INDEX_op_bswap32_i64:
1071 case INDEX_op_bswap64_i64:
1072 case INDEX_op_not_i32:
1073 case INDEX_op_not_i64:
1074 case INDEX_op_neg_i32:
1075 case INDEX_op_neg_i64:
1076 tci_args_rr(insn, &r0, &r1);
1077 info->fprintf_func(info->stream, "%-12s %s, %s",
1078 op_name, str_r(r0), str_r(r1));
1079 break;
1080
1081 case INDEX_op_add_i32:
1082 case INDEX_op_add_i64:
1083 case INDEX_op_sub_i32:
1084 case INDEX_op_sub_i64:
1085 case INDEX_op_mul_i32:
1086 case INDEX_op_mul_i64:
1087 case INDEX_op_and_i32:
1088 case INDEX_op_and_i64:
1089 case INDEX_op_or_i32:
1090 case INDEX_op_or_i64:
1091 case INDEX_op_xor_i32:
1092 case INDEX_op_xor_i64:
1093 case INDEX_op_div_i32:
1094 case INDEX_op_div_i64:
1095 case INDEX_op_rem_i32:
1096 case INDEX_op_rem_i64:
1097 case INDEX_op_divu_i32:
1098 case INDEX_op_divu_i64:
1099 case INDEX_op_remu_i32:
1100 case INDEX_op_remu_i64:
1101 case INDEX_op_shl_i32:
1102 case INDEX_op_shl_i64:
1103 case INDEX_op_shr_i32:
1104 case INDEX_op_shr_i64:
1105 case INDEX_op_sar_i32:
1106 case INDEX_op_sar_i64:
1107 case INDEX_op_rotl_i32:
1108 case INDEX_op_rotl_i64:
1109 case INDEX_op_rotr_i32:
1110 case INDEX_op_rotr_i64:
1111 tci_args_rrr(insn, &r0, &r1, &r2);
1112 info->fprintf_func(info->stream, "%-12s %s, %s, %s",
1113 op_name, str_r(r0), str_r(r1), str_r(r2));
1114 break;
1115
1116 case INDEX_op_deposit_i32:
1117 case INDEX_op_deposit_i64:
1118 tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
1119 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %d, %d",
1120 op_name, str_r(r0), str_r(r1), str_r(r2), pos, len);
1121 break;
1122
1123 #if TCG_TARGET_REG_BITS == 32
1124 case INDEX_op_setcond2_i32:
1125 tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &c);
1126 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s, %s, %s",
1127 op_name, str_r(r0), str_r(r1), str_r(r2),
1128 str_r(r3), str_r(r4), str_c(c));
1129 break;
1130
1131 case INDEX_op_mulu2_i32:
1132 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
1133 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
1134 op_name, str_r(r0), str_r(r1),
1135 str_r(r2), str_r(r3));
1136 break;
1137
1138 case INDEX_op_add2_i32:
1139 case INDEX_op_sub2_i32:
1140 tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
1141 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s, %s, %s",
1142 op_name, str_r(r0), str_r(r1), str_r(r2),
1143 str_r(r3), str_r(r4), str_r(r5));
1144 break;
1145 #endif
1146
1147 case INDEX_op_qemu_ld_i64:
1148 case INDEX_op_qemu_st_i64:
1149 len = DIV_ROUND_UP(64, TCG_TARGET_REG_BITS);
1150 goto do_qemu_ldst;
1151 case INDEX_op_qemu_ld_i32:
1152 case INDEX_op_qemu_st_i32:
1153 len = 1;
1154 do_qemu_ldst:
1155 len += DIV_ROUND_UP(TARGET_LONG_BITS, TCG_TARGET_REG_BITS);
1156 switch (len) {
1157 case 2:
1158 tci_args_rrm(insn, &r0, &r1, &oi);
1159 info->fprintf_func(info->stream, "%-12s %s, %s, %x",
1160 op_name, str_r(r0), str_r(r1), oi);
1161 break;
1162 case 3:
1163 tci_args_rrrm(insn, &r0, &r1, &r2, &oi);
1164 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %x",
1165 op_name, str_r(r0), str_r(r1), str_r(r2), oi);
1166 break;
1167 case 4:
1168 tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
1169 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s, %s",
1170 op_name, str_r(r0), str_r(r1),
1171 str_r(r2), str_r(r3), str_r(r4));
1172 break;
1173 default:
1174 g_assert_not_reached();
1175 }
1176 break;
1177
1178 case 0:
1179 /* tcg_out_nop_fill uses zeros */
1180 if (insn == 0) {
1181 info->fprintf_func(info->stream, "align");
1182 break;
1183 }
1184 /* fall through */
1185
1186 default:
1187 info->fprintf_func(info->stream, "illegal opcode %d", op);
1188 break;
1189 }
1190
1191 return sizeof(insn);
1192 }