]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/tcg.c
tcg-hppa: Fix const errors in hppa-dis.c
[mirror_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
a6c6f76c 30#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
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
be210acb 673
8fcd3692 674static void tcg_reg_alloc_start(TCGContext *s)
c896fe29
FB
675{
676 int i;
677 TCGTemp *ts;
678 for(i = 0; i < s->nb_globals; i++) {
679 ts = &s->temps[i];
680 if (ts->fixed_reg) {
681 ts->val_type = TEMP_VAL_REG;
682 } else {
683 ts->val_type = TEMP_VAL_MEM;
684 }
685 }
e8996ee0
FB
686 for(i = s->nb_globals; i < s->nb_temps; i++) {
687 ts = &s->temps[i];
688 ts->val_type = TEMP_VAL_DEAD;
689 ts->mem_allocated = 0;
690 ts->fixed_reg = 0;
691 }
c896fe29
FB
692 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
693 s->reg_to_temp[i] = -1;
694 }
695}
696
ac56dd48
PB
697static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
698 int idx)
c896fe29
FB
699{
700 TCGTemp *ts;
ac56dd48
PB
701
702 ts = &s->temps[idx];
703 if (idx < s->nb_globals) {
704 pstrcpy(buf, buf_size, ts->name);
c896fe29 705 } else {
641d5fbe
FB
706 if (ts->temp_local)
707 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
708 else
709 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
c896fe29
FB
710 }
711 return buf;
712}
713
a7812ae4
PB
714char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
715{
716 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
717}
718
719char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
ac56dd48 720{
a810a2de 721 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
ac56dd48
PB
722}
723
e8996ee0 724static int helper_cmp(const void *p1, const void *p2)
4dc81f28 725{
e8996ee0
FB
726 const TCGHelperInfo *th1 = p1;
727 const TCGHelperInfo *th2 = p2;
728 if (th1->func < th2->func)
729 return -1;
730 else if (th1->func == th2->func)
731 return 0;
732 else
733 return 1;
4dc81f28
FB
734}
735
e8996ee0
FB
736/* find helper definition (Note: A hash table would be better) */
737static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
4dc81f28 738{
e8996ee0 739 int m, m_min, m_max;
4dc81f28 740 TCGHelperInfo *th;
e8996ee0 741 tcg_target_ulong v;
4dc81f28 742
e8996ee0
FB
743 if (unlikely(!s->helpers_sorted)) {
744 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
745 helper_cmp);
746 s->helpers_sorted = 1;
747 }
748
749 /* binary search */
750 m_min = 0;
751 m_max = s->nb_helpers - 1;
752 while (m_min <= m_max) {
753 m = (m_min + m_max) >> 1;
754 th = &s->helpers[m];
755 v = th->func;
756 if (v == val)
757 return th;
758 else if (val < v) {
759 m_max = m - 1;
760 } else {
761 m_min = m + 1;
4dc81f28
FB
762 }
763 }
e8996ee0 764 return NULL;
4dc81f28
FB
765}
766
f48f3ede
BS
767static const char * const cond_name[] =
768{
769 [TCG_COND_EQ] = "eq",
770 [TCG_COND_NE] = "ne",
771 [TCG_COND_LT] = "lt",
772 [TCG_COND_GE] = "ge",
773 [TCG_COND_LE] = "le",
774 [TCG_COND_GT] = "gt",
775 [TCG_COND_LTU] = "ltu",
776 [TCG_COND_GEU] = "geu",
777 [TCG_COND_LEU] = "leu",
778 [TCG_COND_GTU] = "gtu"
779};
780
c896fe29
FB
781void tcg_dump_ops(TCGContext *s, FILE *outfile)
782{
783 const uint16_t *opc_ptr;
784 const TCGArg *args;
785 TCGArg arg;
7e4597d7 786 int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
c896fe29
FB
787 const TCGOpDef *def;
788 char buf[128];
789
7e4597d7 790 first_insn = 1;
c896fe29
FB
791 opc_ptr = gen_opc_buf;
792 args = gen_opparam_buf;
793 while (opc_ptr < gen_opc_ptr) {
794 c = *opc_ptr++;
795 def = &tcg_op_defs[c];
7e4597d7
FB
796 if (c == INDEX_op_debug_insn_start) {
797 uint64_t pc;
798#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
799 pc = ((uint64_t)args[1] << 32) | args[0];
800#else
801 pc = args[0];
802#endif
803 if (!first_insn)
804 fprintf(outfile, "\n");
805 fprintf(outfile, " ---- 0x%" PRIx64, pc);
806 first_insn = 0;
807 nb_oargs = def->nb_oargs;
808 nb_iargs = def->nb_iargs;
809 nb_cargs = def->nb_cargs;
810 } else if (c == INDEX_op_call) {
c896fe29 811 TCGArg arg;
4dc81f28 812
c896fe29
FB
813 /* variable number of arguments */
814 arg = *args++;
815 nb_oargs = arg >> 16;
816 nb_iargs = arg & 0xffff;
817 nb_cargs = def->nb_cargs;
c896fe29 818
7e4597d7
FB
819 fprintf(outfile, " %s ", def->name);
820
b03cce8e 821 /* function name */
ac56dd48 822 fprintf(outfile, "%s",
e8996ee0 823 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
b03cce8e
FB
824 /* flags */
825 fprintf(outfile, ",$0x%" TCG_PRIlx,
826 args[nb_oargs + nb_iargs]);
827 /* nb out args */
828 fprintf(outfile, ",$%d", nb_oargs);
829 for(i = 0; i < nb_oargs; i++) {
830 fprintf(outfile, ",");
831 fprintf(outfile, "%s",
832 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
833 }
834 for(i = 0; i < (nb_iargs - 1); i++) {
c896fe29 835 fprintf(outfile, ",");
39cf05d3
FB
836 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
837 fprintf(outfile, "<dummy>");
838 } else {
839 fprintf(outfile, "%s",
840 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
841 }
b03cce8e 842 }
e8996ee0
FB
843 } else if (c == INDEX_op_movi_i32
844#if TCG_TARGET_REG_BITS == 64
845 || c == INDEX_op_movi_i64
846#endif
847 ) {
848 tcg_target_ulong val;
849 TCGHelperInfo *th;
850
851 nb_oargs = def->nb_oargs;
852 nb_iargs = def->nb_iargs;
853 nb_cargs = def->nb_cargs;
854 fprintf(outfile, " %s %s,$", def->name,
855 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
856 val = args[1];
857 th = tcg_find_helper(s, val);
858 if (th) {
3e9a474e 859 fprintf(outfile, "%s", th->name);
e8996ee0
FB
860 } else {
861 if (c == INDEX_op_movi_i32)
862 fprintf(outfile, "0x%x", (uint32_t)val);
863 else
864 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
865 }
b03cce8e 866 } else {
7e4597d7 867 fprintf(outfile, " %s ", def->name);
b03cce8e
FB
868 if (c == INDEX_op_nopn) {
869 /* variable number of arguments */
870 nb_cargs = *args;
871 nb_oargs = 0;
872 nb_iargs = 0;
873 } else {
874 nb_oargs = def->nb_oargs;
875 nb_iargs = def->nb_iargs;
876 nb_cargs = def->nb_cargs;
877 }
878
879 k = 0;
880 for(i = 0; i < nb_oargs; i++) {
881 if (k != 0)
882 fprintf(outfile, ",");
883 fprintf(outfile, "%s",
884 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
885 }
886 for(i = 0; i < nb_iargs; i++) {
887 if (k != 0)
888 fprintf(outfile, ",");
889 fprintf(outfile, "%s",
890 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
891 }
be210acb
RH
892 switch (c) {
893 case INDEX_op_brcond_i32:
894#if TCG_TARGET_REG_BITS == 32
895 case INDEX_op_brcond2_i32:
896#elif TCG_TARGET_REG_BITS == 64
897 case INDEX_op_brcond_i64:
898#endif
899 case INDEX_op_setcond_i32:
f48f3ede 900#if TCG_TARGET_REG_BITS == 32
be210acb 901 case INDEX_op_setcond2_i32:
f48f3ede 902#elif TCG_TARGET_REG_BITS == 64
be210acb 903 case INDEX_op_setcond_i64:
f48f3ede 904#endif
f48f3ede
BS
905 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
906 fprintf(outfile, ",%s", cond_name[args[k++]]);
907 else
908 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
909 i = 1;
be210acb
RH
910 break;
911 default:
f48f3ede 912 i = 0;
be210acb
RH
913 break;
914 }
f48f3ede 915 for(; i < nb_cargs; i++) {
b03cce8e
FB
916 if (k != 0)
917 fprintf(outfile, ",");
918 arg = args[k++];
919 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
920 }
c896fe29
FB
921 }
922 fprintf(outfile, "\n");
923 args += nb_iargs + nb_oargs + nb_cargs;
924 }
925}
926
927/* we give more priority to constraints with less registers */
928static int get_constraint_priority(const TCGOpDef *def, int k)
929{
930 const TCGArgConstraint *arg_ct;
931
932 int i, n;
933 arg_ct = &def->args_ct[k];
934 if (arg_ct->ct & TCG_CT_ALIAS) {
935 /* an alias is equivalent to a single register */
936 n = 1;
937 } else {
938 if (!(arg_ct->ct & TCG_CT_REG))
939 return 0;
940 n = 0;
941 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
942 if (tcg_regset_test_reg(arg_ct->u.regs, i))
943 n++;
944 }
945 }
946 return TCG_TARGET_NB_REGS - n + 1;
947}
948
949/* sort from highest priority to lowest */
950static void sort_constraints(TCGOpDef *def, int start, int n)
951{
952 int i, j, p1, p2, tmp;
953
954 for(i = 0; i < n; i++)
955 def->sorted_args[start + i] = start + i;
956 if (n <= 1)
957 return;
958 for(i = 0; i < n - 1; i++) {
959 for(j = i + 1; j < n; j++) {
960 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
961 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
962 if (p1 < p2) {
963 tmp = def->sorted_args[start + i];
964 def->sorted_args[start + i] = def->sorted_args[start + j];
965 def->sorted_args[start + j] = tmp;
966 }
967 }
968 }
969}
970
971void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
972{
973 int op;
974 TCGOpDef *def;
975 const char *ct_str;
976 int i, nb_args;
977
978 for(;;) {
979 if (tdefs->op < 0)
980 break;
981 op = tdefs->op;
982 assert(op >= 0 && op < NB_OPS);
983 def = &tcg_op_defs[op];
c68aaa18
SW
984#if defined(CONFIG_DEBUG_TCG)
985 /* Duplicate entry in op definitions? */
986 assert(!def->used);
987 def->used = 1;
988#endif
c896fe29
FB
989 nb_args = def->nb_iargs + def->nb_oargs;
990 for(i = 0; i < nb_args; i++) {
991 ct_str = tdefs->args_ct_str[i];
c68aaa18
SW
992 /* Incomplete TCGTargetOpDef entry? */
993 assert(ct_str != NULL);
c896fe29
FB
994 tcg_regset_clear(def->args_ct[i].u.regs);
995 def->args_ct[i].ct = 0;
996 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
997 int oarg;
998 oarg = ct_str[0] - '0';
999 assert(oarg < def->nb_oargs);
1000 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1001 /* TCG_CT_ALIAS is for the output arguments. The input
5ff9d6a4 1002 argument is tagged with TCG_CT_IALIAS. */
c896fe29 1003 def->args_ct[i] = def->args_ct[oarg];
5ff9d6a4
FB
1004 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1005 def->args_ct[oarg].alias_index = i;
c896fe29 1006 def->args_ct[i].ct |= TCG_CT_IALIAS;
5ff9d6a4 1007 def->args_ct[i].alias_index = oarg;
c896fe29
FB
1008 } else {
1009 for(;;) {
1010 if (*ct_str == '\0')
1011 break;
1012 switch(*ct_str) {
1013 case 'i':
1014 def->args_ct[i].ct |= TCG_CT_CONST;
1015 ct_str++;
1016 break;
1017 default:
1018 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1019 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1020 ct_str, i, def->name);
1021 exit(1);
1022 }
1023 }
1024 }
1025 }
1026 }
1027
c68aaa18
SW
1028 /* TCGTargetOpDef entry with too much information? */
1029 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1030
c896fe29
FB
1031 /* sort the constraints (XXX: this is just an heuristic) */
1032 sort_constraints(def, 0, def->nb_oargs);
1033 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1034
1035#if 0
1036 {
1037 int i;
1038
1039 printf("%s: sorted=", def->name);
1040 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1041 printf(" %d", def->sorted_args[i]);
1042 printf("\n");
1043 }
1044#endif
1045 tdefs++;
1046 }
1047
c68aaa18
SW
1048#if defined(CONFIG_DEBUG_TCG)
1049 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1050 if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
1051 /* Wrong entry in op definitions? */
1052 assert(!tcg_op_defs[op].used);
1053 } else {
1054 /* Missing entry in op definitions? */
1055 assert(tcg_op_defs[op].used);
1056 }
1057 }
1058#endif
c896fe29
FB
1059}
1060
1061#ifdef USE_LIVENESS_ANALYSIS
1062
1063/* set a nop for an operation using 'nb_args' */
1064static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1065 TCGArg *args, int nb_args)
1066{
1067 if (nb_args == 0) {
1068 *opc_ptr = INDEX_op_nop;
1069 } else {
1070 *opc_ptr = INDEX_op_nopn;
1071 args[0] = nb_args;
1072 args[nb_args - 1] = nb_args;
1073 }
1074}
1075
641d5fbe
FB
1076/* liveness analysis: end of function: globals are live, temps are
1077 dead. */
1078/* XXX: at this stage, not used as there would be little gains because
1079 most TBs end with a conditional jump. */
1080static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
c896fe29
FB
1081{
1082 memset(dead_temps, 0, s->nb_globals);
1083 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1084}
1085
641d5fbe
FB
1086/* liveness analysis: end of basic block: globals are live, temps are
1087 dead, local temps are live. */
1088static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1089{
1090 int i;
1091 TCGTemp *ts;
1092
1093 memset(dead_temps, 0, s->nb_globals);
1094 ts = &s->temps[s->nb_globals];
1095 for(i = s->nb_globals; i < s->nb_temps; i++) {
1096 if (ts->temp_local)
1097 dead_temps[i] = 0;
1098 else
1099 dead_temps[i] = 1;
1100 ts++;
1101 }
1102}
1103
c896fe29
FB
1104/* Liveness analysis : update the opc_dead_iargs array to tell if a
1105 given input arguments is dead. Instructions updating dead
1106 temporaries are removed. */
8fcd3692 1107static void tcg_liveness_analysis(TCGContext *s)
c896fe29
FB
1108{
1109 int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1110 TCGArg *args;
1111 const TCGOpDef *def;
1112 uint8_t *dead_temps;
1113 unsigned int dead_iargs;
1114
1115 gen_opc_ptr++; /* skip end */
1116
1117 nb_ops = gen_opc_ptr - gen_opc_buf;
1118
94f4af02 1119 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
c896fe29
FB
1120
1121 dead_temps = tcg_malloc(s->nb_temps);
1122 memset(dead_temps, 1, s->nb_temps);
1123
1124 args = gen_opparam_ptr;
1125 op_index = nb_ops - 1;
1126 while (op_index >= 0) {
1127 op = gen_opc_buf[op_index];
1128 def = &tcg_op_defs[op];
1129 switch(op) {
1130 case INDEX_op_call:
c6e113f5
FB
1131 {
1132 int call_flags;
c896fe29 1133
c6e113f5
FB
1134 nb_args = args[-1];
1135 args -= nb_args;
1136 nb_iargs = args[0] & 0xffff;
1137 nb_oargs = args[0] >> 16;
1138 args++;
1139 call_flags = args[nb_oargs + nb_iargs];
1140
1141 /* pure functions can be removed if their result is not
1142 used */
1143 if (call_flags & TCG_CALL_PURE) {
1144 for(i = 0; i < nb_oargs; i++) {
1145 arg = args[i];
1146 if (!dead_temps[arg])
1147 goto do_not_remove_call;
1148 }
1149 tcg_set_nop(s, gen_opc_buf + op_index,
1150 args - 1, nb_args);
1151 } else {
1152 do_not_remove_call:
c896fe29 1153
c6e113f5
FB
1154 /* output args are dead */
1155 for(i = 0; i < nb_oargs; i++) {
1156 arg = args[i];
1157 dead_temps[arg] = 1;
1158 }
1159
b9c18f56
AJ
1160 if (!(call_flags & TCG_CALL_CONST)) {
1161 /* globals are live (they may be used by the call) */
1162 memset(dead_temps, 0, s->nb_globals);
1163 }
1164
c6e113f5
FB
1165 /* input args are live */
1166 dead_iargs = 0;
1167 for(i = 0; i < nb_iargs; i++) {
1168 arg = args[i + nb_oargs];
39cf05d3
FB
1169 if (arg != TCG_CALL_DUMMY_ARG) {
1170 if (dead_temps[arg]) {
1171 dead_iargs |= (1 << i);
1172 }
1173 dead_temps[arg] = 0;
c6e113f5 1174 }
c6e113f5
FB
1175 }
1176 s->op_dead_iargs[op_index] = dead_iargs;
c896fe29 1177 }
c6e113f5 1178 args--;
c896fe29 1179 }
c896fe29
FB
1180 break;
1181 case INDEX_op_set_label:
1182 args--;
1183 /* mark end of basic block */
1184 tcg_la_bb_end(s, dead_temps);
1185 break;
7e4597d7
FB
1186 case INDEX_op_debug_insn_start:
1187 args -= def->nb_args;
1188 break;
c896fe29
FB
1189 case INDEX_op_nopn:
1190 nb_args = args[-1];
1191 args -= nb_args;
1192 break;
5ff9d6a4
FB
1193 case INDEX_op_discard:
1194 args--;
1195 /* mark the temporary as dead */
1196 dead_temps[args[0]] = 1;
1197 break;
c896fe29
FB
1198 case INDEX_op_end:
1199 break;
1200 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1201 default:
49516bc0
AJ
1202 args -= def->nb_args;
1203 nb_iargs = def->nb_iargs;
1204 nb_oargs = def->nb_oargs;
c896fe29 1205
49516bc0
AJ
1206 /* Test if the operation can be removed because all
1207 its outputs are dead. We assume that nb_oargs == 0
1208 implies side effects */
1209 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1210 for(i = 0; i < nb_oargs; i++) {
1211 arg = args[i];
1212 if (!dead_temps[arg])
1213 goto do_not_remove;
1214 }
1215 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
c896fe29 1216#ifdef CONFIG_PROFILER
49516bc0 1217 s->del_op_count++;
c896fe29 1218#endif
49516bc0
AJ
1219 } else {
1220 do_not_remove:
c896fe29 1221
49516bc0
AJ
1222 /* output args are dead */
1223 for(i = 0; i < nb_oargs; i++) {
1224 arg = args[i];
1225 dead_temps[arg] = 1;
1226 }
1227
1228 /* if end of basic block, update */
1229 if (def->flags & TCG_OPF_BB_END) {
1230 tcg_la_bb_end(s, dead_temps);
1231 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1232 /* globals are live */
1233 memset(dead_temps, 0, s->nb_globals);
1234 }
1235
1236 /* input args are live */
1237 dead_iargs = 0;
1238 for(i = 0; i < nb_iargs; i++) {
1239 arg = args[i + nb_oargs];
1240 if (dead_temps[arg]) {
1241 dead_iargs |= (1 << i);
c896fe29 1242 }
49516bc0 1243 dead_temps[arg] = 0;
c896fe29 1244 }
49516bc0 1245 s->op_dead_iargs[op_index] = dead_iargs;
c896fe29
FB
1246 }
1247 break;
1248 }
1249 op_index--;
1250 }
1251
1252 if (args != gen_opparam_buf)
1253 tcg_abort();
1254}
1255#else
1256/* dummy liveness analysis */
1257void tcg_liveness_analysis(TCGContext *s)
1258{
1259 int nb_ops;
1260 nb_ops = gen_opc_ptr - gen_opc_buf;
1261
1262 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1263 memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1264}
1265#endif
1266
1267#ifndef NDEBUG
1268static void dump_regs(TCGContext *s)
1269{
1270 TCGTemp *ts;
1271 int i;
1272 char buf[64];
1273
1274 for(i = 0; i < s->nb_temps; i++) {
1275 ts = &s->temps[i];
ac56dd48 1276 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
c896fe29
FB
1277 switch(ts->val_type) {
1278 case TEMP_VAL_REG:
1279 printf("%s", tcg_target_reg_names[ts->reg]);
1280 break;
1281 case TEMP_VAL_MEM:
1282 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1283 break;
1284 case TEMP_VAL_CONST:
1285 printf("$0x%" TCG_PRIlx, ts->val);
1286 break;
1287 case TEMP_VAL_DEAD:
1288 printf("D");
1289 break;
1290 default:
1291 printf("???");
1292 break;
1293 }
1294 printf("\n");
1295 }
1296
1297 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1298 if (s->reg_to_temp[i] >= 0) {
1299 printf("%s: %s\n",
1300 tcg_target_reg_names[i],
ac56dd48 1301 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
c896fe29
FB
1302 }
1303 }
1304}
1305
1306static void check_regs(TCGContext *s)
1307{
1308 int reg, k;
1309 TCGTemp *ts;
1310 char buf[64];
1311
1312 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1313 k = s->reg_to_temp[reg];
1314 if (k >= 0) {
1315 ts = &s->temps[k];
1316 if (ts->val_type != TEMP_VAL_REG ||
1317 ts->reg != reg) {
1318 printf("Inconsistency for register %s:\n",
1319 tcg_target_reg_names[reg]);
b03cce8e 1320 goto fail;
c896fe29
FB
1321 }
1322 }
1323 }
1324 for(k = 0; k < s->nb_temps; k++) {
1325 ts = &s->temps[k];
1326 if (ts->val_type == TEMP_VAL_REG &&
1327 !ts->fixed_reg &&
1328 s->reg_to_temp[ts->reg] != k) {
1329 printf("Inconsistency for temp %s:\n",
ac56dd48 1330 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
b03cce8e 1331 fail:
c896fe29
FB
1332 printf("reg state:\n");
1333 dump_regs(s);
1334 tcg_abort();
1335 }
1336 }
1337}
1338#endif
1339
1340static void temp_allocate_frame(TCGContext *s, int temp)
1341{
1342 TCGTemp *ts;
1343 ts = &s->temps[temp];
1344 s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1345 if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
5ff9d6a4 1346 tcg_abort();
c896fe29
FB
1347 ts->mem_offset = s->current_frame_offset;
1348 ts->mem_reg = s->frame_reg;
1349 ts->mem_allocated = 1;
1350 s->current_frame_offset += sizeof(tcg_target_long);
1351}
1352
1353/* free register 'reg' by spilling the corresponding temporary if necessary */
1354static void tcg_reg_free(TCGContext *s, int reg)
1355{
1356 TCGTemp *ts;
1357 int temp;
1358
1359 temp = s->reg_to_temp[reg];
1360 if (temp != -1) {
1361 ts = &s->temps[temp];
1362 assert(ts->val_type == TEMP_VAL_REG);
1363 if (!ts->mem_coherent) {
1364 if (!ts->mem_allocated)
1365 temp_allocate_frame(s, temp);
e4d5434c 1366 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1367 }
1368 ts->val_type = TEMP_VAL_MEM;
1369 s->reg_to_temp[reg] = -1;
1370 }
1371}
1372
1373/* Allocate a register belonging to reg1 & ~reg2 */
1374static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1375{
1376 int i, reg;
1377 TCGRegSet reg_ct;
1378
1379 tcg_regset_andnot(reg_ct, reg1, reg2);
1380
1381 /* first try free registers */
0954d0d9 1382 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1383 reg = tcg_target_reg_alloc_order[i];
1384 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1385 return reg;
1386 }
1387
1388 /* XXX: do better spill choice */
0954d0d9 1389 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1390 reg = tcg_target_reg_alloc_order[i];
1391 if (tcg_regset_test_reg(reg_ct, reg)) {
1392 tcg_reg_free(s, reg);
1393 return reg;
1394 }
1395 }
1396
1397 tcg_abort();
1398}
1399
641d5fbe
FB
1400/* save a temporary to memory. 'allocated_regs' is used in case a
1401 temporary registers needs to be allocated to store a constant. */
1402static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1403{
1404 TCGTemp *ts;
1405 int reg;
1406
1407 ts = &s->temps[temp];
1408 if (!ts->fixed_reg) {
1409 switch(ts->val_type) {
1410 case TEMP_VAL_REG:
1411 tcg_reg_free(s, ts->reg);
1412 break;
1413 case TEMP_VAL_DEAD:
1414 ts->val_type = TEMP_VAL_MEM;
1415 break;
1416 case TEMP_VAL_CONST:
d6859202
AJ
1417 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1418 allocated_regs);
641d5fbe
FB
1419 if (!ts->mem_allocated)
1420 temp_allocate_frame(s, temp);
d6859202
AJ
1421 tcg_out_movi(s, ts->type, reg, ts->val);
1422 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
641d5fbe
FB
1423 ts->val_type = TEMP_VAL_MEM;
1424 break;
1425 case TEMP_VAL_MEM:
1426 break;
1427 default:
1428 tcg_abort();
1429 }
1430 }
1431}
1432
e5097dc8 1433/* save globals to their cannonical location and assume they can be
e8996ee0
FB
1434 modified be the following code. 'allocated_regs' is used in case a
1435 temporary registers needs to be allocated to store a constant. */
1436static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
c896fe29 1437{
641d5fbe 1438 int i;
c896fe29
FB
1439
1440 for(i = 0; i < s->nb_globals; i++) {
641d5fbe 1441 temp_save(s, i, allocated_regs);
c896fe29 1442 }
e5097dc8
FB
1443}
1444
1445/* at the end of a basic block, we assume all temporaries are dead and
e8996ee0
FB
1446 all globals are stored at their canonical location. */
1447static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
e5097dc8
FB
1448{
1449 TCGTemp *ts;
1450 int i;
1451
c896fe29
FB
1452 for(i = s->nb_globals; i < s->nb_temps; i++) {
1453 ts = &s->temps[i];
641d5fbe
FB
1454 if (ts->temp_local) {
1455 temp_save(s, i, allocated_regs);
1456 } else {
1457 if (ts->val_type == TEMP_VAL_REG) {
1458 s->reg_to_temp[ts->reg] = -1;
1459 }
1460 ts->val_type = TEMP_VAL_DEAD;
c896fe29
FB
1461 }
1462 }
e8996ee0
FB
1463
1464 save_globals(s, allocated_regs);
c896fe29
FB
1465}
1466
1467#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1468
e8996ee0
FB
1469static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1470{
1471 TCGTemp *ots;
1472 tcg_target_ulong val;
1473
1474 ots = &s->temps[args[0]];
1475 val = args[1];
1476
1477 if (ots->fixed_reg) {
1478 /* for fixed registers, we do not do any constant
1479 propagation */
1480 tcg_out_movi(s, ots->type, ots->reg, val);
1481 } else {
1235fc06 1482 /* The movi is not explicitly generated here */
e8996ee0
FB
1483 if (ots->val_type == TEMP_VAL_REG)
1484 s->reg_to_temp[ots->reg] = -1;
1485 ots->val_type = TEMP_VAL_CONST;
1486 ots->val = val;
1487 }
1488}
1489
c896fe29
FB
1490static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1491 const TCGArg *args,
1492 unsigned int dead_iargs)
1493{
1494 TCGTemp *ts, *ots;
1495 int reg;
1496 const TCGArgConstraint *arg_ct;
1497
1498 ots = &s->temps[args[0]];
1499 ts = &s->temps[args[1]];
1500 arg_ct = &def->args_ct[0];
1501
e8996ee0 1502 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
c896fe29
FB
1503 if (ts->val_type == TEMP_VAL_REG) {
1504 if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1505 /* the mov can be suppressed */
1506 if (ots->val_type == TEMP_VAL_REG)
1507 s->reg_to_temp[ots->reg] = -1;
1508 reg = ts->reg;
1509 s->reg_to_temp[reg] = -1;
1510 ts->val_type = TEMP_VAL_DEAD;
1511 } else {
1512 if (ots->val_type == TEMP_VAL_REG) {
1513 reg = ots->reg;
1514 } else {
1515 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1516 }
1517 if (ts->reg != reg) {
1518 tcg_out_mov(s, reg, ts->reg);
1519 }
1520 }
1521 } else if (ts->val_type == TEMP_VAL_MEM) {
1522 if (ots->val_type == TEMP_VAL_REG) {
1523 reg = ots->reg;
1524 } else {
1525 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1526 }
e4d5434c 1527 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1528 } else if (ts->val_type == TEMP_VAL_CONST) {
e8996ee0 1529 if (ots->fixed_reg) {
c896fe29 1530 reg = ots->reg;
e8996ee0 1531 tcg_out_movi(s, ots->type, reg, ts->val);
c896fe29 1532 } else {
e8996ee0
FB
1533 /* propagate constant */
1534 if (ots->val_type == TEMP_VAL_REG)
1535 s->reg_to_temp[ots->reg] = -1;
1536 ots->val_type = TEMP_VAL_CONST;
1537 ots->val = ts->val;
1538 return;
c896fe29 1539 }
c896fe29
FB
1540 } else {
1541 tcg_abort();
1542 }
1543 s->reg_to_temp[reg] = args[0];
1544 ots->reg = reg;
1545 ots->val_type = TEMP_VAL_REG;
1546 ots->mem_coherent = 0;
1547}
1548
1549static void tcg_reg_alloc_op(TCGContext *s,
1550 const TCGOpDef *def, int opc,
1551 const TCGArg *args,
1552 unsigned int dead_iargs)
1553{
1554 TCGRegSet allocated_regs;
1555 int i, k, nb_iargs, nb_oargs, reg;
1556 TCGArg arg;
1557 const TCGArgConstraint *arg_ct;
1558 TCGTemp *ts;
1559 TCGArg new_args[TCG_MAX_OP_ARGS];
1560 int const_args[TCG_MAX_OP_ARGS];
1561
1562 nb_oargs = def->nb_oargs;
1563 nb_iargs = def->nb_iargs;
1564
1565 /* copy constants */
1566 memcpy(new_args + nb_oargs + nb_iargs,
1567 args + nb_oargs + nb_iargs,
1568 sizeof(TCGArg) * def->nb_cargs);
1569
1570 /* satisfy input constraints */
1571 tcg_regset_set(allocated_regs, s->reserved_regs);
1572 for(k = 0; k < nb_iargs; k++) {
1573 i = def->sorted_args[nb_oargs + k];
1574 arg = args[i];
1575 arg_ct = &def->args_ct[i];
1576 ts = &s->temps[arg];
1577 if (ts->val_type == TEMP_VAL_MEM) {
1578 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1579 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1580 ts->val_type = TEMP_VAL_REG;
1581 ts->reg = reg;
1582 ts->mem_coherent = 1;
1583 s->reg_to_temp[reg] = arg;
1584 } else if (ts->val_type == TEMP_VAL_CONST) {
1585 if (tcg_target_const_match(ts->val, arg_ct)) {
1586 /* constant is OK for instruction */
1587 const_args[i] = 1;
1588 new_args[i] = ts->val;
1589 goto iarg_end;
1590 } else {
e8996ee0 1591 /* need to move to a register */
c896fe29
FB
1592 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1593 tcg_out_movi(s, ts->type, reg, ts->val);
e8996ee0
FB
1594 ts->val_type = TEMP_VAL_REG;
1595 ts->reg = reg;
1596 ts->mem_coherent = 0;
1597 s->reg_to_temp[reg] = arg;
c896fe29
FB
1598 }
1599 }
1600 assert(ts->val_type == TEMP_VAL_REG);
5ff9d6a4
FB
1601 if (arg_ct->ct & TCG_CT_IALIAS) {
1602 if (ts->fixed_reg) {
1603 /* if fixed register, we must allocate a new register
1604 if the alias is not the same register */
1605 if (arg != args[arg_ct->alias_index])
1606 goto allocate_in_reg;
1607 } else {
1608 /* if the input is aliased to an output and if it is
1609 not dead after the instruction, we must allocate
1610 a new register and move it */
1611 if (!IS_DEAD_IARG(i - nb_oargs))
1612 goto allocate_in_reg;
1613 }
c896fe29
FB
1614 }
1615 reg = ts->reg;
1616 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1617 /* nothing to do : the constraint is satisfied */
1618 } else {
1619 allocate_in_reg:
1620 /* allocate a new register matching the constraint
1621 and move the temporary register into it */
1622 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1623 tcg_out_mov(s, reg, ts->reg);
1624 }
c896fe29
FB
1625 new_args[i] = reg;
1626 const_args[i] = 0;
1627 tcg_regset_set_reg(allocated_regs, reg);
1628 iarg_end: ;
1629 }
1630
e8996ee0
FB
1631 if (def->flags & TCG_OPF_BB_END) {
1632 tcg_reg_alloc_bb_end(s, allocated_regs);
1633 } else {
1634 /* mark dead temporaries and free the associated registers */
1635 for(i = 0; i < nb_iargs; i++) {
1636 arg = args[nb_oargs + i];
1637 if (IS_DEAD_IARG(i)) {
1638 ts = &s->temps[arg];
1639 if (!ts->fixed_reg) {
1640 if (ts->val_type == TEMP_VAL_REG)
1641 s->reg_to_temp[ts->reg] = -1;
1642 ts->val_type = TEMP_VAL_DEAD;
1643 }
c896fe29
FB
1644 }
1645 }
e8996ee0
FB
1646
1647 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1648 /* XXX: permit generic clobber register list ? */
1649 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1650 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1651 tcg_reg_free(s, reg);
1652 }
c896fe29 1653 }
e8996ee0
FB
1654 /* XXX: for load/store we could do that only for the slow path
1655 (i.e. when a memory callback is called) */
1656
1657 /* store globals and free associated registers (we assume the insn
1658 can modify any global. */
1659 save_globals(s, allocated_regs);
c896fe29 1660 }
e8996ee0
FB
1661
1662 /* satisfy the output constraints */
1663 tcg_regset_set(allocated_regs, s->reserved_regs);
1664 for(k = 0; k < nb_oargs; k++) {
1665 i = def->sorted_args[k];
1666 arg = args[i];
1667 arg_ct = &def->args_ct[i];
1668 ts = &s->temps[arg];
1669 if (arg_ct->ct & TCG_CT_ALIAS) {
1670 reg = new_args[arg_ct->alias_index];
1671 } else {
1672 /* if fixed register, we try to use it */
1673 reg = ts->reg;
1674 if (ts->fixed_reg &&
1675 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1676 goto oarg_end;
1677 }
1678 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
c896fe29 1679 }
e8996ee0
FB
1680 tcg_regset_set_reg(allocated_regs, reg);
1681 /* if a fixed register is used, then a move will be done afterwards */
1682 if (!ts->fixed_reg) {
1683 if (ts->val_type == TEMP_VAL_REG)
1684 s->reg_to_temp[ts->reg] = -1;
1685 ts->val_type = TEMP_VAL_REG;
1686 ts->reg = reg;
1687 /* temp value is modified, so the value kept in memory is
1688 potentially not the same */
1689 ts->mem_coherent = 0;
1690 s->reg_to_temp[reg] = arg;
1691 }
1692 oarg_end:
1693 new_args[i] = reg;
c896fe29 1694 }
c896fe29
FB
1695 }
1696
c896fe29
FB
1697 /* emit instruction */
1698 tcg_out_op(s, opc, new_args, const_args);
1699
1700 /* move the outputs in the correct register if needed */
1701 for(i = 0; i < nb_oargs; i++) {
1702 ts = &s->temps[args[i]];
1703 reg = new_args[i];
1704 if (ts->fixed_reg && ts->reg != reg) {
1705 tcg_out_mov(s, ts->reg, reg);
1706 }
1707 }
1708}
1709
b03cce8e
FB
1710#ifdef TCG_TARGET_STACK_GROWSUP
1711#define STACK_DIR(x) (-(x))
1712#else
1713#define STACK_DIR(x) (x)
1714#endif
1715
c896fe29
FB
1716static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1717 int opc, const TCGArg *args,
1718 unsigned int dead_iargs)
1719{
1720 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1721 TCGArg arg, func_arg;
1722 TCGTemp *ts;
f54b3f92 1723 tcg_target_long stack_offset, call_stack_size, func_addr;
b03cce8e 1724 int const_func_arg, allocate_args;
c896fe29
FB
1725 TCGRegSet allocated_regs;
1726 const TCGArgConstraint *arg_ct;
1727
1728 arg = *args++;
1729
1730 nb_oargs = arg >> 16;
1731 nb_iargs = arg & 0xffff;
1732 nb_params = nb_iargs - 1;
1733
1734 flags = args[nb_oargs + nb_iargs];
1735
1736 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1737 if (nb_regs > nb_params)
1738 nb_regs = nb_params;
1739
1740 /* assign stack slots first */
1741 /* XXX: preallocate call stack */
1742 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1743 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1744 ~(TCG_TARGET_STACK_ALIGN - 1);
b03cce8e
FB
1745 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1746 if (allocate_args) {
1747 tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1748 }
39cf05d3
FB
1749
1750 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
c896fe29
FB
1751 for(i = nb_regs; i < nb_params; i++) {
1752 arg = args[nb_oargs + i];
39cf05d3
FB
1753#ifdef TCG_TARGET_STACK_GROWSUP
1754 stack_offset -= sizeof(tcg_target_long);
1755#endif
1756 if (arg != TCG_CALL_DUMMY_ARG) {
1757 ts = &s->temps[arg];
1758 if (ts->val_type == TEMP_VAL_REG) {
1759 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1760 } else if (ts->val_type == TEMP_VAL_MEM) {
1761 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1762 s->reserved_regs);
1763 /* XXX: not correct if reading values from the stack */
1764 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1765 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1766 } else if (ts->val_type == TEMP_VAL_CONST) {
1767 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1768 s->reserved_regs);
1769 /* XXX: sign extend may be needed on some targets */
1770 tcg_out_movi(s, ts->type, reg, ts->val);
1771 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1772 } else {
1773 tcg_abort();
1774 }
c896fe29 1775 }
39cf05d3
FB
1776#ifndef TCG_TARGET_STACK_GROWSUP
1777 stack_offset += sizeof(tcg_target_long);
1778#endif
c896fe29
FB
1779 }
1780
1781 /* assign input registers */
1782 tcg_regset_set(allocated_regs, s->reserved_regs);
1783 for(i = 0; i < nb_regs; i++) {
1784 arg = args[nb_oargs + i];
39cf05d3
FB
1785 if (arg != TCG_CALL_DUMMY_ARG) {
1786 ts = &s->temps[arg];
1787 reg = tcg_target_call_iarg_regs[i];
1788 tcg_reg_free(s, reg);
1789 if (ts->val_type == TEMP_VAL_REG) {
1790 if (ts->reg != reg) {
1791 tcg_out_mov(s, reg, ts->reg);
1792 }
1793 } else if (ts->val_type == TEMP_VAL_MEM) {
1794 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1795 } else if (ts->val_type == TEMP_VAL_CONST) {
1796 /* XXX: sign extend ? */
1797 tcg_out_movi(s, ts->type, reg, ts->val);
1798 } else {
1799 tcg_abort();
c896fe29 1800 }
39cf05d3 1801 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1802 }
c896fe29
FB
1803 }
1804
1805 /* assign function address */
1806 func_arg = args[nb_oargs + nb_iargs - 1];
1807 arg_ct = &def->args_ct[0];
1808 ts = &s->temps[func_arg];
f54b3f92 1809 func_addr = ts->val;
c896fe29
FB
1810 const_func_arg = 0;
1811 if (ts->val_type == TEMP_VAL_MEM) {
1812 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1813 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1814 func_arg = reg;
e8996ee0 1815 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1816 } else if (ts->val_type == TEMP_VAL_REG) {
1817 reg = ts->reg;
1818 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1819 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1820 tcg_out_mov(s, reg, ts->reg);
1821 }
1822 func_arg = reg;
e8996ee0 1823 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1824 } else if (ts->val_type == TEMP_VAL_CONST) {
f54b3f92 1825 if (tcg_target_const_match(func_addr, arg_ct)) {
c896fe29 1826 const_func_arg = 1;
f54b3f92 1827 func_arg = func_addr;
c896fe29
FB
1828 } else {
1829 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
f54b3f92 1830 tcg_out_movi(s, ts->type, reg, func_addr);
c896fe29 1831 func_arg = reg;
e8996ee0 1832 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1833 }
1834 } else {
1835 tcg_abort();
1836 }
e8996ee0 1837
c896fe29
FB
1838
1839 /* mark dead temporaries and free the associated registers */
c6e113f5 1840 for(i = 0; i < nb_iargs; i++) {
c896fe29
FB
1841 arg = args[nb_oargs + i];
1842 if (IS_DEAD_IARG(i)) {
1843 ts = &s->temps[arg];
e8996ee0 1844 if (!ts->fixed_reg) {
c896fe29
FB
1845 if (ts->val_type == TEMP_VAL_REG)
1846 s->reg_to_temp[ts->reg] = -1;
1847 ts->val_type = TEMP_VAL_DEAD;
1848 }
1849 }
1850 }
1851
1852 /* clobber call registers */
1853 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1854 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1855 tcg_reg_free(s, reg);
1856 }
1857 }
1858
1859 /* store globals and free associated registers (we assume the call
1860 can modify any global. */
b9c18f56
AJ
1861 if (!(flags & TCG_CALL_CONST)) {
1862 save_globals(s, allocated_regs);
1863 }
c896fe29
FB
1864
1865 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1866
b03cce8e
FB
1867 if (allocate_args) {
1868 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1869 }
c896fe29
FB
1870
1871 /* assign output registers and emit moves if needed */
1872 for(i = 0; i < nb_oargs; i++) {
1873 arg = args[i];
1874 ts = &s->temps[arg];
1875 reg = tcg_target_call_oarg_regs[i];
e8996ee0 1876 assert(s->reg_to_temp[reg] == -1);
c896fe29
FB
1877 if (ts->fixed_reg) {
1878 if (ts->reg != reg) {
1879 tcg_out_mov(s, ts->reg, reg);
1880 }
1881 } else {
1882 if (ts->val_type == TEMP_VAL_REG)
1883 s->reg_to_temp[ts->reg] = -1;
1884 ts->val_type = TEMP_VAL_REG;
1885 ts->reg = reg;
1886 ts->mem_coherent = 0;
1887 s->reg_to_temp[reg] = arg;
1888 }
1889 }
1890
1891 return nb_iargs + nb_oargs + def->nb_cargs + 1;
1892}
1893
1894#ifdef CONFIG_PROFILER
1895
54604f74 1896static int64_t tcg_table_op_count[NB_OPS];
c896fe29 1897
871e6c35 1898static void dump_op_count(void)
c896fe29
FB
1899{
1900 int i;
1901 FILE *f;
54604f74 1902 f = fopen("/tmp/op.log", "w");
c896fe29 1903 for(i = INDEX_op_end; i < NB_OPS; i++) {
54604f74 1904 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
c896fe29
FB
1905 }
1906 fclose(f);
1907}
1908#endif
1909
1910
1911static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2ba1eeb6 1912 long search_pc)
c896fe29 1913{
b314f270 1914 int opc, op_index;
c896fe29
FB
1915 const TCGOpDef *def;
1916 unsigned int dead_iargs;
1917 const TCGArg *args;
1918
1919#ifdef DEBUG_DISAS
8fec2b8c 1920 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
93fcfe39 1921 qemu_log("OP:\n");
c896fe29 1922 tcg_dump_ops(s, logfile);
93fcfe39 1923 qemu_log("\n");
c896fe29
FB
1924 }
1925#endif
1926
a23a9ec6
FB
1927#ifdef CONFIG_PROFILER
1928 s->la_time -= profile_getclock();
1929#endif
c896fe29 1930 tcg_liveness_analysis(s);
a23a9ec6
FB
1931#ifdef CONFIG_PROFILER
1932 s->la_time += profile_getclock();
1933#endif
c896fe29
FB
1934
1935#ifdef DEBUG_DISAS
8fec2b8c 1936 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
6a957025 1937 qemu_log("OP after liveness analysis:\n");
c896fe29 1938 tcg_dump_ops(s, logfile);
93fcfe39 1939 qemu_log("\n");
c896fe29
FB
1940 }
1941#endif
1942
1943 tcg_reg_alloc_start(s);
1944
1945 s->code_buf = gen_code_buf;
1946 s->code_ptr = gen_code_buf;
1947
c896fe29
FB
1948 args = gen_opparam_buf;
1949 op_index = 0;
b3db8758 1950
c896fe29
FB
1951 for(;;) {
1952 opc = gen_opc_buf[op_index];
1953#ifdef CONFIG_PROFILER
54604f74 1954 tcg_table_op_count[opc]++;
c896fe29
FB
1955#endif
1956 def = &tcg_op_defs[opc];
1957#if 0
1958 printf("%s: %d %d %d\n", def->name,
1959 def->nb_oargs, def->nb_iargs, def->nb_cargs);
1960 // dump_regs(s);
1961#endif
1962 switch(opc) {
1963 case INDEX_op_mov_i32:
1964#if TCG_TARGET_REG_BITS == 64
1965 case INDEX_op_mov_i64:
1966#endif
1967 dead_iargs = s->op_dead_iargs[op_index];
1968 tcg_reg_alloc_mov(s, def, args, dead_iargs);
1969 break;
e8996ee0
FB
1970 case INDEX_op_movi_i32:
1971#if TCG_TARGET_REG_BITS == 64
1972 case INDEX_op_movi_i64:
1973#endif
1974 tcg_reg_alloc_movi(s, args);
1975 break;
7e4597d7
FB
1976 case INDEX_op_debug_insn_start:
1977 /* debug instruction */
1978 break;
c896fe29
FB
1979 case INDEX_op_nop:
1980 case INDEX_op_nop1:
1981 case INDEX_op_nop2:
1982 case INDEX_op_nop3:
1983 break;
1984 case INDEX_op_nopn:
1985 args += args[0];
1986 goto next;
5ff9d6a4
FB
1987 case INDEX_op_discard:
1988 {
1989 TCGTemp *ts;
1990 ts = &s->temps[args[0]];
1991 /* mark the temporary as dead */
e8996ee0 1992 if (!ts->fixed_reg) {
5ff9d6a4
FB
1993 if (ts->val_type == TEMP_VAL_REG)
1994 s->reg_to_temp[ts->reg] = -1;
1995 ts->val_type = TEMP_VAL_DEAD;
1996 }
1997 }
1998 break;
c896fe29 1999 case INDEX_op_set_label:
e8996ee0 2000 tcg_reg_alloc_bb_end(s, s->reserved_regs);
c896fe29
FB
2001 tcg_out_label(s, args[0], (long)s->code_ptr);
2002 break;
2003 case INDEX_op_call:
2004 dead_iargs = s->op_dead_iargs[op_index];
2005 args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2006 goto next;
2007 case INDEX_op_end:
2008 goto the_end;
c896fe29
FB
2009 default:
2010 /* Note: in order to speed up the code, it would be much
2011 faster to have specialized register allocator functions for
2012 some common argument patterns */
2013 dead_iargs = s->op_dead_iargs[op_index];
2014 tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2015 break;
2016 }
2017 args += def->nb_args;
8df1ca4b 2018 next:
2ba1eeb6 2019 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
b314f270 2020 return op_index;
c896fe29
FB
2021 }
2022 op_index++;
2023#ifndef NDEBUG
2024 check_regs(s);
2025#endif
2026 }
2027 the_end:
2028 return -1;
2029}
2030
54604f74 2031int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
c896fe29
FB
2032{
2033#ifdef CONFIG_PROFILER
2034 {
c896fe29
FB
2035 int n;
2036 n = (gen_opc_ptr - gen_opc_buf);
a23a9ec6
FB
2037 s->op_count += n;
2038 if (n > s->op_count_max)
2039 s->op_count_max = n;
2040
2041 s->temp_count += s->nb_temps;
2042 if (s->nb_temps > s->temp_count_max)
2043 s->temp_count_max = s->nb_temps;
c896fe29
FB
2044 }
2045#endif
2046
2ba1eeb6 2047 tcg_gen_code_common(s, gen_code_buf, -1);
c896fe29
FB
2048
2049 /* flush instruction cache */
2050 flush_icache_range((unsigned long)gen_code_buf,
2051 (unsigned long)s->code_ptr);
2052 return s->code_ptr - gen_code_buf;
2053}
2054
2ba1eeb6 2055/* Return the index of the micro operation such as the pc after is <
623e265c
PB
2056 offset bytes from the start of the TB. The contents of gen_code_buf must
2057 not be changed, though writing the same values is ok.
2058 Return -1 if not found. */
54604f74 2059int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
c896fe29 2060{
623e265c 2061 return tcg_gen_code_common(s, gen_code_buf, offset);
c896fe29 2062}
a23a9ec6
FB
2063
2064#ifdef CONFIG_PROFILER
2065void tcg_dump_info(FILE *f,
2066 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2067{
2068 TCGContext *s = &tcg_ctx;
2069 int64_t tot;
2070
2071 tot = s->interm_time + s->code_time;
2072 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2073 tot, tot / 2.4e9);
2074 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2075 s->tb_count,
2076 s->tb_count1 - s->tb_count,
2077 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2078 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2079 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
a23a9ec6
FB
2080 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2081 s->tb_count ?
2082 (double)s->del_op_count / s->tb_count : 0);
2083 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2084 s->tb_count ?
2085 (double)s->temp_count / s->tb_count : 0,
2086 s->temp_count_max);
2087
2088 cpu_fprintf(f, "cycles/op %0.1f\n",
2089 s->op_count ? (double)tot / s->op_count : 0);
2090 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2091 s->code_in_len ? (double)tot / s->code_in_len : 0);
2092 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2093 s->code_out_len ? (double)tot / s->code_out_len : 0);
2094 if (tot == 0)
2095 tot = 1;
2096 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2097 (double)s->interm_time / tot * 100.0);
2098 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2099 (double)s->code_time / tot * 100.0);
2100 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2101 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2102 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2103 s->restore_count);
2104 cpu_fprintf(f, " avg cycles %0.1f\n",
2105 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
871e6c35
BS
2106
2107 dump_op_count();
a23a9ec6
FB
2108}
2109#else
24bf7b3a 2110void tcg_dump_info(FILE *f,
a23a9ec6
FB
2111 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2112{
24bf7b3a 2113 cpu_fprintf(f, "[TCG profiler not compiled]\n");
a23a9ec6
FB
2114}
2115#endif