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