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