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