18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Tiny Code Generator for QEMU
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2008 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* define it to use liveness analysis (better code) */
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define USE_LIVENESS_ANALYSIS
2786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define USE_TCG_OPTIMIZATIONS
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "config.h"
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Define to jump the ELF file used to communicate with GDB.  */
3286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#undef DEBUG_JIT
3386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
346a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* define it to suppress various consistency checks (faster) */
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define NDEBUG
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h"
4037dc41a01f33a1e6aca0458b205c2b1609fe82c3David 'Digit' Turner#include "qemu/cache-utils.h"
41e90d665cd63a0bc5c3306e1ee3e98ad362546b16David 'Digit' Turner#include "qemu/host-utils.h"
427a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Note: the long term plan is to reduce the dependancies on the QEMU
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   CPU definitions. Currently they are used for qemu_ld/st
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instructions */
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NO_CPU_IO_DEFS
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h"
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg-op.h"
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if UINTPTR_MAX == UINT32_MAX
5386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define ELF_CLASS  ELFCLASS32
5486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
5586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define ELF_CLASS  ELFCLASS64
56b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner#endif
5786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef HOST_WORDS_BIGENDIAN
5886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define ELF_DATA   ELFDATA2MSB
5986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
6086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define ELF_DATA   ELFDATA2LSB
6186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
6286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
6386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include "elf.h"
64b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner
6586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Forward declarations for functions declared in tcg-target.c and used here. */
66f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_target_init(TCGContext *s);
67f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_target_qemu_prologue(TCGContext *s);
6886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void patch_reloc(uint8_t *code_ptr, int type,
6986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        intptr_t value, intptr_t addend);
7086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
7186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* The CIE and FDE header definitions will be common to all hosts.  */
7286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnertypedef struct {
7386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint32_t len __attribute__((aligned((sizeof(void *)))));
7486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint32_t id;
7586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t version;
7686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    char augmentation[1];
7786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t code_align;
7886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t data_align;
7986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t return_column;
8086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner} DebugFrameCIE;
8186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
8286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnertypedef struct QEMU_PACKED {
8386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint32_t len __attribute__((aligned((sizeof(void *)))));
8486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint32_t cie_offset;
8586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uintptr_t func_start;
8686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uintptr_t func_len;
8786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner} DebugFrameFDEHeader;
8886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
8986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_register_jit_int(void *buf, size_t size,
9086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 void *debug_frame, size_t debug_frame_size)
9186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    __attribute__((unused));
9286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
9386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Forward declarations for functions declared and used in tcg-target.c. */
9486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
9586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
9686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       intptr_t arg2);
9786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
9886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_movi(TCGContext *s, TCGType type,
9986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                         TCGReg ret, tcg_target_long arg);
10086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
10186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       const int *const_args);
10286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
10386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       intptr_t arg2);
10486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic int tcg_target_const_match(tcg_target_long val,
10586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                  const TCGArgConstraint *arg_ct);
10686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_tb_init(TCGContext *s);
10786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_tb_finalize(TCGContext *s);
10886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
10986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
11086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' TurnerTCGOpDef tcg_op_defs[] = {
111f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg-opc.h"
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef DEF
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
11586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerconst size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGRegSet tcg_target_available_regs[2];
1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGRegSet tcg_target_call_clobber_regs;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void tcg_out8(TCGContext *s, uint8_t v)
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *s->code_ptr++ = v;
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void tcg_out16(TCGContext *s, uint16_t v)
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t *p = s->code_ptr;
12886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *(uint16_t *)p = v;
12986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->code_ptr = p + 2;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void tcg_out32(TCGContext *s, uint32_t v)
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t *p = s->code_ptr;
13586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *(uint32_t *)p = v;
13686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->code_ptr = p + 4;
13786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
13886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
13986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_out64(TCGContext *s, uint64_t v)
14086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
14186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t *p = s->code_ptr;
14286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *(uint64_t *)p = v;
14386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->code_ptr = p + 8;
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* label relocation processing */
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
148f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
14986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                          int label_index, intptr_t addend)
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGLabel *l;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGRelocation *r;
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    l = &s->labels[label_index];
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (l->has_value) {
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* FIXME: This may break relocations on RISC targets that
15786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           modify instruction fields in place.  The caller may not have
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           written the initial value.  */
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        patch_reloc(code_ptr, type, l->u.value, addend);
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add a new relocation entry */
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        r = tcg_malloc(sizeof(TCGRelocation));
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        r->type = type;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        r->ptr = code_ptr;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        r->addend = addend;
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        r->next = l->u.first_reloc;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        l->u.first_reloc = r;
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_label(TCGContext *s, int label_index, void *ptr)
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGLabel *l;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGRelocation *r;
17586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    intptr_t value = (intptr_t)ptr;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    l = &s->labels[label_index];
17886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (l->has_value) {
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
18086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    r = l->u.first_reloc;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (r != NULL) {
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        patch_reloc(r->ptr, r->type, value, r->addend);
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        r = r->next;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    l->has_value = 1;
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    l->u.value = value;
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint gen_new_label(void)
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGContext *s = &tcg_ctx;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int idx;
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGLabel *l;
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->nb_labels >= TCG_MAX_LABELS)
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    idx = s->nb_labels++;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    l = &s->labels[idx];
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    l->has_value = 0;
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    l->u.first_reloc = NULL;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return idx;
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg-target.c"
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* pool based memory allocation */
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid *tcg_malloc_internal(TCGContext *s, int size)
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGPool *p;
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pool_size;
21286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size > TCG_POOL_CHUNK_SIZE) {
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* big malloc: insert a new pool (XXX: could optimize) */
215aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        p = g_malloc(sizeof(TCGPool) + size);
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p->size = size;
21786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        p->next = s->pool_first_large;
21886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        s->pool_first_large = p;
21986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return p->data;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = s->pool_current;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!p) {
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = s->pool_first;
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!p)
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto new_pool;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!p->next) {
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            new_pool:
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                pool_size = TCG_POOL_CHUNK_SIZE;
230aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner                p = g_malloc(sizeof(TCGPool) + pool_size);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p->size = pool_size;
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p->next = NULL;
23386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (s->pool_current)
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->pool_current->next = p;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->pool_first = p;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p = p->next;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pool_current = p;
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pool_cur = p->data + size;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pool_end = p->data + p->size;
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return p->data;
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid tcg_pool_reset(TCGContext *s)
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGPool *p, *t;
25186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for (p = s->pool_first_large; p; p = t) {
25286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        t = p->next;
25386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        g_free(p);
25486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
25586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->pool_first_large = NULL;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pool_cur = s->pool_end = NULL;
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pool_current = NULL;
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26026d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner#include "helper.h"
26126d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner
26226d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turnertypedef struct TCGHelperInfo {
26386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    void *func;
26486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const char *name;
26526d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner} TCGHelperInfo;
26626d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner
26726d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turnerstatic const TCGHelperInfo all_helpers[] = {
26826d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner#define GEN_HELPER 2
26926d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner#include "helper.h"
27086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
27186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Include tcg-runtime.c functions.  */
27286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_div_i32, "div_i32" },
27386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_rem_i32, "rem_i32" },
27486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_divu_i32, "divu_i32" },
27586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_remu_i32, "remu_i32" },
27686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
27786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_shl_i64, "shl_i64" },
27886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_shr_i64, "shr_i64" },
27986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_sar_i64, "sar_i64" },
28086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_div_i64, "div_i64" },
28186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_rem_i64, "rem_i64" },
28286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_divu_i64, "divu_i64" },
28386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_remu_i64, "remu_i64" },
28486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_mulsh_i64, "mulsh_i64" },
28586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { tcg_helper_muluh_i64, "muluh_i64" },
28626d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner};
28726d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid tcg_context_init(TCGContext *s)
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
29026d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner    int op, total_args, n, i;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGOpDef *def;
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGArgConstraint *args_ct;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int *sorted_args;
29426d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner    GHashTable *helper_table;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(s, 0, sizeof(*s));
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->nb_globals = 0;
29886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Count total number of arguments and allocate the corresponding
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       space */
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    total_args = 0;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(op = 0; op < NB_OPS; op++) {
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def = &tcg_op_defs[op];
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = def->nb_iargs + def->nb_oargs;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        total_args += n;
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
308aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
309aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    sorted_args = g_malloc(sizeof(int) * total_args);
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(op = 0; op < NB_OPS; op++) {
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def = &tcg_op_defs[op];
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def->args_ct = args_ct;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def->sorted_args = sorted_args;
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = def->nb_iargs + def->nb_oargs;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sorted_args += n;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        args_ct += n;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
319c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner
32086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Register helpers.  */
32186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
32226d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner    s->helpers = helper_table = g_hash_table_new(NULL, NULL);
32326d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner
32426d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner    for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
32526d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner        g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
32626d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner                            (gpointer)all_helpers[i].name);
32726d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner    }
32826d285dfa9f482e5b2f6d6df2bcb0eaed06cb1a9David 'Digit' Turner
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_target_init(s);
330f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
332f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnervoid tcg_prologue_init(TCGContext *s)
333f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* init global prologue and epilogue */
335975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    s->code_buf = s->code_gen_prologue;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->code_ptr = s->code_buf;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_target_qemu_prologue(s);
33886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
33986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
34086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef DEBUG_DISAS
34186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
34286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        size_t size = s->code_ptr - s->code_buf;
34386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        qemu_log("PROLOGUE: [size=%zu]\n", size);
34486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        log_disas(s->code_buf, size);
34586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        qemu_log("\n");
34686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        qemu_log_flush();
34786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
34886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->frame_start = start;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->frame_end = start + size;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->frame_reg = reg;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid tcg_func_start(TCGContext *s)
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_pool_reset(s);
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->nb_temps = s->nb_globals;
36286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
36386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* No temps have been previously allocated for size or locality.  */
36486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memset(s->free_temps, 0, sizeof(s->free_temps));
36586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->nb_labels = 0;
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->current_frame_offset = s->frame_start;
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef CONFIG_DEBUG_TCG
37186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->goto_tb_issue_mask = 0;
37286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
37386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
374975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    s->gen_opc_ptr = s->gen_opc_buf;
375975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    s->gen_opparam_ptr = s->gen_opparam_buf;
37686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
37786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->be = tcg_malloc(sizeof(TCGBackendData));
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void tcg_temp_alloc(TCGContext *s, int n)
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n > TCG_MAX_TEMPS)
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline int tcg_global_reg_new_internal(TCGType type, int reg,
3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              const char *name)
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGContext *s = &tcg_ctx;
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int idx;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if TCG_TARGET_REG_BITS == 32
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (type != TCG_TYPE_I32)
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tcg_regset_test_reg(s->reserved_regs, reg))
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    idx = s->nb_globals;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_temp_alloc(s, s->nb_globals + 1);
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts = &s->temps[s->nb_globals];
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->base_type = type;
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->type = type;
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->fixed_reg = 1;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->reg = reg;
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->name = name;
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->nb_globals++;
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_regset_set_reg(s->reserved_regs, reg);
4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return idx;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int idx;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return MAKE_TCGV_I32(idx);
4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int idx;
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return MAKE_TCGV_I64(idx);
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline int tcg_global_mem_new_internal(TCGType type, int reg,
42986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                              intptr_t offset,
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              const char *name)
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGContext *s = &tcg_ctx;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int idx;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    idx = s->nb_globals;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if TCG_TARGET_REG_BITS == 32
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (type == TCG_TYPE_I64) {
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char buf[64];
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_temp_alloc(s, s->nb_globals + 2);
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[s->nb_globals];
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->base_type = type;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->type = TCG_TYPE_I32;
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->fixed_reg = 0;
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_allocated = 1;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_reg = reg;
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCG_TARGET_WORDS_BIGENDIAN
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_offset = offset + 4;
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_offset = offset;
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(buf, sizeof(buf), name);
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcat(buf, sizeof(buf), "_0");
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->name = strdup(buf);
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts++;
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->base_type = type;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->type = TCG_TYPE_I32;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->fixed_reg = 0;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_allocated = 1;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_reg = reg;
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCG_TARGET_WORDS_BIGENDIAN
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_offset = offset;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_offset = offset + 4;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(buf, sizeof(buf), name);
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcat(buf, sizeof(buf), "_1");
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->name = strdup(buf);
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->nb_globals += 2;
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_temp_alloc(s, s->nb_globals + 1);
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[s->nb_globals];
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->base_type = type;
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->type = type;
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->fixed_reg = 0;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_allocated = 1;
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_reg = reg;
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_offset = offset;
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->name = name;
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->nb_globals++;
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return idx;
4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
48986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' TurnerTCGv_i32 tcg_global_mem_new_i32(int reg, intptr_t offset, const char *name)
4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
49186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return MAKE_TCGV_I32(idx);
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
49586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' TurnerTCGv_i64 tcg_global_mem_new_i64(int reg, intptr_t offset, const char *name)
4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
49786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return MAKE_TCGV_I64(idx);
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline int tcg_temp_new_internal(TCGType type, int temp_local)
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGContext *s = &tcg_ctx;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int idx, k;
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
50786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    k = type + (temp_local ? TCG_TYPE_COUNT : 0);
50886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    idx = find_first_bit(s->free_temps[k].l, TCG_MAX_TEMPS);
50986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (idx < TCG_MAX_TEMPS) {
51086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* There is already an available temp with the right type.  */
51186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        clear_bit(idx, s->free_temps[k].l);
51286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[idx];
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->temp_allocated = 1;
51586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        assert(ts->base_type == type);
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        assert(ts->temp_local == temp_local);
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        idx = s->nb_temps;
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if TCG_TARGET_REG_BITS == 32
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (type == TCG_TYPE_I64) {
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_temp_alloc(s, s->nb_temps + 2);
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts = &s->temps[s->nb_temps];
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->base_type = type;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->type = TCG_TYPE_I32;
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->temp_allocated = 1;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->temp_local = temp_local;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->name = NULL;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts++;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->base_type = TCG_TYPE_I32;
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->type = TCG_TYPE_I32;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->temp_allocated = 1;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->temp_local = temp_local;
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->name = NULL;
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->nb_temps += 2;
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_temp_alloc(s, s->nb_temps + 1);
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts = &s->temps[s->nb_temps];
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->base_type = type;
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->type = type;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->temp_allocated = 1;
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->temp_local = temp_local;
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->name = NULL;
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->nb_temps++;
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
548f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
549f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(CONFIG_DEBUG_TCG)
550f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    s->temps_in_use++;
551f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return idx;
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i32 tcg_temp_new_internal_i32(int temp_local)
5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int idx;
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return MAKE_TCGV_I32(idx);
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i64 tcg_temp_new_internal_i64(int temp_local)
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int idx;
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return MAKE_TCGV_I64(idx);
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
57186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_temp_free_internal(int idx)
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGContext *s = &tcg_ctx;
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int k;
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
577f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(CONFIG_DEBUG_TCG)
578f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    s->temps_in_use--;
579f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (s->temps_in_use < 0) {
580f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        fprintf(stderr, "More temporaries freed than allocated!\n");
581f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
582f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
583f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    assert(idx >= s->nb_globals && idx < s->nb_temps);
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts = &s->temps[idx];
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    assert(ts->temp_allocated != 0);
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->temp_allocated = 0;
58886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
58986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    k = ts->type + (ts->temp_local ? TCG_TYPE_COUNT : 0);
59086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    set_bit(idx, s->free_temps[k].l);
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid tcg_temp_free_i32(TCGv_i32 arg)
5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_temp_free_internal(GET_TCGV_I32(arg));
5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid tcg_temp_free_i64(TCGv_i64 arg)
5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_temp_free_internal(GET_TCGV_I64(arg));
6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i32 tcg_const_i32(int32_t val)
6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i32 t0;
6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    t0 = tcg_temp_new_i32();
6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_movi_i32(t0, val);
6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return t0;
6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i64 tcg_const_i64(int64_t val)
6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 t0;
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    t0 = tcg_temp_new_i64();
6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_movi_i64(t0, val);
6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return t0;
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i32 tcg_const_local_i32(int32_t val)
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i32 t0;
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    t0 = tcg_temp_local_new_i32();
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_movi_i32(t0, val);
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return t0;
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerTCGv_i64 tcg_const_local_i64(int64_t val)
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 t0;
6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    t0 = tcg_temp_local_new_i64();
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_movi_i64(t0, val);
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return t0;
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
635f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(CONFIG_DEBUG_TCG)
636f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnervoid tcg_clear_temp_count(void)
637f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
638f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCGContext *s = &tcg_ctx;
639f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    s->temps_in_use = 0;
640f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
641f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
642f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerint tcg_check_temp_count(void)
643f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
644f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCGContext *s = &tcg_ctx;
645f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (s->temps_in_use) {
646f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* Clear the count so that we don't give another
647f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner         * warning immediately next time around.
648f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner         */
649f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        s->temps_in_use = 0;
650f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        return 1;
651f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
652f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    return 0;
653f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
654f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
655f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Note: we convert the 64 bit args to 32 bit and do some alignment
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   and endian swap. Maybe it would be better to do the alignment
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   and endian swap in tcg_reg_alloc_call(). */
6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int real_args;
6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int nb_rets;
6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGArg *nparam;
666f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
667f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
668f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    for (i = 0; i < nargs; ++i) {
669f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int is_64bit = sizemask & (1 << (i+1)*2);
670f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int is_signed = sizemask & (2 << (i+1)*2);
671f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (!is_64bit) {
672f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            TCGv_i64 temp = tcg_temp_new_i64();
673f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
674f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (is_signed) {
675f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_gen_ext32s_i64(temp, orig);
676f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            } else {
677f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_gen_ext32u_i64(temp, orig);
678f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
679f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            args[i] = GET_TCGV_I64(temp);
680f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
681f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
682f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif /* TCG_TARGET_EXTEND_ARGS */
683f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
684975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    *s->gen_opc_ptr++ = INDEX_op_call;
685975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    nparam = s->gen_opparam_ptr++;
6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret != TCG_CALL_DUMMY_ARG) {
6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if TCG_TARGET_REG_BITS < 64
6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (sizemask & 1) {
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCG_TARGET_WORDS_BIGENDIAN
690975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = ret + 1;
691975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = ret;
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
693975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = ret;
694975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = ret + 1;
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            nb_rets = 2;
6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else
6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        {
700975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = ret;
7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            nb_rets = 1;
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        nb_rets = 0;
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    real_args = 0;
7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i < nargs; i++) {
7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if TCG_TARGET_REG_BITS < 64
709f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int is_64bit = sizemask & (1 << (i+1)*2);
710f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (is_64bit) {
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCG_TARGET_CALL_ALIGN_ARGS
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* some targets want aligned 64 bit args */
7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (real_args & 1) {
714975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner                *s->gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                real_args++;
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
718f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	    /* If stack grows up, then we will be placing successive
719f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       arguments at lower addresses, which means we need to
720f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       reverse the order compared to how we would normally
721f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       treat either big or little-endian.  For those arguments
722f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       that will wind up in registers, this still works for
723f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       HPPA (the only current STACK_GROWSUP target) since the
724f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       argument registers are *also* allocated in decreasing
725f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       order.  If another such target is added, this logic may
726f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       have to get more complicated to differentiate between
727f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner	       stack arguments and register arguments.  */
728f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
729975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = args[i] + 1;
730975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = args[i];
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
732975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = args[i];
733975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            *s->gen_opparam_ptr++ = args[i] + 1;
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            real_args += 2;
736f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            continue;
737f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
738f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif /* TCG_TARGET_REG_BITS < 64 */
739f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
74086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *s->gen_opparam_ptr++ = args[i];
74186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        real_args++;
74286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
743975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    *s->gen_opparam_ptr++ = GET_TCGV_PTR(func);
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
745975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    *s->gen_opparam_ptr++ = flags;
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    *nparam = (nb_rets << 16) | (real_args + 1);
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* total parameters, needed to go backward in the instruction stream */
750975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    *s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
751f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
752f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
753f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    for (i = 0; i < nargs; ++i) {
754f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int is_64bit = sizemask & (1 << (i+1)*2);
755f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (!is_64bit) {
756f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
757f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_temp_free_i64(temp);
758f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
759f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
760f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif /* TCG_TARGET_EXTEND_ARGS */
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if TCG_TARGET_REG_BITS == 32
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        int c, int right, int arith)
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (c == 0) {
7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (c >= 32) {
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c -= 32;
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (right) {
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arith) {
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        TCGv_i32 t0, t1;
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        t0 = tcg_temp_new_i32();
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        t1 = tcg_temp_new_i32();
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (right) {
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arith)
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            else
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Note: ret can be the same as arg1, so we use t1 */
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tcg_temp_free_i32(t0);
8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tcg_temp_free_i32(t1);
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
81286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
81386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
81486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (op & MO_SIZE) {
81586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_8:
81686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        op &= ~MO_BSWAP;
81786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
81886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_16:
81986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
82086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_32:
82186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (!is64) {
82286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op &= ~MO_SIGN;
82386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
82486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
82586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_64:
82686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (!is64) {
82786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_abort();
82886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
82986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
83086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
83186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (st) {
83286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        op &= ~MO_SIGN;
83386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
83486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return op;
83586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
83686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
83786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic const TCGOpcode old_ld_opc[8] = {
83886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UB] = INDEX_op_qemu_ld8u,
83986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_SB] = INDEX_op_qemu_ld8s,
84086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UW] = INDEX_op_qemu_ld16u,
84186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_SW] = INDEX_op_qemu_ld16s,
84286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 32
84386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UL] = INDEX_op_qemu_ld32,
84486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_SL] = INDEX_op_qemu_ld32,
84586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
84686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UL] = INDEX_op_qemu_ld32u,
84786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_SL] = INDEX_op_qemu_ld32s,
84886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
84986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_Q]  = INDEX_op_qemu_ld64,
85086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
85186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
85286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic const TCGOpcode old_st_opc[4] = {
85386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UB] = INDEX_op_qemu_st8,
85486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UW] = INDEX_op_qemu_st16,
85586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UL] = INDEX_op_qemu_st32,
85686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_Q]  = INDEX_op_qemu_st64,
85786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
85886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
85986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
86086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
86186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memop = tcg_canonicalize_memop(memop, 0, 0);
86286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
86386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_HAS_new_ldst) {
86486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i32;
86586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i32(val);
86686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
86786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = memop;
86886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
86986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
87086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
87186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
87286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* The old opcodes only support target-endian memory operations.  */
87386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
87486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(old_ld_opc[memop & MO_SSIZE] != 0);
87586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
87686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 32) {
87786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
87886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i32(val);
87986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
88086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
88186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
88286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        TCGv_i64 val64 = tcg_temp_new_i64();
88386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
88486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
88586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i64(val64);
88686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
88786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
88886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
88986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_gen_trunc_i64_i32(val, val64);
89086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_temp_free_i64(val64);
89186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
89286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
89386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
89486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
89586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
89686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memop = tcg_canonicalize_memop(memop, 0, 1);
89786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
89886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_HAS_new_ldst) {
89986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i32;
90086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i32(val);
90186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
90286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = memop;
90386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
90486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
90586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
90686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
90786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* The old opcodes only support target-endian memory operations.  */
90886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
90986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(old_st_opc[memop & MO_SIZE] != 0);
91086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
91186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 32) {
91286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
91386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i32(val);
91486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
91586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
91686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
91786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        TCGv_i64 val64 = tcg_temp_new_i64();
91886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
91986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_gen_extu_i32_i64(val64, val);
92086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
92186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
92286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i64(val64);
92386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
92486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
92586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
92686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_temp_free_i64(val64);
92786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
92886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
92986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
93086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
93186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
93286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memop = tcg_canonicalize_memop(memop, 1, 0);
93386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
93486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 32
93586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if ((memop & MO_SIZE) < MO_64) {
93686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
93786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (memop & MO_SIGN) {
93886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
93986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
94086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_gen_movi_i32(TCGV_HIGH(val), 0);
94186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
94286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
94386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
94486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
94586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
94686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_HAS_new_ldst) {
94786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i64;
94886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i64(val);
94986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
95086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = memop;
95186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
95286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
95386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
95486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
95586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* The old opcodes only support target-endian memory operations.  */
95686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
95786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(old_ld_opc[memop & MO_SSIZE] != 0);
95886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
95986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
96086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_add_param_i64(val);
96186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_add_param_tl(addr);
96286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *tcg_ctx.gen_opparam_ptr++ = idx;
96386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
96486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
96586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
96686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
96786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memop = tcg_canonicalize_memop(memop, 1, 1);
96886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
96986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 32
97086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if ((memop & MO_SIZE) < MO_64) {
97186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
97286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
97386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
97486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
97586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
97686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_HAS_new_ldst) {
97786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i64;
97886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_i64(val);
97986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_add_param_tl(addr);
98086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = memop;
98186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *tcg_ctx.gen_opparam_ptr++ = idx;
98286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
98386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
98486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
98586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* The old opcodes only support target-endian memory operations.  */
98686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
98786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(old_st_opc[memop & MO_SIZE] != 0);
98886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
98986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
99086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_add_param_i64(val);
99186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_add_param_tl(addr);
99286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *tcg_ctx.gen_opparam_ptr++ = idx;
99386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
994f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void tcg_reg_alloc_start(TCGContext *s)
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < s->nb_globals; i++) {
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[i];
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ts->fixed_reg) {
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->val_type = TEMP_VAL_REG;
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->val_type = TEMP_VAL_MEM;
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = s->nb_globals; i < s->nb_temps; i++) {
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[i];
100986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (ts->temp_local) {
101086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->val_type = TEMP_VAL_MEM;
101186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
101286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->val_type = TEMP_VAL_DEAD;
101386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->mem_allocated = 0;
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts->fixed_reg = 0;
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->reg_to_temp[i] = -1;
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 int idx)
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
102786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(idx >= 0 && idx < s->nb_temps);
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts = &s->temps[idx];
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (idx < s->nb_globals) {
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(buf, buf_size, ts->name);
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
103286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (ts->temp_local)
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerchar *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerchar *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
105086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Find helper name.  */
10519142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turnerstatic inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10539142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turner    const char *ret = NULL;
10549142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turner    if (s->helpers) {
10559142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turner        ret = g_hash_table_lookup(s->helpers, (gpointer)val);
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10579142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turner    return ret;
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char * const cond_name[] =
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
106286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [TCG_COND_NEVER] = "never",
106386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [TCG_COND_ALWAYS] = "always",
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_EQ] = "eq",
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_NE] = "ne",
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LT] = "lt",
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GE] = "ge",
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LE] = "le",
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GT] = "gt",
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LTU] = "ltu",
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GEU] = "geu",
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LEU] = "leu",
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GTU] = "gtu"
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
107686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic const char * const ldst_name[] =
107786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
107886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UB]   = "ub",
107986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_SB]   = "sb",
108086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEUW] = "leuw",
108186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LESW] = "lesw",
108286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEUL] = "leul",
108386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LESL] = "lesl",
108486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEQ]  = "leq",
108586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEUW] = "beuw",
108686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BESW] = "besw",
108786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEUL] = "beul",
108886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BESL] = "besl",
108986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEQ]  = "beq",
109086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
109186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
109286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_dump_ops(TCGContext *s)
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const uint16_t *opc_ptr;
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGArg *args;
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGArg arg;
1097f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCGOpcode c;
1098f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGOpDef *def;
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf[128];
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    first_insn = 1;
1103975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    opc_ptr = s->gen_opc_buf;
1104975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    args = s->gen_opparam_buf;
1105975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    while (opc_ptr < s->gen_opc_ptr) {
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = *opc_ptr++;
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def = &tcg_op_defs[c];
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == INDEX_op_debug_insn_start) {
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint64_t pc;
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pc = ((uint64_t)args[1] << 32) | args[0];
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pc = args[0];
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
111586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (!first_insn) {
111686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log("\n");
111786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
111886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            qemu_log(" ---- 0x%" PRIx64, pc);
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            first_insn = 0;
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_oargs = def->nb_oargs;
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_iargs = def->nb_iargs;
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_cargs = def->nb_cargs;
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (c == INDEX_op_call) {
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            TCGArg arg;
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* variable number of arguments */
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            arg = *args++;
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_oargs = arg >> 16;
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_iargs = arg & 0xffff;
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_cargs = def->nb_cargs;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
113286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            qemu_log(" %s ", def->name);
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* function name */
113586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            qemu_log("%s",
113686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                     tcg_get_arg_str_idx(s, buf, sizeof(buf),
113786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                         args[nb_oargs + nb_iargs - 1]));
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* flags */
113986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            qemu_log(",$0x%" TCG_PRIlx, args[nb_oargs + nb_iargs]);
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* nb out args */
114186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            qemu_log(",$%d", nb_oargs);
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(i = 0; i < nb_oargs; i++) {
114386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log(",");
114486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
114586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                                   args[i]));
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(i = 0; i < (nb_iargs - 1); i++) {
114886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log(",");
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
115086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log("<dummy>");
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
115286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
115386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                                       args[nb_oargs + i]));
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
115686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_target_ulong val;
11589142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turner            const char *name;
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_oargs = def->nb_oargs;
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_iargs = def->nb_iargs;
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_cargs = def->nb_cargs;
116386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            qemu_log(" %s %s,$", def->name,
116486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = args[1];
11669142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turner            name = tcg_find_helper(s, val);
11679142071536d74f1b8370f79851c9c2ca92496628David 'Digit' Turner            if (name) {
116886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log("%s", name);
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
117086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (c == INDEX_op_movi_i32) {
117186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log("0x%x", (uint32_t)val);
117286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
117386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log("0x%" PRIx64 , (uint64_t)val);
117486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
117786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            qemu_log(" %s ", def->name);
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (c == INDEX_op_nopn) {
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* variable number of arguments */
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_cargs = *args;
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_oargs = 0;
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_iargs = 0;
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_oargs = def->nb_oargs;
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_iargs = def->nb_iargs;
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_cargs = def->nb_cargs;
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
118886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            k = 0;
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(i = 0; i < nb_oargs; i++) {
119186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (k != 0) {
119286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log(",");
119386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
119486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
119586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                                   args[k++]));
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(i = 0; i < nb_iargs; i++) {
119886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (k != 0) {
119986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log(",");
120086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
120186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
120286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                                   args[k++]));
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1204b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            switch (c) {
1205b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            case INDEX_op_brcond_i32:
1206b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            case INDEX_op_setcond_i32:
120786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_movcond_i32:
120886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_brcond2_i32:
1209b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            case INDEX_op_setcond2_i32:
121086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_brcond_i64:
1211b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            case INDEX_op_setcond_i64:
121286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_movcond_i64:
121386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
121486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log(",%s", cond_name[args[k++]]);
121586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
121686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log(",$0x%" TCG_PRIlx, args[k++]);
121786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
121886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                i = 1;
121986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
122086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_qemu_ld_i32:
122186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_qemu_st_i32:
122286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_qemu_ld_i64:
122386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case INDEX_op_qemu_st_i64:
122486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (args[k] < ARRAY_SIZE(ldst_name) && ldst_name[args[k]]) {
122586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log(",%s", ldst_name[args[k++]]);
122686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
122786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log(",$0x%" TCG_PRIlx, args[k++]);
122886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = 1;
1230b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner                break;
1231b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            default:
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = 0;
1233b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner                break;
1234b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            }
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(; i < nb_cargs; i++) {
123686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (k != 0) {
123786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    qemu_log(",");
123886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                arg = args[k++];
124086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                qemu_log("$0x%" TCG_PRIlx, arg);
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
124386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        qemu_log("\n");
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        args += nb_iargs + nb_oargs + nb_cargs;
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* we give more priority to constraints with less registers */
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int get_constraint_priority(const TCGOpDef *def, int k)
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGArgConstraint *arg_ct;
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, n;
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    arg_ct = &def->args_ct[k];
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arg_ct->ct & TCG_CT_ALIAS) {
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* an alias is equivalent to a single register */
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = 1;
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(arg_ct->ct & TCG_CT_REG))
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = 0;
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (tcg_regset_test_reg(arg_ct->u.regs, i))
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                n++;
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return TCG_TARGET_NB_REGS - n + 1;
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sort from highest priority to lowest */
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void sort_constraints(TCGOpDef *def, int start, int n)
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, j, p1, p2, tmp;
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < n; i++)
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def->sorted_args[start + i] = start + i;
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n <= 1)
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < n - 1; i++) {
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(j = i + 1; j < n; j++) {
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (p1 < p2) {
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = def->sorted_args[start + i];
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                def->sorted_args[start + i] = def->sorted_args[start + j];
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                def->sorted_args[start + j] = tmp;
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1294f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCGOpcode op;
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGOpDef *def;
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *ct_str;
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, nb_args;
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
1300f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (tdefs->op == (TCGOpcode)-1)
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = tdefs->op;
1303f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        assert((unsigned)op < NB_OPS);
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def = &tcg_op_defs[op];
1305b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner#if defined(CONFIG_DEBUG_TCG)
1306b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        /* Duplicate entry in op definitions? */
1307b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        assert(!def->used);
1308b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        def->used = 1;
1309b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner#endif
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nb_args = def->nb_iargs + def->nb_oargs;
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(i = 0; i < nb_args; i++) {
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ct_str = tdefs->args_ct_str[i];
1313b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            /* Incomplete TCGTargetOpDef entry? */
1314b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            assert(ct_str != NULL);
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_regset_clear(def->args_ct[i].u.regs);
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            def->args_ct[i].ct = 0;
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int oarg;
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                oarg = ct_str[0] - '0';
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                assert(oarg < def->nb_oargs);
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                assert(def->args_ct[oarg].ct & TCG_CT_REG);
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* TCG_CT_ALIAS is for the output arguments. The input
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   argument is tagged with TCG_CT_IALIAS. */
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                def->args_ct[i] = def->args_ct[oarg];
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                def->args_ct[oarg].ct = TCG_CT_ALIAS;
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                def->args_ct[oarg].alias_index = i;
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                def->args_ct[i].ct |= TCG_CT_IALIAS;
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                def->args_ct[i].alias_index = oarg;
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for(;;) {
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (*ct_str == '\0')
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch(*ct_str) {
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 'i':
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        def->args_ct[i].ct |= TCG_CT_CONST;
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ct_str++;
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default:
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    ct_str, i, def->name);
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            exit(1);
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1349b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        /* TCGTargetOpDef entry with too much information? */
1350b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1351b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* sort the constraints (XXX: this is just an heuristic) */
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sort_constraints(def, 0, def->nb_oargs);
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sort_constraints(def, def->nb_oargs, def->nb_iargs);
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int i;
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            printf("%s: sorted=", def->name);
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                printf(" %d", def->sorted_args[i]);
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            printf("\n");
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tdefs++;
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1369b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner#if defined(CONFIG_DEBUG_TCG)
1370f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    i = 0;
1371b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
137286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        const TCGOpDef *def = &tcg_op_defs[op];
137386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (def->flags & TCG_OPF_NOT_PRESENT) {
1374b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            /* Wrong entry in op definitions? */
137586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (def->used) {
137686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                fprintf(stderr, "Invalid op definition for %s\n", def->name);
1377f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                i = 1;
1378f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
1379b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        } else {
1380b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner            /* Missing entry in op definitions? */
138186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (!def->used) {
138286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                fprintf(stderr, "Missing op definition for %s\n", def->name);
1383f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                i = 1;
138486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
1385b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        }
1386b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner    }
1387f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (i == 1) {
1388f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_abort();
1389f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
1390b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner#endif
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef USE_LIVENESS_ANALYSIS
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* set a nop for an operation using 'nb_args' */
139686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               TCGArg *args, int nb_args)
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_args == 0) {
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *opc_ptr = INDEX_op_nop;
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *opc_ptr = INDEX_op_nopn;
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        args[0] = nb_args;
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        args[nb_args - 1] = nb_args;
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
140886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* liveness analysis: end of function: all temps are dead, and globals
140986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   should be in memory. */
141086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps,
141186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                   uint8_t *mem_temps)
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
141386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memset(dead_temps, 1, s->nb_temps);
141486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memset(mem_temps, 1, s->nb_globals);
141586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memset(mem_temps + s->nb_globals, 0, s->nb_temps - s->nb_globals);
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
141886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* liveness analysis: end of basic block: all temps are dead, globals
141986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   and local temps should be in memory. */
142086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
142186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 uint8_t *mem_temps)
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
142586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memset(dead_temps, 1, s->nb_temps);
142686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memset(mem_temps, 1, s->nb_globals);
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = s->nb_globals; i < s->nb_temps; i++) {
142886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        mem_temps[i] = s->temps[i].temp_local;
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
143253a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner/* Liveness analysis : update the opc_dead_args array to tell if a
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   given input arguments is dead. Instructions updating dead
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   temporaries are removed. */
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void tcg_liveness_analysis(TCGContext *s)
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1437f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
143886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGOpcode op, op_new, op_new2;
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGArg *args;
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGOpDef *def;
144186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t *dead_temps, *mem_temps;
144286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint16_t dead_args;
144386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t sync_args;
144486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    bool have_op_new2;
144586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
1446975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    s->gen_opc_ptr++; /* skip end */
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1448975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
145053a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
145186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
145286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dead_temps = tcg_malloc(s->nb_temps);
145486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    mem_temps = tcg_malloc(s->nb_temps);
145586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_la_func_end(s, dead_temps, mem_temps);
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1457975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    args = s->gen_opparam_ptr;
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    op_index = nb_ops - 1;
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (op_index >= 0) {
1460975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner        op = s->gen_opc_buf[op_index];
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def = &tcg_op_defs[op];
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(op) {
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_call:
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int call_flags;
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_args = args[-1];
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                args -= nb_args;
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_iargs = args[0] & 0xffff;
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nb_oargs = args[0] >> 16;
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                args++;
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                call_flags = args[nb_oargs + nb_iargs];
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* pure functions can be removed if their result is not
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   used */
147686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for(i = 0; i < nb_oargs; i++) {
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        arg = args[i];
147986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        if (!dead_temps[arg] || mem_temps[arg]) {
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto do_not_remove_call;
148186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        }
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
1483975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner                    tcg_set_nop(s, s->gen_opc_buf + op_index,
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                args - 1, nb_args);
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                do_not_remove_call:
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* output args are dead */
14899bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                    dead_args = 0;
149086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    sync_args = 0;
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for(i = 0; i < nb_oargs; i++) {
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        arg = args[i];
14939bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                        if (dead_temps[arg]) {
14949bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                            dead_args |= (1 << i);
14959bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                        }
149686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        if (mem_temps[arg]) {
149786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                            sync_args |= (1 << i);
149886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        }
149986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        dead_temps[arg] = 1;
150086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        mem_temps[arg] = 0;
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
1502c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner
150386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) {
150486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        /* globals should be synced to memory */
150586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        memset(mem_temps, 1, s->nb_globals);
150686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    }
150786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
150886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                        TCG_CALL_NO_READ_GLOBALS))) {
150986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        /* globals should go back to memory */
151086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        memset(dead_temps, 1, s->nb_globals);
15115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* input args are live */
151453a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
151553a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                        arg = args[i];
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (arg != TCG_CALL_DUMMY_ARG) {
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (dead_temps[arg]) {
151853a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                                dead_args |= (1 << i);
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            dead_temps[arg] = 0;
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
152353a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                    s->op_dead_args[op_index] = dead_args;
152486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->op_sync_args[op_index] = sync_args;
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                args--;
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_debug_insn_start:
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args -= def->nb_args;
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_nopn:
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nb_args = args[-1];
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args -= nb_args;
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_discard:
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args--;
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* mark the temporary as dead */
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dead_temps[args[0]] = 1;
154086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mem_temps[args[0]] = 0;
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_end:
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
154486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
154586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_add2_i32:
154686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_add_i32;
154786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_addsub2;
154886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_sub2_i32:
154986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_sub_i32;
155086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_addsub2;
155186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_add2_i64:
155286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_add_i64;
155386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_addsub2;
155486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_sub2_i64:
155586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_sub_i64;
155686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        do_addsub2:
155786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args -= 6;
155886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            nb_iargs = 4;
155986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            nb_oargs = 2;
156086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* Test if the high part of the operation is dead, but not
156186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               the low part.  The result can be optimized to a simple
156286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               add or sub.  This happens often for x86_64 guest when the
156386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               cpu mode is set to 32 bit.  */
156486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
156586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
156686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    goto do_remove;
156786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
156886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* Create the single operation plus nop.  */
156986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op = op_new;
157086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[1] = args[2];
157186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[2] = args[4];
157286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
157386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 3);
157486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* Fall through and mark the single-word operation live.  */
157586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                nb_iargs = 2;
157686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                nb_oargs = 1;
157786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
157886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_not_remove;
157986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
158086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_mulu2_i32:
158186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_mul_i32;
158286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new2 = INDEX_op_muluh_i32;
158386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            have_op_new2 = TCG_TARGET_HAS_muluh_i32;
158486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_mul2;
158586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_muls2_i32:
158686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_mul_i32;
158786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new2 = INDEX_op_mulsh_i32;
158886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            have_op_new2 = TCG_TARGET_HAS_mulsh_i32;
158986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_mul2;
159086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_mulu2_i64:
159186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_mul_i64;
159286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new2 = INDEX_op_muluh_i64;
159386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            have_op_new2 = TCG_TARGET_HAS_muluh_i64;
159486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_mul2;
159586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_muls2_i64:
159686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new = INDEX_op_mul_i64;
159786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op_new2 = INDEX_op_mulsh_i64;
159886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            have_op_new2 = TCG_TARGET_HAS_mulsh_i64;
159986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_mul2;
160086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        do_mul2:
160186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args -= 4;
160286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            nb_iargs = 2;
160386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            nb_oargs = 2;
160486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
160586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
160686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    /* Both parts of the operation are dead.  */
160786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    goto do_remove;
160886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
160986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* The high part of the operation is dead; generate the low. */
161086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op = op_new;
161186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[1] = args[2];
161286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[2] = args[3];
161386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else if (have_op_new2 && dead_temps[args[0]]
161486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && !mem_temps[args[0]]) {
161586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* The low part of the operation is dead; generate the high.  */
161686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op = op_new2;
161786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[0] = args[1];
161886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[1] = args[2];
161986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[2] = args[3];
162086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else {
162186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                goto do_not_remove;
162286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
162386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
162486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1);
162586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* Mark the single-word operation live.  */
162686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            nb_oargs = 1;
162786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_not_remove;
162886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
163086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            args -= def->nb_args;
16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            nb_iargs = def->nb_iargs;
16335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            nb_oargs = def->nb_oargs;
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Test if the operation can be removed because all
16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               its outputs are dead. We assume that nb_oargs == 0
16375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               implies side effects */
16385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
16395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                for(i = 0; i < nb_oargs; i++) {
16405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    arg = args[i];
164186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    if (!dead_temps[arg] || mem_temps[arg]) {
16425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        goto do_not_remove;
164386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    }
16445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
164586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            do_remove:
1646975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner                tcg_set_nop(s, s->gen_opc_buf + op_index, args, def->nb_args);
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_PROFILER
16485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                s->del_op_count++;
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
16515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            do_not_remove:
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* output args are dead */
16549bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                dead_args = 0;
165586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                sync_args = 0;
16565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                for(i = 0; i < nb_oargs; i++) {
16575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    arg = args[i];
16589bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                    if (dead_temps[arg]) {
16599bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                        dead_args |= (1 << i);
16609bf492c3fedbd13ee0e2af94424c8bf48cb2fec5David 'Digit' Turner                    }
166186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    if (mem_temps[arg]) {
166286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        sync_args |= (1 << i);
166386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    }
166486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    dead_temps[arg] = 1;
166586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    mem_temps[arg] = 0;
16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* if end of basic block, update */
16695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (def->flags & TCG_OPF_BB_END) {
167086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    tcg_la_bb_end(s, dead_temps, mem_temps);
167186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
167286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    /* globals should be synced to memory */
167386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    memset(mem_temps, 1, s->nb_globals);
16745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
16755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* input args are live */
167753a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
167853a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                    arg = args[i];
16795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if (dead_temps[arg]) {
168053a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                        dead_args |= (1 << i);
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
16825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    dead_temps[arg] = 0;
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
168453a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                s->op_dead_args[op_index] = dead_args;
168586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->op_sync_args[op_index] = sync_args;
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op_index--;
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
169286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (args != s->gen_opparam_buf) {
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
169486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* dummy liveness analysis */
1698f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_liveness_analysis(TCGContext *s)
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nb_ops;
1701975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
170353a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
170453a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner    memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
170586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
170686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memset(s->op_sync_args, 0, nb_ops * sizeof(uint8_t));
17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef NDEBUG
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void dump_regs(TCGContext *s)
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf[64];
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < s->nb_temps; i++) {
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[i];
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(ts->val_type) {
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TEMP_VAL_REG:
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            printf("%s", tcg_target_reg_names[ts->reg]);
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TEMP_VAL_MEM:
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TEMP_VAL_CONST:
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            printf("$0x%" TCG_PRIlx, ts->val);
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TEMP_VAL_DEAD:
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            printf("D");
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            printf("???");
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        printf("\n");
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->reg_to_temp[i] >= 0) {
174286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            printf("%s: %s\n",
174386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                   tcg_target_reg_names[i],
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void check_regs(TCGContext *s)
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int reg, k;
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf[64];
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        k = s->reg_to_temp[reg];
17578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (k >= 0) {
17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts = &s->temps[k];
17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ts->val_type != TEMP_VAL_REG ||
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ts->reg != reg) {
176186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                printf("Inconsistency for register %s:\n",
17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       tcg_target_reg_names[reg]);
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto fail;
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(k = 0; k < s->nb_temps; k++) {
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[k];
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ts->val_type == TEMP_VAL_REG &&
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            !ts->fixed_reg &&
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->reg_to_temp[ts->reg] != k) {
177286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                printf("Inconsistency for temp %s:\n",
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fail:
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                printf("reg state:\n");
17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dump_regs(s);
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_abort();
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void temp_allocate_frame(TCGContext *s, int temp)
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts = &s->temps[temp];
178786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
178886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Sparc64 stack is accessed with offset of 2047 */
17896b1f7efc7fd26332676d7626f7f139f5b98b756cDavid 'Digit' Turner    s->current_frame_offset = (s->current_frame_offset +
17906b1f7efc7fd26332676d7626f7f139f5b98b756cDavid 'Digit' Turner                               (tcg_target_long)sizeof(tcg_target_long) - 1) &
17916b1f7efc7fd26332676d7626f7f139f5b98b756cDavid 'Digit' Turner        ~(sizeof(tcg_target_long) - 1);
17922e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner#endif
17936b1f7efc7fd26332676d7626f7f139f5b98b756cDavid 'Digit' Turner    if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
17946b1f7efc7fd26332676d7626f7f139f5b98b756cDavid 'Digit' Turner        s->frame_end) {
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
17966b1f7efc7fd26332676d7626f7f139f5b98b756cDavid 'Digit' Turner    }
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->mem_offset = s->current_frame_offset;
17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->mem_reg = s->frame_reg;
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts->mem_allocated = 1;
180086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->current_frame_offset += sizeof(tcg_target_long);
180186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
180286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
180386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* sync register 'reg' by saving it to the corresponding temporary */
180486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_reg_sync(TCGContext *s, int reg)
180586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
180686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGTemp *ts;
180786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int temp;
180886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
180986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temp = s->reg_to_temp[reg];
181086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    ts = &s->temps[temp];
181186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(ts->val_type == TEMP_VAL_REG);
181286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (!ts->mem_coherent && !ts->fixed_reg) {
181386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (!ts->mem_allocated) {
181486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_allocate_frame(s, temp);
181586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
181686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
181786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
181886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    ts->mem_coherent = 1;
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* free register 'reg' by spilling the corresponding temporary if necessary */
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void tcg_reg_free(TCGContext *s, int reg)
18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int temp;
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    temp = s->reg_to_temp[reg];
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (temp != -1) {
182886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_reg_sync(s, reg);
182986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        s->temps[temp].val_type = TEMP_VAL_MEM;
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->reg_to_temp[reg] = -1;
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Allocate a register belonging to reg1 & ~reg2 */
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, reg;
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGRegSet reg_ct;
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_regset_andnot(reg_ct, reg1, reg2);
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first try free registers */
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = tcg_target_reg_alloc_order[i];
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return reg;
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: do better spill choice */
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = tcg_target_reg_alloc_order[i];
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tcg_regset_test_reg(reg_ct, reg)) {
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_reg_free(s, reg);
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return reg;
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_abort();
18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
186186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* mark a temporary as dead. */
186286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void temp_dead(TCGContext *s, int temp)
186386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
186486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGTemp *ts;
186586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
186686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    ts = &s->temps[temp];
186786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (!ts->fixed_reg) {
186886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (ts->val_type == TEMP_VAL_REG) {
186986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            s->reg_to_temp[ts->reg] = -1;
187086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
187186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (temp < s->nb_globals || ts->temp_local) {
187286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->val_type = TEMP_VAL_MEM;
187386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
187486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->val_type = TEMP_VAL_DEAD;
187586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
187686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
187786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
187886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
187986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* sync a temporary to memory. 'allocated_regs' is used in case a
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   temporary registers needs to be allocated to store a constant. */
188186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs)
18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts = &s->temps[temp];
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!ts->fixed_reg) {
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(ts->val_type) {
188886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case TEMP_VAL_CONST:
188986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
189086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                    allocated_regs);
189186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->val_type = TEMP_VAL_REG;
189286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            s->reg_to_temp[ts->reg] = temp;
189386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->mem_coherent = 0;
189486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_movi(s, ts->type, ts->reg, ts->val);
189586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* fallthrough*/
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TEMP_VAL_REG:
189786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_reg_sync(s, ts->reg);
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TEMP_VAL_DEAD:
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case TEMP_VAL_MEM:
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_abort();
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
190886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* save a temporary to memory. 'allocated_regs' is used in case a
190986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   temporary registers needs to be allocated to store a constant. */
191086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
191186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
191286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef USE_LIVENESS_ANALYSIS
191386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* The liveness analysis already ensures that globals are back
191486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       in memory. Keep an assert for safety. */
191586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(s->temps[temp].val_type == TEMP_VAL_MEM || s->temps[temp].fixed_reg);
191686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
191786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temp_sync(s, temp, allocated_regs);
191886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temp_dead(s, temp);
191986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
192086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
192186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
192286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* save globals to their canonical location and assume they can be
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   modified be the following code. 'allocated_regs' is used in case a
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   temporary registers needs to be allocated to store a constant. */
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void save_globals(TCGContext *s, TCGRegSet allocated_regs)
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < s->nb_globals; i++) {
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp_save(s, i, allocated_regs);
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
193486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* sync globals to their canonical location and assume they can be
193586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   read by the following code. 'allocated_regs' is used in case a
193686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   temporary registers needs to be allocated to store a constant. */
193786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
193886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
193986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int i;
194086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
194186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for (i = 0; i < s->nb_globals; i++) {
194286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef USE_LIVENESS_ANALYSIS
194386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        assert(s->temps[i].val_type != TEMP_VAL_REG || s->temps[i].fixed_reg ||
194486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               s->temps[i].mem_coherent);
194586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
194686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temp_sync(s, i, allocated_regs);
194786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
194886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
194986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
195086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* at the end of a basic block, we assume all temporaries are dead and
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   all globals are stored at their canonical location. */
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = s->nb_globals; i < s->nb_temps; i++) {
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[i];
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ts->temp_local) {
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            temp_save(s, i, allocated_regs);
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
196386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef USE_LIVENESS_ANALYSIS
196486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* The liveness analysis already ensures that temps are dead.
196586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               Keep an assert for safety. */
196686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            assert(ts->val_type == TEMP_VAL_DEAD);
196786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
196886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_dead(s, i);
196986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    save_globals(s, allocated_regs);
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
197653a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
197786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define NEED_SYNC_ARG(n) ((sync_args >> (n)) & 1)
19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
197986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
198086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                               uint16_t dead_args, uint8_t sync_args)
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ots;
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_target_ulong val;
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ots = &s->temps[args[0]];
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    val = args[1];
19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ots->fixed_reg) {
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* for fixed registers, we do not do any constant
19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           propagation */
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_movi(s, ots->type, ots->reg, val);
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* The movi is not explicitly generated here */
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ots->val_type == TEMP_VAL_REG)
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->reg_to_temp[ots->reg] = -1;
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ots->val_type = TEMP_VAL_CONST;
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ots->val = val;
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
199986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (NEED_SYNC_ARG(0)) {
200086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temp_sync(s, args[0], s->reserved_regs);
200186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
200286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (IS_DEAD_ARG(0)) {
200386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temp_dead(s, args[0]);
200486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
200886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              const TCGArg *args, uint16_t dead_args,
200986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              uint8_t sync_args)
20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
201186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGRegSet allocated_regs;
20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts, *ots;
201386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGArgConstraint *arg_ct, *oarg_ct;
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
201586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_regset_set(allocated_regs, s->reserved_regs);
20168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ots = &s->temps[args[0]];
20178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts = &s->temps[args[1]];
201886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    oarg_ct = &def->args_ct[0];
201986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    arg_ct = &def->args_ct[1];
202086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
202186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* If the source value is not in a register, and we're going to be
202286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       forced to have it in a register in order to perform the copy,
202386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       then copy the SOURCE value into its own register first.  That way
202486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       we don't have to reload SOURCE the next time it is used. */
202586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
202686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        || ts->val_type == TEMP_VAL_MEM) {
202786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ts->reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
202886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (ts->val_type == TEMP_VAL_MEM) {
202986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_ld(s, ts->type, ts->reg, ts->mem_reg, ts->mem_offset);
203086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->mem_coherent = 1;
203186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else if (ts->val_type == TEMP_VAL_CONST) {
203286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_movi(s, ts->type, ts->reg, ts->val);
203386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
203486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        s->reg_to_temp[ts->reg] = args[1];
203586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ts->val_type = TEMP_VAL_REG;
203686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
203886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
203986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* mov to a non-saved dead register makes no sense (even with
204086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           liveness analysis disabled). */
204186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        assert(NEED_SYNC_ARG(0));
204286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* The code above should have moved the temp to a register. */
204386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        assert(ts->val_type == TEMP_VAL_REG);
204486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (!ots->mem_allocated) {
204586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_allocate_frame(s, args[0]);
204686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
204786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, ots->type, ts->reg, ots->mem_reg, ots->mem_offset);
204886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (IS_DEAD_ARG(1)) {
204986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_dead(s, args[1]);
205086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
205186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temp_dead(s, args[0]);
205286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else if (ts->val_type == TEMP_VAL_CONST) {
205386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* propagate constant */
205486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (ots->val_type == TEMP_VAL_REG) {
205586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            s->reg_to_temp[ots->reg] = -1;
205686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
205786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ots->val_type = TEMP_VAL_CONST;
205886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ots->val = ts->val;
205986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
206086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* The code in the first if block should have moved the
206186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           temp to a register. */
206286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        assert(ts->val_type == TEMP_VAL_REG);
206353a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* the mov can be suppressed */
20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ots->val_type == TEMP_VAL_REG) {
206686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->reg_to_temp[ots->reg] = -1;
20678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
206886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ots->reg = ts->reg;
206986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_dead(s, args[1]);
20708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
207186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (ots->val_type != TEMP_VAL_REG) {
207286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* When allocating a new register, make sure to not spill the
207386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                   input one. */
207486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_regset_set_reg(allocated_regs, ts->reg);
207586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                ots->reg = tcg_reg_alloc(s, oarg_ct->u.regs, allocated_regs);
207686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
207786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_mov(s, ots->type, ots->reg, ts->reg);
20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
207986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ots->val_type = TEMP_VAL_REG;
208086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ots->mem_coherent = 0;
208186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        s->reg_to_temp[ots->reg] = args[0];
208286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (NEED_SYNC_ARG(0)) {
208386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_reg_sync(s, ots->reg);
20848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
208886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_reg_alloc_op(TCGContext *s,
2089f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                             const TCGOpDef *def, TCGOpcode opc,
209086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                             const TCGArg *args, uint16_t dead_args,
209186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                             uint8_t sync_args)
20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGRegSet allocated_regs;
20948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, k, nb_iargs, nb_oargs, reg;
20958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGArg arg;
20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGArgConstraint *arg_ct;
20978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGArg new_args[TCG_MAX_OP_ARGS];
20998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int const_args[TCG_MAX_OP_ARGS];
21008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nb_oargs = def->nb_oargs;
21028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nb_iargs = def->nb_iargs;
21038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* copy constants */
210586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memcpy(new_args + nb_oargs + nb_iargs,
210686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           args + nb_oargs + nb_iargs,
21078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           sizeof(TCGArg) * def->nb_cargs);
21088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
210986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* satisfy input constraints */
21108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_regset_set(allocated_regs, s->reserved_regs);
21118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(k = 0; k < nb_iargs; k++) {
21128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        i = def->sorted_args[nb_oargs + k];
21138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        arg = args[i];
21148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        arg_ct = &def->args_ct[i];
21158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[arg];
21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ts->val_type == TEMP_VAL_MEM) {
21178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
21188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->val_type = TEMP_VAL_REG;
21208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->reg = reg;
21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts->mem_coherent = 1;
21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->reg_to_temp[reg] = arg;
21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (ts->val_type == TEMP_VAL_CONST) {
21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (tcg_target_const_match(ts->val, arg_ct)) {
21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* constant is OK for instruction */
21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                const_args[i] = 1;
21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                new_args[i] = ts->val;
21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto iarg_end;
21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* need to move to a register */
21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_movi(s, ts->type, reg, ts->val);
21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ts->val_type = TEMP_VAL_REG;
21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ts->reg = reg;
21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ts->mem_coherent = 0;
21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->reg_to_temp[reg] = arg;
21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        assert(ts->val_type == TEMP_VAL_REG);
21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arg_ct->ct & TCG_CT_IALIAS) {
21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ts->fixed_reg) {
21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* if fixed register, we must allocate a new register
21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   if the alias is not the same register */
21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (arg != args[arg_ct->alias_index])
21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto allocate_in_reg;
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* if the input is aliased to an output and if it is
21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   not dead after the instruction, we must allocate
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   a new register and move it */
215053a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                if (!IS_DEAD_ARG(i)) {
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto allocate_in_reg;
215253a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner                }
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = ts->reg;
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* nothing to do : the constraint is satisfied */
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        allocate_in_reg:
216086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* allocate a new register matching the constraint
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               and move the temporary register into it */
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2163f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_mov(s, ts->type, reg, ts->reg);
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_args[i] = reg;
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const_args[i] = 0;
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(allocated_regs, reg);
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iarg_end: ;
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
217086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
217186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* mark dead temporaries and free the associated registers */
217286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
217386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (IS_DEAD_ARG(i)) {
217486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_dead(s, args[i]);
217586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
217686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
21775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (def->flags & TCG_OPF_BB_END) {
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_reg_alloc_bb_end(s, allocated_regs);
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (def->flags & TCG_OPF_CALL_CLOBBER) {
218286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* XXX: permit generic clobber register list ? */
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_reg_free(s, reg);
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
218986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (def->flags & TCG_OPF_SIDE_EFFECTS) {
219086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* sync globals if the op has side effects and might trigger
219186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               an exception. */
219286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            sync_globals(s, allocated_regs);
219386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
219486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* satisfy the output constraints */
21968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set(allocated_regs, s->reserved_regs);
21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(k = 0; k < nb_oargs; k++) {
21988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = def->sorted_args[k];
21998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            arg = args[i];
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            arg_ct = &def->args_ct[i];
22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts = &s->temps[arg];
22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arg_ct->ct & TCG_CT_ALIAS) {
22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                reg = new_args[arg_ct->alias_index];
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* if fixed register, we try to use it */
22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                reg = ts->reg;
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (ts->fixed_reg &&
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto oarg_end;
22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_regset_set_reg(allocated_regs, reg);
22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* if a fixed register is used, then a move will be done afterwards */
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!ts->fixed_reg) {
221686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (ts->val_type == TEMP_VAL_REG) {
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->reg_to_temp[ts->reg] = -1;
22180352ce4b5167ebc185bdec779e9642af75f1ccacDavid 'Digit' Turner                }
221986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                ts->val_type = TEMP_VAL_REG;
222086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                ts->reg = reg;
222186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* temp value is modified, so the value kept in memory is
222286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                   potentially not the same */
222386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                ts->mem_coherent = 0;
222486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->reg_to_temp[reg] = arg;
22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oarg_end:
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            new_args[i] = reg;
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* emit instruction */
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_out_op(s, opc, new_args, const_args);
223386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* move the outputs in the correct register if needed */
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < nb_oargs; i++) {
22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[args[i]];
22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = new_args[i];
22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ts->fixed_reg && ts->reg != reg) {
2239f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_mov(s, ts->type, ts->reg, reg);
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
224186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (NEED_SYNC_ARG(i)) {
224286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_reg_sync(s, reg);
224386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
224486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (IS_DEAD_ARG(i)) {
224586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_dead(s, args[i]);
224686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCG_TARGET_STACK_GROWSUP
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define STACK_DIR(x) (-(x))
22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
22538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define STACK_DIR(x) (x)
22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
2257f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                              TCGOpcode opc, const TCGArg *args,
225886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              uint16_t dead_args, uint8_t sync_args)
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGArg arg, func_arg;
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGTemp *ts;
226386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    intptr_t stack_offset;
226486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    size_t call_stack_size;
226586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uintptr_t func_addr;
22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int const_func_arg, allocate_args;
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGRegSet allocated_regs;
22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGArgConstraint *arg_ct;
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    arg = *args++;
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nb_oargs = arg >> 16;
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nb_iargs = arg & 0xffff;
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nb_params = nb_iargs - 1;
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    flags = args[nb_oargs + nb_iargs];
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
227886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_regs > nb_params)
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nb_regs = nb_params;
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* assign stack slots first */
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
228486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ~(TCG_TARGET_STACK_ALIGN - 1);
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (allocate_args) {
228898c6a2d2a100cca93f5112ab0ef6d24e51f931f8David 'Digit' Turner        /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
228998c6a2d2a100cca93f5112ab0ef6d24e51f931f8David 'Digit' Turner           preallocate call stack */
229098c6a2d2a100cca93f5112ab0ef6d24e51f931f8David 'Digit' Turner        tcg_abort();
22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = nb_regs; i < nb_params; i++) {
22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        arg = args[nb_oargs + i];
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCG_TARGET_STACK_GROWSUP
22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stack_offset -= sizeof(tcg_target_long);
22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arg != TCG_CALL_DUMMY_ARG) {
23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts = &s->temps[arg];
23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ts->val_type == TEMP_VAL_REG) {
23028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (ts->val_type == TEMP_VAL_MEM) {
230486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    s->reserved_regs);
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: not correct if reading values from the stack */
23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
23088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (ts->val_type == TEMP_VAL_CONST) {
231086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    s->reserved_regs);
23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: sign extend may be needed on some targets */
23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_movi(s, ts->type, reg, ts->val);
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_abort();
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef TCG_TARGET_STACK_GROWSUP
23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stack_offset += sizeof(tcg_target_long);
23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
232386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* assign input registers */
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_regset_set(allocated_regs, s->reserved_regs);
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < nb_regs; i++) {
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        arg = args[nb_oargs + i];
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arg != TCG_CALL_DUMMY_ARG) {
23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ts = &s->temps[arg];
23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            reg = tcg_target_call_iarg_regs[i];
23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_reg_free(s, reg);
23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ts->val_type == TEMP_VAL_REG) {
23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (ts->reg != reg) {
2334f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                    tcg_out_mov(s, ts->type, reg, ts->reg);
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (ts->val_type == TEMP_VAL_MEM) {
23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (ts->val_type == TEMP_VAL_CONST) {
23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: sign extend ? */
23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out_movi(s, ts->type, reg, ts->val);
23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
23428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_abort();
23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_regset_set_reg(allocated_regs, reg);
23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
234786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* assign function address */
23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    func_arg = args[nb_oargs + nb_iargs - 1];
23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    arg_ct = &def->args_ct[0];
23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ts = &s->temps[func_arg];
23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    func_addr = ts->val;
23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const_func_arg = 0;
23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ts->val_type == TEMP_VAL_MEM) {
23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
23568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        func_arg = reg;
23588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(allocated_regs, reg);
23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (ts->val_type == TEMP_VAL_REG) {
23608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = ts->reg;
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2363f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_mov(s, ts->type, reg, ts->reg);
23648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        func_arg = reg;
23668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(allocated_regs, reg);
23678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (ts->val_type == TEMP_VAL_CONST) {
23688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tcg_target_const_match(func_addr, arg_ct)) {
23698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const_func_arg = 1;
23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            func_arg = func_addr;
23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_out_movi(s, ts->type, reg, func_addr);
23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            func_arg = reg;
23758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_regset_set_reg(allocated_regs, reg);
23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
238086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
238186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* mark dead temporaries and free the associated registers */
238386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
238453a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner        if (IS_DEAD_ARG(i)) {
238586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_dead(s, args[i]);
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
238886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* clobber call registers */
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_reg_free(s, reg);
23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
239686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Save globals if they might be written by the helper, sync them if
239786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       they might be read. */
239886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (flags & TCG_CALL_NO_READ_GLOBALS) {
239986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Nothing to do */
240086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else if (flags & TCG_CALL_NO_WRITE_GLOBALS) {
240186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        sync_globals(s, allocated_regs);
240286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
24035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        save_globals(s, allocated_regs);
24045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_out_op(s, opc, &func_arg, &const_func_arg);
24075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* assign output registers and emit moves if needed */
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0; i < nb_oargs; i++) {
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        arg = args[i];
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ts = &s->temps[arg];
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = tcg_target_call_oarg_regs[i];
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        assert(s->reg_to_temp[reg] == -1);
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ts->fixed_reg) {
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ts->reg != reg) {
2416f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_mov(s, ts->type, ts->reg, reg);
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
241986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (ts->val_type == TEMP_VAL_REG) {
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->reg_to_temp[ts->reg] = -1;
242186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
242286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->val_type = TEMP_VAL_REG;
242386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->reg = reg;
242486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ts->mem_coherent = 0;
242586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            s->reg_to_temp[reg] = arg;
242686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (NEED_SYNC_ARG(i)) {
242786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_reg_sync(s, reg);
242886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
24290352ce4b5167ebc185bdec779e9642af75f1ccacDavid 'Digit' Turner            if (IS_DEAD_ARG(i)) {
243086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                temp_dead(s, args[i]);
24310352ce4b5167ebc185bdec779e9642af75f1ccacDavid 'Digit' Turner            }
24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
24338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
243486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
24358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return nb_iargs + nb_oargs + def->nb_cargs + 1;
24368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_PROFILER
24398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int64_t tcg_table_op_count[NB_OPS];
24418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2442f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void dump_op_count(void)
24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FILE *f;
24465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f = fopen("/tmp/op.log", "w");
24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = INDEX_op_end; i < NB_OPS; i++) {
24485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fclose(f);
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      long search_pc)
24578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2458f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCGOpcode opc;
2459f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int op_index;
24608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGOpDef *def;
24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const TCGArg *args;
24620b3979707c09e058442c22d046b326ce244edda1Andrew Hsieh
24638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DISAS
24645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
24655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("OP:\n");
246686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_dump_ops(s);
24675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("\n");
24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
24708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_PROFILER
247286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->opt_time -= profile_getclock();
247386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
247486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
247586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef USE_TCG_OPTIMIZATIONS
247686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->gen_opparam_ptr =
247786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_optimize(s, s->gen_opc_ptr, s->gen_opparam_buf, tcg_op_defs);
247886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
247986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
248086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef CONFIG_PROFILER
248186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->opt_time += profile_getclock();
24828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->la_time -= profile_getclock();
24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
248486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_liveness_analysis(s);
248686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
24878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_PROFILER
24888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->la_time += profile_getclock();
24898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
24908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DISAS
24925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
249386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        qemu_log("OP after optimization and liveness analysis:\n");
249486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_dump_ops(s);
24955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("\n");
24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_reg_alloc_start(s);
25008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->code_buf = gen_code_buf;
25028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->code_ptr = gen_code_buf;
25038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
250486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_tb_init(s);
250586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
2506975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    args = s->gen_opparam_buf;
25078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    op_index = 0;
25088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
2510975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner        opc = s->gen_opc_buf[op_index];
25118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_PROFILER
25125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tcg_table_op_count[opc]++;
25138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
25148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        def = &tcg_op_defs[opc];
25158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
25168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        printf("%s: %d %d %d\n", def->name,
25178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               def->nb_oargs, def->nb_iargs, def->nb_cargs);
25188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        //        dump_regs(s);
25198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
25208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(opc) {
25218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_mov_i32:
25228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_mov_i64:
252386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_reg_alloc_mov(s, def, args, s->op_dead_args[op_index],
252486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              s->op_sync_args[op_index]);
25258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
25268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_movi_i32:
25278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_movi_i64:
252886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_reg_alloc_movi(s, args, s->op_dead_args[op_index],
252986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                               s->op_sync_args[op_index]);
25308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
25318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_debug_insn_start:
25328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* debug instruction */
25338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
25348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_nop:
25358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_nop1:
25368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_nop2:
25378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_nop3:
25388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
25398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_nopn:
25408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args += args[0];
25418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto next;
25428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_discard:
254386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temp_dead(s, args[0]);
25448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
25458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_set_label:
25468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_reg_alloc_bb_end(s, s->reserved_regs);
254786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_label(s, args[0], s->code_ptr);
25488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_call:
255086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args += tcg_reg_alloc_call(s, def, opc, args,
255186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                       s->op_dead_args[op_index],
255286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                       s->op_sync_args[op_index]);
25538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto next;
25548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case INDEX_op_end:
25558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto the_end;
25568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
255786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* Sanity check that we've not introduced any unhandled opcodes. */
255886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (def->flags & TCG_OPF_NOT_PRESENT) {
255986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_abort();
256086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Note: in order to speed up the code, it would be much
25628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               faster to have specialized register allocator functions for
25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               some common argument patterns */
256486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_reg_alloc_op(s, def, opc, args, s->op_dead_args[op_index],
256586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                             s->op_sync_args[op_index]);
25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        args += def->nb_args;
25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    next:
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return op_index;
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op_index++;
25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef NDEBUG
25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        check_regs(s);
25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
25778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project the_end:
257986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Generate TB finalization at the end of block */
258086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_tb_finalize(s);
25818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
25828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
25858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_PROFILER
25878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int n;
2589975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner        n = (s->gen_opc_ptr - s->gen_opc_buf);
25908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->op_count += n;
25918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n > s->op_count_max)
25928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->op_count_max = n;
25938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->temp_count += s->nb_temps;
25958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->nb_temps > s->temp_count_max)
25968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->temp_count_max = s->nb_temps;
25978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
25998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_code_common(s, gen_code_buf, -1);
26018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* flush instruction cache */
260386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    flush_icache_range((uintptr_t)gen_code_buf, (uintptr_t)s->code_ptr);
260486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
26058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s->code_ptr -  gen_code_buf;
26068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the index of the micro operation such as the pc after is <
26098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   offset bytes from the start of the TB.  The contents of gen_code_buf must
26108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   not be changed, though writing the same values is ok.
26118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Return -1 if not found. */
26125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
26138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tcg_gen_code_common(s, gen_code_buf, offset);
26158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_PROFILER
2618f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnervoid tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
26198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGContext *s = &tcg_ctx;
26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t tot;
26228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tot = s->interm_time + s->code_time;
26248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
26258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tot, tot / 2.4e9);
262686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
262786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->tb_count,
26288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->tb_count1 - s->tb_count,
26298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
263086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n",
26318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
26328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
263386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->tb_count ?
26348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (double)s->del_op_count / s->tb_count : 0);
26358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
263686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->tb_count ?
26378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (double)s->temp_count / s->tb_count : 0,
26388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->temp_count_max);
263986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
264086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "cycles/op           %0.1f\n",
26418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->op_count ? (double)tot / s->op_count : 0);
264286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "cycles/in byte      %0.1f\n",
26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->code_in_len ? (double)tot / s->code_in_len : 0);
264486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "cycles/out byte     %0.1f\n",
26458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->code_out_len ? (double)tot / s->code_out_len : 0);
26468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tot == 0)
26478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tot = 1;
264886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n",
26498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (double)s->interm_time / tot * 100.0);
265086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "  gen_code time     %0.1f%%\n",
26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (double)s->code_time / tot * 100.0);
265286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "optim./code time    %0.1f%%\n",
265386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                (double)s->opt_time / (s->code_time ? s->code_time : 1)
265486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                * 100.0);
265586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    cpu_fprintf(f, "liveness/code time  %0.1f%%\n",
26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
26588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->restore_count);
26598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "  avg cycles        %0.1f\n",
26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2661b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner
2662b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner    dump_op_count();
26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2665f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnervoid tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
26668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "[TCG profiler not compiled]\n");
26688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
267086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
267186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef ELF_HOST_MACHINE
267286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* In order to use this feature, the backend needs to do three things:
267386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
267486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   (1) Define ELF_HOST_MACHINE to indicate both what value to
267586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       put into the ELF image and to indicate support for the feature.
267686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
267786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   (2) Define tcg_register_jit.  This should create a buffer containing
267886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       the contents of a .debug_frame section that describes the post-
267986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       prologue unwind info for the tcg machine.
268086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
268186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   (3) Call tcg_register_jit_int, with the constructed .debug_frame.
268286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner*/
268386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
268486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
268586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnertypedef enum {
268686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    JIT_NOACTION = 0,
268786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    JIT_REGISTER_FN,
268886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    JIT_UNREGISTER_FN
268986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner} jit_actions_t;
269086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
269186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstruct jit_code_entry {
269286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    struct jit_code_entry *next_entry;
269386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    struct jit_code_entry *prev_entry;
269486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const void *symfile_addr;
269586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint64_t symfile_size;
269686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
269786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
269886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstruct jit_descriptor {
269986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint32_t version;
270086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint32_t action_flag;
270186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    struct jit_code_entry *relevant_entry;
270286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    struct jit_code_entry *first_entry;
270386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
270486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
270586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid __jit_debug_register_code(void) __attribute__((noinline));
270686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid __jit_debug_register_code(void)
270786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
270886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    asm("");
270986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
271086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
271186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Must statically initialize the version, because GDB may check
271286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   the version before we can set it.  */
271386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstruct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
271486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
271586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* End GDB interface.  */
271686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
271786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic int find_string(const char *strtab, const char *str)
271886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
271986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const char *p = strtab + 1;
272086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
272186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    while (1) {
272286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (strcmp(p, str) == 0) {
272386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return p - strtab;
272486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
272586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        p += strlen(p) + 1;
272686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
272786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
272886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
272986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
273086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 void *debug_frame, size_t debug_frame_size)
273186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
273286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    struct __attribute__((packed)) DebugInfo {
273386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint32_t  len;
273486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint16_t  version;
273586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint32_t  abbrev;
273686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint8_t   ptr_size;
273786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint8_t   cu_die;
273886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint16_t  cu_lang;
273986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uintptr_t cu_low_pc;
274086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uintptr_t cu_high_pc;
274186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint8_t   fn_die;
274286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        char      fn_name[16];
274386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uintptr_t fn_low_pc;
274486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uintptr_t fn_high_pc;
274586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint8_t   cu_eoc;
274686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    };
274786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
274886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    struct ElfImage {
274986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ElfW(Ehdr) ehdr;
275086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ElfW(Phdr) phdr;
275186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ElfW(Shdr) shdr[7];
275286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ElfW(Sym)  sym[2];
275386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        struct DebugInfo di;
275486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint8_t    da[24];
275586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        char       str[80];
275686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    };
275786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
275886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    struct ElfImage *img;
275986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
276086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    static const struct ElfImage img_template = {
276186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        .ehdr = {
276286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_MAG0] = ELFMAG0,
276386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_MAG1] = ELFMAG1,
276486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_MAG2] = ELFMAG2,
276586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_MAG3] = ELFMAG3,
276686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_CLASS] = ELF_CLASS,
276786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_DATA] = ELF_DATA,
276886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_VERSION] = EV_CURRENT,
276986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_type = ET_EXEC,
277086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_machine = ELF_HOST_MACHINE,
277186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_version = EV_CURRENT,
277286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_phoff = offsetof(struct ElfImage, phdr),
277386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_shoff = offsetof(struct ElfImage, shdr),
277486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ehsize = sizeof(ElfW(Shdr)),
277586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_phentsize = sizeof(ElfW(Phdr)),
277686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_phnum = 1,
277786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_shentsize = sizeof(ElfW(Shdr)),
277886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_shnum = ARRAY_SIZE(img->shdr),
277986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
278086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef ELF_HOST_FLAGS
278186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_flags = ELF_HOST_FLAGS,
278286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
278386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef ELF_OSABI
278486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .e_ident[EI_OSABI] = ELF_OSABI,
278586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
278686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        },
278786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        .phdr = {
278886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .p_type = PT_LOAD,
278986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .p_flags = PF_X,
279086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        },
279186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        .shdr = {
279286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [0] = { .sh_type = SHT_NULL },
279386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* Trick: The contents of code_gen_buffer are not present in
279486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               this fake ELF file; that got allocated elsewhere.  Therefore
279586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               we mark .text as SHT_NOBITS (similar to .bss) so that readers
279686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               will not look for contents.  We can record any address.  */
279786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [1] = { /* .text */
279886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_type = SHT_NOBITS,
279986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
280086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            },
280186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [2] = { /* .debug_info */
280286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_type = SHT_PROGBITS,
280386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_offset = offsetof(struct ElfImage, di),
280486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_size = sizeof(struct DebugInfo),
280586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            },
280686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [3] = { /* .debug_abbrev */
280786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_type = SHT_PROGBITS,
280886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_offset = offsetof(struct ElfImage, da),
280986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_size = sizeof(img->da),
281086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            },
281186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [4] = { /* .debug_frame */
281286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_type = SHT_PROGBITS,
281386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_offset = sizeof(struct ElfImage),
281486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            },
281586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [5] = { /* .symtab */
281686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_type = SHT_SYMTAB,
281786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_offset = offsetof(struct ElfImage, sym),
281886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_size = sizeof(img->sym),
281986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_info = 1,
282086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_link = ARRAY_SIZE(img->shdr) - 1,
282186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_entsize = sizeof(ElfW(Sym)),
282286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            },
282386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [6] = { /* .strtab */
282486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_type = SHT_STRTAB,
282586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_offset = offsetof(struct ElfImage, str),
282686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .sh_size = sizeof(img->str),
282786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
282886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        },
282986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        .sym = {
283086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            [1] = { /* code_gen_buffer */
283186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
283286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                .st_shndx = 1,
283386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
283486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        },
283586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        .di = {
283686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .len = sizeof(struct DebugInfo) - 4,
283786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .version = 2,
283886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .ptr_size = sizeof(void *),
283986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .cu_die = 1,
284086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .cu_lang = 0x8001,  /* DW_LANG_Mips_Assembler */
284186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .fn_die = 2,
284286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            .fn_name = "code_gen_buffer"
284386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        },
284486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        .da = {
284586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            1,          /* abbrev number (the cu) */
284686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x11, 1,    /* DW_TAG_compile_unit, has children */
284786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x13, 0x5,  /* DW_AT_language, DW_FORM_data2 */
284886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
284986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
285086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0, 0,       /* end of abbrev */
285186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            2,          /* abbrev number (the fn) */
285286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x2e, 0,    /* DW_TAG_subprogram, no children */
285386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x3, 0x8,   /* DW_AT_name, DW_FORM_string */
285486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
285586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
285686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0, 0,       /* end of abbrev */
285786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            0           /* no more abbrev */
285886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        },
285986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
286086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
286186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    };
286286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
286386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* We only need a single jit entry; statically allocate it.  */
286486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    static struct jit_code_entry one_entry;
286586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
286686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uintptr_t buf = (uintptr_t)buf_ptr;
286786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
286886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
286986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img = g_malloc(img_size);
287086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *img = img_template;
287186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    memcpy(img + 1, debug_frame, debug_frame_size);
287286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
287386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->phdr.p_vaddr = buf;
287486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->phdr.p_paddr = buf;
287586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->phdr.p_memsz = buf_size;
287686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
287786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[1].sh_name = find_string(img->str, ".text");
287886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[1].sh_addr = buf;
287986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[1].sh_size = buf_size;
288086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
288186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[2].sh_name = find_string(img->str, ".debug_info");
288286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
288386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
288486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
288586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[4].sh_size = debug_frame_size;
288686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
288786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[5].sh_name = find_string(img->str, ".symtab");
288886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->shdr[6].sh_name = find_string(img->str, ".strtab");
288986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
289086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
289186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->sym[1].st_value = buf;
289286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->sym[1].st_size = buf_size;
289386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
289486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->di.cu_low_pc = buf;
289586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->di.cu_high_pc = buf + buf_size;
289686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->di.fn_low_pc = buf;
289786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    img->di.fn_high_pc = buf + buf_size;
289886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
289986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef DEBUG_JIT
290086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Enable this block to be able to debug the ELF image file creation.
290186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       One can use readelf, objdump, or other inspection utilities.  */
290286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    {
290386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        FILE *f = fopen("/tmp/qemu.jit", "w+b");
290486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (f) {
290586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (fwrite(img, img_size, 1, f) != img_size) {
290686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* Avoid stupid unused return value warning for fwrite.  */
290786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
290886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            fclose(f);
290986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
291086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
291186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
291286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
291386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    one_entry.symfile_addr = img;
291486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    one_entry.symfile_size = img_size;
291586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
291686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
291786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    __jit_debug_descriptor.relevant_entry = &one_entry;
291886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    __jit_debug_descriptor.first_entry = &one_entry;
291986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    __jit_debug_register_code();
292086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
292186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
292286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* No support for the feature.  Provide the entry point expected by exec.c,
292386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   and implement the internal function we declared earlier.  */
292486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
292586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_register_jit_int(void *buf, size_t size,
292686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 void *debug_frame, size_t debug_frame_size)
292786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
292886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
292986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
293086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_register_jit(void *buf, size_t buf_size)
293186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
293286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
293386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif /* ELF_HOST_MACHINE */
2934