Chromium Code Reviews| 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 |