OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // | 4 // |
5 // Modified by the Subzero authors. | 5 // Modified by the Subzero authors. |
6 // | 6 // |
7 //===- subzero/src/assembler_ia32.cpp - Assembler for x86-32 -------------===// | 7 //===- subzero/src/assembler_ia32.cpp - Assembler for x86-32 -------------===// |
8 // | 8 // |
9 // The Subzero Code Generator | 9 // The Subzero Code Generator |
10 // | 10 // |
11 // This file is distributed under the University of Illinois Open Source | 11 // This file is distributed under the University of Illinois Open Source |
12 // License. See LICENSE.TXT for details. | 12 // License. See LICENSE.TXT for details. |
13 // | 13 // |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 // | 15 // |
16 // This file implements the Assembler class for x86-32. | 16 // This file implements the Assembler class for x86-32. |
17 // | 17 // |
18 //===----------------------------------------------------------------------===// | 18 //===----------------------------------------------------------------------===// |
19 | 19 |
20 #include "assembler_ia32.h" | 20 #include "assembler_ia32.h" |
21 #include "IceCfg.h" | 21 #include "IceCfg.h" |
22 #include "IceMemoryRegion.h" | 22 #include "IceMemoryRegion.h" |
23 #include "IceOperand.h" | 23 #include "IceOperand.h" |
24 | 24 |
25 namespace Ice { | 25 namespace Ice { |
26 namespace x86 { | 26 namespace x86 { |
27 | 27 |
28 const Type BrokenType = IceType_i32; | |
Jim Stichnoth
2014/10/10 17:37:25
Yay!
| |
29 | |
30 class DirectCallRelocation : public AssemblerFixup { | 28 class DirectCallRelocation : public AssemblerFixup { |
31 public: | 29 public: |
32 static DirectCallRelocation *create(Assembler *Asm, FixupKind Kind, | 30 static DirectCallRelocation *create(Assembler *Asm, FixupKind Kind, |
33 const ConstantRelocatable *Sym) { | 31 const ConstantRelocatable *Sym) { |
34 return new (Asm->Allocate<DirectCallRelocation>()) | 32 return new (Asm->Allocate<DirectCallRelocation>()) |
35 DirectCallRelocation(Kind, Sym); | 33 DirectCallRelocation(Kind, Sym); |
36 } | 34 } |
37 | 35 |
38 void Process(const MemoryRegion ®ion, intptr_t position) override { | 36 void Process(const MemoryRegion ®ion, intptr_t position) override { |
39 // Direct calls are relative to the following instruction on x86. | 37 // Direct calls are relative to the following instruction on x86. |
(...skipping 15 matching lines...) Expand all Loading... | |
55 llvm::raw_string_ostream StrBuf(Buffer); | 53 llvm::raw_string_ostream StrBuf(Buffer); |
56 Type Ty = Imm->getType(); | 54 Type Ty = Imm->getType(); |
57 assert(llvm::isa<ConstantFloat>(Imm) || llvm::isa<ConstantDouble>(Imm)); | 55 assert(llvm::isa<ConstantFloat>(Imm) || llvm::isa<ConstantDouble>(Imm)); |
58 StrBuf << "L$" << Ty << "$" << Imm->getPoolEntryID(); | 56 StrBuf << "L$" << Ty << "$" << Imm->getPoolEntryID(); |
59 const int64_t Offset = 0; | 57 const int64_t Offset = 0; |
60 const bool SuppressMangling = true; | 58 const bool SuppressMangling = true; |
61 Constant *Sym = | 59 Constant *Sym = |
62 Ctx->getConstantSym(Ty, Offset, StrBuf.str(), SuppressMangling); | 60 Ctx->getConstantSym(Ty, Offset, StrBuf.str(), SuppressMangling); |
63 AssemblerFixup *Fixup = x86::DisplacementRelocation::create( | 61 AssemblerFixup *Fixup = x86::DisplacementRelocation::create( |
64 Asm, FK_Abs_4, llvm::cast<ConstantRelocatable>(Sym)); | 62 Asm, FK_Abs_4, llvm::cast<ConstantRelocatable>(Sym)); |
65 return x86::Address::Absolute(Offset, Fixup); | 63 return x86::Address::Absolute(Fixup); |
66 } | 64 } |
67 | 65 |
68 void AssemblerX86::call(GPRRegister reg) { | 66 void AssemblerX86::call(GPRRegister reg) { |
69 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 67 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
70 EmitUint8(0xFF); | 68 EmitUint8(0xFF); |
71 EmitRegisterOperand(2, reg); | 69 EmitRegisterOperand(2, reg); |
72 } | 70 } |
73 | 71 |
74 void AssemblerX86::call(const Address &address) { | 72 void AssemblerX86::call(const Address &address) { |
75 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 73 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
120 EmitUint8(0x61); | 118 EmitUint8(0x61); |
121 } | 119 } |
122 | 120 |
123 void AssemblerX86::setcc(CondX86::BrCond condition, ByteRegister dst) { | 121 void AssemblerX86::setcc(CondX86::BrCond condition, ByteRegister dst) { |
124 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 122 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
125 EmitUint8(0x0F); | 123 EmitUint8(0x0F); |
126 EmitUint8(0x90 + condition); | 124 EmitUint8(0x90 + condition); |
127 EmitUint8(0xC0 + dst); | 125 EmitUint8(0xC0 + dst); |
128 } | 126 } |
129 | 127 |
130 void AssemblerX86::movl(GPRRegister dst, const Immediate &imm) { | 128 void AssemblerX86::mov(Type Ty, GPRRegister dst, const Immediate &imm) { |
131 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 129 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
130 if (isByteSizedType(Ty)) { | |
131 EmitUint8(0xB0 + dst); | |
132 EmitUint8(imm.value() & 0xFF); | |
133 return; | |
134 } | |
135 if (Ty == IceType_i16) | |
136 EmitOperandSizeOverride(); | |
132 EmitUint8(0xB8 + dst); | 137 EmitUint8(0xB8 + dst); |
133 EmitImmediate(BrokenType, imm); | 138 EmitImmediate(Ty, imm); |
134 } | 139 } |
135 | 140 |
136 void AssemblerX86::movl(GPRRegister dst, GPRRegister src) { | 141 void AssemblerX86::mov(Type Ty, GPRRegister dst, GPRRegister src) { |
137 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 142 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
138 EmitUint8(0x89); | 143 if (Ty == IceType_i16) |
144 EmitOperandSizeOverride(); | |
145 if (isByteSizedType(Ty)) { | |
146 EmitUint8(0x88); | |
147 } else { | |
148 EmitUint8(0x89); | |
149 } | |
139 EmitRegisterOperand(src, dst); | 150 EmitRegisterOperand(src, dst); |
140 } | 151 } |
141 | 152 |
142 void AssemblerX86::movl(GPRRegister dst, const Address &src) { | 153 void AssemblerX86::mov(Type Ty, GPRRegister dst, const Address &src) { |
143 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 154 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
144 EmitUint8(0x8B); | 155 if (Ty == IceType_i16) |
156 EmitOperandSizeOverride(); | |
157 if (isByteSizedType(Ty)) { | |
158 EmitUint8(0x8A); | |
159 } else { | |
160 EmitUint8(0x8B); | |
161 } | |
145 EmitOperand(dst, src); | 162 EmitOperand(dst, src); |
146 } | 163 } |
147 | 164 |
148 void AssemblerX86::movl(const Address &dst, GPRRegister src) { | 165 void AssemblerX86::mov(Type Ty, const Address &dst, GPRRegister src) { |
149 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 166 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
150 EmitUint8(0x89); | 167 if (Ty == IceType_i16) |
168 EmitOperandSizeOverride(); | |
169 if (isByteSizedType(Ty)) { | |
170 EmitUint8(0x88); | |
171 } else { | |
172 EmitUint8(0x89); | |
173 } | |
151 EmitOperand(src, dst); | 174 EmitOperand(src, dst); |
152 } | 175 } |
153 | 176 |
154 void AssemblerX86::movl(const Address &dst, const Immediate &imm) { | 177 void AssemblerX86::mov(Type Ty, const Address &dst, const Immediate &imm) { |
155 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 178 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
156 EmitUint8(0xC7); | 179 if (Ty == IceType_i16) |
157 EmitOperand(0, dst); | 180 EmitOperandSizeOverride(); |
158 EmitImmediate(BrokenType, imm); | 181 if (isByteSizedType(Ty)) { |
182 EmitUint8(0xC6); | |
183 EmitOperand(0, dst); | |
184 EmitUint8(imm.value() & 0xFF); | |
185 } else { | |
186 EmitUint8(0xC7); | |
187 EmitOperand(0, dst); | |
188 EmitImmediate(Ty, imm); | |
189 } | |
159 } | 190 } |
160 | 191 |
161 void AssemblerX86::movzxb(GPRRegister dst, ByteRegister src) { | 192 void AssemblerX86::movzxb(GPRRegister dst, ByteRegister src) { |
162 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 193 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
163 EmitUint8(0x0F); | 194 EmitUint8(0x0F); |
164 EmitUint8(0xB6); | 195 EmitUint8(0xB6); |
165 EmitRegisterOperand(dst, src); | 196 EmitRegisterOperand(dst, src); |
166 } | 197 } |
167 | 198 |
168 void AssemblerX86::movzxb(GPRRegister dst, const Address &src) { | 199 void AssemblerX86::movzxb(GPRRegister dst, const Address &src) { |
(...skipping 10 matching lines...) Expand all Loading... | |
179 EmitRegisterOperand(dst, src); | 210 EmitRegisterOperand(dst, src); |
180 } | 211 } |
181 | 212 |
182 void AssemblerX86::movsxb(GPRRegister dst, const Address &src) { | 213 void AssemblerX86::movsxb(GPRRegister dst, const Address &src) { |
183 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 214 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
184 EmitUint8(0x0F); | 215 EmitUint8(0x0F); |
185 EmitUint8(0xBE); | 216 EmitUint8(0xBE); |
186 EmitOperand(dst, src); | 217 EmitOperand(dst, src); |
187 } | 218 } |
188 | 219 |
189 void AssemblerX86::movb(ByteRegister dst, const Address &src) { | |
190 (void)dst; | |
191 (void)src; | |
192 // FATAL | |
193 llvm_unreachable("Use movzxb or movsxb instead."); | |
194 } | |
195 | |
196 void AssemblerX86::movb(const Address &dst, ByteRegister src) { | |
197 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
198 EmitUint8(0x88); | |
199 EmitOperand(src, dst); | |
200 } | |
201 | |
202 void AssemblerX86::movb(const Address &dst, const Immediate &imm) { | |
203 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
204 EmitUint8(0xC6); | |
205 EmitOperand(RegX8632::Encoded_Reg_eax, dst); | |
206 assert(imm.is_int8()); | |
207 EmitUint8(imm.value() & 0xFF); | |
208 } | |
209 | |
210 void AssemblerX86::movzxw(GPRRegister dst, GPRRegister src) { | 220 void AssemblerX86::movzxw(GPRRegister dst, GPRRegister src) { |
211 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 221 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
212 EmitUint8(0x0F); | 222 EmitUint8(0x0F); |
213 EmitUint8(0xB7); | 223 EmitUint8(0xB7); |
214 EmitRegisterOperand(dst, src); | 224 EmitRegisterOperand(dst, src); |
215 } | 225 } |
216 | 226 |
217 void AssemblerX86::movzxw(GPRRegister dst, const Address &src) { | 227 void AssemblerX86::movzxw(GPRRegister dst, const Address &src) { |
218 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 228 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
219 EmitUint8(0x0F); | 229 EmitUint8(0x0F); |
220 EmitUint8(0xB7); | 230 EmitUint8(0xB7); |
221 EmitOperand(dst, src); | 231 EmitOperand(dst, src); |
222 } | 232 } |
223 | 233 |
224 void AssemblerX86::movsxw(GPRRegister dst, GPRRegister src) { | 234 void AssemblerX86::movsxw(GPRRegister dst, GPRRegister src) { |
225 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 235 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
226 EmitUint8(0x0F); | 236 EmitUint8(0x0F); |
227 EmitUint8(0xBF); | 237 EmitUint8(0xBF); |
228 EmitRegisterOperand(dst, src); | 238 EmitRegisterOperand(dst, src); |
229 } | 239 } |
230 | 240 |
231 void AssemblerX86::movsxw(GPRRegister dst, const Address &src) { | 241 void AssemblerX86::movsxw(GPRRegister dst, const Address &src) { |
232 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 242 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
233 EmitUint8(0x0F); | 243 EmitUint8(0x0F); |
234 EmitUint8(0xBF); | 244 EmitUint8(0xBF); |
235 EmitOperand(dst, src); | 245 EmitOperand(dst, src); |
236 } | 246 } |
237 | 247 |
238 void AssemblerX86::movw(GPRRegister dst, const Address &src) { | |
239 (void)dst; | |
240 (void)src; | |
241 // FATAL | |
242 llvm_unreachable("Use movzxw or movsxw instead."); | |
243 } | |
244 | |
245 void AssemblerX86::movw(const Address &dst, GPRRegister src) { | |
246 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
247 EmitOperandSizeOverride(); | |
248 EmitUint8(0x89); | |
249 EmitOperand(src, dst); | |
250 } | |
251 | |
252 void AssemblerX86::lea(Type Ty, GPRRegister dst, const Address &src) { | 248 void AssemblerX86::lea(Type Ty, GPRRegister dst, const Address &src) { |
253 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 249 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
254 assert(Ty == IceType_i16 || Ty == IceType_i32); | 250 assert(Ty == IceType_i16 || Ty == IceType_i32); |
255 if (Ty == IceType_i16) | 251 if (Ty == IceType_i16) |
256 EmitOperandSizeOverride(); | 252 EmitOperandSizeOverride(); |
257 EmitUint8(0x8D); | 253 EmitUint8(0x8D); |
258 EmitOperand(dst, src); | 254 EmitOperand(dst, src); |
259 } | 255 } |
260 | 256 |
261 void AssemblerX86::cmov(CondX86::BrCond cond, GPRRegister dst, | 257 void AssemblerX86::cmov(CondX86::BrCond cond, GPRRegister dst, |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
882 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 878 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
883 EmitUint8(0x66); | 879 EmitUint8(0x66); |
884 EmitUint8(0x0F); | 880 EmitUint8(0x0F); |
885 EmitUint8(0x15); | 881 EmitUint8(0x15); |
886 EmitXmmRegisterOperand(dst, src); | 882 EmitXmmRegisterOperand(dst, src); |
887 } | 883 } |
888 | 884 |
889 void AssemblerX86::set1ps(XmmRegister dst, GPRRegister tmp1, | 885 void AssemblerX86::set1ps(XmmRegister dst, GPRRegister tmp1, |
890 const Immediate &imm) { | 886 const Immediate &imm) { |
891 // Load 32-bit immediate value into tmp1. | 887 // Load 32-bit immediate value into tmp1. |
892 movl(tmp1, imm); | 888 mov(IceType_i32, tmp1, imm); |
893 // Move value from tmp1 into dst. | 889 // Move value from tmp1 into dst. |
894 movd(dst, tmp1); | 890 movd(dst, tmp1); |
895 // Broadcast low lane into other three lanes. | 891 // Broadcast low lane into other three lanes. |
896 shufps(dst, dst, Immediate(0x0)); | 892 shufps(dst, dst, Immediate(0x0)); |
897 } | 893 } |
898 | 894 |
899 void AssemblerX86::shufps(XmmRegister dst, XmmRegister src, | 895 void AssemblerX86::shufps(XmmRegister dst, XmmRegister src, |
900 const Immediate &imm) { | 896 const Immediate &imm) { |
901 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 897 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
902 EmitUint8(0x0F); | 898 EmitUint8(0x0F); |
(...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2221 if (operand.fixup()) { | 2217 if (operand.fixup()) { |
2222 EmitFixup(operand.fixup()); | 2218 EmitFixup(operand.fixup()); |
2223 } | 2219 } |
2224 // Emit the rest of the encoded operand. | 2220 // Emit the rest of the encoded operand. |
2225 for (intptr_t i = 1; i < length; i++) { | 2221 for (intptr_t i = 1; i < length; i++) { |
2226 EmitUint8(operand.encoding_[i]); | 2222 EmitUint8(operand.encoding_[i]); |
2227 } | 2223 } |
2228 } | 2224 } |
2229 | 2225 |
2230 void AssemblerX86::EmitImmediate(Type Ty, const Immediate &imm) { | 2226 void AssemblerX86::EmitImmediate(Type Ty, const Immediate &imm) { |
2231 if (Ty == IceType_i16) | 2227 if (Ty == IceType_i16) { |
2228 assert(!imm.fixup()); | |
2232 EmitInt16(imm.value()); | 2229 EmitInt16(imm.value()); |
2233 else | 2230 } else { |
2231 if (imm.fixup()) { | |
2232 EmitFixup(imm.fixup()); | |
2233 } | |
2234 EmitInt32(imm.value()); | 2234 EmitInt32(imm.value()); |
2235 } | |
2235 } | 2236 } |
2236 | 2237 |
2237 void AssemblerX86::EmitComplexI8(int rm, const Operand &operand, | 2238 void AssemblerX86::EmitComplexI8(int rm, const Operand &operand, |
2238 const Immediate &immediate) { | 2239 const Immediate &immediate) { |
2239 assert(rm >= 0 && rm < 8); | 2240 assert(rm >= 0 && rm < 8); |
2240 assert(immediate.is_int8()); | 2241 assert(immediate.is_int8()); |
2241 if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) { | 2242 if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) { |
2242 // Use short form if the destination is al. | 2243 // Use short form if the destination is al. |
2243 EmitUint8(0x04 + (rm << 3)); | 2244 EmitUint8(0x04 + (rm << 3)); |
2244 EmitUint8(immediate.value() & 0xFF); | 2245 EmitUint8(immediate.value() & 0xFF); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2315 assert(shifter == RegX8632::Encoded_Reg_ecx); | 2316 assert(shifter == RegX8632::Encoded_Reg_ecx); |
2316 (void)shifter; | 2317 (void)shifter; |
2317 if (Ty == IceType_i16) | 2318 if (Ty == IceType_i16) |
2318 EmitOperandSizeOverride(); | 2319 EmitOperandSizeOverride(); |
2319 EmitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); | 2320 EmitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); |
2320 EmitOperand(rm, operand); | 2321 EmitOperand(rm, operand); |
2321 } | 2322 } |
2322 | 2323 |
2323 } // end of namespace x86 | 2324 } // end of namespace x86 |
2324 } // end of namespace Ice | 2325 } // end of namespace Ice |
OLD | NEW |