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