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