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 */
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include "tcg-be-ldst.h"
2686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
2786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifdef _WIN32
2886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner// For some reason, the Mingw32 headers define the 'small' macro which
2986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner// prevents this source from compiling.
3086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#undef small
3186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
3286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef NDEBUG
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
36f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
37f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
38f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
39f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
40f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const int tcg_target_reg_alloc_order[] = {
45f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
46f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RBP,
47f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RBX,
48f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R12,
49f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R13,
50f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R14,
51f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R15,
52f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R10,
53f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R11,
54f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R9,
55f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R8,
56f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RCX,
57f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RDX,
58f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RSI,
59f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RDI,
60f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RAX,
61f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCG_REG_EBX,
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCG_REG_ESI,
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCG_REG_EDI,
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCG_REG_EBP,
6686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_REG_ECX,
6786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_REG_EDX,
6886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_REG_EAX,
69f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
70f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner};
71f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
72f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic const int tcg_target_call_iarg_regs[] = {
73f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
7486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if defined(_WIN64)
7586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_REG_RCX,
7686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_REG_RDX,
7786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
78f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RDI,
79f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RSI,
80f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RDX,
81f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RCX,
8286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
83f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R8,
84f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R9,
85f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
8686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* 32 bit mode uses stack based calling convention (GCC default). */
87f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic const int tcg_target_call_oarg_regs[] = {
91f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_EAX,
9286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 32
93f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_EDX
9486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
95f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner};
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Registers used with L constraint, which are the first argument
9886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   registers on x86_64, and two random call clobbered registers on
9986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   i386. */
10086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
10186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define TCG_REG_L0 tcg_target_call_iarg_regs[0]
10286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define TCG_REG_L1 tcg_target_call_iarg_regs[1]
10386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
10486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define TCG_REG_L0 TCG_REG_EAX
10586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define TCG_REG_L1 TCG_REG_EDX
10686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
10786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
10886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* For 32-bit, we are going to attempt to determine at runtime whether cmov
10986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   is available.  However, the host compiler must supply <cpuid.h>, as we're
11086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   not going to go so far as our own inline assembly.  */
11186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
11286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define have_cmov 1
11386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#elif defined(CONFIG_CPUID_H)
11486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include <cpuid.h>
11586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic bool have_cmov;
11686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
11786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define have_cmov 0
11886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
11986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint8_t *tb_ret_addr;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
122f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void patch_reloc(uint8_t *code_ptr, int type,
12386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        intptr_t value, intptr_t addend)
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    value += addend;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch(type) {
127f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case R_386_PC32:
128f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        value -= (uintptr_t)code_ptr;
129f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (value != (int32_t)value) {
130f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_abort();
131f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *(uint32_t *)code_ptr = value;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
134f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case R_386_PC8:
135f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        value -= (uintptr_t)code_ptr;
136f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (value != (int8_t)value) {
137f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_abort();
138f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
139f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        *(uint8_t *)code_ptr = value;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse target specific constraints */
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *ct_str;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ct_str = *pct_str;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch(ct_str[0]) {
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'a':
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'b':
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'c':
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'd':
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'S':
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'D':
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'q':
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
179f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
180f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_regset_set32(ct->u.regs, 0, 0xffff);
181f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
182f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_regset_set32(ct->u.regs, 0, 0xf);
183f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case 'Q':
18686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ct->ct |= TCG_CT_REG;
18786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_regset_set32(ct->u.regs, 0, 0xf);
18886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'r':
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
191f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
192f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_regset_set32(ct->u.regs, 0, 0xffff);
193f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
194f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_regset_set32(ct->u.regs, 0, 0xff);
195f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* qemu_ld/st address constraint */
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 'L':
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ct->ct |= TCG_CT_REG;
201f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
202f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_regset_set32(ct->u.regs, 0, 0xffff);
203f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
204f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_regset_set32(ct->u.regs, 0, 0xff);
205f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
20686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
20786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
209f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
210f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case 'e':
211f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        ct->ct |= TCG_CT_CONST_S32;
212f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
213f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case 'Z':
214f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        ct->ct |= TCG_CT_CONST_U32;
215f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
216f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ct_str++;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pct_str = ct_str;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* test if a constant matches the constraint */
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int tcg_target_const_match(tcg_target_long val,
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                         const TCGArgConstraint *arg_ct)
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
229f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int ct = arg_ct->ct;
230f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (ct & TCG_CT_CONST) {
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
232f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
233f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
234f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        return 1;
235f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
236f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
237f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        return 1;
238f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
239f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    return 0;
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
242f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
243f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define LOWREGMASK(x)	((x) & 7)
244f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
245f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define LOWREGMASK(x)	(x)
246f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
247f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
248f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define P_EXT		0x100		/* 0x0f opcode prefix */
249f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define P_DATA16	0x200		/* 0x66 opcode prefix */
250f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
251f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_ADDR32	0x400		/* 0x67 opcode prefix */
252f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_REXW		0x800		/* Set REX.W = 1 */
253f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_REXB_R	0x1000		/* REG field as byte register */
254f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_REXB_RM	0x2000		/* R/M field as byte register */
25586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define P_GS           0x4000          /* gs segment override */
256f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
257f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_ADDR32	0
258f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_REXW		0
259f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_REXB_R	0
260f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define P_REXB_RM	0
26186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define P_GS           0
262f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
263f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
264f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_ARITH_EvIz	(0x81)
265f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_ARITH_EvIb	(0x83)
266f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_ARITH_GvEv	(0x03)		/* ... plus (ARITH_FOO << 3) */
267f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_ADD_GvEv	(OPC_ARITH_GvEv | (ARITH_ADD << 3))
268f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_BSWAP	(0xc8 | P_EXT)
269f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_CALL_Jz	(0xe8)
27086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define OPC_CMOVCC      (0x40 | P_EXT)  /* ... plus condition code */
271f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_CMP_GvEv	(OPC_ARITH_GvEv | (ARITH_CMP << 3))
272f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_DEC_r32	(0x48)
273f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_IMUL_GvEv	(0xaf | P_EXT)
274f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_IMUL_GvEvIb	(0x6b)
275f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_IMUL_GvEvIz	(0x69)
276f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_INC_r32	(0x40)
277f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_JCC_long	(0x80 | P_EXT)	/* ... plus condition code */
278f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_JCC_short	(0x70)		/* ... plus condition code */
279f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_JMP_long	(0xe9)
280f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_JMP_short	(0xeb)
281f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_LEA         (0x8d)
282f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVB_EvGv	(0x88)		/* stores, more or less */
283f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVL_EvGv	(0x89)		/* stores, more or less */
284f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVL_GvEv	(0x8b)		/* loads, more or less */
28586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define OPC_MOVB_EvIz   (0xc6)
286f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVL_EvIz	(0xc7)
287f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVL_Iv     (0xb8)
288f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVSBL	(0xbe | P_EXT)
289f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVSWL	(0xbf | P_EXT)
290f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVSLQ	(0x63 | P_REXW)
291f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVZBL	(0xb6 | P_EXT)
292f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_MOVZWL	(0xb7 | P_EXT)
293f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_POP_r32	(0x58)
294f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_PUSH_r32	(0x50)
295f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_PUSH_Iv	(0x68)
296f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_PUSH_Ib	(0x6a)
297f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_RET		(0xc3)
298f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_SETCC	(0x90 | P_EXT | P_REXB_RM) /* ... plus cc */
299f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_SHIFT_1	(0xd1)
300f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_SHIFT_Ib	(0xc1)
301f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_SHIFT_cl	(0xd3)
302f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_TESTL	(0x85)
303f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_XCHG_ax_r32	(0x90)
304f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
305f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_GRP3_Ev	(0xf7)
306f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define OPC_GRP5	(0xff)
307f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
308f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Group 1 opcode extensions for 0x80-0x83.
309f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   These are also used as modifiers for OPC_ARITH.  */
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_ADD 0
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_OR  1
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_ADC 2
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_SBB 3
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_AND 4
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_SUB 5
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_XOR 6
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_CMP 7
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
319f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3.  */
3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define SHIFT_ROL 0
3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define SHIFT_ROR 1
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SHIFT_SHL 4
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SHIFT_SHR 5
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SHIFT_SAR 7
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
326f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Group 3 opcode extensions for 0xf6, 0xf7.  To be used with OPC_GRP3.  */
327f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT3_NOT   2
328f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT3_NEG   3
329f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT3_MUL   4
330f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT3_IMUL  5
331f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT3_DIV   6
332f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT3_IDIV  7
333f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
334f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Group 5 opcode extensions for 0xff.  To be used with OPC_GRP5.  */
335f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT5_INC_Ev	0
336f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT5_DEC_Ev	1
337f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT5_CALLN_Ev	2
338f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define EXT5_JMPN_Ev	4
339f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
340f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Condition codes to be added to OPC_JCC_{long,short}.  */
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JMP (-1)
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JO  0x0
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JNO 0x1
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JB  0x2
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JAE 0x3
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JE  0x4
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JNE 0x5
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JBE 0x6
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JA  0x7
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JS  0x8
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JNS 0x9
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JP  0xa
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JNP 0xb
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JL  0xc
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JGE 0xd
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JLE 0xe
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define JCC_JG  0xf
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic const uint8_t tcg_cond_to_jcc[] = {
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_EQ] = JCC_JE,
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_NE] = JCC_JNE,
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LT] = JCC_JL,
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GE] = JCC_JGE,
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LE] = JCC_JLE,
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GT] = JCC_JG,
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LTU] = JCC_JB,
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GEU] = JCC_JAE,
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_LEU] = JCC_JBE,
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    [TCG_COND_GTU] = JCC_JA,
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
372f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
373f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
374f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
375f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int rex;
376f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
37786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (opc & P_GS) {
37886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out8(s, 0x65);
37986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
380f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (opc & P_DATA16) {
381f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* We should never be asking for both 16 and 64-bit operation.  */
382f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        assert((opc & P_REXW) == 0);
383f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, 0x66);
384f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
385f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (opc & P_ADDR32) {
386f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, 0x67);
387f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
388f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
389f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    rex = 0;
390f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    rex |= (opc & P_REXW) >> 8;		/* REX.W */
391f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    rex |= (r & 8) >> 1;		/* REX.R */
392f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    rex |= (x & 8) >> 2;		/* REX.X */
393f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    rex |= (rm & 8) >> 3;		/* REX.B */
394f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
395f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* P_REXB_{R,RM} indicates that the given register is the low byte.
396f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
397f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       as otherwise the encoding indicates %[abcd]h.  Note that the values
398f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       that are ORed in merely indicate that the REX byte must be present;
399f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       those bits get discarded in output.  */
400f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    rex |= opc & (r >= 4 ? P_REXB_R : 0);
401f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
402f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
403f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (rex) {
404f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, (uint8_t)(rex | 0x40));
405f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
406f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
407f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (opc & P_EXT) {
408f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, 0x0f);
409f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
410f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out8(s, opc);
411f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
412f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
413f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_opc(TCGContext *s, int opc)
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
415f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (opc & P_DATA16) {
416f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, 0x66);
417f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
418f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (opc & P_EXT) {
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out8(s, 0x0f);
420f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_out8(s, opc);
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
423f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Discard the register arguments to tcg_out_opc early, so as not to penalize
424f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   the 32-bit compilation paths.  This method works with all versions of gcc,
425f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   whereas relying on optimization may not be able to exclude them.  */
426f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#define tcg_out_opc(s, opc, r, rm, x)  (tcg_out_opc)(s, opc)
427f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
429f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
431f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_opc(s, opc, r, rm, 0);
432f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
435f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
436f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   We handle either RM and INDEX missing with a negative value.  In 64-bit
437f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   mode for absolute addresses, ~RM is the size of the immediate operand
438f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   that will follow the instruction.  */
439f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
440f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
44186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                     int index, int shift, intptr_t offset)
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
443f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int mod, len;
444f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
445f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (index < 0 && rm < 0) {
446f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
447f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            /* Try for a rip-relative addressing mode.  This has replaced
448f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner               the 32-bit-mode absolute addressing encoding.  */
44986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            intptr_t pc = (intptr_t)s->code_ptr + 5 + ~rm;
45086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            intptr_t disp = offset - pc;
451f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (disp == (int32_t)disp) {
452f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_opc(s, opc, r, 0, 0);
453f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
454f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out32(s, disp);
455f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                return;
456f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
457f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
458f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            /* Try for an absolute address encoding.  This requires the
459f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner               use of the MODRM+SIB encoding and is therefore larger than
460f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner               rip-relative addressing.  */
461f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (offset == (int32_t)offset) {
462f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_opc(s, opc, r, 0, 0);
463f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out8(s, (LOWREGMASK(r) << 3) | 4);
464f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out8(s, (4 << 3) | 5);
465f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out32(s, offset);
466f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                return;
467f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
468f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
469f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            /* ??? The memory isn't directly addressable.  */
470f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_abort();
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
472f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            /* Absolute address.  */
473f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_opc(s, opc, r, 0, 0);
474f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out8(s, (r << 3) | 5);
475f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out32(s, offset);
476f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            return;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
478f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
479f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
480f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* Find the length of the immediate addend.  Note that the encoding
481f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       that would be used for (%ebp) indicates absolute addressing.  */
482f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (rm < 0) {
483f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        mod = 0, len = 4, rm = 5;
484f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
485f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        mod = 0, len = 0;
486f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else if (offset == (int8_t)offset) {
487f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        mod = 0x40, len = 1;
488f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else {
489f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        mod = 0x80, len = 4;
490f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
491f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
492f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* Use a single byte MODRM format if possible.  Note that the encoding
493f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       that would be used for %esp is the escape to the two byte form.  */
494f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
495f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* Single byte MODRM format.  */
496f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_opc(s, opc, r, rm, 0);
497f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
499f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* Two byte MODRM+SIB format.  */
500f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
501f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* Note that the encoding that would place %esp into the index
502f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner           field indicates no index register.  In 64-bit mode, the REX.X
503f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner           bit counts, so %r12 can be used as the index.  */
504f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (index < 0) {
505f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            index = 4;
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
507f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            assert(index != TCG_REG_ESP);
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
509f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
510f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_opc(s, opc, r, rm, index);
511f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | 4);
512f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, (shift << 6) | (LOWREGMASK(index) << 3) | LOWREGMASK(rm));
513f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
514f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
515f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (len == 1) {
516f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, offset);
517f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else if (len == 4) {
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out32(s, offset);
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
522f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* A simplification of the above with no index or shift.  */
523f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
52486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                        int rm, intptr_t offset)
525f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
526f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
527f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
528f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
529f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Generate dest op= src.  Uses the same ARITH_* codes as tgen_arithi.  */
530f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
531f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
532f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* Propagate an opcode prefix, such as P_REXW.  */
533f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int ext = subop & ~0x7;
534f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    subop &= 0x7;
535f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
536f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
537f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
538f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
53986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_out_mov(TCGContext *s, TCGType type,
54086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                               TCGReg ret, TCGReg arg)
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
542f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (arg != ret) {
543f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
544f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, opc, ret, arg);
545f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
548f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_movi(TCGContext *s, TCGType type,
54986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                         TCGReg ret, tcg_target_long arg)
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
55186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_target_long diff;
55286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arg == 0) {
554f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tgen_arithr(s, ARITH_XOR, ret, ret);
555f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        return;
55686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
55786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
558f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
559f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out32(s, arg);
56086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
56186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
56286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (arg == (int32_t)arg) {
563f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
564f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out32(s, arg);
56586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
566f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
56786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
56886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Try a 7 byte pc-relative lea before the 10 byte movq.  */
56986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    diff = arg - ((uintptr_t)s->code_ptr + 7);
57086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (diff == (int32_t)diff) {
57186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_opc(s, OPC_LEA | P_REXW, ret, 0, 0);
57286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out8(s, (LOWREGMASK(ret) << 3) | 5);
57386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out32(s, diff);
57486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return;
57586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
57686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
57786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
57886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out64(s, arg);
579f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
580f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
581f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
582f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
583f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (val == (int8_t)val) {
584f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_opc(s, OPC_PUSH_Ib, 0, 0, 0);
585f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, val);
586f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else if (val == (int32_t)val) {
587f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
588f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out32(s, val);
589f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else {
590f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_abort();
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
594f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_push(TCGContext *s, int reg)
595f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
596f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_opc(s, OPC_PUSH_r32 + LOWREGMASK(reg), 0, reg, 0);
597f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
598f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
599f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_pop(TCGContext *s, int reg)
600f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
601f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
602f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
603f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
60486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
60586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              TCGReg arg1, intptr_t arg2)
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
607f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
608f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
61186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
61286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              TCGReg arg1, intptr_t arg2)
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
614f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
615f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
61886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_out_sti(TCGContext *s, TCGType type, TCGReg base,
61986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                               tcg_target_long ofs, tcg_target_long val)
62086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
62186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int opc = OPC_MOVL_EvIz + (type == TCG_TYPE_I64 ? P_REXW : 0);
62286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_modrm_offset(s, opc, 0, base, ofs);
62386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out32(s, val);
62486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
62586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
626f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
628f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* Propagate an opcode prefix, such as P_DATA16.  */
629f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int ext = subopc & ~0x7;
630f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    subopc &= 0x7;
631f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
632f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (count == 1) {
633f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_SHIFT_1 + ext, subopc, reg);
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
635f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_SHIFT_Ib + ext, subopc, reg);
636f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, count);
637f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
638f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
639f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
640f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_bswap32(TCGContext *s, int reg)
641f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
642f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_opc(s, OPC_BSWAP + LOWREGMASK(reg), 0, reg, 0);
643f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
644f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
645f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_rolw_8(TCGContext *s, int reg)
646f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
647f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
648f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
649f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
650f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
651f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
652f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* movzbl */
653f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
654f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
655f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
656f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
657f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_ext8s(TCGContext *s, int dest, int src, int rexw)
658f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
659f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* movsbl */
660f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
661f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
662f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
663f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
664f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
665f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
666f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* movzwl */
667f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_MOVZWL, dest, src);
668f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
669f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
670f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
671f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
672f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* movsw[lq] */
673f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
674f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
675f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
676f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
677f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
678f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* 32-bit mov zero extends.  */
679f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
680f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
681f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
682f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
683f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
684f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
685f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
686f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
687f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_bswap64(TCGContext *s, int reg)
688f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
689f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
690f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
691f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
692f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tgen_arithi(TCGContext *s, int c, int r0,
693f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                        tcg_target_long val, int cf)
694f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
695f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int rexw = 0;
696f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
697f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 64) {
698f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        rexw = c & -8;
699f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        c &= 7;
700f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
701f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
702f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
703f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       partial flags update stalls on Pentium4 and are not recommended
704f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       by current Intel optimization manuals.  */
705f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
706f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int is_inc = (c == ARITH_ADD) ^ (val < 0);
707f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
708f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            /* The single-byte increment encodings are re-tasked as the
709f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner               REX prefixes.  Use the MODRM encoding.  */
710f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm(s, OPC_GRP5 + rexw,
711f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                          (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
712f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
713f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
714f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
715f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        return;
716f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
717f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
718f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (c == ARITH_AND) {
719f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
720f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (val == 0xffffffffu) {
721f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_ext32u(s, r0, r0);
722f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                return;
723f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
724f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (val == (uint32_t)val) {
725f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                /* AND with no high bits set can use a 32-bit operation.  */
726f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                rexw = 0;
727f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
728f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
729f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (val == 0xffu && (r0 < 4 || TCG_TARGET_REG_BITS == 64)) {
730f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_ext8u(s, r0, r0);
731f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            return;
732f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
733f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (val == 0xffffu) {
734f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_ext16u(s, r0, r0);
735f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            return;
736f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
737f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
738f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
739f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (val == (int8_t)val) {
740f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_ARITH_EvIb + rexw, c, r0);
741f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out8(s, val);
742f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        return;
743f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
744f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (rexw == 0 || val == (int32_t)val) {
745f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0);
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out32(s, val);
747f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        return;
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
749f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
750f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_abort();
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
755f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (val != 0) {
756f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tgen_arithi(s, ARITH_ADD + P_REXW, reg, val, 0);
757f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
760f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Use SMALL != 0 to force a short forward branch.  */
761f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int32_t val, val1;
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGLabel *l = &s->labels[label_index];
765f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (l->has_value) {
76786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        val = l->u.value - (intptr_t)s->code_ptr;
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val1 = val - 2;
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((int8_t)val1 == val1) {
770f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (opc == -1) {
771f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out8(s, OPC_JMP_short);
772f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            } else {
773f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out8(s, OPC_JCC_short + opc);
774f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_out8(s, val1);
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
777f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (small) {
778f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_abort();
779f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (opc == -1) {
781f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out8(s, OPC_JMP_long);
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out32(s, val - 5);
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
784f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out32(s, val - 6);
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
788f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else if (small) {
789f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (opc == -1) {
790f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out8(s, OPC_JMP_short);
791f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
792f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out8(s, OPC_JCC_short + opc);
793f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
794f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
795f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        s->code_ptr += 1;
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (opc == -1) {
798f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out8(s, OPC_JMP_long);
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
800f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->code_ptr += 4;
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
807f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
808f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                        int const_arg2, int rexw)
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (const_arg2) {
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arg2 == 0) {
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* test r, r */
813f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
815f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
818f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
822f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_brcond32(TCGContext *s, TCGCond cond,
823f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                             TCGArg arg1, TCGArg arg2, int const_arg2,
824f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                             int label_index, int small)
825f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
826f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
827f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
828f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
829f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
830f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
831f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_brcond64(TCGContext *s, TCGCond cond,
832f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                             TCGArg arg1, TCGArg arg2, int const_arg2,
833f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                             int label_index, int small)
834f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
835f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
836f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
837f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
838f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: we implement it at the target level to avoid having to
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   handle cross basic blocks temporaries */
841f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
842f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                            const int *const_args, int small)
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int label_next;
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    label_next = gen_new_label();
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch(args[4]) {
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_EQ:
848f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
849f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         label_next, 1);
850f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3],
851f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_NE:
854f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
855f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
856f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3],
857f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_LT:
860f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
861f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
862f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
863f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
864f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_LE:
867f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
868f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
869f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
870f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
871f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_GT:
874f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
875f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
876f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
877f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
878f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_GE:
881f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
882f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
883f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
884f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
885f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_LTU:
888f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
889f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
890f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
891f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
892f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_LEU:
895f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
896f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
897f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
898f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
899f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_GTU:
902f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
903f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
904f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
905f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
906f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TCG_COND_GEU:
909f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
910f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
911f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JNE, label_next, 1);
912f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
913f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[5], small);
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
91886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_label(s, label_next, s->code_ptr);
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
920f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
921f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
922f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest,
923f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                              TCGArg arg1, TCGArg arg2, int const_arg2)
924f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
925f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
926f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
927f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_ext8u(s, dest, dest);
928f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
929f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
930f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
931f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
932f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                              TCGArg arg1, TCGArg arg2, int const_arg2)
933f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
934f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
935f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
936f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_ext8u(s, dest, dest);
937f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
938f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
939f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
940f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                             const int *const_args)
941f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
942f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCGArg new_args[6];
943f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int label_true, label_over;
944f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
945f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    memcpy(new_args, args+1, 5*sizeof(TCGArg));
946f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
947f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (args[0] == args[1] || args[0] == args[2]
948f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        || (!const_args[3] && args[0] == args[3])
949f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        || (!const_args[4] && args[0] == args[4])) {
950f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* When the destination overlaps with one of the argument
951f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner           registers, don't do anything tricky.  */
952f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        label_true = gen_new_label();
953f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        label_over = gen_new_label();
954f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
955f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        new_args[5] = label_true;
956f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond2(s, new_args, const_args+1, 1);
957f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
958f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
959f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JMP, label_over, 1);
96086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_label(s, label_true, s->code_ptr);
961f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
962f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
96386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_label(s, label_over, s->code_ptr);
964f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else {
965f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* When the destination does not overlap one of the arguments,
966f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner           clear the destination first, jump if cond false, and emit an
967f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner           increment in the true case.  This results in smaller code.  */
968f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
969f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
970f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
971f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        label_over = gen_new_label();
972f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        new_args[4] = tcg_invert_cond(new_args[4]);
973f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        new_args[5] = label_over;
974f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond2(s, new_args, const_args+1, 1);
975f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
976f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
97786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_label(s, label_over, s->code_ptr);
97886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
97986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
98086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
98186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
98286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_movcond32(TCGContext *s, TCGCond cond, TCGArg dest,
98386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              TCGArg c1, TCGArg c2, int const_c2,
98486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              TCGArg v1)
98586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
98686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_cmp(s, c1, c2, const_c2, 0);
98786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (have_cmov) {
98886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond], dest, v1);
98986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
99086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        int over = gen_new_label();
99186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_jxx(s, tcg_cond_to_jcc[tcg_invert_cond(cond)], over, 1);
99286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_mov(s, TCG_TYPE_I32, dest, v1);
99386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_label(s, over, s->code_ptr);
994f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
995f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
99686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
99786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
99886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGArg dest,
99986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              TCGArg c1, TCGArg c2, int const_c2,
100086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                              TCGArg v1)
100186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
100286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_cmp(s, c1, c2, const_c2, P_REXW);
100386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond] | P_REXW, dest, v1);
100486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
1005f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
1006f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
100786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_branch(TCGContext *s, int call, uintptr_t dest)
1008f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
100986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    intptr_t disp = dest - (intptr_t)s->code_ptr - 5;
1010f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1011f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (disp == (int32_t)disp) {
1012f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
1013f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out32(s, disp);
1014f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else {
1015f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
1016f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_GRP5,
1017f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                      call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
1018f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
1019f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
1020f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
102186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_out_calli(TCGContext *s, uintptr_t dest)
1022f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
1023f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_branch(s, 1, dest);
1024f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
1025f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
102686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_jmp(TCGContext *s, uintptr_t dest)
1027f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
1028f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_branch(s, 0, dest);
1029f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_SOFTMMU)
103286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
103386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner *                                     int mmu_idx, uintptr_t ra)
103486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner */
103586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic const void * const qemu_ld_helpers[16] = {
103686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UB]   = helper_ret_ldub_mmu,
103786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEUW] = helper_le_lduw_mmu,
103886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEUL] = helper_le_ldul_mmu,
103986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEQ]  = helper_le_ldq_mmu,
104086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEUW] = helper_be_lduw_mmu,
104186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEUL] = helper_be_ldul_mmu,
104286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEQ]  = helper_be_ldq_mmu,
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
104586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
104686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
104786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner */
104886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic const void * const qemu_st_helpers[16] = {
104986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_UB]   = helper_ret_stb_mmu,
105086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEUW] = helper_le_stw_mmu,
105186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEUL] = helper_le_stl_mmu,
105286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_LEQ]  = helper_le_stq_mmu,
105386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEUW] = helper_be_stw_mmu,
105486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEUL] = helper_be_stl_mmu,
105586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    [MO_BEQ]  = helper_be_stq_mmu,
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1058f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* Perform the TLB load and compare.
1059b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner
1060f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   Inputs:
106186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   ADDRLO and ADDRHI contain the low and high part of the address.
1062f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1063f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   MEM_INDEX and S_BITS are the memory context and log2 size of the load.
1064f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1065f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   WHICH is the offset into the CPUTLBEntry structure of the slot to read.
1066f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   This should be offsetof addr_read or addr_write.
1067f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1068f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   Outputs:
1069f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
1070f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   positions of the displacements of forward jumps to the TLB miss case.
1071f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
107286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   Second argument register is loaded with the low part of the address.
1073f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   In the TLB hit case, it has been adjusted as indicated by the TLB
1074f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   and so is a host address.  In the TLB miss case, it continues to
1075f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   hold a guest address.
1076f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
107786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   First argument register is clobbered.  */
1078f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
107986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
108086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                    int mem_index, TCGMemOp s_bits,
1081f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                                    uint8_t **label_ptr, int which)
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
108386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGReg r0 = TCG_REG_L0;
108486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGReg r1 = TCG_REG_L1;
108586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGType ttype = TCG_TYPE_I32;
108686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGType htype = TCG_TYPE_I32;
108786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int trexw = 0, hrexw = 0;
1088f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
108986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 64) {
109086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (TARGET_LONG_BITS == 64) {
109186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ttype = TCG_TYPE_I64;
109286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            trexw = P_REXW;
109386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
109486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (TCG_TYPE_PTR == TCG_TYPE_I64) {
109586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            htype = TCG_TYPE_I64;
109686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            hrexw = P_REXW;
109786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
1098f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
110086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_mov(s, htype, r0, addrlo);
110186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_mov(s, ttype, r1, addrlo);
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
110386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_shifti(s, SHIFT_SHR + hrexw, r0,
1104f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                   TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
110686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tgen_arithi(s, ARITH_AND + trexw, r1,
1107f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
110886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tgen_arithi(s, ARITH_AND + hrexw, r0,
1109f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
1110f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
111186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_modrm_sib_offset(s, OPC_LEA + hrexw, r0, TCG_AREG0, r0, 0,
111286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                             offsetof(CPUArchState, tlb_table[mem_index][0])
1113f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                             + which);
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
111586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* cmp 0(r0), r1 */
111686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw, r1, r0, 0);
1117f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
111886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Prepare for both the fast path add of the tlb addend, and the slow
111986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       path function argument setup.  There are two cases worth note:
112086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       For 32-bit guest and x86_64 host, MOVL zero-extends the guest address
112186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       before the fastpath ADDQ below.  For 64-bit guest and x32 host, MOVQ
112286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       copies the entire guest address for the slow path, while truncation
112386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       for the 32-bit host happens with the fastpath ADDL below.  */
112486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_mov(s, ttype, r1, addrlo);
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
112686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* jne slow_path */
112786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
1128f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    label_ptr[0] = s->code_ptr;
112986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s->code_ptr += 4;
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1131f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
113286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* cmp 4(r0), addrhi */
113386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, r0, 4);
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
113586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* jne slow_path */
113686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
1137f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        label_ptr[1] = s->code_ptr;
113886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        s->code_ptr += 4;
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1141f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* TLB Hit.  */
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
114386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* add addend(r0), r1 */
114486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r1, r0,
1145f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         offsetof(CPUTLBEntry, addend) - which);
1146f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
114786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
114886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/*
114986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * Record the context of a call to the out of line helper code for the slow path
115086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * for a load or store, so that we can later generate the correct helper code
115186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner */
115286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
115386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                TCGReg datalo, TCGReg datahi,
115486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                TCGReg addrlo, TCGReg addrhi,
115586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                int mem_index, uint8_t *raddr,
115686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                uint8_t **label_ptr)
115786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
115886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGLabelQemuLdst *label = new_ldst_label(s);
115986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
116086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->is_ld = is_ld;
116186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->opc = opc;
116286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->datalo_reg = datalo;
116386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->datahi_reg = datahi;
116486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->addrlo_reg = addrlo;
116586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->addrhi_reg = addrhi;
116686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->mem_index = mem_index;
116786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->raddr = raddr;
116886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    label->label_ptr[0] = label_ptr[0];
116986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
117086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        label->label_ptr[1] = label_ptr[1];
117186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
117286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
117386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
117486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/*
117586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * Generate code for the slow path for a load at the end of block
117686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner */
117786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
117886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
117986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGMemOp opc = l->opc;
118086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGReg data_reg;
118186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t **label_ptr = &l->label_ptr[0];
118286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
118386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* resolve label address */
118486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
118586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
118686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
118786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
118886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
118986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 32) {
119086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        int ofs = 0;
119186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
119286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
119386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ofs += 4;
119486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
119586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
119686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ofs += 4;
119786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
119886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (TARGET_LONG_BITS == 64) {
119986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
120086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ofs += 4;
120186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
120286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
120386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
120486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ofs += 4;
120586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
120686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, (uintptr_t)l->raddr);
120786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
120886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
120986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* The second argument is already loaded with addrlo.  */
121086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
121186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                     l->mem_index);
121286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[3],
121386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                     (uintptr_t)l->raddr);
121486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
121586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
121686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[opc & ~MO_SIGN]);
121786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
121886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    data_reg = l->datalo_reg;
121986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (opc & MO_SSIZE) {
122086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_SB:
122186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
122286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
122386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_SW:
122486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
122586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
122686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
122786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_SL:
122886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
122986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
123186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_UB:
123286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_UW:
123386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Note that the helpers have zero-extended to tcg_target_long.  */
123486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_UL:
123586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
123686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
123786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_Q:
123886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
123986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
124086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else if (data_reg == TCG_REG_EDX) {
124186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* xchg %edx, %eax */
124286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
124386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EAX);
124486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
124586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
124686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EDX);
124786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
124886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
124986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    default:
125086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_abort();
125186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
125286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
125386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Jump to the code corresponding to next IR of qemu_st */
125486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_jmp(s, (uintptr_t)l->raddr);
125586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
125686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
125786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/*
125886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * Generate code for the slow path for a store at the end of block
125986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner */
126086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
126186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
126286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGMemOp opc = l->opc;
126386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGMemOp s_bits = opc & MO_SIZE;
126486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t **label_ptr = &l->label_ptr[0];
126586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGReg retaddr;
126686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
126786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* resolve label address */
126886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
126986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
127086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
127186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
127286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
127386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 32) {
127486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        int ofs = 0;
127586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
127686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
127786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ofs += 4;
127886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
127986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
128086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ofs += 4;
128186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
128286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (TARGET_LONG_BITS == 64) {
128386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
128486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ofs += 4;
128586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
128686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
128786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, TCG_TYPE_I32, l->datalo_reg, TCG_REG_ESP, ofs);
128886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ofs += 4;
128986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
129086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (s_bits == MO_64) {
129186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_st(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_ESP, ofs);
129286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            ofs += 4;
129386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
129486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
129586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
129686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        ofs += 4;
129786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
129886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        retaddr = TCG_REG_EAX;
129986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_I32, retaddr, (uintptr_t)l->raddr);
130086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_st(s, TCG_TYPE_I32, retaddr, TCG_REG_ESP, ofs);
130186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
130286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
130386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* The second argument is already loaded with addrlo.  */
130486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_mov(s, (s_bits == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
130586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    tcg_target_call_iarg_regs[2], l->datalo_reg);
130686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
130786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                     l->mem_index);
130886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
130986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (ARRAY_SIZE(tcg_target_call_iarg_regs) > 4) {
131086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            retaddr = tcg_target_call_iarg_regs[4];
131186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
131286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
131386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            retaddr = TCG_REG_RAX;
131486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
131586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP, 0);
131686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
131786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
131886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
131986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* "Tail call" to the helper, with the return address back inline.  */
132086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_push(s, retaddr);
132186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[opc]);
132286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
132386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#elif defined(__x86_64__) && defined(__linux__)
132486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# include <asm/prctl.h>
132586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# include <sys/prctl.h>
132686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
132786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerint arch_prctl(int code, unsigned long addr);
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
132986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic int guest_base_flags;
133086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void setup_guest_base_seg(void)
1331f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
133286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (arch_prctl(ARCH_SET_GS, GUEST_BASE) == 0) {
133386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        guest_base_flags = P_GS;
133486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
133586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
133786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner# define guest_base_flags 0
133886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic inline void setup_guest_base_seg(void) { }
133986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif /* SOFTMMU */
134086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
134186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
134286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                   TCGReg base, intptr_t ofs, int seg,
134386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                   TCGMemOp memop)
134486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
134586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGMemOp bswap = memop & MO_BSWAP;
134686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
134786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (memop & MO_SSIZE) {
134886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_UB:
134986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVZBL + seg, datalo, base, ofs);
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
135186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_SB:
135286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW + seg, datalo, base, ofs);
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
135486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_UW:
135586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bswap) {
1357f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_rolw_8(s, datalo);
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
136086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_SW:
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bswap) {
136286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
1363f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_rolw_8(s, datalo);
1364f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
1365f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
136686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW + seg,
136786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 datalo, base, ofs);
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
137086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_UL:
137186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bswap) {
1373f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_bswap32(s, datalo);
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1376f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
137786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_SL:
1378f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (bswap) {
137986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
1380f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_bswap32(s, datalo);
1381f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_ext32s(s, datalo, datalo);
1382f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
138386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVSLQ + seg, datalo, base, ofs);
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1385f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1386f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
138786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_Q:
1388f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
138986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_GvEv + P_REXW + seg,
139086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 datalo, base, ofs);
1391f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (bswap) {
1392f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_bswap64(s, datalo);
1393f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
1395f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (bswap) {
1396f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                int t = datalo;
1397f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                datalo = datahi;
1398f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                datahi = t;
1399f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
1400f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (base != datalo) {
140186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
140286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                     datalo, base, ofs);
140386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
140486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                     datahi, base, ofs + 4);
1405f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            } else {
140686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
140786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                     datahi, base, ofs + 4);
140886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg,
140986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                     datalo, base, ofs);
1410f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
1411f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (bswap) {
1412f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_bswap32(s, datalo);
1413f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_bswap32(s, datahi);
1414f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1422f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
1423f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   EAX. It will be useful once fixed registers globals are less
1424f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner   common. */
142586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
142786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGReg datalo, datahi, addrlo;
142886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGReg addrhi __attribute__((unused));
142986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGMemOp opc;
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_SOFTMMU)
143186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int mem_index;
143286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGMemOp s_bits;
143386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t *label_ptr[2];
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
143686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    datalo = *args++;
143786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
143886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    addrlo = *args++;
143986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
144086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    opc = *args++;
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1442f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(CONFIG_SOFTMMU)
144386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    mem_index = *args++;
144486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s_bits = opc & MO_SIZE;
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
144686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_tlb_load(s, addrlo, addrhi, mem_index, s_bits,
1447f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                     label_ptr, offsetof(CPUTLBEntry, addr_read));
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1449f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* TLB Hit.  */
145086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
1451f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
145286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Record the current context of a load into ldst label */
145386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
145486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        mem_index, s->code_ptr, label_ptr);
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1456f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    {
1457f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int32_t offset = GUEST_BASE;
145886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        TCGReg base = addrlo;
145986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        int seg = 0;
146086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
146186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* ??? We assume all operations have left us with register contents
146286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           that are zero extended.  So far this appears to be true.  If we
146386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           want to enforce this, we can either do an explicit zero-extension
146486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           here, or (if GUEST_BASE == 0, or a segment register is in use)
146586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           use the ADDR32 prefix.  For now, do nothing.  */
146686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (GUEST_BASE && guest_base_flags) {
146786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            seg = guest_base_flags;
146886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            offset = 0;
146986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) {
147086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE);
147186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base);
147286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            base = TCG_REG_L1;
147386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            offset = 0;
1474f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1475f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
147686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_qemu_ld_direct(s, datalo, datahi, base, offset, seg, opc);
1477f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1479f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
148186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
148286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                   TCGReg base, intptr_t ofs, int seg,
148386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                   TCGMemOp memop)
1484f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
148586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGMemOp bswap = memop & MO_BSWAP;
148686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
1487f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* ??? Ideally we wouldn't need a scratch register.  For user-only,
1488f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       we could perform the bswap twice to restore the original value
1489f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner       instead of moving to the scratch.  But as it is, the L constraint
149086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       means that TCG_REG_L0 is definitely free here.  */
149186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGReg scratch = TCG_REG_L0;
149286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
149386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (memop & MO_SIZE) {
149486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_8:
149586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* In 32-bit mode, 8-byte stores can only happen from [abcd]x.
149686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           Use the scratch register if necessary.  */
149786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 32 && datalo >= 4) {
149886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
149986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            datalo = scratch;
150086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
150186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg,
150286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                             datalo, base, ofs);
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
150486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_16:
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bswap) {
1506f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1507f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_rolw_8(s, scratch);
1508f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            datalo = scratch;
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
151086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16 + seg,
151186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                             datalo, base, ofs);
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
151386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_32:
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bswap) {
1515f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1516f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_bswap32(s, scratch);
1517f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            datalo = scratch;
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
151986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs);
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
152186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case MO_64:
1522f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (TCG_TARGET_REG_BITS == 64) {
1523f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (bswap) {
1524f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
1525f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_bswap64(s, scratch);
1526f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                datalo = scratch;
1527f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
152886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_REXW + seg,
152986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 datalo, base, ofs);
1530f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else if (bswap) {
1531f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
1532f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_bswap32(s, scratch);
153386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, scratch, base, ofs);
1534f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1535f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_bswap32(s, scratch);
153686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, scratch, base, ofs+4);
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
153886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs);
153986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datahi, base, ofs+4);
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1545f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner}
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
154786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
1548f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner{
154986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGReg datalo, datahi, addrlo;
155086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGReg addrhi __attribute__((unused));
155186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGMemOp opc;
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_SOFTMMU)
155386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int mem_index;
155486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGMemOp s_bits;
155586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t *label_ptr[2];
1556f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
1557f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
155886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    datalo = *args++;
155986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
156086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    addrlo = *args++;
156186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
156286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    opc = *args++;
1563f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1564f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if defined(CONFIG_SOFTMMU)
156586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    mem_index = *args++;
156686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    s_bits = opc & MO_SIZE;
1567f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
156886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_tlb_load(s, addrlo, addrhi, mem_index, s_bits,
1569f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                     label_ptr, offsetof(CPUTLBEntry, addr_write));
1570f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1571f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* TLB Hit.  */
157286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
1573f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
157486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Record the current context of a store into ldst label */
157586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
157686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        mem_index, s->code_ptr, label_ptr);
1577f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
1578f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    {
1579f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        int32_t offset = GUEST_BASE;
158086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        TCGReg base = addrlo;
158186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        int seg = 0;
158286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
158386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* ??? We assume all operations have left us with register contents
158486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           that are zero extended.  So far this appears to be true.  If we
158586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           want to enforce this, we can either do an explicit zero-extension
158686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           here, or (if GUEST_BASE == 0, or a segment register is in use)
158786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           use the ADDR32 prefix.  For now, do nothing.  */
158886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (GUEST_BASE && guest_base_flags) {
158986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            seg = guest_base_flags;
159086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            offset = 0;
159186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) {
159286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE);
159386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base);
159486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            base = TCG_REG_L1;
159586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            offset = 0;
1596f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1597f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
159886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);
1599f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1603f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              const TCGArg *args, const int *const_args)
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1606f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    int c, rexw = 0;
1607f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1608f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
1609f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define OP_32_64(x) \
1610f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        case glue(glue(INDEX_op_, x), _i64): \
1611f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            rexw = P_REXW; /* FALLTHRU */    \
1612f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        case glue(glue(INDEX_op_, x), _i32)
1613f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
1614f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner# define OP_32_64(x) \
1615f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        case glue(glue(INDEX_op_, x), _i32)
1616f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
1617f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch(opc) {
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_exit_tb:
1620f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
162186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_jmp(s, (uintptr_t)tb_ret_addr);
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_goto_tb:
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->tb_jmp_offset) {
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* direct jump method */
1626f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out8(s, OPC_JMP_long); /* jmp im */
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_out32(s, 0);
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* indirect jump method */
1631f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
163286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 (intptr_t)(s->tb_next + args[0]));
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_call:
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (const_args[0]) {
1638f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_calli(s, args[0]);
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
1640f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            /* call *reg */
1641f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_br:
1645f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_jxx(s, JCC_JMP, args[0], 0);
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_movi_i32:
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1650f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ld8u):
1651f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
1652f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1654f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ld8s):
1655f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVSBL + rexw, args[0], args[1], args[2]);
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1657f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ld16u):
1658f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
1659f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1661f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ld16s):
1662f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVSWL + rexw, args[0], args[1], args[2]);
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1664f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
1665f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_ld32u_i64:
1666f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_ld_i32:
1668f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1670f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1671f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(st8):
167286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (const_args[0]) {
167386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVB_EvIz,
167486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 0, args[1], args[2]);
167586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out8(s, args[0]);
167686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
167786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
167886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 args[0], args[1], args[2]);
167986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1681f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(st16):
168286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (const_args[0]) {
168386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_DATA16,
168486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 0, args[1], args[2]);
168586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out16(s, args[0]);
168686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
168786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
168886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 args[0], args[1], args[2]);
168986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1691f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
1692f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_st32_i64:
1693f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_st_i32:
169586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (const_args[0]) {
169686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvIz, 0, args[1], args[2]);
169786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out32(s, args[0]);
169886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
169986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
170086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1702f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1703f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(add):
1704f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        /* For 3-operand addition, use LEA.  */
1705f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (args[0] != args[1]) {
1706f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
1707f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1708f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            if (const_args[2]) {
1709f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                c3 = a2, a2 = -1;
1710f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            } else if (a0 == a2) {
1711f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                /* Watch out for dest = src + dest, since we've removed
1712f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                   the matching constraint on the add.  */
1713f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
1714f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                break;
1715f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            }
1716f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1717f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
1718f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            break;
1719f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1720f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        c = ARITH_ADD;
1721f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        goto gen_arith;
1722f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(sub):
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = ARITH_SUB;
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto gen_arith;
1725f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(and):
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = ARITH_AND;
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto gen_arith;
1728f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(or):
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = ARITH_OR;
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto gen_arith;
1731f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(xor):
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = ARITH_XOR;
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto gen_arith;
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_arith:
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (const_args[2]) {
1736f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tgen_arithi(s, c + rexw, args[0], args[2], 0);
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
1738f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tgen_arithr(s, c + rexw, args[0], args[2]);
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1741f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1742f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(mul):
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (const_args[2]) {
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int32_t val;
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = args[2];
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (val == (int8_t)val) {
1747f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_modrm(s, OPC_IMUL_GvEvIb + rexw, args[0], args[0]);
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out8(s, val);
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
1750f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                tcg_out_modrm(s, OPC_IMUL_GvEvIz + rexw, args[0], args[0]);
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_out32(s, val);
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
1754f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm(s, OPC_IMUL_GvEv + rexw, args[0], args[2]);
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1757f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1758f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(div2):
1759f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1761f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(divu2):
1762f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1764f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1765f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(shl):
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = SHIFT_SHL;
1767f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        goto gen_shift;
1768f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(shr):
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = SHIFT_SHR;
1770f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        goto gen_shift;
1771f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(sar):
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        c = SHIFT_SAR;
1773f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        goto gen_shift;
1774f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(rotl):
17755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        c = SHIFT_ROL;
1776f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        goto gen_shift;
1777f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(rotr):
17785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        c = SHIFT_ROR;
1779f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        goto gen_shift;
1780f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    gen_shift:
1781f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (const_args[2]) {
1782f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_shifti(s, c + rexw, args[0], args[2]);
1783f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
1784f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner            tcg_out_modrm(s, OPC_SHIFT_cl + rexw, c, args[0]);
1785f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1787f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case INDEX_op_brcond_i32:
1789f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond32(s, args[2], args[0], args[1], const_args[1],
1790f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[3], 0);
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1792f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_setcond_i32:
1793f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_setcond32(s, args[3], args[0], args[1],
1794f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                          args[2], const_args[2]);
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
179686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_movcond_i32:
179786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_movcond32(s, args[5], args[0], args[1],
179886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                          args[2], const_args[2], args[3]);
179986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1801f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(bswap16):
1802f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_rolw_8(s, args[0]);
18035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1804f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(bswap32):
1805f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_bswap32(s, args[0]);
18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1808f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(neg):
1809f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, args[0]);
18105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1811f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(not):
1812f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, args[0]);
18135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1815f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ext8s):
1816f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ext8s(s, args[0], args[1], rexw);
18175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1818f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ext16s):
1819f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ext16s(s, args[0], args[1], rexw);
18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1821f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ext8u):
1822f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ext8u(s, args[0], args[1]);
1823b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        break;
1824f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    OP_32_64(ext16u):
1825f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ext16u(s, args[0], args[1]);
1826b9317727862dd690cc67bb51f71991c404f9e4f6David 'Digit' Turner        break;
18275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
182886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_qemu_ld_i32:
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_qemu_ld(s, args, 0);
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
183186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_qemu_ld_i64:
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_qemu_ld(s, args, 1);
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
183486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_qemu_st_i32:
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_qemu_st(s, args, 0);
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
183786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_qemu_st_i64:
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_qemu_st(s, args, 1);
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
184186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    OP_32_64(mulu2):
184286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_MUL, args[3]);
1843f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
184486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    OP_32_64(muls2):
184586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IMUL, args[3]);
1846f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
184786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    OP_32_64(add2):
1848f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (const_args[4]) {
184986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithi(s, ARITH_ADD + rexw, args[0], args[4], 1);
1850f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
185186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithr(s, ARITH_ADD + rexw, args[0], args[4]);
1852f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1853f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (const_args[5]) {
185486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithi(s, ARITH_ADC + rexw, args[1], args[5], 1);
1855f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
185686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithr(s, ARITH_ADC + rexw, args[1], args[5]);
1857f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1858f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
185986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    OP_32_64(sub2):
1860f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (const_args[4]) {
186186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithi(s, ARITH_SUB + rexw, args[0], args[4], 1);
1862f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
186386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithr(s, ARITH_SUB + rexw, args[0], args[4]);
1864f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1865f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        if (const_args[5]) {
186686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithi(s, ARITH_SBB + rexw, args[1], args[5], 1);
1867f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        } else {
186886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tgen_arithr(s, ARITH_SBB + rexw, args[1], args[5]);
1869f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        }
1870f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
187186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
187286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 32
187386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_brcond2_i32:
187486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_brcond2(s, args, const_args, 0);
187586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
187686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_setcond2_i32:
187786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_setcond2(s, args, const_args);
187886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
1879f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else /* TCG_TARGET_REG_BITS == 64 */
1880f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_movi_i64:
1881f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
1882f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1883f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_ld32s_i64:
1884f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
1885f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1886f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_ld_i64:
1887f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
1888f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1889f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_st_i64:
189086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (const_args[0]) {
189186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_REXW,
189286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                 0, args[1], args[2]);
189386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out32(s, args[0]);
189486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
189586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
189686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
1897f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1898f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1899f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_brcond_i64:
1900f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
1901f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                         args[3], 0);
1902f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1903f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_setcond_i64:
1904f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_setcond64(s, args[3], args[0], args[1],
1905f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner                          args[2], const_args[2]);
1906f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
190786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_movcond_i64:
190886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_out_movcond64(s, args[5], args[0], args[1],
190986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                          args[2], const_args[2], args[3]);
191086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
1911f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1912f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_bswap64_i64:
1913f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_bswap64(s, args[0]);
1914f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1915f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_ext32u_i64:
1916f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ext32u(s, args[0], args[1]);
1917f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1918f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    case INDEX_op_ext32s_i64:
1919f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_out_ext32s(s, args[0], args[1]);
1920f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        break;
1921f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
1922f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
192386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    OP_32_64(deposit):
192486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (args[3] == 0 && args[4] == 8) {
192586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* load bits 0..7 */
192686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM,
192786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                          args[2], args[0]);
192886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else if (args[3] == 8 && args[4] == 8) {
192986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* load bits 8..15 */
193086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm(s, OPC_MOVB_EvGv, args[2], args[0] + 4);
193186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else if (args[3] == 0 && args[4] == 16) {
193286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* load bits 0..15 */
193386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, args[2], args[0]);
193486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
193586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_abort();
193686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
193786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        break;
193886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_abort();
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1942f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1943f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#undef OP_32_64
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const TCGTargetOpDef x86_op_defs[] = {
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_exit_tb, { } },
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_goto_tb, { } },
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_call, { "ri" } },
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_br, { } },
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_mov_i32, { "r", "r" } },
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_movi_i32, { "r" } },
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_ld8u_i32, { "r", "r" } },
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_ld8s_i32, { "r", "r" } },
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_ld16u_i32, { "r", "r" } },
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_ld16s_i32, { "r", "r" } },
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_ld_i32, { "r", "r" } },
195886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_st8_i32, { "qi", "r" } },
195986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_st16_i32, { "ri", "r" } },
196086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_st_i32, { "ri", "r" } },
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1962f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_add_i32, { "r", "r", "ri" } },
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_sub_i32, { "r", "0", "ri" } },
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_mul_i32, { "r", "0", "ri" } },
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_and_i32, { "r", "0", "ri" } },
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_or_i32, { "r", "0", "ri" } },
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_xor_i32, { "r", "0", "ri" } },
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_shl_i32, { "r", "0", "ci" } },
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_shr_i32, { "r", "0", "ci" } },
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_sar_i32, { "r", "0", "ci" } },
19745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_rotl_i32, { "r", "0", "ci" } },
19755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_rotr_i32, { "r", "0", "ci" } },
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { INDEX_op_brcond_i32, { "r", "ri" } },
19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_bswap16_i32, { "r", "0" } },
19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_bswap32_i32, { "r", "0" } },
19815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_neg_i32, { "r", "0" } },
19835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_not_i32, { "r", "0" } },
19855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_ext8s_i32, { "r", "q" } },
19875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    { INDEX_op_ext16s_i32, { "r", "r" } },
1988f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext8u_i32, { "r", "q" } },
1989f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext16u_i32, { "r", "r" } },
1990f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
1991f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_setcond_i32, { "q", "r", "ri" } },
19925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
199386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_deposit_i32, { "Q", "0", "Q" } },
199486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_HAS_movcond_i32
199586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } },
199686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
199786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
1998f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
199986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_muls2_i32, { "a", "d", "a", "r" } },
2000f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
2001f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
200286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
200386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 32
2004f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
2005f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
2006f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
2007f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_mov_i64, { "r", "r" } },
2008f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_movi_i64, { "r" } },
2009f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ld8u_i64, { "r", "r" } },
2010f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ld8s_i64, { "r", "r" } },
2011f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ld16u_i64, { "r", "r" } },
2012f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ld16s_i64, { "r", "r" } },
2013f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ld32u_i64, { "r", "r" } },
2014f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ld32s_i64, { "r", "r" } },
2015f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ld_i64, { "r", "r" } },
201686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_st8_i64, { "ri", "r" } },
201786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_st16_i64, { "ri", "r" } },
201886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_st32_i64, { "ri", "r" } },
201986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_st_i64, { "re", "r" } },
2020f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
202186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_add_i64, { "r", "r", "re" } },
2022f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_mul_i64, { "r", "0", "re" } },
2023f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
2024f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
2025f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_sub_i64, { "r", "0", "re" } },
2026f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_and_i64, { "r", "0", "reZ" } },
2027f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_or_i64, { "r", "0", "re" } },
2028f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_xor_i64, { "r", "0", "re" } },
2029f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2030f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_shl_i64, { "r", "0", "ci" } },
2031f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_shr_i64, { "r", "0", "ci" } },
2032f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_sar_i64, { "r", "0", "ci" } },
2033f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_rotl_i64, { "r", "0", "ci" } },
2034f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_rotr_i64, { "r", "0", "ci" } },
2035f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2036f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_brcond_i64, { "r", "re" } },
2037f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_setcond_i64, { "r", "r", "re" } },
2038f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2039f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_bswap16_i64, { "r", "0" } },
2040f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_bswap32_i64, { "r", "0" } },
2041f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_bswap64_i64, { "r", "0" } },
2042f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_neg_i64, { "r", "0" } },
2043f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_not_i64, { "r", "0" } },
2044f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2045f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext8s_i64, { "r", "r" } },
2046f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext16s_i64, { "r", "r" } },
2047f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext32s_i64, { "r", "r" } },
2048f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext8u_i64, { "r", "r" } },
2049f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext16u_i64, { "r", "r" } },
2050f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    { INDEX_op_ext32u_i64, { "r", "r" } },
205186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
205286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_deposit_i64, { "Q", "0", "Q" } },
205386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_movcond_i64, { "r", "r", "re", "r", "0" } },
205486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
205586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_mulu2_i64, { "a", "d", "a", "r" } },
205686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_muls2_i64, { "a", "d", "a", "r" } },
205786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_add2_i64, { "r", "r", "0", "1", "re", "re" } },
205886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_sub2_i64, { "r", "r", "0", "1", "re", "re" } },
2059f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
2060f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2061f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
206286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_ld_i32, { "r", "L" } },
206386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_st_i32, { "L", "L" } },
206486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_ld_i64, { "r", "L" } },
206586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_st_i64, { "L", "L" } },
2066f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
206786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_ld_i32, { "r", "L" } },
206886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_st_i32, { "L", "L" } },
206986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
207086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_st_i64, { "L", "L", "L" } },
20718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
207286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
207386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_st_i32, { "L", "L", "L" } },
207486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_ld_i64, { "r", "r", "L", "L" } },
207586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    { INDEX_op_qemu_st_i64, { "L", "L", "L", "L" } },
20768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { -1 },
20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
20798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int tcg_target_callee_save_regs[] = {
2081f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#if TCG_TARGET_REG_BITS == 64
2082f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RBP,
2083f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_RBX,
208486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if defined(_WIN64)
208586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_REG_RDI,
208686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_REG_RSI,
208786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
2088f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R12,
2089f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R13,
2090a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner    TCG_REG_R14, /* Currently used for the global env. */
2091f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    TCG_REG_R15,
2092f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#else
2093a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner    TCG_REG_EBP, /* Currently used for the global env. */
20948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCG_REG_EBX,
20958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCG_REG_ESI,
20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCG_REG_EDI,
2097f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
20998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
210086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Compute frame size via macros, to share between tcg_target_qemu_prologue
210186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   and tcg_register_jit.  */
210286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
210386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define PUSH_SIZE \
210486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    ((1 + ARRAY_SIZE(tcg_target_callee_save_regs)) \
210586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner     * (TCG_TARGET_REG_BITS / 8))
210686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
210786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define FRAME_SIZE \
210886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    ((PUSH_SIZE \
210986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner      + TCG_STATIC_CALL_ARGS_SIZE \
211086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner      + CPU_TEMP_BUF_NLONGS * sizeof(long) \
211186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner      + TCG_TARGET_STACK_ALIGN - 1) \
211286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner     & ~(TCG_TARGET_STACK_ALIGN - 1))
211386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
21148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate global QEMU prologue and epilogue code */
2115f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_target_qemu_prologue(TCGContext *s)
21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
211786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int i, stack_addend;
2118f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* TB prologue */
2120f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
21212e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner    /* Reserve some stack space, also for TCG temps.  */
212286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    stack_addend = FRAME_SIZE - PUSH_SIZE;
21232e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner    tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
21242e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner                  CPU_TEMP_BUF_NLONGS * sizeof(long));
21252e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner
21262e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner    /* Save all callee saved registers.  */
21272e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
21282e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner        tcg_out_push(s, tcg_target_callee_save_regs[i]);
21292e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner    }
21302e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner
213186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if TCG_TARGET_REG_BITS == 32
213286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
213386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               (ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4);
21342e787a1d54ea4a34a6b75dcffe7dc9fa3aecb83fDavid 'Digit' Turner    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
213586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* jmp *tb.  */
213686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_ESP,
213786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner		         (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4
213886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner			 + stack_addend);
213986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
2140a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
214186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
2142f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    /* jmp *tb.  */
2143a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner    tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
214486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
2145f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* TB epilogue */
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_ret_addr = s->code_ptr;
2148f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
21497af8cffa01a3f75abfdea216c1f85bfa2622067fDavid 'Digit' Turner    tcg_out_addi(s, TCG_REG_CALL_STACK, stack_addend);
2150f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2151f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2154f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_out_opc(s, OPC_RET, 0, 0, 0);
215586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
215686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if !defined(CONFIG_SOFTMMU)
215786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Try to set up a segment register to point to GUEST_BASE.  */
215886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (GUEST_BASE) {
215986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        setup_guest_base_seg();
216086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
216186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2164f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turnerstatic void tcg_target_init(TCGContext *s)
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
216686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* For 32-bit, 99% certainty that we're running on hardware that supports
216786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       cmov, but we still need to check.  In case cmov is not available, we'll
216886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       use a small forward branch.  */
216986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#ifndef have_cmov
217086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    {
217186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        unsigned a, b, c, d;
217286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        have_cmov = (__get_cpuid(1, &a, &b, &c, &d) && (d & bit_CMOV));
217386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
2174f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner#endif
2175f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2176f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 64) {
2177f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
2178f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
2179f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    } else {
2180f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
2181f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
2182f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner
2183f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_regset_clear(tcg_target_call_clobber_regs);
2184f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
2185f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
2186f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
2187f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    if (TCG_TARGET_REG_BITS == 64) {
218886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if !defined(_WIN64)
2189f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
2190f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
219186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
2192f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
2193f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
2194f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
2195f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
2196f1d9bf153726533acf659efd796aa484dfd0b412David 'Digit' Turner    }
21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_regset_clear(s->reserved_regs);
21997af8cffa01a3f75abfdea216c1f85bfa2622067fDavid 'Digit' Turner    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_add_target_add_op_defs(x86_op_defs);
22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
220386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
220486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnertypedef struct {
220586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    DebugFrameCIE cie;
220686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    DebugFrameFDEHeader fde;
220786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t fde_def_cfa[4];
220886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint8_t fde_reg_ofs[14];
220986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner} DebugFrame;
221086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
221186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* We're expecting a 2 byte uleb128 encoded value.  */
221286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' TurnerQEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
221386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
221486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if !defined(__ELF__)
221586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Host machine without ELF. */
221686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#elif TCG_TARGET_REG_BITS == 64
221786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define ELF_HOST_MACHINE EM_X86_64
221886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic DebugFrame debug_frame = {
221986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
222086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.id = -1,
222186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.version = 1,
222286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.code_align = 1,
222386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.data_align = 0x78,             /* sleb128 -8 */
222486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.return_column = 16,
222586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
222686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Total FDE size does not include the "len" member.  */
222786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
222886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
222986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .fde_def_cfa = {
223086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        12, 7,                          /* DW_CFA_def_cfa %rsp, ... */
223186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
223286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        (FRAME_SIZE >> 7)
223386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    },
223486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .fde_reg_ofs = {
223586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x90, 1,                        /* DW_CFA_offset, %rip, -8 */
223686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* The following ordering must match tcg_target_callee_save_regs.  */
223786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x86, 2,                        /* DW_CFA_offset, %rbp, -16 */
223886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x83, 3,                        /* DW_CFA_offset, %rbx, -24 */
223986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x8c, 4,                        /* DW_CFA_offset, %r12, -32 */
224086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x8d, 5,                        /* DW_CFA_offset, %r13, -40 */
224186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x8e, 6,                        /* DW_CFA_offset, %r14, -48 */
224286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x8f, 7,                        /* DW_CFA_offset, %r15, -56 */
224386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
224486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
224586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#else
224686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define ELF_HOST_MACHINE EM_386
224786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic DebugFrame debug_frame = {
224886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
224986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.id = -1,
225086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.version = 1,
225186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.code_align = 1,
225286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.data_align = 0x7c,             /* sleb128 -4 */
225386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .cie.return_column = 8,
225486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
225586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Total FDE size does not include the "len" member.  */
225686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
225786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
225886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .fde_def_cfa = {
225986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        12, 4,                          /* DW_CFA_def_cfa %esp, ... */
226086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
226186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        (FRAME_SIZE >> 7)
226286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    },
226386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    .fde_reg_ofs = {
226486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x88, 1,                        /* DW_CFA_offset, %eip, -4 */
226586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* The following ordering must match tcg_target_callee_save_regs.  */
226686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x85, 2,                        /* DW_CFA_offset, %ebp, -8 */
226786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x83, 3,                        /* DW_CFA_offset, %ebx, -12 */
226886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x86, 4,                        /* DW_CFA_offset, %esi, -16 */
226986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        0x87, 5,                        /* DW_CFA_offset, %edi, -20 */
227086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
227186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
227286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
227386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
227486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#if defined(ELF_HOST_MACHINE)
227586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnervoid tcg_register_jit(void *buf, size_t buf_size)
227686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
227786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    debug_frame.fde.func_start = (uintptr_t)buf;
227886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    debug_frame.fde.func_len = buf_size;
227986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
228086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
228186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
228286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#endif
2283