Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// |
| 2 // | 2 // |
| 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
| 5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
| 6 // | 6 // |
| 7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
| 8 // | 8 // |
| 9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
| 10 // | 10 // |
| 11 // The Subzero Code Generator | 11 // The Subzero Code Generator |
| 12 // | 12 // |
| 13 // This file is distributed under the University of Illinois Open Source | 13 // This file is distributed under the University of Illinois Open Source |
| 14 // License. See LICENSE.TXT for details. | 14 // License. See LICENSE.TXT for details. |
| 15 // | 15 // |
| 16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
| 17 /// | 17 /// |
| 18 /// \file | 18 /// \file |
| 19 /// This file implements the Assembler class for ARM32. | 19 /// This file implements the Assembler class for ARM32. |
| 20 /// | 20 /// |
| 21 //===----------------------------------------------------------------------===// | 21 //===----------------------------------------------------------------------===// |
| 22 | 22 |
| 23 #include "IceAssemblerARM32.h" | 23 #include "IceAssemblerARM32.h" |
| 24 | 24 |
| 25 namespace Ice { | 25 namespace { |
| 26 | |
| 27 using namespace Ice; | |
| 26 | 28 |
| 27 // The following define individual bits. | 29 // The following define individual bits. |
| 28 static constexpr uint32_t B0 = 1; | 30 static constexpr uint32_t B0 = 1; |
| 29 static constexpr uint32_t B2 = 1 << 2; | 31 static constexpr uint32_t B2 = 1 << 2; |
| 30 static constexpr uint32_t B3 = 1 << 3; | 32 static constexpr uint32_t B3 = 1 << 3; |
| 31 static constexpr uint32_t B4 = 1 << 4; | 33 static constexpr uint32_t B4 = 1 << 4; |
| 32 static constexpr uint32_t B5 = 1 << 5; | 34 static constexpr uint32_t B5 = 1 << 5; |
| 33 static constexpr uint32_t B6 = 1 << 6; | 35 static constexpr uint32_t B6 = 1 << 6; |
| 34 static constexpr uint32_t B21 = 1 << 21; | 36 static constexpr uint32_t B21 = 1 << 21; |
| 35 static constexpr uint32_t B24 = 1 << 24; | 37 static constexpr uint32_t B24 = 1 << 24; |
| 36 | 38 |
| 37 // Constants used for the decoding or encoding of the individual fields of | 39 // Constants used for the decoding or encoding of the individual fields of |
| 38 // instructions. Based on ARM section A5.1. | 40 // instructions. Based on ARM section A5.1. |
| 39 static constexpr uint32_t kConditionShift = 28; | 41 static constexpr uint32_t kConditionShift = 28; |
| 40 static constexpr uint32_t kOpcodeShift = 21; | 42 static constexpr uint32_t kOpcodeShift = 21; |
| 41 static constexpr uint32_t kRdShift = 12; | 43 static constexpr uint32_t kRdShift = 12; |
| 42 static constexpr uint32_t kRmShift = 0; | 44 static constexpr uint32_t kRmShift = 0; |
| 43 static constexpr uint32_t kRnShift = 16; | 45 static constexpr uint32_t kRnShift = 16; |
| 44 static constexpr uint32_t kSShift = 20; | 46 static constexpr uint32_t kSShift = 20; |
| 45 static constexpr uint32_t kTypeShift = 25; | 47 static constexpr uint32_t kTypeShift = 25; |
| 46 | 48 |
| 47 // Immediate instruction fields encoding. | 49 // Immediate instruction fields encoding. |
| 48 static constexpr uint32_t kImmed8Bits = 8; | 50 static constexpr uint32_t kImmed8Bits = 8; |
| 49 static constexpr uint32_t kImmed8Shift = 0; | 51 static constexpr uint32_t kImmed8Shift = 0; |
| 50 static constexpr uint32_t kRotateBits = 4; | 52 static constexpr uint32_t kRotateBits = 4; |
| 51 static constexpr uint32_t kRotateShift = 8; | 53 static constexpr uint32_t kRotateShift = 8; |
| 52 | 54 |
| 53 // Types of instructions. | |
| 54 static constexpr uint32_t kInstTypeImmediate = 1; | |
| 55 | |
| 56 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } | 55 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |
| 57 | 56 |
| 58 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { | 57 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |
| 59 return static_cast<uint32_t>(Rn); | 58 return static_cast<uint32_t>(Rn); |
| 60 } | 59 } |
| 61 | 60 |
| 62 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { | 61 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { |
| 63 return R != RegARM32::Encoded_Not_GPR; | 62 return R != RegARM32::Encoded_Not_GPR; |
| 64 } | 63 } |
| 65 | 64 |
| 66 inline bool isGPRRegisterDefined(uint32_t R) { | 65 inline bool isGPRRegisterDefined(uint32_t R) { |
| 67 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); | 66 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); |
| 68 } | 67 } |
| 69 | 68 |
| 70 inline bool isConditionDefined(CondARM32::Cond Cond) { | 69 inline bool isConditionDefined(CondARM32::Cond Cond) { |
| 71 return Cond != CondARM32::kNone; | 70 return Cond != CondARM32::kNone; |
| 72 } | 71 } |
| 73 | 72 |
| 74 inline uint32_t encodeCondition(CondARM32::Cond Cond) { | 73 inline uint32_t encodeCondition(CondARM32::Cond Cond) { |
| 75 return static_cast<uint32_t>(Cond); | 74 return static_cast<uint32_t>(Cond); |
| 76 } | 75 } |
| 77 | 76 |
| 78 // Converts rotated immediate into imm12. | 77 // The way an operand was decoded in function decode below. |
| 79 inline uint32_t encodeImm12FromFlexImm(const OperandARM32FlexImm &FlexImm) { | 78 enum DecodedResult { |
| 80 uint32_t Immed8 = FlexImm.getImm(); | 79 CantDecode = 0, // I.e. will fail in test. |
| 81 uint32_t Rotate = FlexImm.getRotateAmt(); | 80 DecodedAsRegister, |
| 82 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); | 81 DecodedAsRotatedImm8 |
| 83 return (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 82 }; |
| 83 | |
| 84 DecodedResult decode(const Ice::Operand *Operand, uint32_t &Value) { | |
|
Jim Stichnoth
2015/10/13 21:28:52
Can you use Operand instead of Ice::Operand?
Also
Karl
2015/10/13 21:39:25
Done.
| |
| 85 if (const auto *Var = llvm::dyn_cast<Variable>(Operand)) { | |
| 86 if (Var->hasReg()) { | |
| 87 Value = Var->getRegNum(); | |
| 88 return DecodedAsRegister; | |
| 89 } | |
| 90 } else if (const auto *FlexImm = | |
| 91 llvm::dyn_cast<OperandARM32FlexImm>(Operand)) { | |
| 92 uint32_t Immed8 = FlexImm->getImm(); | |
| 93 uint32_t Rotate = FlexImm->getRotateAmt(); | |
| 94 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); | |
| 95 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | |
| 96 return DecodedAsRotatedImm8; | |
| 97 } | |
| 98 return CantDecode; | |
| 84 } | 99 } |
| 85 | 100 |
| 101 } // end of anonymous namespace | |
| 102 | |
| 103 namespace Ice { | |
| 104 | |
| 86 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, | 105 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, |
| 87 LabelVector &Labels) { | 106 LabelVector &Labels) { |
| 88 Label *L = nullptr; | 107 Label *L = nullptr; |
| 89 if (Number == Labels.size()) { | 108 if (Number == Labels.size()) { |
| 90 L = new (this->allocate<Label>()) Label(); | 109 L = new (this->allocate<Label>()) Label(); |
| 91 Labels.push_back(L); | 110 Labels.push_back(L); |
| 92 return L; | 111 return L; |
| 93 } | 112 } |
| 94 if (Number > Labels.size()) { | 113 if (Number > Labels.size()) { |
| 95 Labels.resize(Number + 1); | 114 Labels.resize(Number + 1); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 113 } | 132 } |
| 114 // TODO(kschimpf) Decide if we have near jumps. | 133 // TODO(kschimpf) Decide if we have near jumps. |
| 115 label->bindTo(bound); | 134 label->bindTo(bound); |
| 116 } | 135 } |
| 117 | 136 |
| 118 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, | 137 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |
| 119 uint32_t Opcode, bool SetCc, uint32_t Rn, | 138 uint32_t Opcode, bool SetCc, uint32_t Rn, |
| 120 uint32_t Rd, uint32_t Imm12) { | 139 uint32_t Rd, uint32_t Imm12) { |
| 121 assert(isGPRRegisterDefined(Rd)); | 140 assert(isGPRRegisterDefined(Rd)); |
| 122 assert(Cond != CondARM32::kNone); | 141 assert(Cond != CondARM32::kNone); |
| 142 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
| 123 uint32_t Encoding = encodeCondition(Cond) << kConditionShift | | 143 uint32_t Encoding = encodeCondition(Cond) << kConditionShift | |
| 124 (Type << kTypeShift) | (Opcode << kOpcodeShift) | | 144 (Type << kTypeShift) | (Opcode << kOpcodeShift) | |
| 125 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | | 145 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | |
| 126 (Rd << kRdShift) | Imm12; | 146 (Rd << kRdShift) | Imm12; |
| 127 emitInst(Encoding); | 147 emitInst(Encoding); |
| 128 } | 148 } |
| 129 | 149 |
| 150 void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, | |
| 151 const Operand *OpSrc1, bool SetFlags, | |
| 152 CondARM32::Cond Cond) { | |
| 153 // Note: Loop is used so that we can short circuit using break; | |
| 154 do { | |
| 155 uint32_t Rd; | |
| 156 if (decode(OpRd, Rd) != DecodedAsRegister) | |
| 157 break; | |
| 158 uint32_t Rn; | |
| 159 if (decode(OpRn, Rn) != DecodedAsRegister) | |
| 160 break; | |
| 161 uint32_t Src1Value; | |
| 162 // TODO(kschimpf) Other possible decodings of add. | |
| 163 if (decode(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { | |
| 164 // ADD (Immediate): See ARM section A8.8.5, rule A1. | |
| 165 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | |
| 166 // s=SetFlags and iiiiiiiiiiii=Src1Value | |
| 167 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || | |
| 168 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) | |
| 169 // Conditions of rule violated. | |
| 170 break; | |
| 171 uint32_t Add = B2; // 0100 | |
| 172 uint32_t InstType = 1; | |
| 173 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | |
| 174 return; | |
| 175 } | |
| 176 } while (0); | |
| 177 UnimplementedError(Ctx->getFlags()); | |
| 178 } | |
| 179 | |
| 130 void ARM32::AssemblerARM32::bkpt(uint16_t imm16) { | 180 void ARM32::AssemblerARM32::bkpt(uint16_t imm16) { |
| 131 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 181 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 132 uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | | 182 uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | |
| 133 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); | 183 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); |
| 134 emitInst(Encoding); | 184 emitInst(Encoding); |
| 135 } | 185 } |
| 136 | 186 |
| 137 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { | 187 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
| 138 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 188 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
| 139 // (ARM section A8.8.27, encoding A1). | 189 // (ARM section A8.8.27, encoding A1). |
| 140 assert(isGPRRegisterDefined(Rm)); | 190 assert(isGPRRegisterDefined(Rm)); |
| 141 assert(isConditionDefined(Cond)); | 191 assert(isConditionDefined(Cond)); |
| 142 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 192 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 143 uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | | 193 uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | |
| 144 (0xfff << 8) | B4 | (encodeGPRRegister(Rm) << kRmShift); | 194 (0xfff << 8) | B4 | (encodeGPRRegister(Rm) << kRmShift); |
| 145 emitInst(Encoding); | 195 emitInst(Encoding); |
| 146 } | 196 } |
| 147 | 197 |
| 148 void ARM32::AssemblerARM32::mov(RegARM32::GPRRegister Rd, | 198 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
| 149 const OperandARM32FlexImm &FlexImm, | |
| 150 CondARM32::Cond Cond) { | 199 CondARM32::Cond Cond) { |
| 151 // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) | 200 // Note: Loop is used so that we can short ciruit using break; |
| 152 assert(isConditionDefined(Cond)); | 201 do { |
| 153 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 202 uint32_t Rd; |
| 154 bool SetCc = false; // Note: We don't use movs in this assembler. | 203 if (decode(OpRd, Rd) != DecodedAsRegister) |
| 155 uint32_t Rn = 0; | 204 break; |
| 156 uint32_t Mov = B3 | B2 | B0; // 1101. | 205 uint32_t Src; |
| 157 emitType01(Cond, kInstTypeImmediate, Mov, SetCc, Rn, encodeGPRRegister(Rd), | 206 // TODO(kschimpf) Handle other forms of mov. |
| 158 encodeImm12FromFlexImm(FlexImm)); | 207 if (decode(OpSrc, Src) == DecodedAsRotatedImm8) { |
| 208 // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) | |
| 209 // Note: We don't use movs in this assembler. | |
| 210 constexpr bool SetFlags = false; | |
| 211 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags)) | |
| 212 // Conditions of rule violated. | |
| 213 break; | |
| 214 uint32_t Rn = 0; | |
| 215 uint32_t Mov = B3 | B2 | B0; // 1101. | |
| 216 uint32_t InstType = 1; | |
| 217 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); | |
| 218 return; | |
| 219 } | |
| 220 } while (0); | |
| 221 UnimplementedError(Ctx->getFlags()); | |
| 159 } | 222 } |
| 160 | 223 |
| 161 } // end of namespace Ice | 224 } // end of namespace Ice |
| OLD | NEW |