]> git.proxmox.com Git - qemu.git/blame - tcg/tcg.c
Fix incorrect use of pstrcpy (malc)
[qemu.git] / tcg / tcg.c
CommitLineData
c896fe29
FB
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 suppress various consistency checks (faster) */
26#define NDEBUG
27
28/* define it to use liveness analysis (better code) */
29#define USE_LIVENESS_ANALYSIS
30
31#include <assert.h>
32#include <stdarg.h>
33#include <stdlib.h>
34#include <stdio.h>
35#include <string.h>
36#include <inttypes.h>
3fe43da7
FB
37#ifdef _WIN32
38#include <malloc.h>
39#endif
c896fe29
FB
40
41#include "config.h"
ca10f867 42#include "qemu-common.h"
c896fe29
FB
43
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
46 instructions */
47#define NO_CPU_IO_DEFS
48#include "cpu.h"
49#include "exec-all.h"
50
51#include "tcg-op.h"
52#include "elf.h"
53
54
55static void patch_reloc(uint8_t *code_ptr, int type,
f54b3f92 56 tcg_target_long value, tcg_target_long addend);
c896fe29
FB
57
58TCGOpDef 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 },
61#include "tcg-opc.h"
62#undef DEF
63#undef DEF2
64};
65
66TCGRegSet tcg_target_available_regs[2];
67TCGRegSet tcg_target_call_clobber_regs;
68
69/* XXX: move that inside the context */
70uint16_t *gen_opc_ptr;
71TCGArg *gen_opparam_ptr;
72
73static inline void tcg_out8(TCGContext *s, uint8_t v)
74{
75 *s->code_ptr++ = v;
76}
77
78static inline void tcg_out16(TCGContext *s, uint16_t v)
79{
80 *(uint16_t *)s->code_ptr = v;
81 s->code_ptr += 2;
82}
83
84static inline void tcg_out32(TCGContext *s, uint32_t v)
85{
86 *(uint32_t *)s->code_ptr = v;
87 s->code_ptr += 4;
88}
89
90/* label relocation processing */
91
92void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
93 int label_index, long addend)
94{
95 TCGLabel *l;
96 TCGRelocation *r;
97
98 l = &s->labels[label_index];
99 if (l->has_value) {
623e265c
PB
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. */
f54b3f92 103 patch_reloc(code_ptr, type, l->u.value, addend);
c896fe29
FB
104 } else {
105 /* add a new relocation entry */
106 r = tcg_malloc(sizeof(TCGRelocation));
107 r->type = type;
108 r->ptr = code_ptr;
109 r->addend = addend;
110 r->next = l->u.first_reloc;
111 l->u.first_reloc = r;
112 }
113}
114
115static void tcg_out_label(TCGContext *s, int label_index,
116 tcg_target_long value)
117{
118 TCGLabel *l;
119 TCGRelocation *r;
120
121 l = &s->labels[label_index];
122 if (l->has_value)
123 tcg_abort();
124 r = l->u.first_reloc;
125 while (r != NULL) {
f54b3f92 126 patch_reloc(r->ptr, r->type, value, r->addend);
c896fe29
FB
127 r = r->next;
128 }
129 l->has_value = 1;
130 l->u.value = value;
131}
132
133int gen_new_label(void)
134{
135 TCGContext *s = &tcg_ctx;
136 int idx;
137 TCGLabel *l;
138
139 if (s->nb_labels >= TCG_MAX_LABELS)
140 tcg_abort();
141 idx = s->nb_labels++;
142 l = &s->labels[idx];
143 l->has_value = 0;
144 l->u.first_reloc = NULL;
145 return idx;
146}
147
148#include "tcg-target.c"
149
c896fe29
FB
150/* pool based memory allocation */
151void *tcg_malloc_internal(TCGContext *s, int size)
152{
153 TCGPool *p;
154 int pool_size;
155
156 if (size > TCG_POOL_CHUNK_SIZE) {
157 /* big malloc: insert a new pool (XXX: could optimize) */
158 p = qemu_malloc(sizeof(TCGPool) + size);
159 p->size = size;
160 if (s->pool_current)
161 s->pool_current->next = p;
162 else
163 s->pool_first = p;
164 p->next = s->pool_current;
165 } else {
166 p = s->pool_current;
167 if (!p) {
168 p = s->pool_first;
169 if (!p)
170 goto new_pool;
171 } else {
172 if (!p->next) {
173 new_pool:
174 pool_size = TCG_POOL_CHUNK_SIZE;
175 p = qemu_malloc(sizeof(TCGPool) + pool_size);
176 p->size = pool_size;
177 p->next = NULL;
178 if (s->pool_current)
179 s->pool_current->next = p;
180 else
181 s->pool_first = p;
182 } else {
183 p = p->next;
184 }
185 }
186 }
187 s->pool_current = p;
188 s->pool_cur = p->data + size;
189 s->pool_end = p->data + p->size;
190 return p->data;
191}
192
193void tcg_pool_reset(TCGContext *s)
194{
195 s->pool_cur = s->pool_end = NULL;
196 s->pool_current = NULL;
197}
198
c896fe29
FB
199void tcg_context_init(TCGContext *s)
200{
201 int op, total_args, n;
202 TCGOpDef *def;
203 TCGArgConstraint *args_ct;
204 int *sorted_args;
205
206 memset(s, 0, sizeof(*s));
207 s->temps = s->static_temps;
208 s->nb_globals = 0;
209
210 /* Count total number of arguments and allocate the corresponding
211 space */
212 total_args = 0;
213 for(op = 0; op < NB_OPS; op++) {
214 def = &tcg_op_defs[op];
215 n = def->nb_iargs + def->nb_oargs;
216 total_args += n;
217 }
218
219 args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
220 sorted_args = qemu_malloc(sizeof(int) * total_args);
221
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;
227 sorted_args += n;
228 args_ct += n;
229 }
230
231 tcg_target_init(s);
b03cce8e
FB
232
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);
c896fe29
FB
239}
240
241void tcg_set_frame(TCGContext *s, int reg,
242 tcg_target_long start, tcg_target_long size)
243{
244 s->frame_start = start;
245 s->frame_end = start + size;
246 s->frame_reg = reg;
247}
248
c896fe29
FB
249void tcg_func_start(TCGContext *s)
250{
e8996ee0 251 int i;
c896fe29
FB
252 tcg_pool_reset(s);
253 s->nb_temps = s->nb_globals;
641d5fbe 254 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
e8996ee0 255 s->first_free_temp[i] = -1;
c896fe29
FB
256 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
257 s->nb_labels = 0;
258 s->current_frame_offset = s->frame_start;
259
260 gen_opc_ptr = gen_opc_buf;
261 gen_opparam_ptr = gen_opparam_buf;
262}
263
264static inline void tcg_temp_alloc(TCGContext *s, int n)
265{
266 if (n > TCG_MAX_TEMPS)
267 tcg_abort();
268}
269
ac56dd48 270TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
c896fe29
FB
271{
272 TCGContext *s = &tcg_ctx;
273 TCGTemp *ts;
274 int idx;
275
276#if TCG_TARGET_REG_BITS == 32
277 if (type != TCG_TYPE_I32)
278 tcg_abort();
279#endif
280 if (tcg_regset_test_reg(s->reserved_regs, reg))
281 tcg_abort();
282 idx = s->nb_globals;
283 tcg_temp_alloc(s, s->nb_globals + 1);
284 ts = &s->temps[s->nb_globals];
285 ts->base_type = type;
286 ts->type = type;
287 ts->fixed_reg = 1;
288 ts->reg = reg;
c896fe29
FB
289 ts->name = name;
290 s->nb_globals++;
291 tcg_regset_set_reg(s->reserved_regs, reg);
ac56dd48 292 return MAKE_TCGV(idx);
c896fe29
FB
293}
294
6a8d7b76
FB
295#if TCG_TARGET_REG_BITS == 32
296/* temporary hack to avoid register shortage for tcg_qemu_st64() */
297TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
298 const char *name)
299{
300 TCGContext *s = &tcg_ctx;
301 TCGTemp *ts;
302 int idx;
303 char buf[64];
304
305 if (type != TCG_TYPE_I64)
306 tcg_abort();
307 idx = s->nb_globals;
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;
312 ts->fixed_reg = 1;
313 ts->reg = reg1;
6a8d7b76
FB
314 pstrcpy(buf, sizeof(buf), name);
315 pstrcat(buf, sizeof(buf), "_0");
316 ts->name = strdup(buf);
317
318 ts++;
319 ts->base_type = type;
320 ts->type = TCG_TYPE_I32;
321 ts->fixed_reg = 1;
322 ts->reg = reg2;
6a8d7b76
FB
323 pstrcpy(buf, sizeof(buf), name);
324 pstrcat(buf, sizeof(buf), "_1");
325 ts->name = strdup(buf);
326
327 s->nb_globals += 2;
328 return MAKE_TCGV(idx);
329}
330#endif
331
ac56dd48
PB
332TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
333 const char *name)
c896fe29
FB
334{
335 TCGContext *s = &tcg_ctx;
336 TCGTemp *ts;
337 int idx;
338
339 idx = s->nb_globals;
340#if TCG_TARGET_REG_BITS == 32
341 if (type == TCG_TYPE_I64) {
342 char buf[64];
c588979b 343 tcg_temp_alloc(s, s->nb_globals + 2);
c896fe29
FB
344 ts = &s->temps[s->nb_globals];
345 ts->base_type = type;
346 ts->type = TCG_TYPE_I32;
347 ts->fixed_reg = 0;
348 ts->mem_allocated = 1;
349 ts->mem_reg = reg;
350#ifdef TCG_TARGET_WORDS_BIGENDIAN
351 ts->mem_offset = offset + 4;
352#else
353 ts->mem_offset = offset;
354#endif
c896fe29
FB
355 pstrcpy(buf, sizeof(buf), name);
356 pstrcat(buf, sizeof(buf), "_0");
357 ts->name = strdup(buf);
358 ts++;
359
360 ts->base_type = type;
361 ts->type = TCG_TYPE_I32;
362 ts->fixed_reg = 0;
363 ts->mem_allocated = 1;
364 ts->mem_reg = reg;
365#ifdef TCG_TARGET_WORDS_BIGENDIAN
366 ts->mem_offset = offset;
367#else
368 ts->mem_offset = offset + 4;
369#endif
c896fe29
FB
370 pstrcpy(buf, sizeof(buf), name);
371 pstrcat(buf, sizeof(buf), "_1");
372 ts->name = strdup(buf);
373
374 s->nb_globals += 2;
375 } else
376#endif
377 {
378 tcg_temp_alloc(s, s->nb_globals + 1);
379 ts = &s->temps[s->nb_globals];
380 ts->base_type = type;
381 ts->type = type;
382 ts->fixed_reg = 0;
383 ts->mem_allocated = 1;
384 ts->mem_reg = reg;
385 ts->mem_offset = offset;
c896fe29
FB
386 ts->name = name;
387 s->nb_globals++;
388 }
ac56dd48 389 return MAKE_TCGV(idx);
c896fe29
FB
390}
391
641d5fbe 392TCGv tcg_temp_new_internal(TCGType type, int temp_local)
c896fe29
FB
393{
394 TCGContext *s = &tcg_ctx;
395 TCGTemp *ts;
641d5fbe 396 int idx, k;
c896fe29 397
641d5fbe
FB
398 k = type;
399 if (temp_local)
400 k += TCG_TYPE_COUNT;
401 idx = s->first_free_temp[k];
e8996ee0
FB
402 if (idx != -1) {
403 /* There is already an available temp with the
404 right type */
405 ts = &s->temps[idx];
641d5fbe 406 s->first_free_temp[k] = ts->next_free_temp;
e8996ee0 407 ts->temp_allocated = 1;
641d5fbe 408 assert(ts->temp_local == temp_local);
e8996ee0
FB
409 } else {
410 idx = s->nb_temps;
c896fe29 411#if TCG_TARGET_REG_BITS == 32
e8996ee0 412 if (type == TCG_TYPE_I64) {
8df1ca4b 413 tcg_temp_alloc(s, s->nb_temps + 2);
e8996ee0
FB
414 ts = &s->temps[s->nb_temps];
415 ts->base_type = type;
416 ts->type = TCG_TYPE_I32;
417 ts->temp_allocated = 1;
641d5fbe 418 ts->temp_local = temp_local;
e8996ee0
FB
419 ts->name = NULL;
420 ts++;
421 ts->base_type = TCG_TYPE_I32;
422 ts->type = TCG_TYPE_I32;
423 ts->temp_allocated = 1;
641d5fbe 424 ts->temp_local = temp_local;
e8996ee0
FB
425 ts->name = NULL;
426 s->nb_temps += 2;
427 } else
c896fe29 428#endif
e8996ee0
FB
429 {
430 tcg_temp_alloc(s, s->nb_temps + 1);
431 ts = &s->temps[s->nb_temps];
432 ts->base_type = type;
433 ts->type = type;
434 ts->temp_allocated = 1;
641d5fbe 435 ts->temp_local = temp_local;
e8996ee0
FB
436 ts->name = NULL;
437 s->nb_temps++;
438 }
c896fe29 439 }
ac56dd48 440 return MAKE_TCGV(idx);
c896fe29
FB
441}
442
e8996ee0 443void tcg_temp_free(TCGv arg)
c896fe29
FB
444{
445 TCGContext *s = &tcg_ctx;
446 TCGTemp *ts;
e8996ee0 447 int idx = GET_TCGV(arg);
641d5fbe 448 int k;
c896fe29 449
e8996ee0 450 assert(idx >= s->nb_globals && idx < s->nb_temps);
c896fe29 451 ts = &s->temps[idx];
e8996ee0
FB
452 assert(ts->temp_allocated != 0);
453 ts->temp_allocated = 0;
641d5fbe
FB
454 k = ts->base_type;
455 if (ts->temp_local)
456 k += TCG_TYPE_COUNT;
457 ts->next_free_temp = s->first_free_temp[k];
458 s->first_free_temp[k] = idx;
c896fe29
FB
459}
460
e8996ee0
FB
461
462TCGv tcg_const_i32(int32_t val)
c896fe29 463{
e8996ee0
FB
464 TCGv t0;
465 t0 = tcg_temp_new(TCG_TYPE_I32);
466 tcg_gen_movi_i32(t0, val);
467 return t0;
468}
c896fe29 469
e8996ee0
FB
470TCGv tcg_const_i64(int64_t val)
471{
472 TCGv t0;
473 t0 = tcg_temp_new(TCG_TYPE_I64);
474 tcg_gen_movi_i64(t0, val);
475 return t0;
c896fe29
FB
476}
477
bdffd4a9
AJ
478TCGv tcg_const_local_i32(int32_t val)
479{
480 TCGv t0;
481 t0 = tcg_temp_local_new(TCG_TYPE_I32);
482 tcg_gen_movi_i32(t0, val);
483 return t0;
484}
485
486TCGv tcg_const_local_i64(int64_t val)
487{
488 TCGv t0;
489 t0 = tcg_temp_local_new(TCG_TYPE_I64);
490 tcg_gen_movi_i64(t0, val);
491 return t0;
492}
493
c896fe29
FB
494void tcg_register_helper(void *func, const char *name)
495{
496 TCGContext *s = &tcg_ctx;
497 int n;
498 if ((s->nb_helpers + 1) > s->allocated_helpers) {
499 n = s->allocated_helpers;
500 if (n == 0) {
501 n = 4;
502 } else {
503 n *= 2;
504 }
505 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
506 s->allocated_helpers = n;
507 }
4dc81f28 508 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
c896fe29
FB
509 s->helpers[s->nb_helpers].name = name;
510 s->nb_helpers++;
511}
512
ac56dd48 513static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
c896fe29 514{
ac56dd48 515 return s->temps[GET_TCGV(arg)].base_type;
c896fe29
FB
516}
517
ac56dd48 518static void tcg_gen_call_internal(TCGContext *s, TCGv func,
c896fe29 519 unsigned int flags,
ac56dd48
PB
520 unsigned int nb_rets, const TCGv *rets,
521 unsigned int nb_params, const TCGv *params)
c896fe29
FB
522{
523 int i;
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++) {
ac56dd48 527 *gen_opparam_ptr++ = GET_TCGV(rets[i]);
c896fe29
FB
528 }
529 for(i = 0; i < nb_params; i++) {
ac56dd48 530 *gen_opparam_ptr++ = GET_TCGV(params[i]);
c896fe29 531 }
ac56dd48 532 *gen_opparam_ptr++ = GET_TCGV(func);
c896fe29
FB
533
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;
537}
538
539
540#if TCG_TARGET_REG_BITS < 64
39cf05d3
FB
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(). */
ac56dd48
PB
544void 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)
c896fe29 547{
ac56dd48 548 TCGv ret, *args2, rets_2[2], arg;
c896fe29
FB
549 int j, i, call_type;
550
551 if (nb_rets == 1) {
552 ret = rets[0];
553 if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
554 nb_rets = 2;
39cf05d3
FB
555#ifdef TCG_TARGET_WORDS_BIGENDIAN
556 rets_2[0] = TCGV_HIGH(ret);
557 rets_2[1] = ret;
558#else
c896fe29 559 rets_2[0] = ret;
ac56dd48 560 rets_2[1] = TCGV_HIGH(ret);
39cf05d3 561#endif
c896fe29
FB
562 rets = rets_2;
563 }
564 }
39cf05d3 565 args2 = alloca((nb_params * 3) * sizeof(TCGv));
c896fe29
FB
566 j = 0;
567 call_type = (flags & TCG_CALL_TYPE_MASK);
568 for(i = 0; i < nb_params; i++) {
569 arg = args1[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;
577 }
578 args2[j++] = arg;
ac56dd48 579 args2[j++] = TCGV_HIGH(arg);
c896fe29 580#else
39cf05d3
FB
581#ifdef TCG_TARGET_CALL_ALIGN_ARGS
582 /* some targets want aligned 64 bit args */
583 if (j & 1) {
584 args2[j++] = TCG_CALL_DUMMY_ARG;
585 }
586#endif
c896fe29 587#ifdef TCG_TARGET_WORDS_BIGENDIAN
a0d69e00 588 args2[j++] = TCGV_HIGH(arg);
c896fe29
FB
589 args2[j++] = arg;
590#else
591 args2[j++] = arg;
ac56dd48 592 args2[j++] = TCGV_HIGH(arg);
c896fe29
FB
593#endif
594#endif
595 } else {
596 args2[j++] = arg;
597 }
598 }
599 tcg_gen_call_internal(s, func, flags,
600 nb_rets, rets, j, args2);
601}
602#else
ac56dd48
PB
603void 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)
c896fe29
FB
606{
607 tcg_gen_call_internal(s, func, flags,
608 nb_rets, rets, nb_params, args1);
609}
610#endif
611
ac56dd48
PB
612#if TCG_TARGET_REG_BITS == 32
613void tcg_gen_shifti_i64(TCGv ret, TCGv arg1,
c896fe29
FB
614 int c, int right, int arith)
615{
cf60bce4
FB
616 if (c == 0) {
617 tcg_gen_mov_i32(ret, arg1);
618 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
619 } else if (c >= 32) {
c896fe29
FB
620 c -= 32;
621 if (right) {
622 if (arith) {
ac56dd48
PB
623 tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
624 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
c896fe29 625 } else {
ac56dd48
PB
626 tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
627 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
c896fe29
FB
628 }
629 } else {
ac56dd48 630 tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
c896fe29
FB
631 tcg_gen_movi_i32(ret, 0);
632 }
633 } else {
ac56dd48 634 TCGv t0, t1;
c896fe29
FB
635
636 t0 = tcg_temp_new(TCG_TYPE_I32);
637 t1 = tcg_temp_new(TCG_TYPE_I32);
638 if (right) {
ac56dd48 639 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
c896fe29 640 if (arith)
ac56dd48 641 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
c896fe29 642 else
ac56dd48 643 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
c896fe29
FB
644 tcg_gen_shri_i32(ret, arg1, c);
645 tcg_gen_or_i32(ret, ret, t0);
ac56dd48 646 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
c896fe29
FB
647 } else {
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);
ac56dd48
PB
651 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
652 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
c896fe29
FB
653 tcg_gen_mov_i32(ret, t1);
654 }
e8996ee0
FB
655 tcg_temp_free(t0);
656 tcg_temp_free(t1);
c896fe29
FB
657 }
658}
ac56dd48 659#endif
c896fe29 660
8fcd3692 661static void tcg_reg_alloc_start(TCGContext *s)
c896fe29
FB
662{
663 int i;
664 TCGTemp *ts;
665 for(i = 0; i < s->nb_globals; i++) {
666 ts = &s->temps[i];
667 if (ts->fixed_reg) {
668 ts->val_type = TEMP_VAL_REG;
669 } else {
670 ts->val_type = TEMP_VAL_MEM;
671 }
672 }
e8996ee0
FB
673 for(i = s->nb_globals; i < s->nb_temps; i++) {
674 ts = &s->temps[i];
675 ts->val_type = TEMP_VAL_DEAD;
676 ts->mem_allocated = 0;
677 ts->fixed_reg = 0;
678 }
c896fe29
FB
679 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
680 s->reg_to_temp[i] = -1;
681 }
682}
683
ac56dd48
PB
684static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
685 int idx)
c896fe29
FB
686{
687 TCGTemp *ts;
ac56dd48
PB
688
689 ts = &s->temps[idx];
690 if (idx < s->nb_globals) {
691 pstrcpy(buf, buf_size, ts->name);
c896fe29 692 } else {
641d5fbe
FB
693 if (ts->temp_local)
694 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
695 else
696 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
c896fe29
FB
697 }
698 return buf;
699}
700
ac56dd48
PB
701char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
702{
703 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
704}
705
e8996ee0 706static int helper_cmp(const void *p1, const void *p2)
4dc81f28 707{
e8996ee0
FB
708 const TCGHelperInfo *th1 = p1;
709 const TCGHelperInfo *th2 = p2;
710 if (th1->func < th2->func)
711 return -1;
712 else if (th1->func == th2->func)
713 return 0;
714 else
715 return 1;
4dc81f28
FB
716}
717
e8996ee0
FB
718/* find helper definition (Note: A hash table would be better) */
719static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
4dc81f28 720{
e8996ee0 721 int m, m_min, m_max;
4dc81f28 722 TCGHelperInfo *th;
e8996ee0 723 tcg_target_ulong v;
4dc81f28 724
e8996ee0
FB
725 if (unlikely(!s->helpers_sorted)) {
726 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
727 helper_cmp);
728 s->helpers_sorted = 1;
729 }
730
731 /* binary search */
732 m_min = 0;
733 m_max = s->nb_helpers - 1;
734 while (m_min <= m_max) {
735 m = (m_min + m_max) >> 1;
736 th = &s->helpers[m];
737 v = th->func;
738 if (v == val)
739 return th;
740 else if (val < v) {
741 m_max = m - 1;
742 } else {
743 m_min = m + 1;
4dc81f28
FB
744 }
745 }
e8996ee0 746 return NULL;
4dc81f28
FB
747}
748
f48f3ede
BS
749static const char * const cond_name[] =
750{
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"
761};
762
c896fe29
FB
763void tcg_dump_ops(TCGContext *s, FILE *outfile)
764{
765 const uint16_t *opc_ptr;
766 const TCGArg *args;
767 TCGArg arg;
7e4597d7 768 int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
c896fe29
FB
769 const TCGOpDef *def;
770 char buf[128];
771
7e4597d7 772 first_insn = 1;
c896fe29
FB
773 opc_ptr = gen_opc_buf;
774 args = gen_opparam_buf;
775 while (opc_ptr < gen_opc_ptr) {
776 c = *opc_ptr++;
777 def = &tcg_op_defs[c];
7e4597d7
FB
778 if (c == INDEX_op_debug_insn_start) {
779 uint64_t pc;
780#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
781 pc = ((uint64_t)args[1] << 32) | args[0];
782#else
783 pc = args[0];
784#endif
785 if (!first_insn)
786 fprintf(outfile, "\n");
787 fprintf(outfile, " ---- 0x%" PRIx64, pc);
788 first_insn = 0;
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) {
c896fe29 793 TCGArg arg;
4dc81f28 794
c896fe29
FB
795 /* variable number of arguments */
796 arg = *args++;
797 nb_oargs = arg >> 16;
798 nb_iargs = arg & 0xffff;
799 nb_cargs = def->nb_cargs;
c896fe29 800
7e4597d7
FB
801 fprintf(outfile, " %s ", def->name);
802
b03cce8e 803 /* function name */
ac56dd48 804 fprintf(outfile, "%s",
e8996ee0 805 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
b03cce8e
FB
806 /* flags */
807 fprintf(outfile, ",$0x%" TCG_PRIlx,
808 args[nb_oargs + nb_iargs]);
809 /* nb out args */
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]));
815 }
816 for(i = 0; i < (nb_iargs - 1); i++) {
c896fe29 817 fprintf(outfile, ",");
39cf05d3
FB
818 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
819 fprintf(outfile, "<dummy>");
820 } else {
821 fprintf(outfile, "%s",
822 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
823 }
b03cce8e 824 }
e8996ee0
FB
825 } else if (c == INDEX_op_movi_i32
826#if TCG_TARGET_REG_BITS == 64
827 || c == INDEX_op_movi_i64
828#endif
829 ) {
830 tcg_target_ulong val;
831 TCGHelperInfo *th;
832
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]));
838 val = args[1];
839 th = tcg_find_helper(s, val);
840 if (th) {
841 fprintf(outfile, th->name);
842 } else {
843 if (c == INDEX_op_movi_i32)
844 fprintf(outfile, "0x%x", (uint32_t)val);
845 else
846 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
847 }
b03cce8e 848 } else {
7e4597d7 849 fprintf(outfile, " %s ", def->name);
b03cce8e
FB
850 if (c == INDEX_op_nopn) {
851 /* variable number of arguments */
852 nb_cargs = *args;
853 nb_oargs = 0;
854 nb_iargs = 0;
855 } else {
856 nb_oargs = def->nb_oargs;
857 nb_iargs = def->nb_iargs;
858 nb_cargs = def->nb_cargs;
859 }
860
861 k = 0;
862 for(i = 0; i < nb_oargs; i++) {
863 if (k != 0)
864 fprintf(outfile, ",");
865 fprintf(outfile, "%s",
866 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
867 }
868 for(i = 0; i < nb_iargs; i++) {
869 if (k != 0)
870 fprintf(outfile, ",");
871 fprintf(outfile, "%s",
872 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
873 }
f48f3ede
BS
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
879#endif
880 ) {
881 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
882 fprintf(outfile, ",%s", cond_name[args[k++]]);
883 else
884 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
885 i = 1;
886 }
887 else
888 i = 0;
889 for(; i < nb_cargs; i++) {
b03cce8e
FB
890 if (k != 0)
891 fprintf(outfile, ",");
892 arg = args[k++];
893 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
894 }
c896fe29
FB
895 }
896 fprintf(outfile, "\n");
897 args += nb_iargs + nb_oargs + nb_cargs;
898 }
899}
900
901/* we give more priority to constraints with less registers */
902static int get_constraint_priority(const TCGOpDef *def, int k)
903{
904 const TCGArgConstraint *arg_ct;
905
906 int i, n;
907 arg_ct = &def->args_ct[k];
908 if (arg_ct->ct & TCG_CT_ALIAS) {
909 /* an alias is equivalent to a single register */
910 n = 1;
911 } else {
912 if (!(arg_ct->ct & TCG_CT_REG))
913 return 0;
914 n = 0;
915 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
916 if (tcg_regset_test_reg(arg_ct->u.regs, i))
917 n++;
918 }
919 }
920 return TCG_TARGET_NB_REGS - n + 1;
921}
922
923/* sort from highest priority to lowest */
924static void sort_constraints(TCGOpDef *def, int start, int n)
925{
926 int i, j, p1, p2, tmp;
927
928 for(i = 0; i < n; i++)
929 def->sorted_args[start + i] = start + i;
930 if (n <= 1)
931 return;
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]);
936 if (p1 < p2) {
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;
940 }
941 }
942 }
943}
944
945void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
946{
947 int op;
948 TCGOpDef *def;
949 const char *ct_str;
950 int i, nb_args;
951
952 for(;;) {
953 if (tdefs->op < 0)
954 break;
955 op = tdefs->op;
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') {
964 int oarg;
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
5ff9d6a4 969 argument is tagged with TCG_CT_IALIAS. */
c896fe29 970 def->args_ct[i] = def->args_ct[oarg];
5ff9d6a4
FB
971 def->args_ct[oarg].ct = TCG_CT_ALIAS;
972 def->args_ct[oarg].alias_index = i;
c896fe29 973 def->args_ct[i].ct |= TCG_CT_IALIAS;
5ff9d6a4 974 def->args_ct[i].alias_index = oarg;
c896fe29
FB
975 } else {
976 for(;;) {
977 if (*ct_str == '\0')
978 break;
979 switch(*ct_str) {
980 case 'i':
981 def->args_ct[i].ct |= TCG_CT_CONST;
982 ct_str++;
983 break;
984 default:
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);
988 exit(1);
989 }
990 }
991 }
992 }
993 }
994
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);
998
999#if 0
1000 {
1001 int i;
1002
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]);
1006 printf("\n");
1007 }
1008#endif
1009 tdefs++;
1010 }
1011
1012}
1013
1014#ifdef USE_LIVENESS_ANALYSIS
1015
1016/* set a nop for an operation using 'nb_args' */
1017static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1018 TCGArg *args, int nb_args)
1019{
1020 if (nb_args == 0) {
1021 *opc_ptr = INDEX_op_nop;
1022 } else {
1023 *opc_ptr = INDEX_op_nopn;
1024 args[0] = nb_args;
1025 args[nb_args - 1] = nb_args;
1026 }
1027}
1028
641d5fbe
FB
1029/* liveness analysis: end of function: globals are live, temps are
1030 dead. */
1031/* XXX: at this stage, not used as there would be little gains because
1032 most TBs end with a conditional jump. */
1033static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
c896fe29
FB
1034{
1035 memset(dead_temps, 0, s->nb_globals);
1036 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1037}
1038
641d5fbe
FB
1039/* liveness analysis: end of basic block: globals are live, temps are
1040 dead, local temps are live. */
1041static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1042{
1043 int i;
1044 TCGTemp *ts;
1045
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++) {
1049 if (ts->temp_local)
1050 dead_temps[i] = 0;
1051 else
1052 dead_temps[i] = 1;
1053 ts++;
1054 }
1055}
1056
c896fe29
FB
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. */
8fcd3692 1060static void tcg_liveness_analysis(TCGContext *s)
c896fe29
FB
1061{
1062 int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1063 TCGArg *args;
1064 const TCGOpDef *def;
1065 uint8_t *dead_temps;
1066 unsigned int dead_iargs;
1067
1068 gen_opc_ptr++; /* skip end */
1069
1070 nb_ops = gen_opc_ptr - gen_opc_buf;
1071
1072 /* XXX: make it really dynamic */
1073 s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1074
1075 dead_temps = tcg_malloc(s->nb_temps);
1076 memset(dead_temps, 1, s->nb_temps);
1077
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];
1083 switch(op) {
1084 case INDEX_op_call:
c6e113f5
FB
1085 {
1086 int call_flags;
c896fe29 1087
c6e113f5
FB
1088 nb_args = args[-1];
1089 args -= nb_args;
1090 nb_iargs = args[0] & 0xffff;
1091 nb_oargs = args[0] >> 16;
1092 args++;
1093 call_flags = args[nb_oargs + nb_iargs];
1094
1095 /* pure functions can be removed if their result is not
1096 used */
1097 if (call_flags & TCG_CALL_PURE) {
1098 for(i = 0; i < nb_oargs; i++) {
1099 arg = args[i];
1100 if (!dead_temps[arg])
1101 goto do_not_remove_call;
1102 }
1103 tcg_set_nop(s, gen_opc_buf + op_index,
1104 args - 1, nb_args);
1105 } else {
1106 do_not_remove_call:
c896fe29 1107
c6e113f5
FB
1108 /* output args are dead */
1109 for(i = 0; i < nb_oargs; i++) {
1110 arg = args[i];
1111 dead_temps[arg] = 1;
1112 }
1113
1114 /* globals are live (they may be used by the call) */
1115 memset(dead_temps, 0, s->nb_globals);
1116
1117 /* input args are live */
1118 dead_iargs = 0;
1119 for(i = 0; i < nb_iargs; i++) {
1120 arg = args[i + nb_oargs];
39cf05d3
FB
1121 if (arg != TCG_CALL_DUMMY_ARG) {
1122 if (dead_temps[arg]) {
1123 dead_iargs |= (1 << i);
1124 }
1125 dead_temps[arg] = 0;
c6e113f5 1126 }
c6e113f5
FB
1127 }
1128 s->op_dead_iargs[op_index] = dead_iargs;
c896fe29 1129 }
c6e113f5 1130 args--;
c896fe29 1131 }
c896fe29
FB
1132 break;
1133 case INDEX_op_set_label:
1134 args--;
1135 /* mark end of basic block */
1136 tcg_la_bb_end(s, dead_temps);
1137 break;
7e4597d7
FB
1138 case INDEX_op_debug_insn_start:
1139 args -= def->nb_args;
1140 break;
c896fe29
FB
1141 case INDEX_op_nopn:
1142 nb_args = args[-1];
1143 args -= nb_args;
1144 break;
5ff9d6a4
FB
1145 case INDEX_op_discard:
1146 args--;
1147 /* mark the temporary as dead */
1148 dead_temps[args[0]] = 1;
1149 break;
c896fe29
FB
1150 case INDEX_op_end:
1151 break;
1152 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1153 default:
1154 if (op > INDEX_op_end) {
1155 args -= def->nb_args;
1156 nb_iargs = def->nb_iargs;
1157 nb_oargs = def->nb_oargs;
1158
1159 /* Test if the operation can be removed because all
5ff9d6a4
FB
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) {
c896fe29
FB
1163 for(i = 0; i < nb_oargs; i++) {
1164 arg = args[i];
1165 if (!dead_temps[arg])
1166 goto do_not_remove;
1167 }
1168 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1169#ifdef CONFIG_PROFILER
a23a9ec6 1170 s->del_op_count++;
c896fe29
FB
1171#endif
1172 } else {
1173 do_not_remove:
1174
1175 /* output args are dead */
1176 for(i = 0; i < nb_oargs; i++) {
1177 arg = args[i];
1178 dead_temps[arg] = 1;
1179 }
1180
1181 /* if end of basic block, update */
1182 if (def->flags & TCG_OPF_BB_END) {
1183 tcg_la_bb_end(s, dead_temps);
b03cce8e
FB
1184 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1185 /* globals are live */
1186 memset(dead_temps, 0, s->nb_globals);
c896fe29
FB
1187 }
1188
1189 /* input args are live */
1190 dead_iargs = 0;
1191 for(i = 0; i < nb_iargs; i++) {
1192 arg = args[i + nb_oargs];
1193 if (dead_temps[arg]) {
1194 dead_iargs |= (1 << i);
1195 }
1196 dead_temps[arg] = 0;
1197 }
1198 s->op_dead_iargs[op_index] = dead_iargs;
1199 }
1200 } else {
1201 /* legacy dyngen operations */
1202 args -= def->nb_args;
1203 /* mark end of basic block */
1204 tcg_la_bb_end(s, dead_temps);
1205 }
1206 break;
1207 }
1208 op_index--;
1209 }
1210
1211 if (args != gen_opparam_buf)
1212 tcg_abort();
1213}
1214#else
1215/* dummy liveness analysis */
1216void tcg_liveness_analysis(TCGContext *s)
1217{
1218 int nb_ops;
1219 nb_ops = gen_opc_ptr - gen_opc_buf;
1220
1221 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1222 memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1223}
1224#endif
1225
1226#ifndef NDEBUG
1227static void dump_regs(TCGContext *s)
1228{
1229 TCGTemp *ts;
1230 int i;
1231 char buf[64];
1232
1233 for(i = 0; i < s->nb_temps; i++) {
1234 ts = &s->temps[i];
ac56dd48 1235 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
c896fe29
FB
1236 switch(ts->val_type) {
1237 case TEMP_VAL_REG:
1238 printf("%s", tcg_target_reg_names[ts->reg]);
1239 break;
1240 case TEMP_VAL_MEM:
1241 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1242 break;
1243 case TEMP_VAL_CONST:
1244 printf("$0x%" TCG_PRIlx, ts->val);
1245 break;
1246 case TEMP_VAL_DEAD:
1247 printf("D");
1248 break;
1249 default:
1250 printf("???");
1251 break;
1252 }
1253 printf("\n");
1254 }
1255
1256 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1257 if (s->reg_to_temp[i] >= 0) {
1258 printf("%s: %s\n",
1259 tcg_target_reg_names[i],
ac56dd48 1260 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
c896fe29
FB
1261 }
1262 }
1263}
1264
1265static void check_regs(TCGContext *s)
1266{
1267 int reg, k;
1268 TCGTemp *ts;
1269 char buf[64];
1270
1271 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1272 k = s->reg_to_temp[reg];
1273 if (k >= 0) {
1274 ts = &s->temps[k];
1275 if (ts->val_type != TEMP_VAL_REG ||
1276 ts->reg != reg) {
1277 printf("Inconsistency for register %s:\n",
1278 tcg_target_reg_names[reg]);
b03cce8e 1279 goto fail;
c896fe29
FB
1280 }
1281 }
1282 }
1283 for(k = 0; k < s->nb_temps; k++) {
1284 ts = &s->temps[k];
1285 if (ts->val_type == TEMP_VAL_REG &&
1286 !ts->fixed_reg &&
1287 s->reg_to_temp[ts->reg] != k) {
1288 printf("Inconsistency for temp %s:\n",
ac56dd48 1289 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
b03cce8e 1290 fail:
c896fe29
FB
1291 printf("reg state:\n");
1292 dump_regs(s);
1293 tcg_abort();
1294 }
1295 }
1296}
1297#endif
1298
1299static void temp_allocate_frame(TCGContext *s, int temp)
1300{
1301 TCGTemp *ts;
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)
5ff9d6a4 1305 tcg_abort();
c896fe29
FB
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);
1310}
1311
1312/* free register 'reg' by spilling the corresponding temporary if necessary */
1313static void tcg_reg_free(TCGContext *s, int reg)
1314{
1315 TCGTemp *ts;
1316 int temp;
1317
1318 temp = s->reg_to_temp[reg];
1319 if (temp != -1) {
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);
e4d5434c 1325 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1326 }
1327 ts->val_type = TEMP_VAL_MEM;
1328 s->reg_to_temp[reg] = -1;
1329 }
1330}
1331
1332/* Allocate a register belonging to reg1 & ~reg2 */
1333static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1334{
1335 int i, reg;
1336 TCGRegSet reg_ct;
1337
1338 tcg_regset_andnot(reg_ct, reg1, reg2);
1339
1340 /* first try free registers */
0954d0d9 1341 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1342 reg = tcg_target_reg_alloc_order[i];
1343 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1344 return reg;
1345 }
1346
1347 /* XXX: do better spill choice */
0954d0d9 1348 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1349 reg = tcg_target_reg_alloc_order[i];
1350 if (tcg_regset_test_reg(reg_ct, reg)) {
1351 tcg_reg_free(s, reg);
1352 return reg;
1353 }
1354 }
1355
1356 tcg_abort();
1357}
1358
641d5fbe
FB
1359/* save a temporary to memory. 'allocated_regs' is used in case a
1360 temporary registers needs to be allocated to store a constant. */
1361static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1362{
1363 TCGTemp *ts;
1364 int reg;
1365
1366 ts = &s->temps[temp];
1367 if (!ts->fixed_reg) {
1368 switch(ts->val_type) {
1369 case TEMP_VAL_REG:
1370 tcg_reg_free(s, ts->reg);
1371 break;
1372 case TEMP_VAL_DEAD:
1373 ts->val_type = TEMP_VAL_MEM;
1374 break;
1375 case TEMP_VAL_CONST:
1376 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1377 allocated_regs);
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;
1383 break;
1384 case TEMP_VAL_MEM:
1385 break;
1386 default:
1387 tcg_abort();
1388 }
1389 }
1390}
1391
e5097dc8 1392/* save globals to their cannonical location and assume they can be
e8996ee0
FB
1393 modified be the following code. 'allocated_regs' is used in case a
1394 temporary registers needs to be allocated to store a constant. */
1395static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
c896fe29 1396{
641d5fbe 1397 int i;
c896fe29
FB
1398
1399 for(i = 0; i < s->nb_globals; i++) {
641d5fbe 1400 temp_save(s, i, allocated_regs);
c896fe29 1401 }
e5097dc8
FB
1402}
1403
1404/* at the end of a basic block, we assume all temporaries are dead and
e8996ee0
FB
1405 all globals are stored at their canonical location. */
1406static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
e5097dc8
FB
1407{
1408 TCGTemp *ts;
1409 int i;
1410
c896fe29
FB
1411 for(i = s->nb_globals; i < s->nb_temps; i++) {
1412 ts = &s->temps[i];
641d5fbe
FB
1413 if (ts->temp_local) {
1414 temp_save(s, i, allocated_regs);
1415 } else {
1416 if (ts->val_type == TEMP_VAL_REG) {
1417 s->reg_to_temp[ts->reg] = -1;
1418 }
1419 ts->val_type = TEMP_VAL_DEAD;
c896fe29
FB
1420 }
1421 }
e8996ee0
FB
1422
1423 save_globals(s, allocated_regs);
c896fe29
FB
1424}
1425
1426#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1427
e8996ee0
FB
1428static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1429{
1430 TCGTemp *ots;
1431 tcg_target_ulong val;
1432
1433 ots = &s->temps[args[0]];
1434 val = args[1];
1435
1436 if (ots->fixed_reg) {
1437 /* for fixed registers, we do not do any constant
1438 propagation */
1439 tcg_out_movi(s, ots->type, ots->reg, val);
1440 } else {
1235fc06 1441 /* The movi is not explicitly generated here */
e8996ee0
FB
1442 if (ots->val_type == TEMP_VAL_REG)
1443 s->reg_to_temp[ots->reg] = -1;
1444 ots->val_type = TEMP_VAL_CONST;
1445 ots->val = val;
1446 }
1447}
1448
c896fe29
FB
1449static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1450 const TCGArg *args,
1451 unsigned int dead_iargs)
1452{
1453 TCGTemp *ts, *ots;
1454 int reg;
1455 const TCGArgConstraint *arg_ct;
1456
1457 ots = &s->temps[args[0]];
1458 ts = &s->temps[args[1]];
1459 arg_ct = &def->args_ct[0];
1460
e8996ee0 1461 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
c896fe29
FB
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;
1467 reg = ts->reg;
1468 s->reg_to_temp[reg] = -1;
1469 ts->val_type = TEMP_VAL_DEAD;
1470 } else {
1471 if (ots->val_type == TEMP_VAL_REG) {
1472 reg = ots->reg;
1473 } else {
1474 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1475 }
1476 if (ts->reg != reg) {
1477 tcg_out_mov(s, reg, ts->reg);
1478 }
1479 }
1480 } else if (ts->val_type == TEMP_VAL_MEM) {
1481 if (ots->val_type == TEMP_VAL_REG) {
1482 reg = ots->reg;
1483 } else {
1484 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1485 }
e4d5434c 1486 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1487 } else if (ts->val_type == TEMP_VAL_CONST) {
e8996ee0 1488 if (ots->fixed_reg) {
c896fe29 1489 reg = ots->reg;
e8996ee0 1490 tcg_out_movi(s, ots->type, reg, ts->val);
c896fe29 1491 } else {
e8996ee0
FB
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;
1496 ots->val = ts->val;
1497 return;
c896fe29 1498 }
c896fe29
FB
1499 } else {
1500 tcg_abort();
1501 }
1502 s->reg_to_temp[reg] = args[0];
1503 ots->reg = reg;
1504 ots->val_type = TEMP_VAL_REG;
1505 ots->mem_coherent = 0;
1506}
1507
1508static void tcg_reg_alloc_op(TCGContext *s,
1509 const TCGOpDef *def, int opc,
1510 const TCGArg *args,
1511 unsigned int dead_iargs)
1512{
1513 TCGRegSet allocated_regs;
1514 int i, k, nb_iargs, nb_oargs, reg;
1515 TCGArg arg;
1516 const TCGArgConstraint *arg_ct;
1517 TCGTemp *ts;
1518 TCGArg new_args[TCG_MAX_OP_ARGS];
1519 int const_args[TCG_MAX_OP_ARGS];
1520
1521 nb_oargs = def->nb_oargs;
1522 nb_iargs = def->nb_iargs;
1523
1524 /* copy constants */
1525 memcpy(new_args + nb_oargs + nb_iargs,
1526 args + nb_oargs + nb_iargs,
1527 sizeof(TCGArg) * def->nb_cargs);
1528
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];
1533 arg = args[i];
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);
e4d5434c 1538 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1539 ts->val_type = TEMP_VAL_REG;
1540 ts->reg = 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 */
1546 const_args[i] = 1;
1547 new_args[i] = ts->val;
1548 goto iarg_end;
1549 } else {
e8996ee0 1550 /* need to move to a register */
c896fe29
FB
1551 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1552 tcg_out_movi(s, ts->type, reg, ts->val);
e8996ee0
FB
1553 ts->val_type = TEMP_VAL_REG;
1554 ts->reg = reg;
1555 ts->mem_coherent = 0;
1556 s->reg_to_temp[reg] = arg;
c896fe29
FB
1557 }
1558 }
1559 assert(ts->val_type == TEMP_VAL_REG);
5ff9d6a4
FB
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;
1566 } else {
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;
1572 }
c896fe29
FB
1573 }
1574 reg = ts->reg;
1575 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1576 /* nothing to do : the constraint is satisfied */
1577 } else {
1578 allocate_in_reg:
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);
1583 }
c896fe29
FB
1584 new_args[i] = reg;
1585 const_args[i] = 0;
1586 tcg_regset_set_reg(allocated_regs, reg);
1587 iarg_end: ;
1588 }
1589
e8996ee0
FB
1590 if (def->flags & TCG_OPF_BB_END) {
1591 tcg_reg_alloc_bb_end(s, allocated_regs);
1592 } else {
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;
1602 }
c896fe29
FB
1603 }
1604 }
e8996ee0
FB
1605
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);
1611 }
c896fe29 1612 }
e8996ee0
FB
1613 /* XXX: for load/store we could do that only for the slow path
1614 (i.e. when a memory callback is called) */
1615
1616 /* store globals and free associated registers (we assume the insn
1617 can modify any global. */
1618 save_globals(s, allocated_regs);
c896fe29 1619 }
e8996ee0
FB
1620
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];
1625 arg = args[i];
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];
1630 } else {
1631 /* if fixed register, we try to use it */
1632 reg = ts->reg;
1633 if (ts->fixed_reg &&
1634 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1635 goto oarg_end;
1636 }
1637 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
c896fe29 1638 }
e8996ee0
FB
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;
1645 ts->reg = 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;
1650 }
1651 oarg_end:
1652 new_args[i] = reg;
c896fe29 1653 }
c896fe29
FB
1654 }
1655
c896fe29
FB
1656 /* emit instruction */
1657 tcg_out_op(s, opc, new_args, const_args);
1658
1659 /* move the outputs in the correct register if needed */
1660 for(i = 0; i < nb_oargs; i++) {
1661 ts = &s->temps[args[i]];
1662 reg = new_args[i];
1663 if (ts->fixed_reg && ts->reg != reg) {
1664 tcg_out_mov(s, ts->reg, reg);
1665 }
1666 }
1667}
1668
b03cce8e
FB
1669#ifdef TCG_TARGET_STACK_GROWSUP
1670#define STACK_DIR(x) (-(x))
1671#else
1672#define STACK_DIR(x) (x)
1673#endif
1674
c896fe29
FB
1675static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1676 int opc, const TCGArg *args,
1677 unsigned int dead_iargs)
1678{
1679 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1680 TCGArg arg, func_arg;
1681 TCGTemp *ts;
f54b3f92 1682 tcg_target_long stack_offset, call_stack_size, func_addr;
b03cce8e 1683 int const_func_arg, allocate_args;
c896fe29
FB
1684 TCGRegSet allocated_regs;
1685 const TCGArgConstraint *arg_ct;
1686
1687 arg = *args++;
1688
1689 nb_oargs = arg >> 16;
1690 nb_iargs = arg & 0xffff;
1691 nb_params = nb_iargs - 1;
1692
1693 flags = args[nb_oargs + nb_iargs];
1694
1695 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1696 if (nb_regs > nb_params)
1697 nb_regs = nb_params;
1698
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);
b03cce8e
FB
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));
1707 }
39cf05d3
FB
1708
1709 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
c896fe29
FB
1710 for(i = nb_regs; i < nb_params; i++) {
1711 arg = args[nb_oargs + i];
39cf05d3
FB
1712#ifdef TCG_TARGET_STACK_GROWSUP
1713 stack_offset -= sizeof(tcg_target_long);
1714#endif
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],
1721 s->reserved_regs);
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],
1727 s->reserved_regs);
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);
1731 } else {
1732 tcg_abort();
1733 }
c896fe29 1734 }
39cf05d3
FB
1735#ifndef TCG_TARGET_STACK_GROWSUP
1736 stack_offset += sizeof(tcg_target_long);
1737#endif
c896fe29
FB
1738 }
1739
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];
39cf05d3
FB
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);
1751 }
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);
1757 } else {
1758 tcg_abort();
c896fe29 1759 }
39cf05d3 1760 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1761 }
c896fe29
FB
1762 }
1763
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];
f54b3f92 1768 func_addr = ts->val;
c896fe29
FB
1769 const_func_arg = 0;
1770 if (ts->val_type == TEMP_VAL_MEM) {
1771 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1772 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1773 func_arg = reg;
e8996ee0 1774 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1775 } else if (ts->val_type == TEMP_VAL_REG) {
1776 reg = ts->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);
1780 }
1781 func_arg = reg;
e8996ee0 1782 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1783 } else if (ts->val_type == TEMP_VAL_CONST) {
f54b3f92 1784 if (tcg_target_const_match(func_addr, arg_ct)) {
c896fe29 1785 const_func_arg = 1;
f54b3f92 1786 func_arg = func_addr;
c896fe29
FB
1787 } else {
1788 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
f54b3f92 1789 tcg_out_movi(s, ts->type, reg, func_addr);
c896fe29 1790 func_arg = reg;
e8996ee0 1791 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1792 }
1793 } else {
1794 tcg_abort();
1795 }
e8996ee0 1796
c896fe29
FB
1797
1798 /* mark dead temporaries and free the associated registers */
c6e113f5 1799 for(i = 0; i < nb_iargs; i++) {
c896fe29
FB
1800 arg = args[nb_oargs + i];
1801 if (IS_DEAD_IARG(i)) {
1802 ts = &s->temps[arg];
e8996ee0 1803 if (!ts->fixed_reg) {
c896fe29
FB
1804 if (ts->val_type == TEMP_VAL_REG)
1805 s->reg_to_temp[ts->reg] = -1;
1806 ts->val_type = TEMP_VAL_DEAD;
1807 }
1808 }
1809 }
1810
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);
1815 }
1816 }
1817
1818 /* store globals and free associated registers (we assume the call
1819 can modify any global. */
e8996ee0 1820 save_globals(s, allocated_regs);
c896fe29
FB
1821
1822 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1823
b03cce8e
FB
1824 if (allocate_args) {
1825 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1826 }
c896fe29
FB
1827
1828 /* assign output registers and emit moves if needed */
1829 for(i = 0; i < nb_oargs; i++) {
1830 arg = args[i];
1831 ts = &s->temps[arg];
1832 reg = tcg_target_call_oarg_regs[i];
e8996ee0 1833 assert(s->reg_to_temp[reg] == -1);
c896fe29
FB
1834 if (ts->fixed_reg) {
1835 if (ts->reg != reg) {
1836 tcg_out_mov(s, ts->reg, reg);
1837 }
1838 } else {
1839 if (ts->val_type == TEMP_VAL_REG)
1840 s->reg_to_temp[ts->reg] = -1;
1841 ts->val_type = TEMP_VAL_REG;
1842 ts->reg = reg;
1843 ts->mem_coherent = 0;
1844 s->reg_to_temp[reg] = arg;
1845 }
1846 }
1847
1848 return nb_iargs + nb_oargs + def->nb_cargs + 1;
1849}
1850
1851#ifdef CONFIG_PROFILER
1852
1853static int64_t dyngen_table_op_count[NB_OPS];
1854
1855void dump_op_count(void)
1856{
1857 int i;
1858 FILE *f;
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]);
1862 }
1863 fclose(f);
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]);
1867 }
1868 fclose(f);
1869}
1870#endif
1871
1872
1873static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2ba1eeb6 1874 long search_pc)
c896fe29 1875{
b314f270 1876 int opc, op_index;
c896fe29
FB
1877 const TCGOpDef *def;
1878 unsigned int dead_iargs;
1879 const TCGArg *args;
1880
1881#ifdef DEBUG_DISAS
1882 if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1883 fprintf(logfile, "OP:\n");
1884 tcg_dump_ops(s, logfile);
1885 fprintf(logfile, "\n");
1886 }
1887#endif
1888
a23a9ec6
FB
1889#ifdef CONFIG_PROFILER
1890 s->la_time -= profile_getclock();
1891#endif
c896fe29 1892 tcg_liveness_analysis(s);
a23a9ec6
FB
1893#ifdef CONFIG_PROFILER
1894 s->la_time += profile_getclock();
1895#endif
c896fe29
FB
1896
1897#ifdef DEBUG_DISAS
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");
1902 }
1903#endif
1904
1905 tcg_reg_alloc_start(s);
1906
1907 s->code_buf = gen_code_buf;
1908 s->code_ptr = gen_code_buf;
1909
c896fe29
FB
1910 args = gen_opparam_buf;
1911 op_index = 0;
b3db8758 1912
c896fe29
FB
1913 for(;;) {
1914 opc = gen_opc_buf[op_index];
1915#ifdef CONFIG_PROFILER
1916 dyngen_table_op_count[opc]++;
1917#endif
1918 def = &tcg_op_defs[opc];
1919#if 0
1920 printf("%s: %d %d %d\n", def->name,
1921 def->nb_oargs, def->nb_iargs, def->nb_cargs);
1922 // dump_regs(s);
1923#endif
1924 switch(opc) {
1925 case INDEX_op_mov_i32:
1926#if TCG_TARGET_REG_BITS == 64
1927 case INDEX_op_mov_i64:
1928#endif
1929 dead_iargs = s->op_dead_iargs[op_index];
1930 tcg_reg_alloc_mov(s, def, args, dead_iargs);
1931 break;
e8996ee0
FB
1932 case INDEX_op_movi_i32:
1933#if TCG_TARGET_REG_BITS == 64
1934 case INDEX_op_movi_i64:
1935#endif
1936 tcg_reg_alloc_movi(s, args);
1937 break;
7e4597d7
FB
1938 case INDEX_op_debug_insn_start:
1939 /* debug instruction */
1940 break;
c896fe29
FB
1941 case INDEX_op_nop:
1942 case INDEX_op_nop1:
1943 case INDEX_op_nop2:
1944 case INDEX_op_nop3:
1945 break;
1946 case INDEX_op_nopn:
1947 args += args[0];
1948 goto next;
5ff9d6a4
FB
1949 case INDEX_op_discard:
1950 {
1951 TCGTemp *ts;
1952 ts = &s->temps[args[0]];
1953 /* mark the temporary as dead */
e8996ee0 1954 if (!ts->fixed_reg) {
5ff9d6a4
FB
1955 if (ts->val_type == TEMP_VAL_REG)
1956 s->reg_to_temp[ts->reg] = -1;
1957 ts->val_type = TEMP_VAL_DEAD;
1958 }
1959 }
1960 break;
c896fe29 1961 case INDEX_op_set_label:
e8996ee0 1962 tcg_reg_alloc_bb_end(s, s->reserved_regs);
c896fe29
FB
1963 tcg_out_label(s, args[0], (long)s->code_ptr);
1964 break;
1965 case INDEX_op_call:
1966 dead_iargs = s->op_dead_iargs[op_index];
1967 args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1968 goto next;
1969 case INDEX_op_end:
1970 goto the_end;
cf2be984 1971
bf6247fb 1972#ifdef CONFIG_DYNGEN_OP
c896fe29
FB
1973 case 0 ... INDEX_op_end - 1:
1974 /* legacy dyngen ops */
1975#ifdef CONFIG_PROFILER
a23a9ec6 1976 s->old_op_count++;
c896fe29 1977#endif
e8996ee0 1978 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2ba1eeb6 1979 if (search_pc >= 0) {
c896fe29
FB
1980 s->code_ptr += def->copy_size;
1981 args += def->nb_args;
1982 } else {
1983 args = dyngen_op(s, opc, args);
1984 }
1985 goto next;
cf2be984 1986#endif
c896fe29
FB
1987 default:
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);
1993 break;
1994 }
1995 args += def->nb_args;
8df1ca4b 1996 next:
2ba1eeb6 1997 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
b314f270 1998 return op_index;
c896fe29
FB
1999 }
2000 op_index++;
2001#ifndef NDEBUG
2002 check_regs(s);
2003#endif
2004 }
2005 the_end:
2006 return -1;
2007}
2008
2009int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
2010{
2011#ifdef CONFIG_PROFILER
2012 {
c896fe29
FB
2013 int n;
2014 n = (gen_opc_ptr - gen_opc_buf);
a23a9ec6
FB
2015 s->op_count += n;
2016 if (n > s->op_count_max)
2017 s->op_count_max = n;
2018
2019 s->temp_count += s->nb_temps;
2020 if (s->nb_temps > s->temp_count_max)
2021 s->temp_count_max = s->nb_temps;
c896fe29
FB
2022 }
2023#endif
2024
2ba1eeb6 2025 tcg_gen_code_common(s, gen_code_buf, -1);
c896fe29
FB
2026
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;
2031}
2032
2ba1eeb6 2033/* Return the index of the micro operation such as the pc after is <
623e265c
PB
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. */
2037int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
c896fe29 2038{
623e265c 2039 return tcg_gen_code_common(s, gen_code_buf, offset);
c896fe29 2040}
a23a9ec6
FB
2041
2042#ifdef CONFIG_PROFILER
2043void tcg_dump_info(FILE *f,
2044 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2045{
2046 TCGContext *s = &tcg_ctx;
2047 int64_t tot;
2048
2049 tot = s->interm_time + s->code_time;
2050 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2051 tot, tot / 2.4e9);
2052 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2053 s->tb_count,
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",
2061 s->tb_count ?
2062 (double)s->del_op_count / s->tb_count : 0);
2063 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2064 s->tb_count ?
2065 (double)s->temp_count / s->tb_count : 0,
2066 s->temp_count_max);
2067
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);
2074 if (tot == 0)
2075 tot = 1;
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",
2083 s->restore_count);
2084 cpu_fprintf(f, " avg cycles %0.1f\n",
2085 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2086 {
2087 extern void dump_op_count(void);
2088 dump_op_count();
2089 }
2090}
2091#else
24bf7b3a 2092void tcg_dump_info(FILE *f,
a23a9ec6
FB
2093 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2094{
24bf7b3a 2095 cpu_fprintf(f, "[TCG profiler not compiled]\n");
a23a9ec6
FB
2096}
2097#endif