1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_ 18#define ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_ 19 20#include "asm_support_x86.h" 21#include "interpreter/cfi_asm_support.h" 22 23// Regular gas(1) & current clang/llvm assembler support named macro parameters. 24#define MACRO0(macro_name) .macro macro_name 25#define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1 26#define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2 27#define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3 28#define MACRO4(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4) .macro macro_name macro_arg1, macro_arg2, macro_arg3, macro_arg4 29#define MACRO5(macro_name, macro_arg1, macro_arg2, macro_arg3, macro_arg4, macro_arg5) .macro macro_name macro_arg1, macro_arg2, macro_arg3, macro_arg4, macro_arg5 30#define END_MACRO .endm 31 32#if defined(__clang__) 33 // Clang/llvm does not support .altmacro. However, the clang/llvm preprocessor doesn't 34 // separate the backslash and parameter by a space. Everything just works. 35 #define RAW_VAR(name) \name 36 #define VAR(name) \name 37 #define CALLVAR(name) SYMBOL(\name) 38 #define PLT_VAR(name) \name@PLT 39 #define REG_VAR(name) %\name 40 #define CALL_MACRO(name) \name 41#else 42 // Regular gas(1) uses \argument_name for macro arguments. 43 // We need to turn on alternate macro syntax so we can use & instead or the preprocessor 44 // will screw us by inserting a space between the \ and the name. Even in this mode there's 45 // no special meaning to $, so literals are still just $x. The use of altmacro means % is a 46 // special character meaning care needs to be taken when passing registers as macro 47 // arguments. 48 .altmacro 49 #define RAW_VAR(name) name& 50 #define VAR(name) name& 51 #define CALLVAR(name) SYMBOL(name&) 52 #define PLT_VAR(name) name&@PLT 53 #define REG_VAR(name) %name 54 #define CALL_MACRO(name) name& 55#endif 56 57#define LITERAL(value) $value 58#if defined(__APPLE__) 59 #define MACRO_LITERAL(value) $(value) 60#else 61 #define MACRO_LITERAL(value) $value 62#endif 63 64#if defined(__APPLE__) 65 #define FUNCTION_TYPE(name) 66 #define SIZE(name) 67#else 68 #define FUNCTION_TYPE(name) .type name, @function 69 #define SIZE(name) .size name, .-name 70#endif 71 72 // CFI support. 73#if !defined(__APPLE__) 74 #define CFI_STARTPROC .cfi_startproc 75 #define CFI_ENDPROC .cfi_endproc 76 #define CFI_ADJUST_CFA_OFFSET(size) .cfi_adjust_cfa_offset size 77 #define CFI_DEF_CFA(reg,size) .cfi_def_cfa reg,size 78 #define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg 79 #define CFI_RESTORE(reg) .cfi_restore reg 80 #define CFI_REL_OFFSET(reg,size) .cfi_rel_offset reg,size 81 #define CFI_REGISTER(orig_reg, current_reg) .cfi_register orig_reg, current_reg 82 #define CFI_REMEMBER_STATE .cfi_remember_state 83 // The spec is not clear whether the CFA is part of the saved state and tools 84 // differ in the behaviour, so explicitly set the CFA to avoid any ambiguity. 85 // The restored CFA state should match the CFA state during CFI_REMEMBER_STATE. 86 // `objdump -Wf libart.so | egrep "_cfa|_state"` is useful to audit the opcodes. 87 #define CFI_RESTORE_STATE_AND_DEF_CFA(reg,off) .cfi_restore_state .cfi_def_cfa reg,off 88 #define CFI_ESCAPE(...) .cfi_escape __VA_ARGS__ 89#else 90 // Mac OS' doesn't like cfi_* directives. 91 #define CFI_STARTPROC 92 #define CFI_ENDPROC 93 #define CFI_ADJUST_CFA_OFFSET(size) 94 #define CFI_DEF_CFA(reg,size) 95 #define CFI_DEF_CFA_REGISTER(reg) 96 #define CFI_RESTORE(reg) 97 #define CFI_REL_OFFSET(reg,size) 98 #define CFI_REGISTER(orig_reg, current_reg) 99 #define CFI_REMEMBER_STATE 100 #define CFI_RESTORE_STATE_AND_DEF_CFA(reg,off) 101 #define CFI_ESCAPE(...) 102#endif 103 104#define CFI_REG_eax 0 105#define CFI_REG_ecx 1 106#define CFI_REG_edx 2 107#define CFI_REG_ebx 3 108#define CFI_REG_esp 4 109#define CFI_REG_ebp 5 110#define CFI_REG_esi 6 111#define CFI_REG_edi 7 112#define CFI_REG_eip 8 113 114#define CFI_REG(reg) CFI_REG_##reg 115 116MACRO3(CFI_EXPRESSION_BREG, n, b, offset) 117 .if (-0x40 <= (\offset)) && ((\offset) < 0x40) 118 CFI_EXPRESSION_BREG_1(\n, \b, \offset) 119 .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000) 120 CFI_EXPRESSION_BREG_2(\n, \b, \offset) 121 .else 122 .error "Unsupported offset" 123 .endif 124END_MACRO 125 126 // Symbols. On a Mac, we need a leading underscore. 127#if !defined(__APPLE__) 128 #define SYMBOL(name) name 129 #define PLT_SYMBOL(name) name ## @PLT 130#else 131 // Mac OS' symbols have an _ prefix. 132 #define SYMBOL(name) _ ## name 133 #define PLT_SYMBOL(name) _ ## name 134#endif 135 136// Directive to hide a function symbol. 137#if defined(__APPLE__) 138 #define ASM_HIDDEN .private_extern 139#else 140 #define ASM_HIDDEN .hidden 141#endif 142 143 /* Cache alignment for function entry */ 144MACRO0(ALIGN_FUNCTION_ENTRY) 145 // ART-compiled functions have OatQuickMethodHeader but assembly funtions do not. 146 // Prefix the assembly code with 0xFFs, which means there is no method header. 147 .byte 0xFF, 0xFF, 0xFF, 0xFF 148 // Cache alignment for function entry. 149 .balign 16, 0xFF 150END_MACRO 151 152MACRO2(DEFINE_FUNCTION_CUSTOM_CFA, c_name, cfa_offset) 153 FUNCTION_TYPE(SYMBOL(\c_name)) 154 ASM_HIDDEN CALLVAR(c_name) 155 .globl CALLVAR(c_name) 156 ALIGN_FUNCTION_ENTRY 157CALLVAR(c_name): 158 CFI_STARTPROC 159 // Ensure we get an appropriate starting CFA. 160 CFI_DEF_CFA(esp, RAW_VAR(cfa_offset)) 161END_MACRO 162 163MACRO1(DEFINE_FUNCTION, c_name) 164 DEFINE_FUNCTION_CUSTOM_CFA RAW_VAR(c_name), __SIZEOF_POINTER__ 165END_MACRO 166 167MACRO1(END_FUNCTION, c_name) 168 CFI_ENDPROC 169 SIZE(SYMBOL(\c_name)) 170END_MACRO 171 172MACRO1(PUSH, reg) 173 pushl REG_VAR(reg) 174 CFI_ADJUST_CFA_OFFSET(4) 175 CFI_REL_OFFSET(REG_VAR(reg), 0) 176END_MACRO 177 178MACRO1(POP, reg) 179 popl REG_VAR(reg) 180 CFI_ADJUST_CFA_OFFSET(-4) 181 CFI_RESTORE(REG_VAR(reg)) 182END_MACRO 183 184// Arguments do not need .cfi_rel_offset as they are caller-saved and 185// therefore cannot hold caller's variables or unwinding data. 186MACRO1(PUSH_ARG, reg) 187 pushl REG_VAR(reg) 188 CFI_ADJUST_CFA_OFFSET(4) 189END_MACRO 190 191MACRO1(POP_ARG, reg) 192 popl REG_VAR(reg) 193 CFI_ADJUST_CFA_OFFSET(-4) 194END_MACRO 195 196MACRO1(CFI_RESTORE_REG, reg) 197 CFI_RESTORE(REG_VAR(reg)) 198END_MACRO 199 200MACRO1(INCREASE_FRAME, frame_adjustment) 201 subl MACRO_LITERAL(RAW_VAR(frame_adjustment)), %esp 202 CFI_ADJUST_CFA_OFFSET((RAW_VAR(frame_adjustment))) 203END_MACRO 204 205MACRO1(DECREASE_FRAME, frame_adjustment) 206 addl MACRO_LITERAL(RAW_VAR(frame_adjustment)), %esp 207 CFI_ADJUST_CFA_OFFSET(-(RAW_VAR(frame_adjustment))) 208END_MACRO 209 210#define UNREACHABLE int3 211 212MACRO1(UNIMPLEMENTED,name) 213 FUNCTION_TYPE(\name) 214 .globl VAR(name) 215 ALIGN_FUNCTION_ENTRY 216VAR(name): 217 CFI_STARTPROC 218 UNREACHABLE 219 UNREACHABLE 220 CFI_ENDPROC 221 SIZE(\name) 222END_MACRO 223 224MACRO1(SETUP_GOT_NOSAVE, got_reg) 225#ifndef __APPLE__ 226 .ifc VAR(got_reg), ebx 227 call __x86.get_pc_thunk.bx 228 addl $_GLOBAL_OFFSET_TABLE_, %ebx 229 .else 230 .error "Unknown GOT register \got_reg" 231 .endif 232#endif 233END_MACRO 234 235MACRO2(LOAD_RUNTIME_INSTANCE, reg, got_reg) 236 SETUP_GOT_NOSAVE \got_reg 237 // Load Runtime::instance_ from GOT. 238 movl SYMBOL(_ZN3art7Runtime9instance_E)@GOT(REG_VAR(got_reg)), REG_VAR(reg) 239 movl (REG_VAR(reg)), REG_VAR(reg) 240END_MACRO 241 242// Macros to poison (negate) the reference for heap poisoning. 243MACRO1(POISON_HEAP_REF, rRef) 244#ifdef USE_HEAP_POISONING 245 neg REG_VAR(rRef) 246#endif // USE_HEAP_POISONING 247END_MACRO 248 249// Macros to unpoison (negate) the reference for heap poisoning. 250MACRO1(UNPOISON_HEAP_REF, rRef) 251#ifdef USE_HEAP_POISONING 252 neg REG_VAR(rRef) 253#endif // USE_HEAP_POISONING 254END_MACRO 255 256 /* 257 * Macro that sets up the callee save frame to conform with 258 * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs), except for pushing the method 259 */ 260MACRO0(SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY) 261 PUSH edi // Save callee saves 262 PUSH esi 263 PUSH ebp 264 PUSH_ARG ebx // Save args. 265 PUSH_ARG edx 266 PUSH_ARG ecx 267 // Create space for FPR args. 268 INCREASE_FRAME 4 * 8 269 // Save FPRs. 270 movsd %xmm0, 0(%esp) 271 movsd %xmm1, 8(%esp) 272 movsd %xmm2, 16(%esp) 273 movsd %xmm3, 24(%esp) 274 275 // Ugly compile-time check, but we only have the preprocessor. 276 // First +4: implicit return address pushed on stack when caller made call. 277 // Last +4: we're not pushing the method on the stack here. 278#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 4 + 6*4 + 4*8 + 4) 279#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(X86) size not as expected." 280#endif 281END_MACRO 282 283MACRO0(RESTORE_SAVE_REFS_AND_ARGS_FRAME) 284 // Restore FPRs. EAX is still on the stack. 285 movsd 4(%esp), %xmm0 286 movsd 12(%esp), %xmm1 287 movsd 20(%esp), %xmm2 288 movsd 28(%esp), %xmm3 289 290 DECREASE_FRAME 36 // Remove FPRs and method pointer. 291 292 POP_ARG ecx // Restore args 293 POP_ARG edx 294 POP_ARG ebx 295 POP ebp // Restore callee saves 296 POP esi 297 POP edi 298END_MACRO 299 300 /* 301 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 302 * exception is Thread::Current()->exception_ when the runtime method frame is ready. 303 */ 304MACRO0(DELIVER_PENDING_EXCEPTION_FRAME_READY) 305 // Outgoing argument set up 306 INCREASE_FRAME 12 // alignment padding 307 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 308 CFI_ADJUST_CFA_OFFSET(4) 309 call SYMBOL(artDeliverPendingExceptionFromCode) // artDeliverPendingExceptionFromCode(Thread*) 310 UNREACHABLE 311 CFI_ADJUST_CFA_OFFSET(-16) // Reset CFA in case there is more code afterwards. 312END_MACRO 313 314#endif // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_ 315