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