Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/IceAssemblerARM32.cpp

Issue 1407613002: Add "add immediate" instruction to the ARM integrated assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix nits. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
OLDNEW
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.h » ('j') | src/IceInstARM32.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698