master
c 1,033 lines 30.7 KB
Raw
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 "tcg/tcg.h"
22 #include "tcg/helper-info.h"
23 #include "tcg/tcg-ldst.h"
24 #include "disas/dis-asm.h"
25 #include "tcg-has.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 /*
42 * Load sets of arguments all at once. The naming convention is:
43 * tci_args_<arguments>
44 * where arguments is a sequence of
45 *
46 * b = immediate (bit position)
47 * c = condition (TCGCond)
48 * i = immediate (uint32_t)
49 * I = immediate (tcg_target_ulong)
50 * l = label or pointer
51 * m = immediate (MemOpIdx)
52 * n = immediate (call return length)
53 * r = register
54 * s = signed ldst offset
55 */
56
57 static void tci_args_l(uint32_t insn, const void *tb_ptr, void **l0)
58 {
59 int diff = sextract32(insn, 12, 20);
60 *l0 = diff ? (void *)tb_ptr + diff : NULL;
61 }
62
63 static void tci_args_r(uint32_t insn, TCGReg *r0)
64 {
65 *r0 = extract32(insn, 8, 4);
66 }
67
68 static void tci_args_nl(uint32_t insn, const void *tb_ptr,
69 uint8_t *n0, void **l1)
70 {
71 *n0 = extract32(insn, 8, 4);
72 *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
73 }
74
75 static void tci_args_rl(uint32_t insn, const void *tb_ptr,
76 TCGReg *r0, void **l1)
77 {
78 *r0 = extract32(insn, 8, 4);
79 *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
80 }
81
82 static void tci_args_rr(uint32_t insn, TCGReg *r0, TCGReg *r1)
83 {
84 *r0 = extract32(insn, 8, 4);
85 *r1 = extract32(insn, 12, 4);
86 }
87
88 static void tci_args_ri(uint32_t insn, TCGReg *r0, tcg_target_ulong *i1)
89 {
90 *r0 = extract32(insn, 8, 4);
91 *i1 = sextract32(insn, 12, 20);
92 }
93
94 static void tci_args_rrm(uint32_t insn, TCGReg *r0,
95 TCGReg *r1, MemOpIdx *m2)
96 {
97 *r0 = extract32(insn, 8, 4);
98 *r1 = extract32(insn, 12, 4);
99 *m2 = extract32(insn, 16, 16);
100 }
101
102 static void tci_args_rrr(uint32_t insn, TCGReg *r0, TCGReg *r1, TCGReg *r2)
103 {
104 *r0 = extract32(insn, 8, 4);
105 *r1 = extract32(insn, 12, 4);
106 *r2 = extract32(insn, 16, 4);
107 }
108
109 static void tci_args_rrs(uint32_t insn, TCGReg *r0, TCGReg *r1, int32_t *i2)
110 {
111 *r0 = extract32(insn, 8, 4);
112 *r1 = extract32(insn, 12, 4);
113 *i2 = sextract32(insn, 16, 16);
114 }
115
116 static void tci_args_rrbb(uint32_t insn, TCGReg *r0, TCGReg *r1,
117 uint8_t *i2, uint8_t *i3)
118 {
119 *r0 = extract32(insn, 8, 4);
120 *r1 = extract32(insn, 12, 4);
121 *i2 = extract32(insn, 16, 6);
122 *i3 = extract32(insn, 22, 6);
123 }
124
125 static void tci_args_rrrc(uint32_t insn,
126 TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGCond *c3)
127 {
128 *r0 = extract32(insn, 8, 4);
129 *r1 = extract32(insn, 12, 4);
130 *r2 = extract32(insn, 16, 4);
131 *c3 = extract32(insn, 20, 4);
132 }
133
134 static void tci_args_rrrbb(uint32_t insn, TCGReg *r0, TCGReg *r1,
135 TCGReg *r2, uint8_t *i3, uint8_t *i4)
136 {
137 *r0 = extract32(insn, 8, 4);
138 *r1 = extract32(insn, 12, 4);
139 *r2 = extract32(insn, 16, 4);
140 *i3 = extract32(insn, 20, 6);
141 *i4 = extract32(insn, 26, 6);
142 }
143
144 static void tci_args_rrrr(uint32_t insn,
145 TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGReg *r3)
146 {
147 *r0 = extract32(insn, 8, 4);
148 *r1 = extract32(insn, 12, 4);
149 *r2 = extract32(insn, 16, 4);
150 *r3 = extract32(insn, 20, 4);
151 }
152
153 static void tci_args_rrrrrc(uint32_t insn, TCGReg *r0, TCGReg *r1,
154 TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGCond *c5)
155 {
156 *r0 = extract32(insn, 8, 4);
157 *r1 = extract32(insn, 12, 4);
158 *r2 = extract32(insn, 16, 4);
159 *r3 = extract32(insn, 20, 4);
160 *r4 = extract32(insn, 24, 4);
161 *c5 = extract32(insn, 28, 4);
162 }
163
164 static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition)
165 {
166 bool result = false;
167 int32_t i0 = u0;
168 int32_t i1 = u1;
169 switch (condition) {
170 case TCG_COND_EQ:
171 result = (u0 == u1);
172 break;
173 case TCG_COND_NE:
174 result = (u0 != u1);
175 break;
176 case TCG_COND_LT:
177 result = (i0 < i1);
178 break;
179 case TCG_COND_GE:
180 result = (i0 >= i1);
181 break;
182 case TCG_COND_LE:
183 result = (i0 <= i1);
184 break;
185 case TCG_COND_GT:
186 result = (i0 > i1);
187 break;
188 case TCG_COND_LTU:
189 result = (u0 < u1);
190 break;
191 case TCG_COND_GEU:
192 result = (u0 >= u1);
193 break;
194 case TCG_COND_LEU:
195 result = (u0 <= u1);
196 break;
197 case TCG_COND_GTU:
198 result = (u0 > u1);
199 break;
200 case TCG_COND_TSTEQ:
201 result = (u0 & u1) == 0;
202 break;
203 case TCG_COND_TSTNE:
204 result = (u0 & u1) != 0;
205 break;
206 default:
207 g_assert_not_reached();
208 }
209 return result;
210 }
211
212 static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
213 {
214 bool result = false;
215 int64_t i0 = u0;
216 int64_t i1 = u1;
217 switch (condition) {
218 case TCG_COND_EQ:
219 result = (u0 == u1);
220 break;
221 case TCG_COND_NE:
222 result = (u0 != u1);
223 break;
224 case TCG_COND_LT:
225 result = (i0 < i1);
226 break;
227 case TCG_COND_GE:
228 result = (i0 >= i1);
229 break;
230 case TCG_COND_LE:
231 result = (i0 <= i1);
232 break;
233 case TCG_COND_GT:
234 result = (i0 > i1);
235 break;
236 case TCG_COND_LTU:
237 result = (u0 < u1);
238 break;
239 case TCG_COND_GEU:
240 result = (u0 >= u1);
241 break;
242 case TCG_COND_LEU:
243 result = (u0 <= u1);
244 break;
245 case TCG_COND_GTU:
246 result = (u0 > u1);
247 break;
248 case TCG_COND_TSTEQ:
249 result = (u0 & u1) == 0;
250 break;
251 case TCG_COND_TSTNE:
252 result = (u0 & u1) != 0;
253 break;
254 default:
255 g_assert_not_reached();
256 }
257 return result;
258 }
259
260 static uint64_t tci_qemu_ld(CPUArchState *env, uint64_t taddr,
261 MemOpIdx oi, const void *tb_ptr)
262 {
263 MemOp mop = get_memop(oi);
264 uintptr_t ra = (uintptr_t)tb_ptr;
265
266 switch (mop & MO_SSIZE) {
267 case MO_UB:
268 return helper_ldub_mmu(env, taddr, oi, ra);
269 case MO_SB:
270 return helper_ldsb_mmu(env, taddr, oi, ra);
271 case MO_UW:
272 return helper_lduw_mmu(env, taddr, oi, ra);
273 case MO_SW:
274 return helper_ldsw_mmu(env, taddr, oi, ra);
275 case MO_UL:
276 return helper_ldul_mmu(env, taddr, oi, ra);
277 case MO_SL:
278 return helper_ldsl_mmu(env, taddr, oi, ra);
279 case MO_UQ:
280 return helper_ldq_mmu(env, taddr, oi, ra);
281 default:
282 g_assert_not_reached();
283 }
284 }
285
286 static void tci_qemu_st(CPUArchState *env, uint64_t taddr, uint64_t val,
287 MemOpIdx oi, const void *tb_ptr)
288 {
289 MemOp mop = get_memop(oi);
290 uintptr_t ra = (uintptr_t)tb_ptr;
291
292 switch (mop & MO_SIZE) {
293 case MO_UB:
294 helper_stb_mmu(env, taddr, val, oi, ra);
295 break;
296 case MO_UW:
297 helper_stw_mmu(env, taddr, val, oi, ra);
298 break;
299 case MO_UL:
300 helper_stl_mmu(env, taddr, val, oi, ra);
301 break;
302 case MO_UQ:
303 helper_stq_mmu(env, taddr, val, oi, ra);
304 break;
305 default:
306 g_assert_not_reached();
307 }
308 }
309
310 /* Interpret pseudo code in tb. */
311 /*
312 * Disable CFI checks.
313 * One possible operation in the pseudo code is a call to binary code.
314 * Therefore, disable CFI checks in the interpreter function
315 */
316 uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
317 const void *v_tb_ptr)
318 {
319 const uint32_t *tb_ptr = v_tb_ptr;
320 tcg_target_ulong regs[TCG_TARGET_NB_REGS];
321 uint64_t stack[(TCG_STATIC_CALL_ARGS_SIZE + TCG_STATIC_FRAME_SIZE)
322 / sizeof(uint64_t)];
323 bool carry = false;
324
325 regs[TCG_AREG0] = (tcg_target_ulong)env;
326 regs[TCG_REG_CALL_STACK] = (uintptr_t)stack;
327 tci_assert(tb_ptr);
328
329 for (;;) {
330 uint32_t insn;
331 TCGOpcode opc;
332 TCGReg r0, r1, r2, r3, r4;
333 tcg_target_ulong t1;
334 TCGCond condition;
335 uint8_t pos, len;
336 uint32_t tmp32;
337 uint64_t taddr;
338 MemOpIdx oi;
339 int32_t ofs;
340 void *ptr;
341
342 insn = *tb_ptr++;
343 opc = extract32(insn, 0, 8);
344
345 switch (opc) {
346 case INDEX_op_call:
347 {
348 void *call_slots[MAX_CALL_IARGS];
349 ffi_cif *cif;
350 void *func;
351 unsigned i, s, n;
352
353 tci_args_nl(insn, tb_ptr, &len, &ptr);
354 func = ((void **)ptr)[0];
355 cif = ((void **)ptr)[1];
356
357 n = cif->nargs;
358 for (i = s = 0; i < n; ++i) {
359 ffi_type *t = cif->arg_types[i];
360 call_slots[i] = &stack[s];
361 s += DIV_ROUND_UP(t->size, 8);
362 }
363
364 /* Helper functions may need to access the "return address" */
365 tci_tb_ptr = (uintptr_t)tb_ptr;
366 ffi_call(cif, func, stack, call_slots);
367 }
368
369 switch (len) {
370 case 0: /* void */
371 break;
372 case 1: /* uint32_t */
373 /*
374 * The result winds up "left-aligned" in the stack[0] slot.
375 * Note that libffi has an odd special case in that it will
376 * always widen an integral result to ffi_arg.
377 */
378 if (sizeof(ffi_arg) == 8) {
379 regs[TCG_REG_R0] = (uint32_t)stack[0];
380 } else {
381 regs[TCG_REG_R0] = *(uint32_t *)stack;
382 }
383 break;
384 case 2: /* uint64_t */
385 memcpy(&regs[TCG_REG_R0], stack, 8);
386 break;
387 case 3: /* Int128 */
388 memcpy(&regs[TCG_REG_R0], stack, 16);
389 break;
390 default:
391 g_assert_not_reached();
392 }
393 break;
394
395 case INDEX_op_br:
396 tci_args_l(insn, tb_ptr, &ptr);
397 tb_ptr = ptr;
398 continue;
399 case INDEX_op_setcond:
400 tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
401 regs[r0] = tci_compare64(regs[r1], regs[r2], condition);
402 break;
403 case INDEX_op_movcond:
404 tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
405 tmp32 = tci_compare64(regs[r1], regs[r2], condition);
406 regs[r0] = regs[tmp32 ? r3 : r4];
407 break;
408 case INDEX_op_mov:
409 tci_args_rr(insn, &r0, &r1);
410 regs[r0] = regs[r1];
411 break;
412 case INDEX_op_tci_movi:
413 tci_args_ri(insn, &r0, &t1);
414 regs[r0] = t1;
415 break;
416 case INDEX_op_tci_movl:
417 tci_args_rl(insn, tb_ptr, &r0, &ptr);
418 regs[r0] = *(tcg_target_ulong *)ptr;
419 break;
420 case INDEX_op_tci_setcarry:
421 carry = true;
422 break;
423
424 /* Load/store operations (32 bit). */
425
426 case INDEX_op_ld8u:
427 tci_args_rrs(insn, &r0, &r1, &ofs);
428 ptr = (void *)(regs[r1] + ofs);
429 regs[r0] = *(uint8_t *)ptr;
430 break;
431 case INDEX_op_ld8s:
432 tci_args_rrs(insn, &r0, &r1, &ofs);
433 ptr = (void *)(regs[r1] + ofs);
434 regs[r0] = *(int8_t *)ptr;
435 break;
436 case INDEX_op_ld16u:
437 tci_args_rrs(insn, &r0, &r1, &ofs);
438 ptr = (void *)(regs[r1] + ofs);
439 regs[r0] = *(uint16_t *)ptr;
440 break;
441 case INDEX_op_ld16s:
442 tci_args_rrs(insn, &r0, &r1, &ofs);
443 ptr = (void *)(regs[r1] + ofs);
444 regs[r0] = *(int16_t *)ptr;
445 break;
446 case INDEX_op_ld:
447 tci_args_rrs(insn, &r0, &r1, &ofs);
448 ptr = (void *)(regs[r1] + ofs);
449 regs[r0] = *(tcg_target_ulong *)ptr;
450 break;
451 case INDEX_op_st8:
452 tci_args_rrs(insn, &r0, &r1, &ofs);
453 ptr = (void *)(regs[r1] + ofs);
454 *(uint8_t *)ptr = regs[r0];
455 break;
456 case INDEX_op_st16:
457 tci_args_rrs(insn, &r0, &r1, &ofs);
458 ptr = (void *)(regs[r1] + ofs);
459 *(uint16_t *)ptr = regs[r0];
460 break;
461 case INDEX_op_st:
462 tci_args_rrs(insn, &r0, &r1, &ofs);
463 ptr = (void *)(regs[r1] + ofs);
464 *(tcg_target_ulong *)ptr = regs[r0];
465 break;
466
467 /* Arithmetic operations (mixed 32/64 bit). */
468
469 case INDEX_op_add:
470 tci_args_rrr(insn, &r0, &r1, &r2);
471 regs[r0] = regs[r1] + regs[r2];
472 break;
473 case INDEX_op_sub:
474 tci_args_rrr(insn, &r0, &r1, &r2);
475 regs[r0] = regs[r1] - regs[r2];
476 break;
477 case INDEX_op_mul:
478 tci_args_rrr(insn, &r0, &r1, &r2);
479 regs[r0] = regs[r1] * regs[r2];
480 break;
481 case INDEX_op_and:
482 tci_args_rrr(insn, &r0, &r1, &r2);
483 regs[r0] = regs[r1] & regs[r2];
484 break;
485 case INDEX_op_or:
486 tci_args_rrr(insn, &r0, &r1, &r2);
487 regs[r0] = regs[r1] | regs[r2];
488 break;
489 case INDEX_op_xor:
490 tci_args_rrr(insn, &r0, &r1, &r2);
491 regs[r0] = regs[r1] ^ regs[r2];
492 break;
493 case INDEX_op_andc:
494 tci_args_rrr(insn, &r0, &r1, &r2);
495 regs[r0] = regs[r1] & ~regs[r2];
496 break;
497 case INDEX_op_orc:
498 tci_args_rrr(insn, &r0, &r1, &r2);
499 regs[r0] = regs[r1] | ~regs[r2];
500 break;
501 case INDEX_op_eqv:
502 tci_args_rrr(insn, &r0, &r1, &r2);
503 regs[r0] = ~(regs[r1] ^ regs[r2]);
504 break;
505 case INDEX_op_nand:
506 tci_args_rrr(insn, &r0, &r1, &r2);
507 regs[r0] = ~(regs[r1] & regs[r2]);
508 break;
509 case INDEX_op_nor:
510 tci_args_rrr(insn, &r0, &r1, &r2);
511 regs[r0] = ~(regs[r1] | regs[r2]);
512 break;
513 case INDEX_op_neg:
514 tci_args_rr(insn, &r0, &r1);
515 regs[r0] = -regs[r1];
516 break;
517 case INDEX_op_not:
518 tci_args_rr(insn, &r0, &r1);
519 regs[r0] = ~regs[r1];
520 break;
521 case INDEX_op_ctpop:
522 tci_args_rr(insn, &r0, &r1);
523 regs[r0] = ctpop64(regs[r1]);
524 break;
525 case INDEX_op_addco:
526 tci_args_rrr(insn, &r0, &r1, &r2);
527 t1 = regs[r1] + regs[r2];
528 carry = t1 < regs[r1];
529 regs[r0] = t1;
530 break;
531 case INDEX_op_addci:
532 tci_args_rrr(insn, &r0, &r1, &r2);
533 regs[r0] = regs[r1] + regs[r2] + carry;
534 break;
535 case INDEX_op_addcio:
536 tci_args_rrr(insn, &r0, &r1, &r2);
537 if (carry) {
538 t1 = regs[r1] + regs[r2] + 1;
539 carry = t1 <= regs[r1];
540 } else {
541 t1 = regs[r1] + regs[r2];
542 carry = t1 < regs[r1];
543 }
544 regs[r0] = t1;
545 break;
546 case INDEX_op_subbo:
547 tci_args_rrr(insn, &r0, &r1, &r2);
548 carry = regs[r1] < regs[r2];
549 regs[r0] = regs[r1] - regs[r2];
550 break;
551 case INDEX_op_subbi:
552 tci_args_rrr(insn, &r0, &r1, &r2);
553 regs[r0] = regs[r1] - regs[r2] - carry;
554 break;
555 case INDEX_op_subbio:
556 tci_args_rrr(insn, &r0, &r1, &r2);
557 if (carry) {
558 carry = regs[r1] <= regs[r2];
559 regs[r0] = regs[r1] - regs[r2] - 1;
560 } else {
561 carry = regs[r1] < regs[r2];
562 regs[r0] = regs[r1] - regs[r2];
563 }
564 break;
565 case INDEX_op_muls2:
566 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
567 muls64(&regs[r0], &regs[r1], regs[r2], regs[r3]);
568 break;
569 case INDEX_op_mulu2:
570 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
571 mulu64(&regs[r0], &regs[r1], regs[r2], regs[r3]);
572 break;
573
574 /* Arithmetic operations (32 bit). */
575
576 case INDEX_op_tci_divs32:
577 tci_args_rrr(insn, &r0, &r1, &r2);
578 regs[r0] = (int32_t)regs[r1] / (int32_t)regs[r2];
579 break;
580 case INDEX_op_tci_divu32:
581 tci_args_rrr(insn, &r0, &r1, &r2);
582 regs[r0] = (uint32_t)regs[r1] / (uint32_t)regs[r2];
583 break;
584 case INDEX_op_tci_rems32:
585 tci_args_rrr(insn, &r0, &r1, &r2);
586 regs[r0] = (int32_t)regs[r1] % (int32_t)regs[r2];
587 break;
588 case INDEX_op_tci_remu32:
589 tci_args_rrr(insn, &r0, &r1, &r2);
590 regs[r0] = (uint32_t)regs[r1] % (uint32_t)regs[r2];
591 break;
592 case INDEX_op_tci_clz32:
593 tci_args_rrr(insn, &r0, &r1, &r2);
594 tmp32 = regs[r1];
595 regs[r0] = tmp32 ? clz32(tmp32) : regs[r2];
596 break;
597 case INDEX_op_tci_ctz32:
598 tci_args_rrr(insn, &r0, &r1, &r2);
599 tmp32 = regs[r1];
600 regs[r0] = tmp32 ? ctz32(tmp32) : regs[r2];
601 break;
602 case INDEX_op_tci_setcond32:
603 tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
604 regs[r0] = tci_compare32(regs[r1], regs[r2], condition);
605 break;
606 case INDEX_op_tci_movcond32:
607 tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
608 tmp32 = tci_compare32(regs[r1], regs[r2], condition);
609 regs[r0] = regs[tmp32 ? r3 : r4];
610 break;
611
612 /* Shift/rotate operations. */
613
614 case INDEX_op_shl:
615 tci_args_rrr(insn, &r0, &r1, &r2);
616 regs[r0] = regs[r1] << (regs[r2] % TCG_TARGET_REG_BITS);
617 break;
618 case INDEX_op_shr:
619 tci_args_rrr(insn, &r0, &r1, &r2);
620 regs[r0] = regs[r1] >> (regs[r2] % TCG_TARGET_REG_BITS);
621 break;
622 case INDEX_op_sar:
623 tci_args_rrr(insn, &r0, &r1, &r2);
624 regs[r0] = ((tcg_target_long)regs[r1]
625 >> (regs[r2] % TCG_TARGET_REG_BITS));
626 break;
627 case INDEX_op_tci_rotl32:
628 tci_args_rrr(insn, &r0, &r1, &r2);
629 regs[r0] = rol32(regs[r1], regs[r2] & 31);
630 break;
631 case INDEX_op_tci_rotr32:
632 tci_args_rrr(insn, &r0, &r1, &r2);
633 regs[r0] = ror32(regs[r1], regs[r2] & 31);
634 break;
635 case INDEX_op_deposit:
636 tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
637 regs[r0] = deposit64(regs[r1], pos, len, regs[r2]);
638 break;
639 case INDEX_op_extract:
640 tci_args_rrbb(insn, &r0, &r1, &pos, &len);
641 regs[r0] = extract64(regs[r1], pos, len);
642 break;
643 case INDEX_op_sextract:
644 tci_args_rrbb(insn, &r0, &r1, &pos, &len);
645 regs[r0] = sextract64(regs[r1], pos, len);
646 break;
647 case INDEX_op_brcond:
648 tci_args_rl(insn, tb_ptr, &r0, &ptr);
649 if (regs[r0]) {
650 tb_ptr = ptr;
651 }
652 break;
653 case INDEX_op_bswap16:
654 tci_args_rr(insn, &r0, &r1);
655 regs[r0] = bswap16(regs[r1]);
656 break;
657 case INDEX_op_bswap32:
658 tci_args_rr(insn, &r0, &r1);
659 regs[r0] = bswap32(regs[r1]);
660 break;
661
662 /* Load/store operations (64 bit). */
663
664 case INDEX_op_ld32u:
665 tci_args_rrs(insn, &r0, &r1, &ofs);
666 ptr = (void *)(regs[r1] + ofs);
667 regs[r0] = *(uint32_t *)ptr;
668 break;
669 case INDEX_op_ld32s:
670 tci_args_rrs(insn, &r0, &r1, &ofs);
671 ptr = (void *)(regs[r1] + ofs);
672 regs[r0] = *(int32_t *)ptr;
673 break;
674 case INDEX_op_st32:
675 tci_args_rrs(insn, &r0, &r1, &ofs);
676 ptr = (void *)(regs[r1] + ofs);
677 *(uint32_t *)ptr = regs[r0];
678 break;
679
680 /* Arithmetic operations (64 bit). */
681
682 case INDEX_op_divs:
683 tci_args_rrr(insn, &r0, &r1, &r2);
684 regs[r0] = (int64_t)regs[r1] / (int64_t)regs[r2];
685 break;
686 case INDEX_op_divu:
687 tci_args_rrr(insn, &r0, &r1, &r2);
688 regs[r0] = (uint64_t)regs[r1] / (uint64_t)regs[r2];
689 break;
690 case INDEX_op_rems:
691 tci_args_rrr(insn, &r0, &r1, &r2);
692 regs[r0] = (int64_t)regs[r1] % (int64_t)regs[r2];
693 break;
694 case INDEX_op_remu:
695 tci_args_rrr(insn, &r0, &r1, &r2);
696 regs[r0] = (uint64_t)regs[r1] % (uint64_t)regs[r2];
697 break;
698 case INDEX_op_clz:
699 tci_args_rrr(insn, &r0, &r1, &r2);
700 regs[r0] = regs[r1] ? clz64(regs[r1]) : regs[r2];
701 break;
702 case INDEX_op_ctz:
703 tci_args_rrr(insn, &r0, &r1, &r2);
704 regs[r0] = regs[r1] ? ctz64(regs[r1]) : regs[r2];
705 break;
706
707 /* Shift/rotate operations (64 bit). */
708
709 case INDEX_op_rotl:
710 tci_args_rrr(insn, &r0, &r1, &r2);
711 regs[r0] = rol64(regs[r1], regs[r2] & 63);
712 break;
713 case INDEX_op_rotr:
714 tci_args_rrr(insn, &r0, &r1, &r2);
715 regs[r0] = ror64(regs[r1], regs[r2] & 63);
716 break;
717 case INDEX_op_ext_i32_i64:
718 tci_args_rr(insn, &r0, &r1);
719 regs[r0] = (int32_t)regs[r1];
720 break;
721 case INDEX_op_extu_i32_i64:
722 tci_args_rr(insn, &r0, &r1);
723 regs[r0] = (uint32_t)regs[r1];
724 break;
725 case INDEX_op_bswap64:
726 tci_args_rr(insn, &r0, &r1);
727 regs[r0] = bswap64(regs[r1]);
728 break;
729
730 /* QEMU specific operations. */
731
732 case INDEX_op_exit_tb:
733 tci_args_l(insn, tb_ptr, &ptr);
734 return (uintptr_t)ptr;
735
736 case INDEX_op_goto_tb:
737 tci_args_l(insn, tb_ptr, &ptr);
738 tb_ptr = *(void **)ptr;
739 break;
740
741 case INDEX_op_goto_ptr:
742 tci_args_r(insn, &r0);
743 ptr = (void *)regs[r0];
744 if (!ptr) {
745 return 0;
746 }
747 tb_ptr = ptr;
748 break;
749
750 case INDEX_op_qemu_ld:
751 tci_args_rrm(insn, &r0, &r1, &oi);
752 taddr = regs[r1];
753 regs[r0] = tci_qemu_ld(env, taddr, oi, tb_ptr);
754 break;
755 case INDEX_op_tci_qemu_ld_rrr:
756 tci_args_rrr(insn, &r0, &r1, &r2);
757 taddr = regs[r1];
758 oi = regs[r2];
759 regs[r0] = tci_qemu_ld(env, taddr, oi, tb_ptr);
760 break;
761
762 case INDEX_op_qemu_st:
763 tci_args_rrm(insn, &r0, &r1, &oi);
764 taddr = regs[r1];
765 tci_qemu_st(env, taddr, regs[r0], oi, tb_ptr);
766 break;
767 case INDEX_op_tci_qemu_st_rrr:
768 tci_args_rrr(insn, &r0, &r1, &r2);
769 taddr = regs[r1];
770 oi = regs[r2];
771 tci_qemu_st(env, taddr, regs[r0], oi, tb_ptr);
772 break;
773
774 case INDEX_op_mb:
775 /* Ensure ordering for all kinds */
776 smp_mb();
777 break;
778 default:
779 g_assert_not_reached();
780 }
781 }
782 }
783
784 /*
785 * Disassembler that matches the interpreter
786 */
787
788 static const char *str_r(TCGReg r)
789 {
790 static const char regs[TCG_TARGET_NB_REGS][4] = {
791 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
792 "r8", "r9", "r10", "r11", "r12", "r13", "env", "sp"
793 };
794
795 QEMU_BUILD_BUG_ON(TCG_AREG0 != TCG_REG_R14);
796 QEMU_BUILD_BUG_ON(TCG_REG_CALL_STACK != TCG_REG_R15);
797
798 assert((unsigned)r < TCG_TARGET_NB_REGS);
799 return regs[r];
800 }
801
802 static const char *str_c(TCGCond c)
803 {
804 static const char cond[16][8] = {
805 [TCG_COND_NEVER] = "never",
806 [TCG_COND_ALWAYS] = "always",
807 [TCG_COND_EQ] = "eq",
808 [TCG_COND_NE] = "ne",
809 [TCG_COND_LT] = "lt",
810 [TCG_COND_GE] = "ge",
811 [TCG_COND_LE] = "le",
812 [TCG_COND_GT] = "gt",
813 [TCG_COND_LTU] = "ltu",
814 [TCG_COND_GEU] = "geu",
815 [TCG_COND_LEU] = "leu",
816 [TCG_COND_GTU] = "gtu",
817 [TCG_COND_TSTEQ] = "tsteq",
818 [TCG_COND_TSTNE] = "tstne",
819 };
820
821 assert((unsigned)c < ARRAY_SIZE(cond));
822 assert(cond[c][0] != 0);
823 return cond[c];
824 }
825
826 /* Disassemble TCI bytecode. */
827 int print_insn_tci(bfd_vma addr, disassemble_info *info)
828 {
829 const uint32_t *tb_ptr = (const void *)(uintptr_t)addr;
830 const TCGOpDef *def;
831 const char *op_name;
832 uint32_t insn;
833 TCGOpcode op;
834 TCGReg r0, r1, r2, r3, r4;
835 tcg_target_ulong i1;
836 int32_t s2;
837 TCGCond c;
838 MemOpIdx oi;
839 uint8_t pos, len;
840 void *ptr;
841
842 /* TCI is always the host, so we don't need to load indirect. */
843 insn = *tb_ptr++;
844
845 info->fprintf_func(info->stream, "%08x ", insn);
846
847 op = extract32(insn, 0, 8);
848 def = &tcg_op_defs[op];
849 op_name = def->name;
850
851 switch (op) {
852 case INDEX_op_br:
853 case INDEX_op_exit_tb:
854 case INDEX_op_goto_tb:
855 tci_args_l(insn, tb_ptr, &ptr);
856 info->fprintf_func(info->stream, "%-12s %p", op_name, ptr);
857 break;
858
859 case INDEX_op_goto_ptr:
860 tci_args_r(insn, &r0);
861 info->fprintf_func(info->stream, "%-12s %s", op_name, str_r(r0));
862 break;
863
864 case INDEX_op_call:
865 tci_args_nl(insn, tb_ptr, &len, &ptr);
866 info->fprintf_func(info->stream, "%-12s %d, %p", op_name, len, ptr);
867 break;
868
869 case INDEX_op_brcond:
870 tci_args_rl(insn, tb_ptr, &r0, &ptr);
871 info->fprintf_func(info->stream, "%-12s %s, 0, ne, %p",
872 op_name, str_r(r0), ptr);
873 break;
874
875 case INDEX_op_setcond:
876 case INDEX_op_tci_setcond32:
877 tci_args_rrrc(insn, &r0, &r1, &r2, &c);
878 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
879 op_name, str_r(r0), str_r(r1), str_r(r2), str_c(c));
880 break;
881
882 case INDEX_op_tci_movi:
883 tci_args_ri(insn, &r0, &i1);
884 info->fprintf_func(info->stream, "%-12s %s, 0x%" TCG_PRIlx,
885 op_name, str_r(r0), i1);
886 break;
887
888 case INDEX_op_tci_movl:
889 tci_args_rl(insn, tb_ptr, &r0, &ptr);
890 info->fprintf_func(info->stream, "%-12s %s, %p",
891 op_name, str_r(r0), ptr);
892 break;
893
894 case INDEX_op_tci_setcarry:
895 info->fprintf_func(info->stream, "%-12s", op_name);
896 break;
897
898 case INDEX_op_ld8u:
899 case INDEX_op_ld8s:
900 case INDEX_op_ld16u:
901 case INDEX_op_ld16s:
902 case INDEX_op_ld32u:
903 case INDEX_op_ld:
904 case INDEX_op_st8:
905 case INDEX_op_st16:
906 case INDEX_op_st32:
907 case INDEX_op_st:
908 tci_args_rrs(insn, &r0, &r1, &s2);
909 info->fprintf_func(info->stream, "%-12s %s, %s, %d",
910 op_name, str_r(r0), str_r(r1), s2);
911 break;
912
913 case INDEX_op_bswap16:
914 case INDEX_op_bswap32:
915 case INDEX_op_ctpop:
916 case INDEX_op_mov:
917 case INDEX_op_neg:
918 case INDEX_op_not:
919 case INDEX_op_ext_i32_i64:
920 case INDEX_op_extu_i32_i64:
921 case INDEX_op_bswap64:
922 tci_args_rr(insn, &r0, &r1);
923 info->fprintf_func(info->stream, "%-12s %s, %s",
924 op_name, str_r(r0), str_r(r1));
925 break;
926
927 case INDEX_op_add:
928 case INDEX_op_addci:
929 case INDEX_op_addcio:
930 case INDEX_op_addco:
931 case INDEX_op_and:
932 case INDEX_op_andc:
933 case INDEX_op_clz:
934 case INDEX_op_ctz:
935 case INDEX_op_divs:
936 case INDEX_op_divu:
937 case INDEX_op_eqv:
938 case INDEX_op_mul:
939 case INDEX_op_nand:
940 case INDEX_op_nor:
941 case INDEX_op_or:
942 case INDEX_op_orc:
943 case INDEX_op_rems:
944 case INDEX_op_remu:
945 case INDEX_op_rotl:
946 case INDEX_op_rotr:
947 case INDEX_op_sar:
948 case INDEX_op_shl:
949 case INDEX_op_shr:
950 case INDEX_op_sub:
951 case INDEX_op_subbi:
952 case INDEX_op_subbio:
953 case INDEX_op_subbo:
954 case INDEX_op_xor:
955 case INDEX_op_tci_ctz32:
956 case INDEX_op_tci_clz32:
957 case INDEX_op_tci_divs32:
958 case INDEX_op_tci_divu32:
959 case INDEX_op_tci_rems32:
960 case INDEX_op_tci_remu32:
961 case INDEX_op_tci_rotl32:
962 case INDEX_op_tci_rotr32:
963 tci_args_rrr(insn, &r0, &r1, &r2);
964 info->fprintf_func(info->stream, "%-12s %s, %s, %s",
965 op_name, str_r(r0), str_r(r1), str_r(r2));
966 break;
967
968 case INDEX_op_deposit:
969 tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
970 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %d, %d",
971 op_name, str_r(r0), str_r(r1), str_r(r2), pos, len);
972 break;
973
974 case INDEX_op_extract:
975 case INDEX_op_sextract:
976 tci_args_rrbb(insn, &r0, &r1, &pos, &len);
977 info->fprintf_func(info->stream, "%-12s %s,%s,%d,%d",
978 op_name, str_r(r0), str_r(r1), pos, len);
979 break;
980
981 case INDEX_op_tci_movcond32:
982 case INDEX_op_movcond:
983 tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &c);
984 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s, %s, %s",
985 op_name, str_r(r0), str_r(r1), str_r(r2),
986 str_r(r3), str_r(r4), str_c(c));
987 break;
988
989 case INDEX_op_muls2:
990 case INDEX_op_mulu2:
991 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
992 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
993 op_name, str_r(r0), str_r(r1),
994 str_r(r2), str_r(r3));
995 break;
996
997 case INDEX_op_qemu_ld:
998 case INDEX_op_qemu_st:
999 tci_args_rrm(insn, &r0, &r1, &oi);
1000 info->fprintf_func(info->stream, "%-12s %s, %s, %x",
1001 op_name, str_r(r0), str_r(r1), oi);
1002 break;
1003
1004 case INDEX_op_tci_qemu_ld_rrr:
1005 case INDEX_op_tci_qemu_st_rrr:
1006 tci_args_rrr(insn, &r0, &r1, &r2);
1007 info->fprintf_func(info->stream, "%-12s %s, %s, %s",
1008 op_name, str_r(r0), str_r(r1), str_r(r2));
1009 break;
1010
1011 case INDEX_op_qemu_ld2:
1012 case INDEX_op_qemu_st2:
1013 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
1014 info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
1015 op_name, str_r(r0), str_r(r1),
1016 str_r(r2), str_r(r3));
1017 break;
1018
1019 case 0:
1020 /* tcg_out_nop_fill uses zeros */
1021 if (insn == 0) {
1022 info->fprintf_func(info->stream, "align");
1023 break;
1024 }
1025 /* fall through */
1026
1027 default:
1028 info->fprintf_func(info->stream, "illegal opcode %d", op);
1029 break;
1030 }
1031
1032 return sizeof(insn);
1033 }