]>
git.saurik.com Git - apple/javascriptcore.git/blob - assembler/MacroAssemblerX86Common.cpp
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))
29 #include "MacroAssemblerX86Common.h"
33 #if ENABLE(MASM_PROBE)
35 #define INDENT printIndent(indentation)
37 void MacroAssemblerX86Common::printCPURegisters(MacroAssemblerX86Common::CPUState
& cpu
, int indentation
)
40 #define PRINT_GPREGISTER(_type, _regName) { \
41 int32_t value = reinterpret_cast<int32_t>(cpu._regName); \
42 INDENT, dataLogF("%6s: 0x%08x %d\n", #_regName, value, value) ; \
45 #define PRINT_GPREGISTER(_type, _regName) { \
46 int64_t value = reinterpret_cast<int64_t>(cpu._regName); \
47 INDENT, dataLogF("%6s: 0x%016llx %lld\n", #_regName, value, value) ; \
50 FOR_EACH_CPU_GPREGISTER(PRINT_GPREGISTER
)
51 FOR_EACH_CPU_SPECIAL_REGISTER(PRINT_GPREGISTER
)
52 #undef PRINT_GPREGISTER
54 #define PRINT_FPREGISTER(_type, _regName) { \
55 uint64_t* u = reinterpret_cast<uint64_t*>(&cpu._regName); \
56 double* d = reinterpret_cast<double*>(&cpu._regName); \
57 INDENT, dataLogF("%6s: 0x%016llx %.13g\n", #_regName, *u, *d); \
59 FOR_EACH_CPU_FPREGISTER(PRINT_FPREGISTER
)
60 #undef PRINT_FPREGISTER
65 void MacroAssemblerX86Common::printRegister(MacroAssemblerX86Common::CPUState
& cpu
, RegisterID regID
)
67 const char* name
= CPUState::registerName(regID
);
72 u
.voidPtr
= cpu
.registerValue(regID
);
73 dataLogF("%s:<%p %ld>", name
, u
.voidPtr
, u
.intptrValue
);
76 void MacroAssemblerX86Common::printRegister(MacroAssemblerX86Common::CPUState
& cpu
, FPRegisterID regID
)
78 const char* name
= CPUState::registerName(regID
);
83 u
.doubleValue
= cpu
.registerValue(regID
);
84 dataLogF("%s:<0x%016llx %.13g>", name
, u
.uint64Value
, u
.doubleValue
);
87 extern "C" void ctiMasmProbeTrampoline();
89 // What code is emitted for the probe?
90 // ==================================
91 // We want to keep the size of the emitted probe invocation code as compact as
92 // possible to minimize the perturbation to the JIT generated code. However,
93 // we also need to preserve the CPU registers and set up the ProbeContext to be
94 // passed to the user probe function.
96 // Hence, we do only the minimum here to preserve a scratch register (i.e. rax
97 // in this case) and the stack pointer (i.e. rsp), and pass the probe arguments.
98 // We'll let the ctiMasmProbeTrampoline handle the rest of the probe invocation
99 // work i.e. saving the CPUState (and setting up the ProbeContext), calling the
100 // user probe function, and restoring the CPUState before returning to JIT
103 // What registers need to be saved?
104 // ===============================
105 // The registers are saved for 2 reasons:
106 // 1. To preserve their state in the JITted code. This means that all registers
107 // that are not callee saved needs to be saved. We also need to save the
108 // condition code registers because the probe can be inserted between a test
110 // 2. To allow the probe to inspect the values of the registers for debugging
111 // purposes. This means all registers need to be saved.
113 // In summary, save everything. But for reasons stated above, we should do the
114 // minimum here and let ctiMasmProbeTrampoline do the heavy lifting to save the
117 // What values are in the saved registers?
118 // ======================================
119 // Conceptually, the saved registers should contain values as if the probe
120 // is not present in the JIT generated code. Hence, they should contain values
121 // that are expected at the start of the instruction immediately following the
124 // Specifically, the saved stack pointer register will point to the stack
125 // position before we push the ProbeContext frame. The saved rip will point to
126 // the address of the instruction immediately following the probe.
128 void MacroAssemblerX86Common::probe(MacroAssemblerX86Common::ProbeFunction function
, void* arg1
, void* arg2
)
130 push(RegisterID::esp
);
131 push(RegisterID::eax
);
132 move(TrustedImmPtr(arg2
), RegisterID::eax
);
133 push(RegisterID::eax
);
134 move(TrustedImmPtr(arg1
), RegisterID::eax
);
135 push(RegisterID::eax
);
136 move(TrustedImmPtr(reinterpret_cast<void*>(function
)), RegisterID::eax
);
137 push(RegisterID::eax
);
138 move(TrustedImmPtr(reinterpret_cast<void*>(ctiMasmProbeTrampoline
)), RegisterID::eax
);
139 call(RegisterID::eax
);
142 #endif // ENABLE(MASM_PROBE)
144 #if CPU(X86) && !OS(MAC_OS_X)
145 MacroAssemblerX86Common::SSE2CheckState
MacroAssemblerX86Common::s_sse2CheckState
= NotCheckedSSE2
;
150 #endif // ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))