2
* Tiny Code Generator for QEMU
4
* Copyright (c) 2008 Fabrice Bellard
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:
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
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
25
/* define it to suppress various consistency checks (faster) */
28
/* define it to use liveness analysis (better code) */
29
#define USE_LIVENESS_ANALYSIS
42
#include "qemu-common.h"
44
/* Note: the long term plan is to reduce the dependancies on the QEMU
45
CPU definitions. Currently they are used for qemu_ld/st
47
#define NO_CPU_IO_DEFS
55
static void patch_reloc(uint8_t *code_ptr, int type,
56
tcg_target_long value, tcg_target_long addend);
58
TCGOpDef tcg_op_defs[] = {
59
#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
60
#define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
66
static TCGRegSet tcg_target_available_regs[2];
67
static TCGRegSet tcg_target_call_clobber_regs;
69
/* XXX: move that inside the context */
70
uint16_t *gen_opc_ptr;
71
TCGArg *gen_opparam_ptr;
73
static inline void tcg_out8(TCGContext *s, uint8_t v)
78
static inline void tcg_out16(TCGContext *s, uint16_t v)
80
*(uint16_t *)s->code_ptr = v;
84
static inline void tcg_out32(TCGContext *s, uint32_t v)
86
*(uint32_t *)s->code_ptr = v;
90
/* label relocation processing */
92
void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
93
int label_index, long addend)
98
l = &s->labels[label_index];
100
/* FIXME: This may break relocations on RISC targets that
101
modify instruction fields in place. The caller may not have
102
written the initial value. */
103
patch_reloc(code_ptr, type, l->u.value, addend);
105
/* add a new relocation entry */
106
r = tcg_malloc(sizeof(TCGRelocation));
110
r->next = l->u.first_reloc;
111
l->u.first_reloc = r;
115
static void tcg_out_label(TCGContext *s, int label_index,
116
tcg_target_long value)
121
l = &s->labels[label_index];
124
r = l->u.first_reloc;
126
patch_reloc(r->ptr, r->type, value, r->addend);
133
int gen_new_label(void)
135
TCGContext *s = &tcg_ctx;
139
if (s->nb_labels >= TCG_MAX_LABELS)
141
idx = s->nb_labels++;
144
l->u.first_reloc = NULL;
148
#include "tcg-target.c"
150
/* pool based memory allocation */
151
void *tcg_malloc_internal(TCGContext *s, int size)
156
if (size > TCG_POOL_CHUNK_SIZE) {
157
/* big malloc: insert a new pool (XXX: could optimize) */
158
p = qemu_malloc(sizeof(TCGPool) + size);
161
s->pool_current->next = p;
164
p->next = s->pool_current;
174
pool_size = TCG_POOL_CHUNK_SIZE;
175
p = qemu_malloc(sizeof(TCGPool) + pool_size);
179
s->pool_current->next = p;
188
s->pool_cur = p->data + size;
189
s->pool_end = p->data + p->size;
193
void tcg_pool_reset(TCGContext *s)
195
s->pool_cur = s->pool_end = NULL;
196
s->pool_current = NULL;
199
void tcg_context_init(TCGContext *s)
201
int op, total_args, n;
203
TCGArgConstraint *args_ct;
206
memset(s, 0, sizeof(*s));
207
s->temps = s->static_temps;
210
/* Count total number of arguments and allocate the corresponding
213
for(op = 0; op < NB_OPS; op++) {
214
def = &tcg_op_defs[op];
215
n = def->nb_iargs + def->nb_oargs;
219
args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
220
sorted_args = qemu_malloc(sizeof(int) * total_args);
222
for(op = 0; op < NB_OPS; op++) {
223
def = &tcg_op_defs[op];
224
def->args_ct = args_ct;
225
def->sorted_args = sorted_args;
226
n = def->nb_iargs + def->nb_oargs;
233
/* init global prologue and epilogue */
234
s->code_buf = code_gen_prologue;
235
s->code_ptr = s->code_buf;
236
tcg_target_qemu_prologue(s);
237
flush_icache_range((unsigned long)s->code_buf,
238
(unsigned long)s->code_ptr);
241
void tcg_set_frame(TCGContext *s, int reg,
242
tcg_target_long start, tcg_target_long size)
244
s->frame_start = start;
245
s->frame_end = start + size;
249
void tcg_func_start(TCGContext *s)
253
s->nb_temps = s->nb_globals;
254
for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
255
s->first_free_temp[i] = -1;
256
s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
258
s->current_frame_offset = s->frame_start;
260
gen_opc_ptr = gen_opc_buf;
261
gen_opparam_ptr = gen_opparam_buf;
264
static inline void tcg_temp_alloc(TCGContext *s, int n)
266
if (n > TCG_MAX_TEMPS)
270
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
272
TCGContext *s = &tcg_ctx;
276
#if TCG_TARGET_REG_BITS == 32
277
if (type != TCG_TYPE_I32)
280
if (tcg_regset_test_reg(s->reserved_regs, reg))
283
tcg_temp_alloc(s, s->nb_globals + 1);
284
ts = &s->temps[s->nb_globals];
285
ts->base_type = type;
291
tcg_regset_set_reg(s->reserved_regs, reg);
292
return MAKE_TCGV(idx);
295
#if TCG_TARGET_REG_BITS == 32
296
/* temporary hack to avoid register shortage for tcg_qemu_st64() */
297
TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
300
TCGContext *s = &tcg_ctx;
305
if (type != TCG_TYPE_I64)
308
tcg_temp_alloc(s, s->nb_globals + 2);
309
ts = &s->temps[s->nb_globals];
310
ts->base_type = type;
311
ts->type = TCG_TYPE_I32;
314
pstrcpy(buf, sizeof(buf), name);
315
pstrcat(buf, sizeof(buf), "_0");
316
ts->name = strdup(buf);
319
ts->base_type = type;
320
ts->type = TCG_TYPE_I32;
323
pstrcpy(buf, sizeof(buf), name);
324
pstrcat(buf, sizeof(buf), "_1");
325
ts->name = strdup(buf);
328
return MAKE_TCGV(idx);
332
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
335
TCGContext *s = &tcg_ctx;
340
#if TCG_TARGET_REG_BITS == 32
341
if (type == TCG_TYPE_I64) {
343
tcg_temp_alloc(s, s->nb_globals + 2);
344
ts = &s->temps[s->nb_globals];
345
ts->base_type = type;
346
ts->type = TCG_TYPE_I32;
348
ts->mem_allocated = 1;
350
#ifdef TCG_TARGET_WORDS_BIGENDIAN
351
ts->mem_offset = offset + 4;
353
ts->mem_offset = offset;
355
pstrcpy(buf, sizeof(buf), name);
356
pstrcat(buf, sizeof(buf), "_0");
357
ts->name = strdup(buf);
360
ts->base_type = type;
361
ts->type = TCG_TYPE_I32;
363
ts->mem_allocated = 1;
365
#ifdef TCG_TARGET_WORDS_BIGENDIAN
366
ts->mem_offset = offset;
368
ts->mem_offset = offset + 4;
370
pstrcpy(buf, sizeof(buf), name);
371
pstrcat(buf, sizeof(buf), "_1");
372
ts->name = strdup(buf);
378
tcg_temp_alloc(s, s->nb_globals + 1);
379
ts = &s->temps[s->nb_globals];
380
ts->base_type = type;
383
ts->mem_allocated = 1;
385
ts->mem_offset = offset;
389
return MAKE_TCGV(idx);
392
TCGv tcg_temp_new_internal(TCGType type, int temp_local)
394
TCGContext *s = &tcg_ctx;
401
idx = s->first_free_temp[k];
403
/* There is already an available temp with the
406
s->first_free_temp[k] = ts->next_free_temp;
407
ts->temp_allocated = 1;
408
assert(ts->temp_local == temp_local);
411
#if TCG_TARGET_REG_BITS == 32
412
if (type == TCG_TYPE_I64) {
413
tcg_temp_alloc(s, s->nb_temps + 2);
414
ts = &s->temps[s->nb_temps];
415
ts->base_type = type;
416
ts->type = TCG_TYPE_I32;
417
ts->temp_allocated = 1;
418
ts->temp_local = temp_local;
421
ts->base_type = TCG_TYPE_I32;
422
ts->type = TCG_TYPE_I32;
423
ts->temp_allocated = 1;
424
ts->temp_local = temp_local;
430
tcg_temp_alloc(s, s->nb_temps + 1);
431
ts = &s->temps[s->nb_temps];
432
ts->base_type = type;
434
ts->temp_allocated = 1;
435
ts->temp_local = temp_local;
440
return MAKE_TCGV(idx);
443
void tcg_temp_free(TCGv arg)
445
TCGContext *s = &tcg_ctx;
447
int idx = GET_TCGV(arg);
450
assert(idx >= s->nb_globals && idx < s->nb_temps);
452
assert(ts->temp_allocated != 0);
453
ts->temp_allocated = 0;
457
ts->next_free_temp = s->first_free_temp[k];
458
s->first_free_temp[k] = idx;
462
TCGv tcg_const_i32(int32_t val)
465
t0 = tcg_temp_new(TCG_TYPE_I32);
466
tcg_gen_movi_i32(t0, val);
470
TCGv tcg_const_i64(int64_t val)
473
t0 = tcg_temp_new(TCG_TYPE_I64);
474
tcg_gen_movi_i64(t0, val);
478
TCGv tcg_const_local_i32(int32_t val)
481
t0 = tcg_temp_local_new(TCG_TYPE_I32);
482
tcg_gen_movi_i32(t0, val);
486
TCGv tcg_const_local_i64(int64_t val)
489
t0 = tcg_temp_local_new(TCG_TYPE_I64);
490
tcg_gen_movi_i64(t0, val);
494
void tcg_register_helper(void *func, const char *name)
496
TCGContext *s = &tcg_ctx;
498
if ((s->nb_helpers + 1) > s->allocated_helpers) {
499
n = s->allocated_helpers;
505
s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
506
s->allocated_helpers = n;
508
s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
509
s->helpers[s->nb_helpers].name = name;
513
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
515
return s->temps[GET_TCGV(arg)].base_type;
518
static void tcg_gen_call_internal(TCGContext *s, TCGv func,
520
unsigned int nb_rets, const TCGv *rets,
521
unsigned int nb_params, const TCGv *params)
524
*gen_opc_ptr++ = INDEX_op_call;
525
*gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
526
for(i = 0; i < nb_rets; i++) {
527
*gen_opparam_ptr++ = GET_TCGV(rets[i]);
529
for(i = 0; i < nb_params; i++) {
530
*gen_opparam_ptr++ = GET_TCGV(params[i]);
532
*gen_opparam_ptr++ = GET_TCGV(func);
534
*gen_opparam_ptr++ = flags;
535
/* total parameters, needed to go backward in the instruction stream */
536
*gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
540
#if TCG_TARGET_REG_BITS < 64
541
/* Note: we convert the 64 bit args to 32 bit and do some alignment
542
and endian swap. Maybe it would be better to do the alignment
543
and endian swap in tcg_reg_alloc_call(). */
544
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
545
unsigned int nb_rets, const TCGv *rets,
546
unsigned int nb_params, const TCGv *args1)
548
TCGv ret, *args2, rets_2[2], arg;
553
if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
555
#ifdef TCG_TARGET_WORDS_BIGENDIAN
556
rets_2[0] = TCGV_HIGH(ret);
560
rets_2[1] = TCGV_HIGH(ret);
565
args2 = alloca((nb_params * 3) * sizeof(TCGv));
567
call_type = (flags & TCG_CALL_TYPE_MASK);
568
for(i = 0; i < nb_params; i++) {
570
if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
571
#ifdef TCG_TARGET_I386
572
/* REGPARM case: if the third parameter is 64 bit, it is
573
allocated on the stack */
574
if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
575
call_type = TCG_CALL_TYPE_REGPARM_2;
576
flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
579
args2[j++] = TCGV_HIGH(arg);
581
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
582
/* some targets want aligned 64 bit args */
584
args2[j++] = TCG_CALL_DUMMY_ARG;
587
#ifdef TCG_TARGET_WORDS_BIGENDIAN
588
args2[j++] = TCGV_HIGH(arg);
592
args2[j++] = TCGV_HIGH(arg);
599
tcg_gen_call_internal(s, func, flags,
600
nb_rets, rets, j, args2);
603
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
604
unsigned int nb_rets, const TCGv *rets,
605
unsigned int nb_params, const TCGv *args1)
607
tcg_gen_call_internal(s, func, flags,
608
nb_rets, rets, nb_params, args1);
612
#if TCG_TARGET_REG_BITS == 32
613
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1,
614
int c, int right, int arith)
617
tcg_gen_mov_i32(ret, arg1);
618
tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
619
} else if (c >= 32) {
623
tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
624
tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
626
tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
627
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
630
tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
631
tcg_gen_movi_i32(ret, 0);
636
t0 = tcg_temp_new(TCG_TYPE_I32);
637
t1 = tcg_temp_new(TCG_TYPE_I32);
639
tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
641
tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
643
tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
644
tcg_gen_shri_i32(ret, arg1, c);
645
tcg_gen_or_i32(ret, ret, t0);
646
tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
648
tcg_gen_shri_i32(t0, arg1, 32 - c);
649
/* Note: ret can be the same as arg1, so we use t1 */
650
tcg_gen_shli_i32(t1, arg1, c);
651
tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
652
tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
653
tcg_gen_mov_i32(ret, t1);
661
static void tcg_reg_alloc_start(TCGContext *s)
665
for(i = 0; i < s->nb_globals; i++) {
668
ts->val_type = TEMP_VAL_REG;
670
ts->val_type = TEMP_VAL_MEM;
673
for(i = s->nb_globals; i < s->nb_temps; i++) {
675
ts->val_type = TEMP_VAL_DEAD;
676
ts->mem_allocated = 0;
679
for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
680
s->reg_to_temp[i] = -1;
684
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
690
if (idx < s->nb_globals) {
691
pstrcpy(buf, buf_size, ts->name);
694
snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
696
snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
701
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
703
return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
706
static int helper_cmp(const void *p1, const void *p2)
708
const TCGHelperInfo *th1 = p1;
709
const TCGHelperInfo *th2 = p2;
710
if (th1->func < th2->func)
712
else if (th1->func == th2->func)
718
/* find helper definition (Note: A hash table would be better) */
719
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
725
if (unlikely(!s->helpers_sorted)) {
726
qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
728
s->helpers_sorted = 1;
733
m_max = s->nb_helpers - 1;
734
while (m_min <= m_max) {
735
m = (m_min + m_max) >> 1;
749
static const char * const cond_name[] =
751
[TCG_COND_EQ] = "eq",
752
[TCG_COND_NE] = "ne",
753
[TCG_COND_LT] = "lt",
754
[TCG_COND_GE] = "ge",
755
[TCG_COND_LE] = "le",
756
[TCG_COND_GT] = "gt",
757
[TCG_COND_LTU] = "ltu",
758
[TCG_COND_GEU] = "geu",
759
[TCG_COND_LEU] = "leu",
760
[TCG_COND_GTU] = "gtu"
763
void tcg_dump_ops(TCGContext *s, FILE *outfile)
765
const uint16_t *opc_ptr;
768
int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
773
opc_ptr = gen_opc_buf;
774
args = gen_opparam_buf;
775
while (opc_ptr < gen_opc_ptr) {
777
def = &tcg_op_defs[c];
778
if (c == INDEX_op_debug_insn_start) {
780
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
781
pc = ((uint64_t)args[1] << 32) | args[0];
786
fprintf(outfile, "\n");
787
fprintf(outfile, " ---- 0x%" PRIx64, pc);
789
nb_oargs = def->nb_oargs;
790
nb_iargs = def->nb_iargs;
791
nb_cargs = def->nb_cargs;
792
} else if (c == INDEX_op_call) {
795
/* variable number of arguments */
797
nb_oargs = arg >> 16;
798
nb_iargs = arg & 0xffff;
799
nb_cargs = def->nb_cargs;
801
fprintf(outfile, " %s ", def->name);
804
fprintf(outfile, "%s",
805
tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
807
fprintf(outfile, ",$0x%" TCG_PRIlx,
808
args[nb_oargs + nb_iargs]);
810
fprintf(outfile, ",$%d", nb_oargs);
811
for(i = 0; i < nb_oargs; i++) {
812
fprintf(outfile, ",");
813
fprintf(outfile, "%s",
814
tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
816
for(i = 0; i < (nb_iargs - 1); i++) {
817
fprintf(outfile, ",");
818
if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
819
fprintf(outfile, "<dummy>");
821
fprintf(outfile, "%s",
822
tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
825
} else if (c == INDEX_op_movi_i32
826
#if TCG_TARGET_REG_BITS == 64
827
|| c == INDEX_op_movi_i64
830
tcg_target_ulong val;
833
nb_oargs = def->nb_oargs;
834
nb_iargs = def->nb_iargs;
835
nb_cargs = def->nb_cargs;
836
fprintf(outfile, " %s %s,$", def->name,
837
tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
839
th = tcg_find_helper(s, val);
841
fprintf(outfile, th->name);
843
if (c == INDEX_op_movi_i32)
844
fprintf(outfile, "0x%x", (uint32_t)val);
846
fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
849
fprintf(outfile, " %s ", def->name);
850
if (c == INDEX_op_nopn) {
851
/* variable number of arguments */
856
nb_oargs = def->nb_oargs;
857
nb_iargs = def->nb_iargs;
858
nb_cargs = def->nb_cargs;
862
for(i = 0; i < nb_oargs; i++) {
864
fprintf(outfile, ",");
865
fprintf(outfile, "%s",
866
tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
868
for(i = 0; i < nb_iargs; i++) {
870
fprintf(outfile, ",");
871
fprintf(outfile, "%s",
872
tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
874
if (c == INDEX_op_brcond_i32
875
#if TCG_TARGET_REG_BITS == 32
876
|| c == INDEX_op_brcond2_i32
877
#elif TCG_TARGET_REG_BITS == 64
878
|| c == INDEX_op_brcond_i64
881
if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
882
fprintf(outfile, ",%s", cond_name[args[k++]]);
884
fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
889
for(; i < nb_cargs; i++) {
891
fprintf(outfile, ",");
893
fprintf(outfile, "$0x%" TCG_PRIlx, arg);
896
fprintf(outfile, "\n");
897
args += nb_iargs + nb_oargs + nb_cargs;
901
/* we give more priority to constraints with less registers */
902
static int get_constraint_priority(const TCGOpDef *def, int k)
904
const TCGArgConstraint *arg_ct;
907
arg_ct = &def->args_ct[k];
908
if (arg_ct->ct & TCG_CT_ALIAS) {
909
/* an alias is equivalent to a single register */
912
if (!(arg_ct->ct & TCG_CT_REG))
915
for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
916
if (tcg_regset_test_reg(arg_ct->u.regs, i))
920
return TCG_TARGET_NB_REGS - n + 1;
923
/* sort from highest priority to lowest */
924
static void sort_constraints(TCGOpDef *def, int start, int n)
926
int i, j, p1, p2, tmp;
928
for(i = 0; i < n; i++)
929
def->sorted_args[start + i] = start + i;
932
for(i = 0; i < n - 1; i++) {
933
for(j = i + 1; j < n; j++) {
934
p1 = get_constraint_priority(def, def->sorted_args[start + i]);
935
p2 = get_constraint_priority(def, def->sorted_args[start + j]);
937
tmp = def->sorted_args[start + i];
938
def->sorted_args[start + i] = def->sorted_args[start + j];
939
def->sorted_args[start + j] = tmp;
945
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
956
assert(op >= 0 && op < NB_OPS);
957
def = &tcg_op_defs[op];
958
nb_args = def->nb_iargs + def->nb_oargs;
959
for(i = 0; i < nb_args; i++) {
960
ct_str = tdefs->args_ct_str[i];
961
tcg_regset_clear(def->args_ct[i].u.regs);
962
def->args_ct[i].ct = 0;
963
if (ct_str[0] >= '0' && ct_str[0] <= '9') {
965
oarg = ct_str[0] - '0';
966
assert(oarg < def->nb_oargs);
967
assert(def->args_ct[oarg].ct & TCG_CT_REG);
968
/* TCG_CT_ALIAS is for the output arguments. The input
969
argument is tagged with TCG_CT_IALIAS. */
970
def->args_ct[i] = def->args_ct[oarg];
971
def->args_ct[oarg].ct = TCG_CT_ALIAS;
972
def->args_ct[oarg].alias_index = i;
973
def->args_ct[i].ct |= TCG_CT_IALIAS;
974
def->args_ct[i].alias_index = oarg;
981
def->args_ct[i].ct |= TCG_CT_CONST;
985
if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
986
fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
987
ct_str, i, def->name);
995
/* sort the constraints (XXX: this is just an heuristic) */
996
sort_constraints(def, 0, def->nb_oargs);
997
sort_constraints(def, def->nb_oargs, def->nb_iargs);
1003
printf("%s: sorted=", def->name);
1004
for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1005
printf(" %d", def->sorted_args[i]);
1014
#ifdef USE_LIVENESS_ANALYSIS
1016
/* set a nop for an operation using 'nb_args' */
1017
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1018
TCGArg *args, int nb_args)
1021
*opc_ptr = INDEX_op_nop;
1023
*opc_ptr = INDEX_op_nopn;
1025
args[nb_args - 1] = nb_args;
1029
/* liveness analysis: end of function: globals are live, temps are
1031
/* XXX: at this stage, not used as there would be little gains because
1032
most TBs end with a conditional jump. */
1033
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1035
memset(dead_temps, 0, s->nb_globals);
1036
memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1039
/* liveness analysis: end of basic block: globals are live, temps are
1040
dead, local temps are live. */
1041
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1046
memset(dead_temps, 0, s->nb_globals);
1047
ts = &s->temps[s->nb_globals];
1048
for(i = s->nb_globals; i < s->nb_temps; i++) {
1057
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1058
given input arguments is dead. Instructions updating dead
1059
temporaries are removed. */
1060
static void tcg_liveness_analysis(TCGContext *s)
1062
int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1064
const TCGOpDef *def;
1065
uint8_t *dead_temps;
1066
unsigned int dead_iargs;
1068
gen_opc_ptr++; /* skip end */
1070
nb_ops = gen_opc_ptr - gen_opc_buf;
1072
/* XXX: make it really dynamic */
1073
s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1075
dead_temps = tcg_malloc(s->nb_temps);
1076
memset(dead_temps, 1, s->nb_temps);
1078
args = gen_opparam_ptr;
1079
op_index = nb_ops - 1;
1080
while (op_index >= 0) {
1081
op = gen_opc_buf[op_index];
1082
def = &tcg_op_defs[op];
1090
nb_iargs = args[0] & 0xffff;
1091
nb_oargs = args[0] >> 16;
1093
call_flags = args[nb_oargs + nb_iargs];
1095
/* pure functions can be removed if their result is not
1097
if (call_flags & TCG_CALL_PURE) {
1098
for(i = 0; i < nb_oargs; i++) {
1100
if (!dead_temps[arg])
1101
goto do_not_remove_call;
1103
tcg_set_nop(s, gen_opc_buf + op_index,
1108
/* output args are dead */
1109
for(i = 0; i < nb_oargs; i++) {
1111
dead_temps[arg] = 1;
1114
/* globals are live (they may be used by the call) */
1115
memset(dead_temps, 0, s->nb_globals);
1117
/* input args are live */
1119
for(i = 0; i < nb_iargs; i++) {
1120
arg = args[i + nb_oargs];
1121
if (arg != TCG_CALL_DUMMY_ARG) {
1122
if (dead_temps[arg]) {
1123
dead_iargs |= (1 << i);
1125
dead_temps[arg] = 0;
1128
s->op_dead_iargs[op_index] = dead_iargs;
1133
case INDEX_op_set_label:
1135
/* mark end of basic block */
1136
tcg_la_bb_end(s, dead_temps);
1138
case INDEX_op_debug_insn_start:
1139
args -= def->nb_args;
1145
case INDEX_op_discard:
1147
/* mark the temporary as dead */
1148
dead_temps[args[0]] = 1;
1152
/* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1154
if (op > INDEX_op_end) {
1155
args -= def->nb_args;
1156
nb_iargs = def->nb_iargs;
1157
nb_oargs = def->nb_oargs;
1159
/* Test if the operation can be removed because all
1160
its outputs are dead. We assume that nb_oargs == 0
1161
implies side effects */
1162
if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1163
for(i = 0; i < nb_oargs; i++) {
1165
if (!dead_temps[arg])
1168
tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1169
#ifdef CONFIG_PROFILER
1175
/* output args are dead */
1176
for(i = 0; i < nb_oargs; i++) {
1178
dead_temps[arg] = 1;
1181
/* if end of basic block, update */
1182
if (def->flags & TCG_OPF_BB_END) {
1183
tcg_la_bb_end(s, dead_temps);
1184
} else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1185
/* globals are live */
1186
memset(dead_temps, 0, s->nb_globals);
1189
/* input args are live */
1191
for(i = 0; i < nb_iargs; i++) {
1192
arg = args[i + nb_oargs];
1193
if (dead_temps[arg]) {
1194
dead_iargs |= (1 << i);
1196
dead_temps[arg] = 0;
1198
s->op_dead_iargs[op_index] = dead_iargs;
1201
/* legacy dyngen operations */
1202
args -= def->nb_args;
1203
/* mark end of basic block */
1204
tcg_la_bb_end(s, dead_temps);
1211
if (args != gen_opparam_buf)
1215
/* dummy liveness analysis */
1216
void tcg_liveness_analysis(TCGContext *s)
1219
nb_ops = gen_opc_ptr - gen_opc_buf;
1221
s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1222
memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1227
static void dump_regs(TCGContext *s)
1233
for(i = 0; i < s->nb_temps; i++) {
1235
printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1236
switch(ts->val_type) {
1238
printf("%s", tcg_target_reg_names[ts->reg]);
1241
printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1243
case TEMP_VAL_CONST:
1244
printf("$0x%" TCG_PRIlx, ts->val);
1256
for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1257
if (s->reg_to_temp[i] >= 0) {
1259
tcg_target_reg_names[i],
1260
tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1265
static void check_regs(TCGContext *s)
1271
for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1272
k = s->reg_to_temp[reg];
1275
if (ts->val_type != TEMP_VAL_REG ||
1277
printf("Inconsistency for register %s:\n",
1278
tcg_target_reg_names[reg]);
1283
for(k = 0; k < s->nb_temps; k++) {
1285
if (ts->val_type == TEMP_VAL_REG &&
1287
s->reg_to_temp[ts->reg] != k) {
1288
printf("Inconsistency for temp %s:\n",
1289
tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1291
printf("reg state:\n");
1299
static void temp_allocate_frame(TCGContext *s, int temp)
1302
ts = &s->temps[temp];
1303
s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1304
if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1306
ts->mem_offset = s->current_frame_offset;
1307
ts->mem_reg = s->frame_reg;
1308
ts->mem_allocated = 1;
1309
s->current_frame_offset += sizeof(tcg_target_long);
1312
/* free register 'reg' by spilling the corresponding temporary if necessary */
1313
static void tcg_reg_free(TCGContext *s, int reg)
1318
temp = s->reg_to_temp[reg];
1320
ts = &s->temps[temp];
1321
assert(ts->val_type == TEMP_VAL_REG);
1322
if (!ts->mem_coherent) {
1323
if (!ts->mem_allocated)
1324
temp_allocate_frame(s, temp);
1325
tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1327
ts->val_type = TEMP_VAL_MEM;
1328
s->reg_to_temp[reg] = -1;
1332
/* Allocate a register belonging to reg1 & ~reg2 */
1333
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1338
tcg_regset_andnot(reg_ct, reg1, reg2);
1340
/* first try free registers */
1341
for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1342
reg = tcg_target_reg_alloc_order[i];
1343
if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1347
/* XXX: do better spill choice */
1348
for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1349
reg = tcg_target_reg_alloc_order[i];
1350
if (tcg_regset_test_reg(reg_ct, reg)) {
1351
tcg_reg_free(s, reg);
1359
/* save a temporary to memory. 'allocated_regs' is used in case a
1360
temporary registers needs to be allocated to store a constant. */
1361
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1366
ts = &s->temps[temp];
1367
if (!ts->fixed_reg) {
1368
switch(ts->val_type) {
1370
tcg_reg_free(s, ts->reg);
1373
ts->val_type = TEMP_VAL_MEM;
1375
case TEMP_VAL_CONST:
1376
reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1378
if (!ts->mem_allocated)
1379
temp_allocate_frame(s, temp);
1380
tcg_out_movi(s, ts->type, reg, ts->val);
1381
tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1382
ts->val_type = TEMP_VAL_MEM;
1392
/* save globals to their cannonical location and assume they can be
1393
modified be the following code. 'allocated_regs' is used in case a
1394
temporary registers needs to be allocated to store a constant. */
1395
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1399
for(i = 0; i < s->nb_globals; i++) {
1400
temp_save(s, i, allocated_regs);
1404
/* at the end of a basic block, we assume all temporaries are dead and
1405
all globals are stored at their canonical location. */
1406
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1411
for(i = s->nb_globals; i < s->nb_temps; i++) {
1413
if (ts->temp_local) {
1414
temp_save(s, i, allocated_regs);
1416
if (ts->val_type == TEMP_VAL_REG) {
1417
s->reg_to_temp[ts->reg] = -1;
1419
ts->val_type = TEMP_VAL_DEAD;
1423
save_globals(s, allocated_regs);
1426
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1428
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1431
tcg_target_ulong val;
1433
ots = &s->temps[args[0]];
1436
if (ots->fixed_reg) {
1437
/* for fixed registers, we do not do any constant
1439
tcg_out_movi(s, ots->type, ots->reg, val);
1441
/* The movi is not explicitly generated here */
1442
if (ots->val_type == TEMP_VAL_REG)
1443
s->reg_to_temp[ots->reg] = -1;
1444
ots->val_type = TEMP_VAL_CONST;
1449
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1451
unsigned int dead_iargs)
1455
const TCGArgConstraint *arg_ct;
1457
ots = &s->temps[args[0]];
1458
ts = &s->temps[args[1]];
1459
arg_ct = &def->args_ct[0];
1461
/* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1462
if (ts->val_type == TEMP_VAL_REG) {
1463
if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1464
/* the mov can be suppressed */
1465
if (ots->val_type == TEMP_VAL_REG)
1466
s->reg_to_temp[ots->reg] = -1;
1468
s->reg_to_temp[reg] = -1;
1469
ts->val_type = TEMP_VAL_DEAD;
1471
if (ots->val_type == TEMP_VAL_REG) {
1474
reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1476
if (ts->reg != reg) {
1477
tcg_out_mov(s, reg, ts->reg);
1480
} else if (ts->val_type == TEMP_VAL_MEM) {
1481
if (ots->val_type == TEMP_VAL_REG) {
1484
reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1486
tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1487
} else if (ts->val_type == TEMP_VAL_CONST) {
1488
if (ots->fixed_reg) {
1490
tcg_out_movi(s, ots->type, reg, ts->val);
1492
/* propagate constant */
1493
if (ots->val_type == TEMP_VAL_REG)
1494
s->reg_to_temp[ots->reg] = -1;
1495
ots->val_type = TEMP_VAL_CONST;
1502
s->reg_to_temp[reg] = args[0];
1504
ots->val_type = TEMP_VAL_REG;
1505
ots->mem_coherent = 0;
1508
static void tcg_reg_alloc_op(TCGContext *s,
1509
const TCGOpDef *def, int opc,
1511
unsigned int dead_iargs)
1513
TCGRegSet allocated_regs;
1514
int i, k, nb_iargs, nb_oargs, reg;
1516
const TCGArgConstraint *arg_ct;
1518
TCGArg new_args[TCG_MAX_OP_ARGS];
1519
int const_args[TCG_MAX_OP_ARGS];
1521
nb_oargs = def->nb_oargs;
1522
nb_iargs = def->nb_iargs;
1524
/* copy constants */
1525
memcpy(new_args + nb_oargs + nb_iargs,
1526
args + nb_oargs + nb_iargs,
1527
sizeof(TCGArg) * def->nb_cargs);
1529
/* satisfy input constraints */
1530
tcg_regset_set(allocated_regs, s->reserved_regs);
1531
for(k = 0; k < nb_iargs; k++) {
1532
i = def->sorted_args[nb_oargs + k];
1534
arg_ct = &def->args_ct[i];
1535
ts = &s->temps[arg];
1536
if (ts->val_type == TEMP_VAL_MEM) {
1537
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1538
tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1539
ts->val_type = TEMP_VAL_REG;
1541
ts->mem_coherent = 1;
1542
s->reg_to_temp[reg] = arg;
1543
} else if (ts->val_type == TEMP_VAL_CONST) {
1544
if (tcg_target_const_match(ts->val, arg_ct)) {
1545
/* constant is OK for instruction */
1547
new_args[i] = ts->val;
1550
/* need to move to a register */
1551
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1552
tcg_out_movi(s, ts->type, reg, ts->val);
1553
ts->val_type = TEMP_VAL_REG;
1555
ts->mem_coherent = 0;
1556
s->reg_to_temp[reg] = arg;
1559
assert(ts->val_type == TEMP_VAL_REG);
1560
if (arg_ct->ct & TCG_CT_IALIAS) {
1561
if (ts->fixed_reg) {
1562
/* if fixed register, we must allocate a new register
1563
if the alias is not the same register */
1564
if (arg != args[arg_ct->alias_index])
1565
goto allocate_in_reg;
1567
/* if the input is aliased to an output and if it is
1568
not dead after the instruction, we must allocate
1569
a new register and move it */
1570
if (!IS_DEAD_IARG(i - nb_oargs))
1571
goto allocate_in_reg;
1575
if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1576
/* nothing to do : the constraint is satisfied */
1579
/* allocate a new register matching the constraint
1580
and move the temporary register into it */
1581
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1582
tcg_out_mov(s, reg, ts->reg);
1586
tcg_regset_set_reg(allocated_regs, reg);
1590
if (def->flags & TCG_OPF_BB_END) {
1591
tcg_reg_alloc_bb_end(s, allocated_regs);
1593
/* mark dead temporaries and free the associated registers */
1594
for(i = 0; i < nb_iargs; i++) {
1595
arg = args[nb_oargs + i];
1596
if (IS_DEAD_IARG(i)) {
1597
ts = &s->temps[arg];
1598
if (!ts->fixed_reg) {
1599
if (ts->val_type == TEMP_VAL_REG)
1600
s->reg_to_temp[ts->reg] = -1;
1601
ts->val_type = TEMP_VAL_DEAD;
1606
if (def->flags & TCG_OPF_CALL_CLOBBER) {
1607
/* XXX: permit generic clobber register list ? */
1608
for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1609
if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1610
tcg_reg_free(s, reg);
1613
/* XXX: for load/store we could do that only for the slow path
1614
(i.e. when a memory callback is called) */
1616
/* store globals and free associated registers (we assume the insn
1617
can modify any global. */
1618
save_globals(s, allocated_regs);
1621
/* satisfy the output constraints */
1622
tcg_regset_set(allocated_regs, s->reserved_regs);
1623
for(k = 0; k < nb_oargs; k++) {
1624
i = def->sorted_args[k];
1626
arg_ct = &def->args_ct[i];
1627
ts = &s->temps[arg];
1628
if (arg_ct->ct & TCG_CT_ALIAS) {
1629
reg = new_args[arg_ct->alias_index];
1631
/* if fixed register, we try to use it */
1633
if (ts->fixed_reg &&
1634
tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1637
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1639
tcg_regset_set_reg(allocated_regs, reg);
1640
/* if a fixed register is used, then a move will be done afterwards */
1641
if (!ts->fixed_reg) {
1642
if (ts->val_type == TEMP_VAL_REG)
1643
s->reg_to_temp[ts->reg] = -1;
1644
ts->val_type = TEMP_VAL_REG;
1646
/* temp value is modified, so the value kept in memory is
1647
potentially not the same */
1648
ts->mem_coherent = 0;
1649
s->reg_to_temp[reg] = arg;
1656
/* emit instruction */
1657
tcg_out_op(s, opc, new_args, const_args);
1659
/* move the outputs in the correct register if needed */
1660
for(i = 0; i < nb_oargs; i++) {
1661
ts = &s->temps[args[i]];
1663
if (ts->fixed_reg && ts->reg != reg) {
1664
tcg_out_mov(s, ts->reg, reg);
1669
#ifdef TCG_TARGET_STACK_GROWSUP
1670
#define STACK_DIR(x) (-(x))
1672
#define STACK_DIR(x) (x)
1675
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1676
int opc, const TCGArg *args,
1677
unsigned int dead_iargs)
1679
int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1680
TCGArg arg, func_arg;
1682
tcg_target_long stack_offset, call_stack_size, func_addr;
1683
int const_func_arg, allocate_args;
1684
TCGRegSet allocated_regs;
1685
const TCGArgConstraint *arg_ct;
1689
nb_oargs = arg >> 16;
1690
nb_iargs = arg & 0xffff;
1691
nb_params = nb_iargs - 1;
1693
flags = args[nb_oargs + nb_iargs];
1695
nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1696
if (nb_regs > nb_params)
1697
nb_regs = nb_params;
1699
/* assign stack slots first */
1700
/* XXX: preallocate call stack */
1701
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1702
call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1703
~(TCG_TARGET_STACK_ALIGN - 1);
1704
allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1705
if (allocate_args) {
1706
tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1709
stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1710
for(i = nb_regs; i < nb_params; i++) {
1711
arg = args[nb_oargs + i];
1712
#ifdef TCG_TARGET_STACK_GROWSUP
1713
stack_offset -= sizeof(tcg_target_long);
1715
if (arg != TCG_CALL_DUMMY_ARG) {
1716
ts = &s->temps[arg];
1717
if (ts->val_type == TEMP_VAL_REG) {
1718
tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1719
} else if (ts->val_type == TEMP_VAL_MEM) {
1720
reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1722
/* XXX: not correct if reading values from the stack */
1723
tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1724
tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1725
} else if (ts->val_type == TEMP_VAL_CONST) {
1726
reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1728
/* XXX: sign extend may be needed on some targets */
1729
tcg_out_movi(s, ts->type, reg, ts->val);
1730
tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1735
#ifndef TCG_TARGET_STACK_GROWSUP
1736
stack_offset += sizeof(tcg_target_long);
1740
/* assign input registers */
1741
tcg_regset_set(allocated_regs, s->reserved_regs);
1742
for(i = 0; i < nb_regs; i++) {
1743
arg = args[nb_oargs + i];
1744
if (arg != TCG_CALL_DUMMY_ARG) {
1745
ts = &s->temps[arg];
1746
reg = tcg_target_call_iarg_regs[i];
1747
tcg_reg_free(s, reg);
1748
if (ts->val_type == TEMP_VAL_REG) {
1749
if (ts->reg != reg) {
1750
tcg_out_mov(s, reg, ts->reg);
1752
} else if (ts->val_type == TEMP_VAL_MEM) {
1753
tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1754
} else if (ts->val_type == TEMP_VAL_CONST) {
1755
/* XXX: sign extend ? */
1756
tcg_out_movi(s, ts->type, reg, ts->val);
1760
tcg_regset_set_reg(allocated_regs, reg);
1764
/* assign function address */
1765
func_arg = args[nb_oargs + nb_iargs - 1];
1766
arg_ct = &def->args_ct[0];
1767
ts = &s->temps[func_arg];
1768
func_addr = ts->val;
1770
if (ts->val_type == TEMP_VAL_MEM) {
1771
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1772
tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1774
tcg_regset_set_reg(allocated_regs, reg);
1775
} else if (ts->val_type == TEMP_VAL_REG) {
1777
if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1778
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1779
tcg_out_mov(s, reg, ts->reg);
1782
tcg_regset_set_reg(allocated_regs, reg);
1783
} else if (ts->val_type == TEMP_VAL_CONST) {
1784
if (tcg_target_const_match(func_addr, arg_ct)) {
1786
func_arg = func_addr;
1788
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1789
tcg_out_movi(s, ts->type, reg, func_addr);
1791
tcg_regset_set_reg(allocated_regs, reg);
1798
/* mark dead temporaries and free the associated registers */
1799
for(i = 0; i < nb_iargs; i++) {
1800
arg = args[nb_oargs + i];
1801
if (IS_DEAD_IARG(i)) {
1802
ts = &s->temps[arg];
1803
if (!ts->fixed_reg) {
1804
if (ts->val_type == TEMP_VAL_REG)
1805
s->reg_to_temp[ts->reg] = -1;
1806
ts->val_type = TEMP_VAL_DEAD;
1811
/* clobber call registers */
1812
for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1813
if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1814
tcg_reg_free(s, reg);
1818
/* store globals and free associated registers (we assume the call
1819
can modify any global. */
1820
save_globals(s, allocated_regs);
1822
tcg_out_op(s, opc, &func_arg, &const_func_arg);
1824
if (allocate_args) {
1825
tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1828
/* assign output registers and emit moves if needed */
1829
for(i = 0; i < nb_oargs; i++) {
1831
ts = &s->temps[arg];
1832
reg = tcg_target_call_oarg_regs[i];
1833
assert(s->reg_to_temp[reg] == -1);
1834
if (ts->fixed_reg) {
1835
if (ts->reg != reg) {
1836
tcg_out_mov(s, ts->reg, reg);
1839
if (ts->val_type == TEMP_VAL_REG)
1840
s->reg_to_temp[ts->reg] = -1;
1841
ts->val_type = TEMP_VAL_REG;
1843
ts->mem_coherent = 0;
1844
s->reg_to_temp[reg] = arg;
1848
return nb_iargs + nb_oargs + def->nb_cargs + 1;
1851
#ifdef CONFIG_PROFILER
1853
static int64_t dyngen_table_op_count[NB_OPS];
1855
void dump_op_count(void)
1859
f = fopen("/tmp/op1.log", "w");
1860
for(i = 0; i < INDEX_op_end; i++) {
1861
fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1864
f = fopen("/tmp/op2.log", "w");
1865
for(i = INDEX_op_end; i < NB_OPS; i++) {
1866
fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1873
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1877
const TCGOpDef *def;
1878
unsigned int dead_iargs;
1882
if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1883
fprintf(logfile, "OP:\n");
1884
tcg_dump_ops(s, logfile);
1885
fprintf(logfile, "\n");
1889
#ifdef CONFIG_PROFILER
1890
s->la_time -= profile_getclock();
1892
tcg_liveness_analysis(s);
1893
#ifdef CONFIG_PROFILER
1894
s->la_time += profile_getclock();
1898
if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1899
fprintf(logfile, "OP after la:\n");
1900
tcg_dump_ops(s, logfile);
1901
fprintf(logfile, "\n");
1905
tcg_reg_alloc_start(s);
1907
s->code_buf = gen_code_buf;
1908
s->code_ptr = gen_code_buf;
1910
args = gen_opparam_buf;
1914
opc = gen_opc_buf[op_index];
1915
#ifdef CONFIG_PROFILER
1916
dyngen_table_op_count[opc]++;
1918
def = &tcg_op_defs[opc];
1920
printf("%s: %d %d %d\n", def->name,
1921
def->nb_oargs, def->nb_iargs, def->nb_cargs);
1925
case INDEX_op_mov_i32:
1926
#if TCG_TARGET_REG_BITS == 64
1927
case INDEX_op_mov_i64:
1929
dead_iargs = s->op_dead_iargs[op_index];
1930
tcg_reg_alloc_mov(s, def, args, dead_iargs);
1932
case INDEX_op_movi_i32:
1933
#if TCG_TARGET_REG_BITS == 64
1934
case INDEX_op_movi_i64:
1936
tcg_reg_alloc_movi(s, args);
1938
case INDEX_op_debug_insn_start:
1939
/* debug instruction */
1949
case INDEX_op_discard:
1952
ts = &s->temps[args[0]];
1953
/* mark the temporary as dead */
1954
if (!ts->fixed_reg) {
1955
if (ts->val_type == TEMP_VAL_REG)
1956
s->reg_to_temp[ts->reg] = -1;
1957
ts->val_type = TEMP_VAL_DEAD;
1961
case INDEX_op_set_label:
1962
tcg_reg_alloc_bb_end(s, s->reserved_regs);
1963
tcg_out_label(s, args[0], (long)s->code_ptr);
1966
dead_iargs = s->op_dead_iargs[op_index];
1967
args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1972
#ifdef CONFIG_DYNGEN_OP
1973
case 0 ... INDEX_op_end - 1:
1974
/* legacy dyngen ops */
1975
#ifdef CONFIG_PROFILER
1978
tcg_reg_alloc_bb_end(s, s->reserved_regs);
1979
if (search_pc >= 0) {
1980
s->code_ptr += def->copy_size;
1981
args += def->nb_args;
1983
args = dyngen_op(s, opc, args);
1988
/* Note: in order to speed up the code, it would be much
1989
faster to have specialized register allocator functions for
1990
some common argument patterns */
1991
dead_iargs = s->op_dead_iargs[op_index];
1992
tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1995
args += def->nb_args;
1997
if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2009
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
2011
#ifdef CONFIG_PROFILER
2014
n = (gen_opc_ptr - gen_opc_buf);
2016
if (n > s->op_count_max)
2017
s->op_count_max = n;
2019
s->temp_count += s->nb_temps;
2020
if (s->nb_temps > s->temp_count_max)
2021
s->temp_count_max = s->nb_temps;
2025
tcg_gen_code_common(s, gen_code_buf, -1);
2027
/* flush instruction cache */
2028
flush_icache_range((unsigned long)gen_code_buf,
2029
(unsigned long)s->code_ptr);
2030
return s->code_ptr - gen_code_buf;
2033
/* Return the index of the micro operation such as the pc after is <
2034
offset bytes from the start of the TB. The contents of gen_code_buf must
2035
not be changed, though writing the same values is ok.
2036
Return -1 if not found. */
2037
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2039
return tcg_gen_code_common(s, gen_code_buf, offset);
2042
#ifdef CONFIG_PROFILER
2043
void tcg_dump_info(FILE *f,
2044
int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2046
TCGContext *s = &tcg_ctx;
2049
tot = s->interm_time + s->code_time;
2050
cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2052
cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2054
s->tb_count1 - s->tb_count,
2055
s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2056
cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2057
s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2058
cpu_fprintf(f, "old ops/total ops %0.1f%%\n",
2059
s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
2060
cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2062
(double)s->del_op_count / s->tb_count : 0);
2063
cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2065
(double)s->temp_count / s->tb_count : 0,
2068
cpu_fprintf(f, "cycles/op %0.1f\n",
2069
s->op_count ? (double)tot / s->op_count : 0);
2070
cpu_fprintf(f, "cycles/in byte %0.1f\n",
2071
s->code_in_len ? (double)tot / s->code_in_len : 0);
2072
cpu_fprintf(f, "cycles/out byte %0.1f\n",
2073
s->code_out_len ? (double)tot / s->code_out_len : 0);
2076
cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2077
(double)s->interm_time / tot * 100.0);
2078
cpu_fprintf(f, " gen_code time %0.1f%%\n",
2079
(double)s->code_time / tot * 100.0);
2080
cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2081
(double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2082
cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2084
cpu_fprintf(f, " avg cycles %0.1f\n",
2085
s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2087
extern void dump_op_count(void);
2092
void tcg_dump_info(FILE *f,
2093
int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2095
cpu_fprintf(f, "[TCG profiler not compiled]\n");