]> git.saurik.com Git - apple/javascriptcore.git/blob - assembler/MacroAssemblerX86Common.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / assembler / MacroAssemblerX86Common.cpp
1 /*
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26 #include "config.h"
27
28 #if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))
29 #include "MacroAssemblerX86Common.h"
30
31 namespace JSC {
32
33 #if ENABLE(MASM_PROBE)
34
35 #define INDENT printIndent(indentation)
36
37 void MacroAssemblerX86Common::printCPURegisters(MacroAssemblerX86Common::CPUState& cpu, int indentation)
38 {
39 #if CPU(X86)
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) ; \
43 }
44 #elif CPU(X86_64)
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) ; \
48 }
49 #endif
50 FOR_EACH_CPU_GPREGISTER(PRINT_GPREGISTER)
51 FOR_EACH_CPU_SPECIAL_REGISTER(PRINT_GPREGISTER)
52 #undef PRINT_GPREGISTER
53
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); \
58 }
59 FOR_EACH_CPU_FPREGISTER(PRINT_FPREGISTER)
60 #undef PRINT_FPREGISTER
61 }
62
63 #undef INDENT
64
65 void MacroAssemblerX86Common::printRegister(MacroAssemblerX86Common::CPUState& cpu, RegisterID regID)
66 {
67 const char* name = CPUState::registerName(regID);
68 union {
69 void* voidPtr;
70 intptr_t intptrValue;
71 } u;
72 u.voidPtr = cpu.registerValue(regID);
73 dataLogF("%s:<%p %ld>", name, u.voidPtr, u.intptrValue);
74 }
75
76 void MacroAssemblerX86Common::printRegister(MacroAssemblerX86Common::CPUState& cpu, FPRegisterID regID)
77 {
78 const char* name = CPUState::registerName(regID);
79 union {
80 double doubleValue;
81 uint64_t uint64Value;
82 } u;
83 u.doubleValue = cpu.registerValue(regID);
84 dataLogF("%s:<0x%016llx %.13g>", name, u.uint64Value, u.doubleValue);
85 }
86
87 extern "C" void ctiMasmProbeTrampoline();
88
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.
95 //
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
101 // generated code.
102 //
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
109 // and a branch.
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.
112 //
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
115 // full set.
116 //
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
122 // probe.
123 //
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.
127
128 void MacroAssemblerX86Common::probe(MacroAssemblerX86Common::ProbeFunction function, void* arg1, void* arg2)
129 {
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);
140 }
141
142 #endif // ENABLE(MASM_PROBE)
143
144 #if CPU(X86) && !OS(MAC_OS_X)
145 MacroAssemblerX86Common::SSE2CheckState MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
146 #endif
147
148 } // namespace JSC
149
150 #endif // ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))