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