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