1 /*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 /* define it to use liveness analysis (better code) */
26 #define USE_LIVENESS_ANALYSIS
27 #define USE_TCG_OPTIMIZATIONS
28
29 #include "config.h"
30
31 /* Define to jump the ELF file used to communicate with GDB. */
32 #undef DEBUG_JIT
33
34 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
35 /* define it to suppress various consistency checks (faster) */
36 #define NDEBUG
37 #endif
38
39 #include "qemu-common.h"
40 #include "qemu/host-utils.h"
41 #include "qemu/timer.h"
42
43 /* Note: the long term plan is to reduce the dependencies on the QEMU
44 CPU definitions. Currently they are used for qemu_ld/st
45 instructions */
46 #define NO_CPU_IO_DEFS
47 #include "cpu.h"
48
49 #include "tcg-op.h"
50
51 #if UINTPTR_MAX == UINT32_MAX
52 # define ELF_CLASS ELFCLASS32
53 #else
54 # define ELF_CLASS ELFCLASS64
55 #endif
56 #ifdef HOST_WORDS_BIGENDIAN
57 # define ELF_DATA ELFDATA2MSB
58 #else
59 # define ELF_DATA ELFDATA2LSB
60 #endif
61
62 #include "elf.h"
63
64 /* Forward declarations for functions declared in tcg-target.c and used here. */
65 static void tcg_target_init(TCGContext *s);
66 static void tcg_target_qemu_prologue(TCGContext *s);
67 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
68 intptr_t value, intptr_t addend);
69
70 /* The CIE and FDE header definitions will be common to all hosts. */
71 typedef struct {
72 //uint32_t QEMU_ALIGN(sizeof(void *), len);
73 uint32_t QEMU_ALIGN(8, len);
74 uint32_t id;
75 uint8_t version;
76 char augmentation[1];
77 uint8_t code_align;
78 uint8_t data_align;
79 uint8_t return_column;
80 } DebugFrameCIE;
81
82 QEMU_PACK( typedef struct {
83 // uint32_t QEMU_ALIGN(sizeof(void *), len);
84 uint32_t QEMU_ALIGN(8, len);
85 uint32_t cie_offset;
86 uintptr_t func_start;
87 uintptr_t func_len;
88 }) DebugFrameFDEHeader;
89
90 QEMU_PACK( typedef struct {
91 DebugFrameCIE cie;
92 DebugFrameFDEHeader fde;
93 }) DebugFrameHeader;
94
95 /* Forward declarations for functions declared and used in tcg-target.c. */
96 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
97 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
98 intptr_t arg2);
99 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
100 static void tcg_out_movi(TCGContext *s, TCGType type,
101 TCGReg ret, tcg_target_long arg);
102 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
103 const int *const_args);
104 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
105 intptr_t arg2);
106 static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
107 static int tcg_target_const_match(tcg_target_long val, TCGType type,
108 const TCGArgConstraint *arg_ct);
109 static void tcg_out_tb_init(TCGContext *s);
110 static void tcg_out_tb_finalize(TCGContext *s);
111
112
113 TCGOpDef tcg_op_defs_org[] = {
114 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
115 #include "tcg-opc.h"
116 #undef DEF
117 };
118
119 #if TCG_TARGET_INSN_UNIT_SIZE == 1
tcg_out8(TCGContext * s,uint8_t v)120 static QEMU_UNUSED_FUNC inline void tcg_out8(TCGContext *s, uint8_t v)
121 {
122 *s->code_ptr++ = v;
123 }
124
tcg_patch8(tcg_insn_unit * p,uint8_t v)125 static QEMU_UNUSED_FUNC inline void tcg_patch8(tcg_insn_unit *p,
126 uint8_t v)
127 {
128 *p = v;
129 }
130 #endif
131
132 #if TCG_TARGET_INSN_UNIT_SIZE <= 2
tcg_out16(TCGContext * s,uint16_t v)133 static QEMU_UNUSED_FUNC inline void tcg_out16(TCGContext *s, uint16_t v)
134 {
135 if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
136 *s->code_ptr++ = (tcg_insn_unit)v;
137 } else {
138 tcg_insn_unit *p = s->code_ptr;
139 memcpy(p, &v, sizeof(v));
140 s->code_ptr = p + (2 / TCG_TARGET_INSN_UNIT_SIZE);
141 }
142 }
143
tcg_patch16(tcg_insn_unit * p,uint16_t v)144 static QEMU_UNUSED_FUNC inline void tcg_patch16(tcg_insn_unit *p,
145 uint16_t v)
146 {
147 if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
148 *p = (tcg_insn_unit)v;
149 } else {
150 memcpy(p, &v, sizeof(v));
151 }
152 }
153 #endif
154
155 #if TCG_TARGET_INSN_UNIT_SIZE <= 4
tcg_out32(TCGContext * s,uint32_t v)156 static QEMU_UNUSED_FUNC inline void tcg_out32(TCGContext *s, uint32_t v)
157 {
158 if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
159 *s->code_ptr++ = v;
160 } else {
161 tcg_insn_unit *p = s->code_ptr;
162 memcpy(p, &v, sizeof(v));
163 s->code_ptr = p + (4 / TCG_TARGET_INSN_UNIT_SIZE);
164 }
165 }
166
tcg_patch32(tcg_insn_unit * p,uint32_t v)167 static QEMU_UNUSED_FUNC inline void tcg_patch32(tcg_insn_unit *p,
168 uint32_t v)
169 {
170 if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
171 *p = v;
172 } else {
173 memcpy(p, &v, sizeof(v));
174 }
175 }
176 #endif
177
178 #if TCG_TARGET_INSN_UNIT_SIZE <= 8
tcg_out64(TCGContext * s,uint64_t v)179 static QEMU_UNUSED_FUNC inline void tcg_out64(TCGContext *s, uint64_t v)
180 {
181 if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
182 *s->code_ptr++ = (tcg_insn_unit)v;
183 } else {
184 tcg_insn_unit *p = s->code_ptr;
185 memcpy(p, &v, sizeof(v));
186 s->code_ptr = p + (8 / TCG_TARGET_INSN_UNIT_SIZE);
187 }
188 }
189
tcg_patch64(tcg_insn_unit * p,uint64_t v)190 static QEMU_UNUSED_FUNC inline void tcg_patch64(tcg_insn_unit *p,
191 uint64_t v)
192 {
193 if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
194 *p = (tcg_insn_unit)v;
195 } else {
196 memcpy(p, &v, sizeof(v));
197 }
198 }
199 #endif
200
201 /* label relocation processing */
202
tcg_out_reloc(TCGContext * s,tcg_insn_unit * code_ptr,int type,int label_index,intptr_t addend)203 static void tcg_out_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
204 int label_index, intptr_t addend)
205 {
206 TCGLabel *l;
207 TCGRelocation *r;
208
209 l = &s->labels[label_index];
210 if (l->has_value) {
211 /* FIXME: This may break relocations on RISC targets that
212 modify instruction fields in place. The caller may not have
213 written the initial value. */
214 patch_reloc(code_ptr, type, l->u.value, addend);
215 } else {
216 /* add a new relocation entry */
217 r = tcg_malloc(s, sizeof(TCGRelocation));
218 r->type = type;
219 r->ptr = code_ptr;
220 r->addend = addend;
221 r->next = l->u.first_reloc;
222 l->u.first_reloc = r;
223 }
224 }
225
tcg_out_label(TCGContext * s,int label_index,tcg_insn_unit * ptr)226 static void tcg_out_label(TCGContext *s, int label_index, tcg_insn_unit *ptr)
227 {
228 TCGLabel *l = &s->labels[label_index];
229 intptr_t value = (intptr_t)ptr;
230 TCGRelocation *r;
231
232 assert(!l->has_value);
233
234 for (r = l->u.first_reloc; r != NULL; r = r->next) {
235 patch_reloc(r->ptr, r->type, value, r->addend);
236 }
237
238 l->has_value = 1;
239 l->u.value_ptr = ptr;
240 }
241
gen_new_label(TCGContext * s)242 int gen_new_label(TCGContext *s)
243 {
244 int idx;
245 TCGLabel *l;
246
247 if (s->nb_labels >= TCG_MAX_LABELS)
248 tcg_abort();
249 idx = s->nb_labels++;
250 l = &s->labels[idx];
251 l->has_value = 0;
252 l->u.first_reloc = NULL;
253 return idx;
254 }
255
256 #include "tcg-target.c"
257
258 /* pool based memory allocation */
tcg_malloc_internal(TCGContext * s,int size)259 void *tcg_malloc_internal(TCGContext *s, int size)
260 {
261 TCGPool *p;
262 int pool_size;
263
264 if (size > TCG_POOL_CHUNK_SIZE) {
265 /* big malloc: insert a new pool (XXX: could optimize) */
266 p = g_malloc0(sizeof(TCGPool) + size);
267 p->size = size;
268 p->next = s->pool_first_large;
269 s->pool_first_large = p;
270 return p->data;
271 } else {
272 p = s->pool_current;
273 if (!p) {
274 p = s->pool_first;
275 if (!p)
276 goto new_pool;
277 } else {
278 if (!p->next) {
279 new_pool:
280 pool_size = TCG_POOL_CHUNK_SIZE;
281 p = g_malloc0(sizeof(TCGPool) + pool_size);
282 p->size = pool_size;
283 p->next = NULL;
284 if (s->pool_current)
285 s->pool_current->next = p;
286 else
287 s->pool_first = p;
288 } else {
289 p = p->next;
290 }
291 }
292 }
293 s->pool_current = p;
294 s->pool_cur = p->data + size;
295 s->pool_end = p->data + p->size;
296 return p->data;
297 }
298
tcg_pool_reset(TCGContext * s)299 void tcg_pool_reset(TCGContext *s)
300 {
301 TCGPool *p, *t;
302 for (p = s->pool_first_large; p; p = t) {
303 t = p->next;
304 g_free(p);
305 }
306 s->pool_first_large = NULL;
307 s->pool_cur = s->pool_end = NULL;
308 s->pool_current = NULL;
309 }
310
311 typedef struct TCGHelperInfo {
312 void *func;
313 const char *name;
314 unsigned flags;
315 unsigned sizemask;
316 } TCGHelperInfo;
317
318 #include "exec/helper-proto.h"
319
320 static const TCGHelperInfo all_helpers[] = {
321 #include "exec/helper-tcg.h"
322 };
323
tcg_context_init(TCGContext * s)324 void tcg_context_init(TCGContext *s)
325 {
326 int op, total_args, n, i;
327 TCGOpDef *def;
328 TCGArgConstraint *args_ct;
329 int *sorted_args;
330 GHashTable *helper_table;
331
332 memset(s, 0, sizeof(*s));
333 s->nb_globals = 0;
334
335 // copy original tcg_op_defs_org for private usage
336 s->tcg_op_defs = g_malloc(sizeof(tcg_op_defs_org));
337 memcpy(s->tcg_op_defs, tcg_op_defs_org, sizeof(tcg_op_defs_org));
338
339 /* Count total number of arguments and allocate the corresponding
340 space */
341 total_args = 0;
342 for(op = 0; op < NB_OPS; op++) {
343 def = &s->tcg_op_defs[op];
344 n = def->nb_iargs + def->nb_oargs;
345 total_args += n;
346 }
347
348 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
349 sorted_args = g_malloc(sizeof(int) * total_args);
350
351 for(op = 0; op < NB_OPS; op++) {
352 def = &s->tcg_op_defs[op];
353 def->args_ct = args_ct;
354 def->sorted_args = sorted_args;
355 n = def->nb_iargs + def->nb_oargs;
356 sorted_args += n;
357 args_ct += n;
358 }
359
360 /* Register helpers. */
361 /* Use g_direct_hash/equal for direct pointer comparisons on func. */
362 s->helpers = helper_table = g_hash_table_new(NULL, NULL);
363
364 for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
365 g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
366 (gpointer)&all_helpers[i]);
367 }
368
369 tcg_target_init(s);
370 }
371
tcg_prologue_init(TCGContext * s)372 void tcg_prologue_init(TCGContext *s)
373 {
374 /* init global prologue and epilogue */
375 s->code_buf = s->code_gen_prologue;
376 s->code_ptr = s->code_buf;
377 tcg_target_qemu_prologue(s);
378 flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
379
380 #ifdef DEBUG_DISAS
381 if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
382 size_t size = tcg_current_code_size(s);
383 qemu_log("PROLOGUE: [size=%zu]\n", size);
384 qemu_log("\n");
385 qemu_log_flush();
386 }
387 #endif
388 }
389
tcg_set_frame(TCGContext * s,int reg,intptr_t start,intptr_t size)390 void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
391 {
392 s->frame_start = start;
393 s->frame_end = start + size;
394 s->frame_reg = reg;
395 }
396
tcg_func_start(TCGContext * s)397 void tcg_func_start(TCGContext *s)
398 {
399 tcg_pool_reset(s);
400 s->nb_temps = s->nb_globals;
401
402 /* No temps have been previously allocated for size or locality. */
403 memset(s->free_temps, 0, sizeof(s->free_temps));
404
405 s->labels = tcg_malloc(s, sizeof(TCGLabel) * TCG_MAX_LABELS);
406 s->nb_labels = 0;
407 s->current_frame_offset = s->frame_start;
408
409 #ifdef CONFIG_DEBUG_TCG
410 s->goto_tb_issue_mask = 0;
411 #endif
412
413 s->gen_opc_ptr = s->gen_opc_buf;
414 s->gen_opparam_ptr = s->gen_opparam_buf;
415
416 s->be = tcg_malloc(s, sizeof(TCGBackendData));
417 }
418
tcg_temp_alloc(TCGContext * s,int n)419 static inline void tcg_temp_alloc(TCGContext *s, int n)
420 {
421 if (n > TCG_MAX_TEMPS)
422 tcg_abort();
423 }
424
tcg_global_reg_new_internal(TCGContext * s,TCGType type,int reg,const char * name)425 static inline int tcg_global_reg_new_internal(TCGContext *s, TCGType type, int reg,
426 const char *name)
427 {
428 TCGTemp *ts;
429 int idx;
430
431 #if TCG_TARGET_REG_BITS == 32
432 if (type != TCG_TYPE_I32)
433 tcg_abort();
434 #endif
435 if (tcg_regset_test_reg(s->reserved_regs, reg))
436 tcg_abort();
437 idx = s->nb_globals;
438 tcg_temp_alloc(s, s->nb_globals + 1);
439 ts = &s->temps[s->nb_globals];
440 ts->base_type = type;
441 ts->type = type;
442 ts->fixed_reg = 1;
443 ts->reg = reg;
444 ts->name = name;
445 s->nb_globals++;
446 tcg_regset_set_reg(s->reserved_regs, reg);
447 return idx;
448 }
449
tcg_global_reg_new_i32(TCGContext * s,int reg,const char * name)450 TCGv_i32 tcg_global_reg_new_i32(TCGContext *s, int reg, const char *name)
451 {
452 int idx;
453
454 idx = tcg_global_reg_new_internal(s, TCG_TYPE_I32, reg, name);
455 return MAKE_TCGV_I32(idx);
456 }
457
tcg_global_reg_new_i64(TCGContext * s,int reg,const char * name)458 TCGv_i64 tcg_global_reg_new_i64(TCGContext *s, int reg, const char *name)
459 {
460 int idx;
461
462 idx = tcg_global_reg_new_internal(s, TCG_TYPE_I64, reg, name);
463 return MAKE_TCGV_I64(idx);
464 }
465
tcg_global_mem_new_internal(TCGContext * s,TCGType type,int reg,intptr_t offset,const char * name)466 static inline int tcg_global_mem_new_internal(TCGContext *s, TCGType type, int reg,
467 intptr_t offset,
468 const char *name)
469 {
470 TCGTemp *ts;
471 int idx;
472
473 idx = s->nb_globals;
474 #if TCG_TARGET_REG_BITS == 32
475 if (type == TCG_TYPE_I64) {
476 char buf[64];
477 tcg_temp_alloc(s, s->nb_globals + 2);
478 ts = &s->temps[s->nb_globals];
479 ts->base_type = type;
480 ts->type = TCG_TYPE_I32;
481 ts->fixed_reg = 0;
482 ts->mem_allocated = 1;
483 ts->mem_reg = reg;
484 #ifdef HOST_WORDS_BIGENDIAN
485 ts->mem_offset = offset + 4;
486 #else
487 ts->mem_offset = offset;
488 #endif
489 pstrcpy(buf, sizeof(buf), name);
490 pstrcat(buf, sizeof(buf), "_0");
491 ts->name = g_strdup(buf);
492 ts++;
493
494 ts->base_type = type;
495 ts->type = TCG_TYPE_I32;
496 ts->fixed_reg = 0;
497 ts->mem_allocated = 1;
498 ts->mem_reg = reg;
499 #ifdef HOST_WORDS_BIGENDIAN
500 ts->mem_offset = offset;
501 #else
502 ts->mem_offset = offset + 4;
503 #endif
504 pstrcpy(buf, sizeof(buf), name);
505 pstrcat(buf, sizeof(buf), "_1");
506 ts->name = g_strdup(buf);
507
508 s->nb_globals += 2;
509 } else
510 #endif
511 {
512 tcg_temp_alloc(s, s->nb_globals + 1);
513 ts = &s->temps[s->nb_globals];
514 ts->base_type = type;
515 ts->type = type;
516 ts->fixed_reg = 0;
517 ts->mem_allocated = 1;
518 ts->mem_reg = reg;
519 ts->mem_offset = offset;
520 ts->name = name;
521 s->nb_globals++;
522 }
523 return idx;
524 }
525
tcg_global_mem_new_i32(TCGContext * s,int reg,intptr_t offset,const char * name)526 TCGv_i32 tcg_global_mem_new_i32(TCGContext *s, int reg, intptr_t offset, const char *name)
527 {
528 int idx = tcg_global_mem_new_internal(s, TCG_TYPE_I32, reg, offset, name);
529 return MAKE_TCGV_I32(idx);
530 }
531
tcg_global_mem_new_i64(TCGContext * s,int reg,intptr_t offset,const char * name)532 TCGv_i64 tcg_global_mem_new_i64(TCGContext *s, int reg, intptr_t offset, const char *name)
533 {
534 int idx = tcg_global_mem_new_internal(s, TCG_TYPE_I64, reg, offset, name);
535 return MAKE_TCGV_I64(idx);
536 }
537
tcg_temp_new_internal(TCGContext * s,TCGType type,int temp_local)538 static inline int tcg_temp_new_internal(TCGContext *s, TCGType type, int temp_local)
539 {
540 TCGTemp *ts;
541 int idx, k;
542
543 k = type + (temp_local ? TCG_TYPE_COUNT : 0);
544 idx = find_first_bit(s->free_temps[k].l, TCG_MAX_TEMPS);
545 if (idx < TCG_MAX_TEMPS) {
546 /* There is already an available temp with the right type. */
547 clear_bit(idx, s->free_temps[k].l);
548
549 ts = &s->temps[idx];
550 ts->temp_allocated = 1;
551 assert(ts->base_type == type);
552 assert(ts->temp_local == temp_local);
553 } else {
554 idx = s->nb_temps;
555 #if TCG_TARGET_REG_BITS == 32
556 if (type == TCG_TYPE_I64) {
557 tcg_temp_alloc(s, s->nb_temps + 2);
558 ts = &s->temps[s->nb_temps];
559 ts->base_type = type;
560 ts->type = TCG_TYPE_I32;
561 ts->temp_allocated = 1;
562 ts->temp_local = temp_local;
563 ts->name = NULL;
564 ts++;
565 ts->base_type = type;
566 ts->type = TCG_TYPE_I32;
567 ts->temp_allocated = 1;
568 ts->temp_local = temp_local;
569 ts->name = NULL;
570 s->nb_temps += 2;
571 } else
572 #endif
573 {
574 tcg_temp_alloc(s, s->nb_temps + 1);
575 ts = &s->temps[s->nb_temps];
576 ts->base_type = type;
577 ts->type = type;
578 ts->temp_allocated = 1;
579 ts->temp_local = temp_local;
580 ts->name = NULL;
581 s->nb_temps++;
582 }
583 }
584
585 #if defined(CONFIG_DEBUG_TCG)
586 s->temps_in_use++;
587 #endif
588 return idx;
589 }
590
tcg_temp_new_internal_i32(TCGContext * s,int temp_local)591 TCGv_i32 tcg_temp_new_internal_i32(TCGContext *s, int temp_local)
592 {
593 int idx;
594
595 idx = tcg_temp_new_internal(s, TCG_TYPE_I32, temp_local);
596 return MAKE_TCGV_I32(idx);
597 }
598
tcg_temp_new_internal_i64(TCGContext * s,int temp_local)599 TCGv_i64 tcg_temp_new_internal_i64(TCGContext *s, int temp_local)
600 {
601 int idx;
602
603 idx = tcg_temp_new_internal(s, TCG_TYPE_I64, temp_local);
604 return MAKE_TCGV_I64(idx);
605 }
606
tcg_temp_free_internal(TCGContext * s,int idx)607 static void tcg_temp_free_internal(TCGContext *s, int idx)
608 {
609 TCGTemp *ts;
610 int k;
611
612 #if defined(CONFIG_DEBUG_TCG)
613 s->temps_in_use--;
614 if (s->temps_in_use < 0) {
615 fprintf(stderr, "More temporaries freed than allocated!\n");
616 }
617 #endif
618
619 assert(idx >= s->nb_globals && idx < s->nb_temps);
620 ts = &s->temps[idx];
621 assert(ts->temp_allocated != 0);
622 ts->temp_allocated = 0;
623
624 k = ts->base_type + (ts->temp_local ? TCG_TYPE_COUNT : 0);
625 set_bit(idx, s->free_temps[k].l);
626 }
627
tcg_temp_free_i32(TCGContext * s,TCGv_i32 arg)628 void tcg_temp_free_i32(TCGContext *s, TCGv_i32 arg)
629 {
630 tcg_temp_free_internal(s, GET_TCGV_I32(arg));
631 }
632
tcg_temp_free_i64(TCGContext * s,TCGv_i64 arg)633 void tcg_temp_free_i64(TCGContext *s, TCGv_i64 arg)
634 {
635 tcg_temp_free_internal(s, GET_TCGV_I64(arg));
636 }
637
tcg_const_i32(TCGContext * s,int32_t val)638 TCGv_i32 tcg_const_i32(TCGContext *s, int32_t val)
639 {
640 TCGv_i32 t0;
641 t0 = tcg_temp_new_i32(s);
642 tcg_gen_movi_i32(s, t0, val);
643 return t0;
644 }
645
tcg_const_i64(TCGContext * s,int64_t val)646 TCGv_i64 tcg_const_i64(TCGContext *s, int64_t val)
647 {
648 TCGv_i64 t0;
649 t0 = tcg_temp_new_i64(s);
650 tcg_gen_movi_i64(s, t0, val);
651 return t0;
652 }
653
tcg_const_local_i32(TCGContext * s,int32_t val)654 TCGv_i32 tcg_const_local_i32(TCGContext *s, int32_t val)
655 {
656 TCGv_i32 t0;
657 t0 = tcg_temp_local_new_i32(s);
658 tcg_gen_movi_i32(s, t0, val);
659 return t0;
660 }
661
tcg_const_local_i64(TCGContext * s,int64_t val)662 TCGv_i64 tcg_const_local_i64(TCGContext *s, int64_t val)
663 {
664 TCGv_i64 t0;
665 t0 = tcg_temp_local_new_i64(s);
666 tcg_gen_movi_i64(s, t0, val);
667 return t0;
668 }
669
670 #if defined(CONFIG_DEBUG_TCG)
tcg_clear_temp_count(TCGContext * s)671 void tcg_clear_temp_count(TCGContext *s)
672 {
673 s->temps_in_use = 0;
674 }
675
tcg_check_temp_count(TCGContext * s)676 int tcg_check_temp_count(TCGContext *s)
677 {
678 if (s->temps_in_use) {
679 /* Clear the count so that we don't give another
680 * warning immediately next time around.
681 */
682 s->temps_in_use = 0;
683 return 1;
684 }
685 return 0;
686 }
687 #endif
688
689 /* Note: we convert the 64 bit args to 32 bit and do some alignment
690 and endian swap. Maybe it would be better to do the alignment
691 and endian swap in tcg_reg_alloc_call(). */
tcg_gen_callN(TCGContext * s,void * func,TCGArg ret,int nargs,TCGArg * args)692 void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
693 int nargs, TCGArg *args)
694 {
695 int i, real_args, nb_rets;
696 unsigned sizemask, flags;
697 TCGArg *nparam;
698 TCGHelperInfo *info;
699
700 info = g_hash_table_lookup(s->helpers, (gpointer)func);
701 flags = info->flags;
702 sizemask = info->sizemask;
703
704 #if defined(__sparc__) && !defined(__arch64__) \
705 && !defined(CONFIG_TCG_INTERPRETER)
706 /* We have 64-bit values in one register, but need to pass as two
707 separate parameters. Split them. */
708 int orig_sizemask = sizemask;
709 int orig_nargs = nargs;
710 TCGv_i64 retl, reth;
711
712 TCGV_UNUSED_I64(retl);
713 TCGV_UNUSED_I64(reth);
714 if (sizemask != 0) {
715 TCGArg *split_args = __builtin_alloca(sizeof(TCGArg) * nargs * 2);
716 for (i = real_args = 0; i < nargs; ++i) {
717 int is_64bit = sizemask & (1 << (i+1)*2);
718 if (is_64bit) {
719 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
720 TCGv_i32 h = tcg_temp_new_i32(s);
721 TCGv_i32 l = tcg_temp_new_i32(s);
722 tcg_gen_extr_i64_i32(l, h, orig);
723 split_args[real_args++] = GET_TCGV_I32(h);
724 split_args[real_args++] = GET_TCGV_I32(l);
725 } else {
726 split_args[real_args++] = args[i];
727 }
728 }
729 nargs = real_args;
730 args = split_args;
731 sizemask = 0;
732 }
733 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
734 for (i = 0; i < nargs; ++i) {
735 int is_64bit = sizemask & (1 << (i+1)*2);
736 int is_signed = sizemask & (2 << (i+1)*2);
737 if (!is_64bit) {
738 TCGv_i64 temp = tcg_temp_new_i64(s);
739 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
740 if (is_signed) {
741 tcg_gen_ext32s_i64(s, temp, orig);
742 } else {
743 tcg_gen_ext32u_i64(s, temp, orig);
744 }
745 args[i] = GET_TCGV_I64(temp);
746 }
747 }
748 #endif /* TCG_TARGET_EXTEND_ARGS */
749
750 *s->gen_opc_ptr++ = INDEX_op_call;
751 nparam = s->gen_opparam_ptr++;
752 if (ret != TCG_CALL_DUMMY_ARG) {
753 #if defined(__sparc__) && !defined(__arch64__) \
754 && !defined(CONFIG_TCG_INTERPRETER)
755 if (orig_sizemask & 1) {
756 /* The 32-bit ABI is going to return the 64-bit value in
757 the %o0/%o1 register pair. Prepare for this by using
758 two return temporaries, and reassemble below. */
759 retl = tcg_temp_new_i64(s);
760 reth = tcg_temp_new_i64(s);
761 *s->gen_opparam_ptr++ = GET_TCGV_I64(reth);
762 *s->gen_opparam_ptr++ = GET_TCGV_I64(retl);
763 nb_rets = 2;
764 } else {
765 *s->gen_opparam_ptr++ = ret;
766 nb_rets = 1;
767 }
768 #else
769 if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
770 #ifdef HOST_WORDS_BIGENDIAN
771 *s->gen_opparam_ptr++ = ret + 1;
772 *s->gen_opparam_ptr++ = ret;
773 #else
774 *s->gen_opparam_ptr++ = ret;
775 *s->gen_opparam_ptr++ = ret + 1;
776 #endif
777 nb_rets = 2;
778 } else {
779 *s->gen_opparam_ptr++ = ret;
780 nb_rets = 1;
781 }
782 #endif
783 } else {
784 nb_rets = 0;
785 }
786 real_args = 0;
787 for (i = 0; i < nargs; i++) {
788 int is_64bit = sizemask & (1 << (i+1)*2);
789 if (TCG_TARGET_REG_BITS < 64 && is_64bit) {
790 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
791 /* some targets want aligned 64 bit args */
792 if (real_args & 1) {
793 *s->gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
794 real_args++;
795 }
796 #endif
797 /* If stack grows up, then we will be placing successive
798 arguments at lower addresses, which means we need to
799 reverse the order compared to how we would normally
800 treat either big or little-endian. For those arguments
801 that will wind up in registers, this still works for
802 HPPA (the only current STACK_GROWSUP target) since the
803 argument registers are *also* allocated in decreasing
804 order. If another such target is added, this logic may
805 have to get more complicated to differentiate between
806 stack arguments and register arguments. */
807 #if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
808 *s->gen_opparam_ptr++ = args[i] + 1;
809 *s->gen_opparam_ptr++ = args[i];
810 #else
811 *s->gen_opparam_ptr++ = args[i];
812 *s->gen_opparam_ptr++ = args[i] + 1;
813 #endif
814 real_args += 2;
815 continue;
816 }
817
818 *s->gen_opparam_ptr++ = args[i];
819 real_args++;
820 }
821 *s->gen_opparam_ptr++ = (uintptr_t)func;
822 *s->gen_opparam_ptr++ = flags;
823
824 *nparam = (nb_rets << 16) | real_args;
825
826 /* total parameters, needed to go backward in the instruction stream */
827 *s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
828
829 #if defined(__sparc__) && !defined(__arch64__) \
830 && !defined(CONFIG_TCG_INTERPRETER)
831 /* Free all of the parts we allocated above. */
832 for (i = real_args = 0; i < orig_nargs; ++i) {
833 int is_64bit = orig_sizemask & (1 << (i+1)*2);
834 if (is_64bit) {
835 TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]);
836 TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]);
837 tcg_temp_free_i32(s, h);
838 tcg_temp_free_i32(s, l);
839 } else {
840 real_args++;
841 }
842 }
843 if (orig_sizemask & 1) {
844 /* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
845 Note that describing these as TCGv_i64 eliminates an unnecessary
846 zero-extension that tcg_gen_concat_i32_i64 would create. */
847 tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth);
848 tcg_temp_free_i64(s, retl);
849 tcg_temp_free_i64(s, reth);
850 }
851 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
852 for (i = 0; i < nargs; ++i) {
853 int is_64bit = sizemask & (1 << (i+1)*2);
854 if (!is_64bit) {
855 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
856 tcg_temp_free_i64(s, temp);
857 }
858 }
859 #endif /* TCG_TARGET_EXTEND_ARGS */
860 }
861
862 #if TCG_TARGET_REG_BITS == 32
tcg_gen_shifti_i64(TCGContext * s,TCGv_i64 ret,TCGv_i64 arg1,int c,int right,int arith)863 void tcg_gen_shifti_i64(TCGContext *s, TCGv_i64 ret, TCGv_i64 arg1,
864 int c, int right, int arith)
865 {
866 if (c == 0) {
867 tcg_gen_mov_i32(s, TCGV_LOW(ret), TCGV_LOW(arg1));
868 tcg_gen_mov_i32(s, TCGV_HIGH(ret), TCGV_HIGH(arg1));
869 } else if (c >= 32) {
870 c -= 32;
871 if (right) {
872 if (arith) {
873 tcg_gen_sari_i32(s, TCGV_LOW(ret), TCGV_HIGH(arg1), c);
874 tcg_gen_sari_i32(s, TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
875 } else {
876 tcg_gen_shri_i32(s, TCGV_LOW(ret), TCGV_HIGH(arg1), c);
877 tcg_gen_movi_i32(s, TCGV_HIGH(ret), 0);
878 }
879 } else {
880 tcg_gen_shli_i32(s, TCGV_HIGH(ret), TCGV_LOW(arg1), c);
881 tcg_gen_movi_i32(s, TCGV_LOW(ret), 0);
882 }
883 } else {
884 TCGv_i32 t0, t1;
885
886 t0 = tcg_temp_new_i32(s);
887 t1 = tcg_temp_new_i32(s);
888 if (right) {
889 tcg_gen_shli_i32(s, t0, TCGV_HIGH(arg1), 32 - c);
890 if (arith)
891 tcg_gen_sari_i32(s, t1, TCGV_HIGH(arg1), c);
892 else
893 tcg_gen_shri_i32(s, t1, TCGV_HIGH(arg1), c);
894 tcg_gen_shri_i32(s, TCGV_LOW(ret), TCGV_LOW(arg1), c);
895 tcg_gen_or_i32(s, TCGV_LOW(ret), TCGV_LOW(ret), t0);
896 tcg_gen_mov_i32(s, TCGV_HIGH(ret), t1);
897 } else {
898 tcg_gen_shri_i32(s, t0, TCGV_LOW(arg1), 32 - c);
899 /* Note: ret can be the same as arg1, so we use t1 */
900 tcg_gen_shli_i32(s, t1, TCGV_LOW(arg1), c);
901 tcg_gen_shli_i32(s, TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
902 tcg_gen_or_i32(s, TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
903 tcg_gen_mov_i32(s, TCGV_LOW(ret), t1);
904 }
905 tcg_temp_free_i32(s, t0);
906 tcg_temp_free_i32(s, t1);
907 }
908 }
909 #endif
910
tcg_canonicalize_memop(TCGMemOp op,bool is64,bool st)911 static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
912 {
913 switch (op & MO_SIZE) {
914 case MO_8:
915 op &= ~MO_BSWAP;
916 break;
917 case MO_16:
918 break;
919 case MO_32:
920 if (!is64) {
921 op &= ~MO_SIGN;
922 }
923 break;
924 case MO_64:
925 if (!is64) {
926 tcg_abort();
927 }
928 break;
929 }
930 if (st) {
931 op &= ~MO_SIGN;
932 }
933 return op;
934 }
935
936 // Unicorn engine
937 // check if the last memory access was invalid
938 // if so, we jump to the block epilogue to quit immediately.
check_exit_request(TCGContext * tcg_ctx)939 void check_exit_request(TCGContext *tcg_ctx)
940 {
941 TCGv_i32 flag;
942
943 flag = tcg_temp_new_i32(tcg_ctx);
944 tcg_gen_ld_i32(tcg_ctx, flag, tcg_ctx->cpu_env,
945 offsetof(CPUState, tcg_exit_req) - ENV_OFFSET);
946 tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_NE, flag, 0, tcg_ctx->exitreq_label);
947 tcg_temp_free_i32(tcg_ctx, flag);
948 }
949
tcg_gen_qemu_ld_i32(struct uc_struct * uc,TCGv_i32 val,TCGv addr,TCGArg idx,TCGMemOp memop)950 void tcg_gen_qemu_ld_i32(struct uc_struct *uc, TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
951 {
952 TCGContext *tcg_ctx = uc->tcg_ctx;
953
954 memop = tcg_canonicalize_memop(memop, 0, 0);
955
956 *tcg_ctx->gen_opc_ptr++ = INDEX_op_qemu_ld_i32;
957 tcg_add_param_i32(tcg_ctx, val);
958 tcg_add_param_tl(tcg_ctx, addr);
959 *tcg_ctx->gen_opparam_ptr++ = memop;
960 *tcg_ctx->gen_opparam_ptr++ = idx;
961
962 check_exit_request(tcg_ctx);
963 }
964
tcg_gen_qemu_st_i32(struct uc_struct * uc,TCGv_i32 val,TCGv addr,TCGArg idx,TCGMemOp memop)965 void tcg_gen_qemu_st_i32(struct uc_struct *uc, TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
966 {
967 TCGContext *tcg_ctx = uc->tcg_ctx;
968
969 memop = tcg_canonicalize_memop(memop, 0, 1);
970
971 *tcg_ctx->gen_opc_ptr++ = INDEX_op_qemu_st_i32;
972 tcg_add_param_i32(tcg_ctx, val);
973 tcg_add_param_tl(tcg_ctx, addr);
974 *tcg_ctx->gen_opparam_ptr++ = memop;
975 *tcg_ctx->gen_opparam_ptr++ = idx;
976
977 check_exit_request(tcg_ctx);
978 }
979
tcg_gen_qemu_ld_i64(struct uc_struct * uc,TCGv_i64 val,TCGv addr,TCGArg idx,TCGMemOp memop)980 void tcg_gen_qemu_ld_i64(struct uc_struct *uc, TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
981 {
982 TCGContext *tcg_ctx = uc->tcg_ctx;
983
984 memop = tcg_canonicalize_memop(memop, 1, 0);
985
986 #if TCG_TARGET_REG_BITS == 32
987 if ((memop & MO_SIZE) < MO_64) {
988 tcg_gen_qemu_ld_i32(uc, TCGV_LOW(val), addr, idx, memop);
989 if (memop & MO_SIGN) {
990 tcg_gen_sari_i32(tcg_ctx, TCGV_HIGH(val), TCGV_LOW(val), 31);
991 } else {
992 tcg_gen_movi_i32(tcg_ctx, TCGV_HIGH(val), 0);
993 }
994
995 check_exit_request(tcg_ctx);
996 return;
997 }
998 #endif
999
1000 *tcg_ctx->gen_opc_ptr++ = INDEX_op_qemu_ld_i64;
1001 tcg_add_param_i64(tcg_ctx, val);
1002 tcg_add_param_tl(tcg_ctx, addr);
1003 *tcg_ctx->gen_opparam_ptr++ = memop;
1004 *tcg_ctx->gen_opparam_ptr++ = idx;
1005
1006 check_exit_request(tcg_ctx);
1007 }
1008
tcg_gen_qemu_st_i64(struct uc_struct * uc,TCGv_i64 val,TCGv addr,TCGArg idx,TCGMemOp memop)1009 void tcg_gen_qemu_st_i64(struct uc_struct *uc, TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
1010 {
1011 TCGContext *tcg_ctx = uc->tcg_ctx;
1012
1013 memop = tcg_canonicalize_memop(memop, 1, 1);
1014
1015 #if TCG_TARGET_REG_BITS == 32
1016 if ((memop & MO_SIZE) < MO_64) {
1017 tcg_gen_qemu_st_i32(uc, TCGV_LOW(val), addr, idx, memop);
1018 check_exit_request(tcg_ctx);
1019 return;
1020 }
1021 #endif
1022
1023 *tcg_ctx->gen_opc_ptr++ = INDEX_op_qemu_st_i64;
1024 tcg_add_param_i64(tcg_ctx, val);
1025 tcg_add_param_tl(tcg_ctx, addr);
1026 *tcg_ctx->gen_opparam_ptr++ = memop;
1027 *tcg_ctx->gen_opparam_ptr++ = idx;
1028
1029 check_exit_request(tcg_ctx);
1030 }
1031
tcg_reg_alloc_start(TCGContext * s)1032 static void tcg_reg_alloc_start(TCGContext *s)
1033 {
1034 int i;
1035 TCGTemp *ts;
1036 for(i = 0; i < s->nb_globals; i++) {
1037 ts = &s->temps[i];
1038 if (ts->fixed_reg) {
1039 ts->val_type = TEMP_VAL_REG;
1040 } else {
1041 ts->val_type = TEMP_VAL_MEM;
1042 }
1043 }
1044 for(i = s->nb_globals; i < s->nb_temps; i++) {
1045 ts = &s->temps[i];
1046 if (ts->temp_local) {
1047 ts->val_type = TEMP_VAL_MEM;
1048 } else {
1049 ts->val_type = TEMP_VAL_DEAD;
1050 }
1051 ts->mem_allocated = 0;
1052 ts->fixed_reg = 0;
1053 }
1054 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1055 s->reg_to_temp[i] = -1;
1056 }
1057 }
1058
tcg_get_arg_str_idx(TCGContext * s,char * buf,int buf_size,int idx)1059 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
1060 int idx)
1061 {
1062 TCGTemp *ts;
1063
1064 assert(idx >= 0 && idx < s->nb_temps);
1065 ts = &s->temps[idx];
1066 if (idx < s->nb_globals) {
1067 pstrcpy(buf, buf_size, ts->name);
1068 } else {
1069 if (ts->temp_local)
1070 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
1071 else
1072 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
1073 }
1074 return buf;
1075 }
1076
tcg_get_arg_str_i32(TCGContext * s,char * buf,int buf_size,TCGv_i32 arg)1077 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
1078 {
1079 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
1080 }
1081
tcg_get_arg_str_i64(TCGContext * s,char * buf,int buf_size,TCGv_i64 arg)1082 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
1083 {
1084 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
1085 }
1086
1087 /* Find helper name. */
tcg_find_helper(TCGContext * s,uintptr_t val)1088 static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
1089 {
1090 const char *ret = NULL;
1091 if (s->helpers) {
1092 TCGHelperInfo *info = g_hash_table_lookup(s->helpers, (gpointer)val);
1093 if (info) {
1094 ret = info->name;
1095 }
1096 }
1097 return ret;
1098 }
1099
1100 static const char * const cond_name[] =
1101 {
1102 #ifdef _MSC_VER
1103 "never", // TCG_COND_NEVER
1104 "always", // TCG_COND_ALWAYS
1105 "lt", // TCG_COND_LT
1106 "ge", // TCG_COND_GE
1107 "ltu", // TCG_COND_LTU
1108 "geu", // TCG_COND_GEU
1109 NULL, // n/a
1110 NULL, // n/a
1111 "eq", // TCG_COND_EQ
1112 "ne", // TCG_COND_NE
1113 "le", // TCG_COND_LE
1114 "gt", // TCG_COND_GT
1115 "leu", // TCG_COND_LEU
1116 "gtu", // TCG_COND_GTU
1117 NULL, // n/a
1118 NULL, // n/a
1119 #else
1120 [TCG_COND_NEVER] = "never",
1121 [TCG_COND_ALWAYS] = "always",
1122 [TCG_COND_EQ] = "eq",
1123 [TCG_COND_NE] = "ne",
1124 [TCG_COND_LT] = "lt",
1125 [TCG_COND_GE] = "ge",
1126 [TCG_COND_LE] = "le",
1127 [TCG_COND_GT] = "gt",
1128 [TCG_COND_LTU] = "ltu",
1129 [TCG_COND_GEU] = "geu",
1130 [TCG_COND_LEU] = "leu",
1131 [TCG_COND_GTU] = "gtu"
1132 #endif
1133 };
1134
1135 static const char * const ldst_name[] =
1136 {
1137 #ifdef _MSC_VER
1138 "ub", // MO_UB
1139 # ifdef HOST_WORDS_BIGENDIAN
1140 "beuw", // MO_BEUW
1141 "beul", // MO_BEUL
1142 "beq", // MO_BEQ
1143 "sb", // MO_SB
1144 "besw", // MO_BESW
1145 "besl", // MO_BESL
1146 NULL, // n/a
1147 NULL, // n/a
1148 "leuw", // MO_LEUW
1149 "leul", // MO_LEUL
1150 "leq", // MO_LEQ
1151 NULL, // n/a
1152 "lesw", // MO_LESW
1153 "lesl", // MO_LESL
1154 NULL, // n/a
1155 # else // !HOST_WORDS_BIGENDIAN
1156 "leuw", // MO_LEUW
1157 "leul", // MO_LEUL
1158 "leq", // MO_LEQ
1159 "sb", // MO_SB
1160 "lesw", // MO_LESW
1161 "lesl", // MO_LESL
1162 NULL, // n/a
1163 NULL, // n/a
1164 "beuw", // MO_BEUW
1165 "beul", // MO_BEUL
1166 "beq", // MO_BEQ
1167 NULL, // n/a
1168 "besw", // MO_BESW
1169 "besl", // MO_BESL
1170 NULL, // n/a
1171 # endif // HOST_WORDS_BIGENDIAN
1172
1173 #else //_MSC_VER
1174 [MO_UB] = "ub",
1175 [MO_SB] = "sb",
1176 [MO_LEUW] = "leuw",
1177 [MO_LESW] = "lesw",
1178 [MO_LEUL] = "leul",
1179 [MO_LESL] = "lesl",
1180 [MO_LEQ] = "leq",
1181 [MO_BEUW] = "beuw",
1182 [MO_BESW] = "besw",
1183 [MO_BEUL] = "beul",
1184 [MO_BESL] = "besl",
1185 [MO_BEQ] = "beq",
1186 #endif // _MSC_VER
1187 };
1188
tcg_dump_ops(TCGContext * s)1189 void tcg_dump_ops(TCGContext *s)
1190 {
1191 const uint16_t *opc_ptr;
1192 const TCGArg *args;
1193 TCGArg arg;
1194 TCGOpcode c;
1195 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
1196 const TCGOpDef *def;
1197 char buf[128];
1198
1199 first_insn = 1;
1200 opc_ptr = s->gen_opc_buf;
1201 args = s->gen_opparam_buf;
1202 while (opc_ptr < s->gen_opc_ptr) {
1203 c = *opc_ptr++;
1204 def = &s->tcg_op_defs[c];
1205 if (c == INDEX_op_debug_insn_start) {
1206 uint64_t pc;
1207 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
1208 pc = ((uint64_t)args[1] << 32) | args[0];
1209 #else
1210 pc = args[0];
1211 #endif
1212 if (!first_insn) {
1213 printf("\n");
1214 }
1215 printf(" ---- 0x%" PRIx64, pc);
1216 first_insn = 0;
1217 nb_oargs = def->nb_oargs;
1218 nb_iargs = def->nb_iargs;
1219 nb_cargs = def->nb_cargs;
1220 } else if (c == INDEX_op_call) {
1221 TCGArg arg;
1222
1223 /* variable number of arguments */
1224 arg = *args++;
1225 nb_oargs = arg >> 16;
1226 nb_iargs = arg & 0xffff;
1227 nb_cargs = def->nb_cargs;
1228
1229 /* function name, flags, out args */
1230 printf(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
1231 tcg_find_helper(s, args[nb_oargs + nb_iargs]),
1232 args[nb_oargs + nb_iargs + 1], nb_oargs);
1233 for (i = 0; i < nb_oargs; i++) {
1234 printf(",%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
1235 args[i]));
1236 }
1237 for (i = 0; i < nb_iargs; i++) {
1238 TCGArg arg = args[nb_oargs + i];
1239 const char *t = "<dummy>";
1240 if (arg != TCG_CALL_DUMMY_ARG) {
1241 t = tcg_get_arg_str_idx(s, buf, sizeof(buf), arg);
1242 }
1243 printf(",%s", t);
1244 }
1245 } else {
1246 printf(" %s ", def->name);
1247 if (c == INDEX_op_nopn) {
1248 /* variable number of arguments */
1249 nb_cargs = *args;
1250 nb_oargs = 0;
1251 nb_iargs = 0;
1252 } else {
1253 nb_oargs = def->nb_oargs;
1254 nb_iargs = def->nb_iargs;
1255 nb_cargs = def->nb_cargs;
1256 }
1257
1258 k = 0;
1259 for(i = 0; i < nb_oargs; i++) {
1260 if (k != 0) {
1261 printf(",");
1262 }
1263 printf("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
1264 args[k++]));
1265 }
1266 for(i = 0; i < nb_iargs; i++) {
1267 if (k != 0) {
1268 printf(",");
1269 }
1270 printf("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
1271 args[k++]));
1272 }
1273 switch (c) {
1274 case INDEX_op_brcond_i32:
1275 case INDEX_op_setcond_i32:
1276 case INDEX_op_movcond_i32:
1277 case INDEX_op_brcond2_i32:
1278 case INDEX_op_setcond2_i32:
1279 case INDEX_op_brcond_i64:
1280 case INDEX_op_setcond_i64:
1281 case INDEX_op_movcond_i64:
1282 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
1283 printf(",%s", cond_name[args[k++]]);
1284 } else {
1285 printf(",$0x%" TCG_PRIlx, args[k++]);
1286 }
1287 i = 1;
1288 break;
1289 case INDEX_op_qemu_ld_i32:
1290 case INDEX_op_qemu_st_i32:
1291 case INDEX_op_qemu_ld_i64:
1292 case INDEX_op_qemu_st_i64:
1293 if (args[k] < ARRAY_SIZE(ldst_name) && ldst_name[args[k]]) {
1294 printf(",%s", ldst_name[args[k++]]);
1295 } else {
1296 printf(",$0x%" TCG_PRIlx, args[k++]);
1297 }
1298 i = 1;
1299 break;
1300 default:
1301 i = 0;
1302 break;
1303 }
1304 for(; i < nb_cargs; i++) {
1305 if (k != 0) {
1306 printf(",");
1307 }
1308 arg = args[k++];
1309 printf("$0x%" TCG_PRIlx, arg);
1310 }
1311 }
1312 printf("\n");
1313 args += nb_iargs + nb_oargs + nb_cargs;
1314 }
1315 printf("###########\n");
1316 }
1317
1318 /* we give more priority to constraints with less registers */
get_constraint_priority(const TCGOpDef * def,int k)1319 static int get_constraint_priority(const TCGOpDef *def, int k)
1320 {
1321 const TCGArgConstraint *arg_ct;
1322
1323 int i, n;
1324 arg_ct = &def->args_ct[k];
1325 if (arg_ct->ct & TCG_CT_ALIAS) {
1326 /* an alias is equivalent to a single register */
1327 n = 1;
1328 } else {
1329 if (!(arg_ct->ct & TCG_CT_REG))
1330 return 0;
1331 n = 0;
1332 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1333 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1334 n++;
1335 }
1336 }
1337 return TCG_TARGET_NB_REGS - n + 1;
1338 }
1339
1340 /* sort from highest priority to lowest */
sort_constraints(TCGOpDef * def,int start,int n)1341 static void sort_constraints(TCGOpDef *def, int start, int n)
1342 {
1343 int i, j, p1, p2, tmp;
1344
1345 for(i = 0; i < n; i++)
1346 def->sorted_args[start + i] = start + i;
1347 if (n <= 1)
1348 return;
1349 for(i = 0; i < n - 1; i++) {
1350 for(j = i + 1; j < n; j++) {
1351 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1352 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1353 if (p1 < p2) {
1354 tmp = def->sorted_args[start + i];
1355 def->sorted_args[start + i] = def->sorted_args[start + j];
1356 def->sorted_args[start + j] = tmp;
1357 }
1358 }
1359 }
1360 }
1361
tcg_add_target_add_op_defs(TCGContext * s,const TCGTargetOpDef * tdefs)1362 void tcg_add_target_add_op_defs(TCGContext *s, const TCGTargetOpDef *tdefs)
1363 {
1364 TCGOpcode op;
1365 TCGOpDef *def;
1366 const char *ct_str;
1367 int i, nb_args;
1368
1369 for(;;) {
1370 if (tdefs->op == (TCGOpcode)-1)
1371 break;
1372 op = tdefs->op;
1373 assert((unsigned)op < NB_OPS);
1374 def = &s->tcg_op_defs[op];
1375 #if defined(CONFIG_DEBUG_TCG)
1376 /* Duplicate entry in op definitions? */
1377 assert(!def->used);
1378 def->used = 1;
1379 #endif
1380 nb_args = def->nb_iargs + def->nb_oargs;
1381 for(i = 0; i < nb_args; i++) {
1382 ct_str = tdefs->args_ct_str[i];
1383 /* Incomplete TCGTargetOpDef entry? */
1384 assert(ct_str != NULL);
1385 tcg_regset_clear(def->args_ct[i].u.regs);
1386 def->args_ct[i].ct = 0;
1387 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1388 int oarg;
1389 oarg = ct_str[0] - '0';
1390 assert(oarg < def->nb_oargs);
1391 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1392 /* TCG_CT_ALIAS is for the output arguments. The input
1393 argument is tagged with TCG_CT_IALIAS. */
1394 def->args_ct[i] = def->args_ct[oarg];
1395 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1396 def->args_ct[oarg].alias_index = i;
1397 def->args_ct[i].ct |= TCG_CT_IALIAS;
1398 def->args_ct[i].alias_index = oarg;
1399 } else {
1400 for(;;) {
1401 if (*ct_str == '\0')
1402 break;
1403 switch(*ct_str) {
1404 case 'i':
1405 def->args_ct[i].ct |= TCG_CT_CONST;
1406 ct_str++;
1407 break;
1408 default:
1409 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1410 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1411 ct_str, i, def->name);
1412 exit(1);
1413 }
1414 }
1415 }
1416 }
1417 }
1418
1419 /* TCGTargetOpDef entry with too much information? */
1420 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1421
1422 /* sort the constraints (XXX: this is just an heuristic) */
1423 sort_constraints(def, 0, def->nb_oargs);
1424 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1425
1426 #if 0
1427 {
1428 int i;
1429
1430 printf("%s: sorted=", def->name);
1431 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1432 printf(" %d", def->sorted_args[i]);
1433 printf("\n");
1434 }
1435 #endif
1436 tdefs++;
1437 }
1438
1439 #if defined(CONFIG_DEBUG_TCG)
1440 i = 0;
1441 for (op = 0; op < ARRAY_SIZE(s->tcg_op_defs); op++) {
1442 const TCGOpDef *def = &s->tcg_op_defs[op];
1443 if (def->flags & TCG_OPF_NOT_PRESENT) {
1444 /* Wrong entry in op definitions? */
1445 if (def->used) {
1446 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1447 i = 1;
1448 }
1449 } else {
1450 /* Missing entry in op definitions? */
1451 if (!def->used) {
1452 fprintf(stderr, "Missing op definition for %s\n", def->name);
1453 i = 1;
1454 }
1455 }
1456 }
1457 if (i == 1) {
1458 tcg_abort();
1459 }
1460 #endif
1461 }
1462
1463 #ifdef USE_LIVENESS_ANALYSIS
1464
1465 /* set a nop for an operation using 'nb_args' */
tcg_set_nop(TCGContext * s,uint16_t * opc_ptr,TCGArg * args,int nb_args)1466 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1467 TCGArg *args, int nb_args)
1468 {
1469 if (nb_args == 0) {
1470 *opc_ptr = INDEX_op_nop;
1471 } else {
1472 *opc_ptr = INDEX_op_nopn;
1473 args[0] = nb_args;
1474 args[nb_args - 1] = nb_args;
1475 }
1476 }
1477
1478 /* liveness analysis: end of function: all temps are dead, and globals
1479 should be in memory. */
tcg_la_func_end(TCGContext * s,uint8_t * dead_temps,uint8_t * mem_temps)1480 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps,
1481 uint8_t *mem_temps)
1482 {
1483 memset(dead_temps, 1, s->nb_temps);
1484 memset(mem_temps, 1, s->nb_globals);
1485 memset(mem_temps + s->nb_globals, 0, s->nb_temps - s->nb_globals);
1486 }
1487
1488 /* liveness analysis: end of basic block: all temps are dead, globals
1489 and local temps should be in memory. */
tcg_la_bb_end(TCGContext * s,uint8_t * dead_temps,uint8_t * mem_temps)1490 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
1491 uint8_t *mem_temps)
1492 {
1493 int i;
1494
1495 memset(dead_temps, 1, s->nb_temps);
1496 memset(mem_temps, 1, s->nb_globals);
1497 for(i = s->nb_globals; i < s->nb_temps; i++) {
1498 mem_temps[i] = s->temps[i].temp_local;
1499 }
1500 }
1501
1502 /*
1503 Unicorn: for brcond, we should refresh liveness states for TCG globals
1504 */
tcg_la_br_end(TCGContext * s,uint8_t * mem_temps)1505 static inline void tcg_la_br_end(TCGContext *s, uint8_t *mem_temps)
1506 {
1507 int i;
1508 memset(mem_temps, 1, s->nb_globals);
1509 for(i = s->nb_globals; i < s->nb_temps; i++) {
1510 mem_temps[i] = s->temps[i].temp_local;
1511 }
1512 }
1513
1514 /* Liveness analysis : update the opc_dead_args array to tell if a
1515 given input arguments is dead. Instructions updating dead
1516 temporaries are removed. */
tcg_liveness_analysis(TCGContext * s)1517 static void tcg_liveness_analysis(TCGContext *s)
1518 {
1519 int i, op_index, nb_args, nb_iargs, nb_oargs, nb_ops;
1520 TCGOpcode op, op_new, op_new2;
1521 TCGArg *args, arg;
1522 const TCGOpDef *def;
1523 uint8_t *dead_temps, *mem_temps;
1524 uint16_t dead_args;
1525 uint8_t sync_args;
1526 bool have_op_new2;
1527
1528 s->gen_opc_ptr++; /* skip end */
1529
1530 nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
1531
1532 s->op_dead_args = tcg_malloc(s, nb_ops * sizeof(uint16_t));
1533 s->op_sync_args = tcg_malloc(s, nb_ops * sizeof(uint8_t));
1534
1535 dead_temps = tcg_malloc(s, s->nb_temps);
1536 mem_temps = tcg_malloc(s, s->nb_temps);
1537 tcg_la_func_end(s, dead_temps, mem_temps);
1538
1539 args = s->gen_opparam_ptr;
1540 op_index = nb_ops - 1;
1541 while (op_index >= 0) {
1542 op = s->gen_opc_buf[op_index];
1543 def = &s->tcg_op_defs[op];
1544 switch(op) {
1545 case INDEX_op_call:
1546 {
1547 int call_flags;
1548
1549 nb_args = args[-1];
1550 args -= nb_args;
1551 arg = *args++;
1552 nb_iargs = arg & 0xffff;
1553 nb_oargs = arg >> 16;
1554 call_flags = args[nb_oargs + nb_iargs + 1];
1555
1556 /* pure functions can be removed if their result is not
1557 used */
1558 if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
1559 for (i = 0; i < nb_oargs; i++) {
1560 arg = args[i];
1561 if (!dead_temps[arg] || mem_temps[arg]) {
1562 goto do_not_remove_call;
1563 }
1564 }
1565 tcg_set_nop(s, s->gen_opc_buf + op_index,
1566 args - 1, nb_args);
1567 } else {
1568 do_not_remove_call:
1569
1570 /* output args are dead */
1571 dead_args = 0;
1572 sync_args = 0;
1573 for (i = 0; i < nb_oargs; i++) {
1574 arg = args[i];
1575 if (dead_temps[arg]) {
1576 dead_args |= (1 << i);
1577 }
1578 if (mem_temps[arg]) {
1579 sync_args |= (1 << i);
1580 }
1581 dead_temps[arg] = 1;
1582 mem_temps[arg] = 0;
1583 }
1584
1585 if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) {
1586 /* globals should be synced to memory */
1587 memset(mem_temps, 1, s->nb_globals);
1588 }
1589 if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
1590 TCG_CALL_NO_READ_GLOBALS))) {
1591 /* globals should go back to memory */
1592 memset(dead_temps, 1, s->nb_globals);
1593 }
1594
1595 /* input args are live */
1596 for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1597 arg = args[i];
1598 if (arg != TCG_CALL_DUMMY_ARG) {
1599 if (dead_temps[arg]) {
1600 dead_args |= (1 << i);
1601 }
1602 dead_temps[arg] = 0;
1603 }
1604 }
1605 s->op_dead_args[op_index] = dead_args;
1606 s->op_sync_args[op_index] = sync_args;
1607 }
1608 args--;
1609 }
1610 break;
1611 case INDEX_op_debug_insn_start:
1612 args -= def->nb_args;
1613 break;
1614 case INDEX_op_nopn:
1615 nb_args = args[-1];
1616 args -= nb_args;
1617 break;
1618 case INDEX_op_discard:
1619 args--;
1620 /* mark the temporary as dead */
1621 dead_temps[args[0]] = 1;
1622 mem_temps[args[0]] = 0;
1623 break;
1624 case INDEX_op_end:
1625 break;
1626
1627 case INDEX_op_add2_i32:
1628 op_new = INDEX_op_add_i32;
1629 goto do_addsub2;
1630 case INDEX_op_sub2_i32:
1631 op_new = INDEX_op_sub_i32;
1632 goto do_addsub2;
1633 case INDEX_op_add2_i64:
1634 op_new = INDEX_op_add_i64;
1635 goto do_addsub2;
1636 case INDEX_op_sub2_i64:
1637 op_new = INDEX_op_sub_i64;
1638 do_addsub2:
1639 args -= 6;
1640 nb_iargs = 4;
1641 nb_oargs = 2;
1642 /* Test if the high part of the operation is dead, but not
1643 the low part. The result can be optimized to a simple
1644 add or sub. This happens often for x86_64 guest when the
1645 cpu mode is set to 32 bit. */
1646 if (dead_temps[args[1]] && !mem_temps[args[1]]) {
1647 if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1648 goto do_remove;
1649 }
1650 /* Create the single operation plus nop. */
1651 s->gen_opc_buf[op_index] = op = op_new;
1652 args[1] = args[2];
1653 args[2] = args[4];
1654 assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
1655 tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 3);
1656 /* Fall through and mark the single-word operation live. */
1657 nb_iargs = 2;
1658 nb_oargs = 1;
1659 }
1660 goto do_not_remove;
1661
1662 case INDEX_op_mulu2_i32:
1663 op_new = INDEX_op_mul_i32;
1664 op_new2 = INDEX_op_muluh_i32;
1665 have_op_new2 = TCG_TARGET_HAS_muluh_i32;
1666 goto do_mul2;
1667 case INDEX_op_muls2_i32:
1668 op_new = INDEX_op_mul_i32;
1669 op_new2 = INDEX_op_mulsh_i32;
1670 have_op_new2 = TCG_TARGET_HAS_mulsh_i32;
1671 goto do_mul2;
1672 case INDEX_op_mulu2_i64:
1673 op_new = INDEX_op_mul_i64;
1674 op_new2 = INDEX_op_muluh_i64;
1675 have_op_new2 = TCG_TARGET_HAS_muluh_i64;
1676 goto do_mul2;
1677 case INDEX_op_muls2_i64:
1678 op_new = INDEX_op_mul_i64;
1679 op_new2 = INDEX_op_mulsh_i64;
1680 have_op_new2 = TCG_TARGET_HAS_mulsh_i64;
1681 goto do_mul2;
1682 do_mul2:
1683 args -= 4;
1684 nb_iargs = 2;
1685 nb_oargs = 2;
1686 if (dead_temps[args[1]] && !mem_temps[args[1]]) {
1687 if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1688 /* Both parts of the operation are dead. */
1689 goto do_remove;
1690 }
1691 /* The high part of the operation is dead; generate the low. */
1692 s->gen_opc_buf[op_index] = op = op_new;
1693 args[1] = args[2];
1694 args[2] = args[3];
1695 } else if (have_op_new2 && dead_temps[args[0]]
1696 && !mem_temps[args[0]]) {
1697 /* The low part of the operation is dead; generate the high. */
1698 s->gen_opc_buf[op_index] = op = op_new2;
1699 args[0] = args[1];
1700 args[1] = args[2];
1701 args[2] = args[3];
1702 } else {
1703 goto do_not_remove;
1704 }
1705 assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
1706 tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1);
1707 /* Mark the single-word operation live. */
1708 nb_oargs = 1;
1709 goto do_not_remove;
1710
1711 default:
1712 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1713 args -= def->nb_args;
1714 nb_iargs = def->nb_iargs;
1715 nb_oargs = def->nb_oargs;
1716
1717 /* Test if the operation can be removed because all
1718 its outputs are dead. We assume that nb_oargs == 0
1719 implies side effects */
1720 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1721 for(i = 0; i < nb_oargs; i++) {
1722 if (args[i] >= TCG_MAX_TEMPS) {
1723 continue;
1724 }
1725 arg = args[i];
1726 if (!dead_temps[arg] || mem_temps[arg]) {
1727 goto do_not_remove;
1728 }
1729 }
1730 do_remove:
1731 tcg_set_nop(s, s->gen_opc_buf + op_index, args, def->nb_args);
1732 #ifdef CONFIG_PROFILER
1733 s->del_op_count++;
1734 #endif
1735 } else {
1736 do_not_remove:
1737
1738 /* output args are dead */
1739 dead_args = 0;
1740 sync_args = 0;
1741 for(i = 0; i < nb_oargs; i++) {
1742 arg = args[i];
1743 if (dead_temps[arg]) {
1744 dead_args |= (1 << i);
1745 }
1746 if (mem_temps[arg]) {
1747 sync_args |= (1 << i);
1748 }
1749 dead_temps[arg] = 1;
1750 mem_temps[arg] = 0;
1751 }
1752
1753 /* if end of basic block, update */
1754 if (def->flags & TCG_OPF_BB_END) {
1755 // Unicorn: do not optimize dead temps on brcond,
1756 // this causes problem because check_exit_request() inserts
1757 // brcond instruction in the middle of the TB,
1758 // which incorrectly flags end-of-block
1759 if (op != INDEX_op_brcond_i32)
1760 tcg_la_bb_end(s, dead_temps, mem_temps);
1761 // Unicorn: we do not touch dead temps for brcond,
1762 // but we should refresh TCG globals In-Memory states,
1763 // otherwise, important CPU states(especially conditional flags) might be forgotten,
1764 // result in wrongly generated host code that run into wrong branch.
1765 // Refer to https://github.com/unicorn-engine/unicorn/issues/287 for further information
1766 else
1767 tcg_la_br_end(s, mem_temps);
1768 } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
1769 /* globals should be synced to memory */
1770 memset(mem_temps, 1, s->nb_globals);
1771 }
1772
1773 /* input args are live */
1774 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1775 arg = args[i];
1776 if (dead_temps[arg]) {
1777 dead_args |= (1 << i);
1778 }
1779 dead_temps[arg] = 0;
1780 }
1781 s->op_dead_args[op_index] = dead_args;
1782 s->op_sync_args[op_index] = sync_args;
1783 }
1784 break;
1785 }
1786 op_index--;
1787 }
1788
1789 if (args != s->gen_opparam_buf) {
1790 tcg_abort();
1791 }
1792 }
1793 #else
1794 /* dummy liveness analysis */
tcg_liveness_analysis(TCGContext * s)1795 static void tcg_liveness_analysis(TCGContext *s)
1796 {
1797 int nb_ops;
1798 nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
1799
1800 s->op_dead_args = tcg_malloc(s, nb_ops * sizeof(uint16_t));
1801 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1802 s->op_sync_args = tcg_malloc(s, nb_ops * sizeof(uint8_t));
1803 memset(s->op_sync_args, 0, nb_ops * sizeof(uint8_t));
1804 }
1805 #endif
1806
1807 #ifndef NDEBUG
dump_regs(TCGContext * s)1808 static void dump_regs(TCGContext *s)
1809 {
1810 TCGTemp *ts;
1811 int i;
1812 char buf[64];
1813
1814 for(i = 0; i < s->nb_temps; i++) {
1815 ts = &s->temps[i];
1816 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1817 switch(ts->val_type) {
1818 case TEMP_VAL_REG:
1819 printf("%s", tcg_target_reg_names[ts->reg]);
1820 break;
1821 case TEMP_VAL_MEM:
1822 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1823 break;
1824 case TEMP_VAL_CONST:
1825 printf("$0x%" TCG_PRIlx, ts->val);
1826 break;
1827 case TEMP_VAL_DEAD:
1828 printf("D");
1829 break;
1830 default:
1831 printf("???");
1832 break;
1833 }
1834 printf("\n");
1835 }
1836
1837 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1838 if (s->reg_to_temp[i] >= 0) {
1839 printf("%s: %s\n",
1840 tcg_target_reg_names[i],
1841 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1842 }
1843 }
1844 }
1845
check_regs(TCGContext * s)1846 static void check_regs(TCGContext *s)
1847 {
1848 int reg, k;
1849 TCGTemp *ts;
1850 char buf[64];
1851
1852 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1853 k = s->reg_to_temp[reg];
1854 if (k >= 0) {
1855 ts = &s->temps[k];
1856 if (ts->val_type != TEMP_VAL_REG ||
1857 ts->reg != reg) {
1858 printf("Inconsistency for register %s:\n",
1859 tcg_target_reg_names[reg]);
1860 goto fail;
1861 }
1862 }
1863 }
1864 for(k = 0; k < s->nb_temps; k++) {
1865 ts = &s->temps[k];
1866 if (ts->val_type == TEMP_VAL_REG &&
1867 !ts->fixed_reg &&
1868 s->reg_to_temp[ts->reg] != k) {
1869 printf("Inconsistency for temp %s:\n",
1870 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1871 fail:
1872 printf("reg state:\n");
1873 dump_regs(s);
1874 tcg_abort();
1875 }
1876 }
1877 }
1878 #endif
1879
temp_allocate_frame(TCGContext * s,int temp)1880 static void temp_allocate_frame(TCGContext *s, int temp)
1881 {
1882 TCGTemp *ts;
1883 ts = &s->temps[temp];
1884 #if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1885 /* Sparc64 stack is accessed with offset of 2047 */
1886 s->current_frame_offset = (s->current_frame_offset +
1887 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1888 ~(sizeof(tcg_target_long) - 1);
1889 #endif
1890 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1891 s->frame_end) {
1892 tcg_abort();
1893 }
1894 ts->mem_offset = s->current_frame_offset;
1895 ts->mem_reg = s->frame_reg;
1896 ts->mem_allocated = 1;
1897 s->current_frame_offset += sizeof(tcg_target_long);
1898 }
1899
1900 /* sync register 'reg' by saving it to the corresponding temporary */
tcg_reg_sync(TCGContext * s,int reg)1901 static inline void tcg_reg_sync(TCGContext *s, int reg)
1902 {
1903 TCGTemp *ts;
1904 int temp;
1905
1906 temp = s->reg_to_temp[reg];
1907 ts = &s->temps[temp];
1908 assert(ts->val_type == TEMP_VAL_REG);
1909 if (!ts->mem_coherent && !ts->fixed_reg) {
1910 if (!ts->mem_allocated) {
1911 temp_allocate_frame(s, temp);
1912 }
1913 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1914 }
1915 ts->mem_coherent = 1;
1916 }
1917
1918 /* free register 'reg' by spilling the corresponding temporary if necessary */
tcg_reg_free(TCGContext * s,int reg)1919 static void tcg_reg_free(TCGContext *s, int reg)
1920 {
1921 int temp;
1922
1923 temp = s->reg_to_temp[reg];
1924 if (temp != -1) {
1925 tcg_reg_sync(s, reg);
1926 s->temps[temp].val_type = TEMP_VAL_MEM;
1927 s->reg_to_temp[reg] = -1;
1928 }
1929 }
1930
1931 /* Allocate a register belonging to reg1 & ~reg2 */
tcg_reg_alloc(TCGContext * s,TCGRegSet reg1,TCGRegSet reg2)1932 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1933 {
1934 int i, reg;
1935 TCGRegSet reg_ct;
1936
1937 tcg_regset_andnot(reg_ct, reg1, reg2);
1938
1939 /* first try free registers */
1940 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1941 reg = tcg_target_reg_alloc_order[i];
1942 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1943 return reg;
1944 }
1945
1946 /* XXX: do better spill choice */
1947 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1948 reg = tcg_target_reg_alloc_order[i];
1949 if (tcg_regset_test_reg(reg_ct, reg)) {
1950 tcg_reg_free(s, reg);
1951 return reg;
1952 }
1953 }
1954
1955 tcg_abort();
1956 }
1957
1958 /* mark a temporary as dead. */
temp_dead(TCGContext * s,int temp)1959 static inline void temp_dead(TCGContext *s, int temp)
1960 {
1961 TCGTemp *ts;
1962
1963 ts = &s->temps[temp];
1964 if (!ts->fixed_reg) {
1965 if (ts->val_type == TEMP_VAL_REG) {
1966 s->reg_to_temp[ts->reg] = -1;
1967 }
1968 if (temp < s->nb_globals || ts->temp_local) {
1969 ts->val_type = TEMP_VAL_MEM;
1970 } else {
1971 ts->val_type = TEMP_VAL_DEAD;
1972 }
1973 }
1974 }
1975
1976 /* sync a temporary to memory. 'allocated_regs' is used in case a
1977 temporary registers needs to be allocated to store a constant. */
temp_sync(TCGContext * s,int temp,TCGRegSet allocated_regs)1978 static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs)
1979 {
1980 TCGTemp *ts;
1981
1982 ts = &s->temps[temp];
1983 if (!ts->fixed_reg) {
1984 switch(ts->val_type) {
1985 case TEMP_VAL_CONST:
1986 ts->reg = tcg_reg_alloc(s, (TCGRegSet)s->tcg_target_available_regs[ts->type],
1987 allocated_regs);
1988 ts->val_type = TEMP_VAL_REG;
1989 s->reg_to_temp[ts->reg] = temp;
1990 ts->mem_coherent = 0;
1991 tcg_out_movi(s, ts->type, ts->reg, ts->val);
1992 /* fallthrough*/
1993 case TEMP_VAL_REG:
1994 tcg_reg_sync(s, ts->reg);
1995 break;
1996 case TEMP_VAL_DEAD:
1997 case TEMP_VAL_MEM:
1998 break;
1999 default:
2000 tcg_abort();
2001 }
2002 }
2003 }
2004
2005 /* save a temporary to memory. 'allocated_regs' is used in case a
2006 temporary registers needs to be allocated to store a constant. */
temp_save(TCGContext * s,int temp,TCGRegSet allocated_regs)2007 static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
2008 {
2009 #ifdef USE_LIVENESS_ANALYSIS
2010 /* The liveness analysis already ensures that globals are back
2011 in memory. Keep an assert for safety. */
2012 assert(s->temps[temp].val_type == TEMP_VAL_MEM || s->temps[temp].fixed_reg);
2013 #else
2014 temp_sync(s, temp, allocated_regs);
2015 temp_dead(s, temp);
2016 #endif
2017 }
2018
2019 /* save globals to their canonical location and assume they can be
2020 modified be the following code. 'allocated_regs' is used in case a
2021 temporary registers needs to be allocated to store a constant. */
save_globals(TCGContext * s,TCGRegSet allocated_regs)2022 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
2023 {
2024 int i;
2025
2026 for(i = 0; i < s->nb_globals; i++) {
2027 temp_save(s, i, allocated_regs);
2028 }
2029 }
2030
2031 /* sync globals to their canonical location and assume they can be
2032 read by the following code. 'allocated_regs' is used in case a
2033 temporary registers needs to be allocated to store a constant. */
sync_globals(TCGContext * s,TCGRegSet allocated_regs)2034 static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
2035 {
2036 int i;
2037
2038 for (i = 0; i < s->nb_globals; i++) {
2039 #ifdef USE_LIVENESS_ANALYSIS
2040 assert(s->temps[i].val_type != TEMP_VAL_REG || s->temps[i].fixed_reg ||
2041 s->temps[i].mem_coherent);
2042 #else
2043 temp_sync(s, i, allocated_regs);
2044 #endif
2045 }
2046 }
2047
2048 /* at the end of a basic block, we assume all temporaries are dead and
2049 all globals are stored at their canonical location. */
tcg_reg_alloc_bb_end(TCGContext * s,TCGRegSet allocated_regs)2050 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
2051 {
2052 TCGTemp *ts;
2053 int i;
2054
2055 for(i = s->nb_globals; i < s->nb_temps; i++) {
2056 ts = &s->temps[i];
2057 if (ts->temp_local) {
2058 temp_save(s, i, allocated_regs);
2059 } else {
2060 #ifdef USE_LIVENESS_ANALYSIS
2061 /* The liveness analysis already ensures that temps are dead.
2062 Keep an assert for safety. */
2063 assert(ts->val_type == TEMP_VAL_DEAD);
2064 #else
2065 temp_dead(s, i);
2066 #endif
2067 }
2068 }
2069
2070 save_globals(s, allocated_regs);
2071 }
2072
2073 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
2074 #define NEED_SYNC_ARG(n) ((sync_args >> (n)) & 1)
2075
tcg_reg_alloc_movi(TCGContext * s,const TCGArg * args,uint16_t dead_args,uint8_t sync_args)2076 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
2077 uint16_t dead_args, uint8_t sync_args)
2078 {
2079 TCGTemp *ots;
2080 tcg_target_ulong val;
2081
2082 ots = &s->temps[args[0]];
2083 val = args[1];
2084
2085 if (ots->fixed_reg) {
2086 /* for fixed registers, we do not do any constant
2087 propagation */
2088 tcg_out_movi(s, ots->type, ots->reg, val);
2089 } else {
2090 /* The movi is not explicitly generated here */
2091 if (ots->val_type == TEMP_VAL_REG)
2092 s->reg_to_temp[ots->reg] = -1;
2093 ots->val_type = TEMP_VAL_CONST;
2094 ots->val = val;
2095 }
2096 if (NEED_SYNC_ARG(0)) {
2097 temp_sync(s, args[0], s->reserved_regs);
2098 }
2099 if (IS_DEAD_ARG(0)) {
2100 temp_dead(s, args[0]);
2101 }
2102 }
2103
tcg_reg_alloc_mov(TCGContext * s,const TCGOpDef * def,const TCGArg * args,uint16_t dead_args,uint8_t sync_args)2104 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
2105 const TCGArg *args, uint16_t dead_args,
2106 uint8_t sync_args)
2107 {
2108 TCGRegSet allocated_regs;
2109 TCGTemp *ts, *ots;
2110 TCGType otype, itype;
2111
2112 tcg_regset_set(allocated_regs, s->reserved_regs);
2113 ots = &s->temps[args[0]];
2114 ts = &s->temps[args[1]];
2115
2116 /* Note that otype != itype for no-op truncation. */
2117 otype = ots->type;
2118 itype = ts->type;
2119
2120 /* If the source value is not in a register, and we're going to be
2121 forced to have it in a register in order to perform the copy,
2122 then copy the SOURCE value into its own register first. That way
2123 we don't have to reload SOURCE the next time it is used. */
2124 if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
2125 || ts->val_type == TEMP_VAL_MEM) {
2126 ts->reg = tcg_reg_alloc(s, (TCGRegSet)s->tcg_target_available_regs[itype],
2127 allocated_regs);
2128 if (ts->val_type == TEMP_VAL_MEM) {
2129 tcg_out_ld(s, itype, ts->reg, ts->mem_reg, ts->mem_offset);
2130 ts->mem_coherent = 1;
2131 } else if (ts->val_type == TEMP_VAL_CONST) {
2132 tcg_out_movi(s, itype, ts->reg, ts->val);
2133 ts->mem_coherent = 0;
2134 }
2135 s->reg_to_temp[ts->reg] = args[1];
2136 ts->val_type = TEMP_VAL_REG;
2137 }
2138
2139 if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
2140 /* mov to a non-saved dead register makes no sense (even with
2141 liveness analysis disabled). */
2142 assert(NEED_SYNC_ARG(0));
2143 /* The code above should have moved the temp to a register. */
2144 assert(ts->val_type == TEMP_VAL_REG);
2145 if (!ots->mem_allocated) {
2146 temp_allocate_frame(s, args[0]);
2147 }
2148 tcg_out_st(s, otype, ts->reg, ots->mem_reg, ots->mem_offset);
2149 if (IS_DEAD_ARG(1)) {
2150 temp_dead(s, args[1]);
2151 }
2152 temp_dead(s, args[0]);
2153 } else if (ts->val_type == TEMP_VAL_CONST) {
2154 /* propagate constant */
2155 if (ots->val_type == TEMP_VAL_REG) {
2156 s->reg_to_temp[ots->reg] = -1;
2157 }
2158 ots->val_type = TEMP_VAL_CONST;
2159 ots->val = ts->val;
2160 } else {
2161 /* The code in the first if block should have moved the
2162 temp to a register. */
2163 assert(ts->val_type == TEMP_VAL_REG);
2164 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
2165 /* the mov can be suppressed */
2166 if (ots->val_type == TEMP_VAL_REG) {
2167 s->reg_to_temp[ots->reg] = -1;
2168 }
2169 ots->reg = ts->reg;
2170 temp_dead(s, args[1]);
2171 } else {
2172 if (ots->val_type != TEMP_VAL_REG) {
2173 /* When allocating a new register, make sure to not spill the
2174 input one. */
2175 tcg_regset_set_reg(allocated_regs, ts->reg);
2176 ots->reg = tcg_reg_alloc(s, (TCGRegSet)s->tcg_target_available_regs[otype],
2177 allocated_regs);
2178 }
2179 tcg_out_mov(s, otype, ots->reg, ts->reg);
2180 }
2181 ots->val_type = TEMP_VAL_REG;
2182 ots->mem_coherent = 0;
2183 s->reg_to_temp[ots->reg] = args[0];
2184 if (NEED_SYNC_ARG(0)) {
2185 tcg_reg_sync(s, ots->reg);
2186 }
2187 }
2188 }
2189
tcg_reg_alloc_op(TCGContext * s,const TCGOpDef * def,TCGOpcode opc,const TCGArg * args,uint16_t dead_args,uint8_t sync_args)2190 static void tcg_reg_alloc_op(TCGContext *s,
2191 const TCGOpDef *def, TCGOpcode opc,
2192 const TCGArg *args, uint16_t dead_args,
2193 uint8_t sync_args)
2194 {
2195 TCGRegSet allocated_regs;
2196 int i, k, nb_iargs, nb_oargs, reg;
2197 TCGArg arg;
2198 const TCGArgConstraint *arg_ct;
2199 TCGTemp *ts;
2200 TCGArg new_args[TCG_MAX_OP_ARGS];
2201 int const_args[TCG_MAX_OP_ARGS];
2202
2203 nb_oargs = def->nb_oargs;
2204 nb_iargs = def->nb_iargs;
2205
2206 /* copy constants */
2207 memcpy(new_args + nb_oargs + nb_iargs,
2208 args + nb_oargs + nb_iargs,
2209 sizeof(TCGArg) * def->nb_cargs);
2210
2211 /* satisfy input constraints */
2212 tcg_regset_set(allocated_regs, s->reserved_regs);
2213 for(k = 0; k < nb_iargs; k++) {
2214 i = def->sorted_args[nb_oargs + k];
2215 arg = args[i];
2216 arg_ct = &def->args_ct[i];
2217 ts = &s->temps[arg];
2218 if (ts->val_type == TEMP_VAL_MEM) {
2219 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2220 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2221 ts->val_type = TEMP_VAL_REG;
2222 ts->reg = reg;
2223 ts->mem_coherent = 1;
2224 s->reg_to_temp[reg] = arg;
2225 } else if (ts->val_type == TEMP_VAL_CONST) {
2226 if (tcg_target_const_match(ts->val, ts->type, arg_ct)) {
2227 /* constant is OK for instruction */
2228 const_args[i] = 1;
2229 new_args[i] = ts->val;
2230 goto iarg_end;
2231 } else {
2232 /* need to move to a register */
2233 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2234 tcg_out_movi(s, ts->type, reg, ts->val);
2235 ts->val_type = TEMP_VAL_REG;
2236 ts->reg = reg;
2237 ts->mem_coherent = 0;
2238 s->reg_to_temp[reg] = arg;
2239 }
2240 }
2241 assert(ts->val_type == TEMP_VAL_REG);
2242 if (arg_ct->ct & TCG_CT_IALIAS) {
2243 if (ts->fixed_reg) {
2244 /* if fixed register, we must allocate a new register
2245 if the alias is not the same register */
2246 if (arg != args[arg_ct->alias_index])
2247 goto allocate_in_reg;
2248 } else {
2249 /* if the input is aliased to an output and if it is
2250 not dead after the instruction, we must allocate
2251 a new register and move it */
2252 if (!IS_DEAD_ARG(i)) {
2253 goto allocate_in_reg;
2254 }
2255 }
2256 }
2257 reg = ts->reg;
2258 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
2259 /* nothing to do : the constraint is satisfied */
2260 } else {
2261 allocate_in_reg:
2262 /* allocate a new register matching the constraint
2263 and move the temporary register into it */
2264 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2265 tcg_out_mov(s, ts->type, reg, ts->reg);
2266 }
2267 new_args[i] = reg;
2268 const_args[i] = 0;
2269 tcg_regset_set_reg(allocated_regs, reg);
2270 iarg_end: ;
2271 }
2272
2273 /* mark dead temporaries and free the associated registers */
2274 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
2275 if (IS_DEAD_ARG(i)) {
2276 temp_dead(s, args[i]);
2277 }
2278 }
2279
2280 if (def->flags & TCG_OPF_BB_END) {
2281 tcg_reg_alloc_bb_end(s, allocated_regs);
2282 } else {
2283 if (def->flags & TCG_OPF_CALL_CLOBBER) {
2284 /* XXX: permit generic clobber register list ? */
2285 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
2286 if (tcg_regset_test_reg(s->tcg_target_call_clobber_regs, reg)) {
2287 tcg_reg_free(s, reg);
2288 }
2289 }
2290 }
2291 if (def->flags & TCG_OPF_SIDE_EFFECTS) {
2292 /* sync globals if the op has side effects and might trigger
2293 an exception. */
2294 sync_globals(s, allocated_regs);
2295 }
2296
2297 /* satisfy the output constraints */
2298 tcg_regset_set(allocated_regs, s->reserved_regs);
2299 for(k = 0; k < nb_oargs; k++) {
2300 i = def->sorted_args[k];
2301 arg = args[i];
2302 arg_ct = &def->args_ct[i];
2303 ts = &s->temps[arg];
2304 if (arg_ct->ct & TCG_CT_ALIAS) {
2305 reg = new_args[arg_ct->alias_index];
2306 } else {
2307 /* if fixed register, we try to use it */
2308 reg = ts->reg;
2309 if (ts->fixed_reg &&
2310 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
2311 goto oarg_end;
2312 }
2313 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2314 }
2315 tcg_regset_set_reg(allocated_regs, reg);
2316 /* if a fixed register is used, then a move will be done afterwards */
2317 if (!ts->fixed_reg) {
2318 if (ts->val_type == TEMP_VAL_REG) {
2319 s->reg_to_temp[ts->reg] = -1;
2320 }
2321 ts->val_type = TEMP_VAL_REG;
2322 ts->reg = reg;
2323 /* temp value is modified, so the value kept in memory is
2324 potentially not the same */
2325 ts->mem_coherent = 0;
2326 s->reg_to_temp[reg] = arg;
2327 }
2328 oarg_end:
2329 new_args[i] = reg;
2330 }
2331 }
2332
2333 /* emit instruction */
2334 tcg_out_op(s, opc, new_args, const_args);
2335
2336 /* move the outputs in the correct register if needed */
2337 for(i = 0; i < nb_oargs; i++) {
2338 ts = &s->temps[args[i]];
2339 reg = new_args[i];
2340 if (ts->fixed_reg && ts->reg != reg) {
2341 tcg_out_mov(s, ts->type, ts->reg, reg);
2342 }
2343 if (NEED_SYNC_ARG(i)) {
2344 tcg_reg_sync(s, reg);
2345 }
2346 if (IS_DEAD_ARG(i)) {
2347 temp_dead(s, args[i]);
2348 }
2349 }
2350 }
2351
2352 #ifdef TCG_TARGET_STACK_GROWSUP
2353 #define STACK_DIR(x) (-(x))
2354 #else
2355 #define STACK_DIR(x) (x)
2356 #endif
2357
tcg_reg_alloc_call(TCGContext * s,const TCGOpDef * def,TCGOpcode opc,const TCGArg * args,uint16_t dead_args,uint8_t sync_args)2358 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
2359 TCGOpcode opc, const TCGArg *args,
2360 uint16_t dead_args, uint8_t sync_args)
2361 {
2362 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
2363 TCGArg arg;
2364 TCGTemp *ts;
2365 intptr_t stack_offset;
2366 size_t call_stack_size;
2367 tcg_insn_unit *func_addr;
2368 int allocate_args;
2369 TCGRegSet allocated_regs;
2370
2371 arg = *args++;
2372
2373 nb_oargs = arg >> 16;
2374 nb_iargs = arg & 0xffff;
2375 nb_params = nb_iargs;
2376
2377 func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs];
2378 flags = args[nb_oargs + nb_iargs + 1];
2379
2380 nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
2381 #ifdef _UC_MSVC_ARRAY_DUMMY
2382 // do this because msvc cannot have arrays with 0 entries.
2383 /* ref: tcg/i386/tcg-target.c: tcg_target_call_iarg_regs,
2384 it is added a dummy value, set back to 0. */
2385 nb_regs = 0;
2386 #endif
2387 if (nb_regs > nb_params) {
2388 nb_regs = nb_params;
2389 }
2390
2391 /* assign stack slots first */
2392 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
2393 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
2394 ~(TCG_TARGET_STACK_ALIGN - 1);
2395 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
2396 if (allocate_args) {
2397 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
2398 preallocate call stack */
2399 return -1;
2400 }
2401
2402 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
2403 for(i = nb_regs; i < nb_params; i++) {
2404 arg = args[nb_oargs + i];
2405 #ifdef TCG_TARGET_STACK_GROWSUP
2406 stack_offset -= sizeof(tcg_target_long);
2407 #endif
2408 if (arg != TCG_CALL_DUMMY_ARG) {
2409 ts = &s->temps[arg];
2410 if (ts->val_type == TEMP_VAL_REG) {
2411 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
2412 } else if (ts->val_type == TEMP_VAL_MEM) {
2413 reg = tcg_reg_alloc(s, (TCGRegSet)s->tcg_target_available_regs[ts->type],
2414 s->reserved_regs);
2415 /* XXX: not correct if reading values from the stack */
2416 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2417 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
2418 } else if (ts->val_type == TEMP_VAL_CONST) {
2419 reg = tcg_reg_alloc(s, (TCGRegSet)s->tcg_target_available_regs[ts->type],
2420 s->reserved_regs);
2421 /* XXX: sign extend may be needed on some targets */
2422 tcg_out_movi(s, ts->type, reg, ts->val);
2423 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
2424 } else {
2425 return -1;
2426 }
2427 }
2428 #ifndef TCG_TARGET_STACK_GROWSUP
2429 stack_offset += sizeof(tcg_target_long);
2430 #endif
2431 }
2432
2433 /* assign input registers */
2434 tcg_regset_set(allocated_regs, s->reserved_regs);
2435 for(i = 0; i < nb_regs; i++) {
2436 arg = args[nb_oargs + i];
2437 if (arg != TCG_CALL_DUMMY_ARG) {
2438 ts = &s->temps[arg];
2439 reg = tcg_target_call_iarg_regs[i];
2440 tcg_reg_free(s, reg);
2441 if (ts->val_type == TEMP_VAL_REG) {
2442 if (ts->reg != reg) {
2443 tcg_out_mov(s, ts->type, reg, ts->reg);
2444 }
2445 } else if (ts->val_type == TEMP_VAL_MEM) {
2446 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2447 } else if (ts->val_type == TEMP_VAL_CONST) {
2448 /* XXX: sign extend ? */
2449 tcg_out_movi(s, ts->type, reg, ts->val);
2450 } else {
2451 return -1;
2452 }
2453 tcg_regset_set_reg(allocated_regs, reg);
2454 }
2455 }
2456
2457 /* mark dead temporaries and free the associated registers */
2458 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
2459 if (IS_DEAD_ARG(i)) {
2460 temp_dead(s, args[i]);
2461 }
2462 }
2463
2464 /* clobber call registers */
2465 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
2466 if (tcg_regset_test_reg(s->tcg_target_call_clobber_regs, reg)) {
2467 tcg_reg_free(s, reg);
2468 }
2469 }
2470
2471 /* Save globals if they might be written by the helper, sync them if
2472 they might be read. */
2473 if (flags & TCG_CALL_NO_READ_GLOBALS) {
2474 /* Nothing to do */
2475 } else if (flags & TCG_CALL_NO_WRITE_GLOBALS) {
2476 sync_globals(s, allocated_regs);
2477 } else {
2478 save_globals(s, allocated_regs);
2479 }
2480
2481 tcg_out_call(s, func_addr);
2482
2483 /* assign output registers and emit moves if needed */
2484 for(i = 0; i < nb_oargs; i++) {
2485 arg = args[i];
2486 ts = &s->temps[arg];
2487 reg = tcg_target_call_oarg_regs[i];
2488 assert(s->reg_to_temp[reg] == -1);
2489
2490 if (ts->fixed_reg) {
2491 if (ts->reg != reg) {
2492 tcg_out_mov(s, ts->type, ts->reg, reg);
2493 }
2494 } else {
2495 if (ts->val_type == TEMP_VAL_REG) {
2496 s->reg_to_temp[ts->reg] = -1;
2497 }
2498 ts->val_type = TEMP_VAL_REG;
2499 ts->reg = reg;
2500 ts->mem_coherent = 0;
2501 s->reg_to_temp[reg] = arg;
2502 if (NEED_SYNC_ARG(i)) {
2503 tcg_reg_sync(s, reg);
2504 }
2505 if (IS_DEAD_ARG(i)) {
2506 temp_dead(s, args[i]);
2507 }
2508 }
2509 }
2510
2511 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2512 }
2513
2514 #ifdef CONFIG_PROFILER
2515
dump_op_count(void)2516 static void dump_op_count(void)
2517 {
2518 int i;
2519
2520 for(i = INDEX_op_end; i < NB_OPS; i++) {
2521 qemu_log("%s %" PRId64 "\n", s->tcg_op_defs[i].name, tcg_table_op_count[i]);
2522 }
2523 }
2524 #endif
2525
2526
tcg_gen_code_common(TCGContext * s,tcg_insn_unit * gen_code_buf,long search_pc)2527 static inline int tcg_gen_code_common(TCGContext *s,
2528 tcg_insn_unit *gen_code_buf,
2529 long search_pc)
2530 {
2531 TCGOpcode opc;
2532 int op_index;
2533 const TCGOpDef *def;
2534 const TCGArg *args;
2535 int ret;
2536
2537 #ifdef DEBUG_DISAS
2538 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2539 qemu_log("OP:\n");
2540 tcg_dump_ops(s);
2541 qemu_log("\n");
2542 }
2543 #endif
2544
2545 #ifdef CONFIG_PROFILER
2546 s->opt_time -= profile_getclock();
2547 #endif
2548
2549 #ifdef USE_TCG_OPTIMIZATIONS
2550 s->gen_opparam_ptr =
2551 tcg_optimize(s, s->gen_opc_ptr, s->gen_opparam_buf, s->tcg_op_defs);
2552 if (s->gen_opparam_ptr == NULL) {
2553 tcg_out_tb_finalize(s);
2554 return -2;
2555 }
2556 #endif
2557
2558 #ifdef CONFIG_PROFILER
2559 s->opt_time += profile_getclock();
2560 s->la_time -= profile_getclock();
2561 #endif
2562
2563 tcg_liveness_analysis(s);
2564
2565 #ifdef CONFIG_PROFILER
2566 s->la_time += profile_getclock();
2567 #endif
2568
2569 #ifdef DEBUG_DISAS
2570 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2571 qemu_log("OP after optimization and liveness analysis:\n");
2572 tcg_dump_ops(s);
2573 qemu_log("\n");
2574 }
2575 #endif
2576
2577 tcg_reg_alloc_start(s);
2578
2579 s->code_buf = gen_code_buf;
2580 s->code_ptr = gen_code_buf;
2581
2582 tcg_out_tb_init(s);
2583
2584 args = s->gen_opparam_buf;
2585 op_index = 0;
2586
2587 for(;;) {
2588 opc = s->gen_opc_buf[op_index];
2589 #ifdef CONFIG_PROFILER
2590 tcg_table_op_count[opc]++;
2591 #endif
2592 def = &s->tcg_op_defs[opc];
2593 #if 0
2594 printf("%s: %d %d %d\n", def->name,
2595 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2596 // dump_regs(s);
2597 #endif
2598 switch(opc) {
2599 case INDEX_op_mov_i32:
2600 case INDEX_op_mov_i64:
2601 tcg_reg_alloc_mov(s, def, args, s->op_dead_args[op_index],
2602 s->op_sync_args[op_index]);
2603 break;
2604 case INDEX_op_movi_i32:
2605 case INDEX_op_movi_i64:
2606 tcg_reg_alloc_movi(s, args, s->op_dead_args[op_index],
2607 s->op_sync_args[op_index]);
2608 break;
2609 case INDEX_op_debug_insn_start:
2610 /* debug instruction */
2611 break;
2612 case INDEX_op_nop:
2613 case INDEX_op_nop1:
2614 case INDEX_op_nop2:
2615 case INDEX_op_nop3:
2616 break;
2617 case INDEX_op_nopn:
2618 args += args[0];
2619 goto next;
2620 case INDEX_op_discard:
2621 temp_dead(s, args[0]);
2622 break;
2623 case INDEX_op_set_label:
2624 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2625 tcg_out_label(s, args[0], s->code_ptr);
2626 break;
2627 case INDEX_op_call:
2628 ret = tcg_reg_alloc_call(s, def, opc, args,
2629 s->op_dead_args[op_index],
2630 s->op_sync_args[op_index]);
2631 if (ret == -1) {
2632 goto the_end;
2633 } else {
2634 args += ret;
2635 }
2636 goto next;
2637 case INDEX_op_end:
2638 goto the_end;
2639 default:
2640 /* Sanity check that we've not introduced any unhandled opcodes. */
2641 if (def->flags & TCG_OPF_NOT_PRESENT) {
2642 goto the_end;
2643 }
2644 /* Note: in order to speed up the code, it would be much
2645 faster to have specialized register allocator functions for
2646 some common argument patterns */
2647 tcg_reg_alloc_op(s, def, opc, args, s->op_dead_args[op_index],
2648 s->op_sync_args[op_index]);
2649 break;
2650 }
2651 args += def->nb_args;
2652 next:
2653 if (search_pc >= 0 && (size_t)search_pc < tcg_current_code_size(s)) {
2654 return op_index;
2655 }
2656 op_index++;
2657 #ifndef NDEBUG
2658 check_regs(s);
2659 #endif
2660 }
2661 the_end:
2662 /* Generate TB finalization at the end of block */
2663 tcg_out_tb_finalize(s);
2664 return -1;
2665 }
2666
tcg_gen_code(TCGContext * s,tcg_insn_unit * gen_code_buf)2667 int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf) // qq
2668 {
2669 int ret;
2670 #ifdef CONFIG_PROFILER
2671 {
2672 int n;
2673 n = (s->gen_opc_ptr - s->gen_opc_buf);
2674 s->op_count += n;
2675 if (n > s->op_count_max)
2676 s->op_count_max = n;
2677
2678 s->temp_count += s->nb_temps;
2679 if (s->nb_temps > s->temp_count_max)
2680 s->temp_count_max = s->nb_temps;
2681 }
2682 #endif
2683
2684 //printf("====== before gen code\n");
2685 //tcg_dump_ops(s);
2686 ret = tcg_gen_code_common(s, gen_code_buf, -1); // qq
2687 if (ret == -2) {
2688 return -1;
2689 }
2690
2691 //printf("====== after gen code\n");
2692 //tcg_dump_ops(s);
2693
2694 /* flush instruction cache */
2695 flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
2696
2697 return tcg_current_code_size(s);
2698 }
2699
2700 /* Return the index of the micro operation such as the pc after is <
2701 offset bytes from the start of the TB. The contents of gen_code_buf must
2702 not be changed, though writing the same values is ok.
2703 Return -1 if not found. */
tcg_gen_code_search_pc(TCGContext * s,tcg_insn_unit * gen_code_buf,long offset)2704 int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
2705 long offset)
2706 {
2707 return tcg_gen_code_common(s, gen_code_buf, offset);
2708 }
2709
2710 #ifdef CONFIG_PROFILER
tcg_dump_info(FILE * f,fprintf_function cpu_fprintf)2711 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2712 {
2713 #if 0
2714 TCGContext *s = &tcg_ctx;
2715 int64_t tot;
2716
2717 tot = s->interm_time + s->code_time;
2718 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2719 tot, tot / 2.4e9);
2720 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2721 s->tb_count,
2722 s->tb_count1 - s->tb_count,
2723 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2724 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2725 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2726 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2727 s->tb_count ?
2728 (double)s->del_op_count / s->tb_count : 0);
2729 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2730 s->tb_count ?
2731 (double)s->temp_count / s->tb_count : 0,
2732 s->temp_count_max);
2733
2734 cpu_fprintf(f, "cycles/op %0.1f\n",
2735 s->op_count ? (double)tot / s->op_count : 0);
2736 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2737 s->code_in_len ? (double)tot / s->code_in_len : 0);
2738 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2739 s->code_out_len ? (double)tot / s->code_out_len : 0);
2740 if (tot == 0)
2741 tot = 1;
2742 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2743 (double)s->interm_time / tot * 100.0);
2744 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2745 (double)s->code_time / tot * 100.0);
2746 cpu_fprintf(f, "optim./code time %0.1f%%\n",
2747 (double)s->opt_time / (s->code_time ? s->code_time : 1)
2748 * 100.0);
2749 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2750 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2751 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2752 s->restore_count);
2753 cpu_fprintf(f, " avg cycles %0.1f\n",
2754 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2755
2756 dump_op_count();
2757 #endif
2758 }
2759 #else
tcg_dump_info(FILE * f,fprintf_function cpu_fprintf)2760 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2761 {
2762 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2763 }
2764 #endif
2765