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