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 // |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 } | 168 } |
| 169 | 169 |
| 170 // Extract out a Bit in Value. | 170 // Extract out a Bit in Value. |
| 171 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } | 171 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } |
| 172 | 172 |
| 173 // Returns the GPR register at given Shift in Value. | 173 // Returns the GPR register at given Shift in Value. |
| 174 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { | 174 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { |
| 175 return decodeGPRRegister((Value >> Shift) & 0xF); | 175 return decodeGPRRegister((Value >> Shift) & 0xF); |
| 176 } | 176 } |
| 177 | 177 |
| 178 // Defines alternate layouts of instruction operands, should the (common) | |
| 179 // default pattern not be used. | |
| 180 enum OpEncoding { | |
| 181 // No alternate layout specified. | |
| 182 DefaultOpEncoding, | |
| 183 // Alternate encoding for ImmRegOffset, where the offset is divided by 4 | |
| 184 // before encoding. | |
| 185 ImmRegOffsetDiv4, | |
| 186 // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and | |
| 187 // ldrh. | |
| 188 OpEncoding3, | |
| 189 // Alternate encoding for memory operands for ldrex and strex, which only | |
| 190 // actually expect a register. | |
| 191 OpEncodingMemEx | |
| 192 }; | |
| 193 | |
| 194 IValueT getEncodedGPRegNum(const Variable *Var) { | 178 IValueT getEncodedGPRegNum(const Variable *Var) { |
| 195 assert(Var->hasReg()); | 179 assert(Var->hasReg()); |
| 196 int32_t Reg = Var->getRegNum(); | 180 int32_t Reg = Var->getRegNum(); |
| 197 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) | 181 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) |
| 198 : RegARM32::getEncodedGPR(Reg); | 182 : RegARM32::getEncodedGPR(Reg); |
| 199 } | 183 } |
| 200 | 184 |
| 201 IValueT getEncodedSRegNum(const Variable *Var) { | 185 IValueT getEncodedSRegNum(const Variable *Var) { |
| 202 assert(Var->hasReg()); | 186 assert(Var->hasReg()); |
| 203 return RegARM32::getEncodedSReg(Var->getRegNum()); | 187 return RegARM32::getEncodedSReg(Var->getRegNum()); |
| 204 } | 188 } |
| 205 | 189 |
| 206 IValueT getEncodedDRegNum(const Variable *Var) { | 190 IValueT getEncodedDRegNum(const Variable *Var) { |
| 207 return RegARM32::getEncodedDReg(Var->getRegNum()); | 191 return RegARM32::getEncodedDReg(Var->getRegNum()); |
| 208 } | 192 } |
| 209 | 193 |
| 210 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; } | 194 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; } |
| 211 | 195 |
| 212 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; } | 196 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; } |
| 213 | 197 |
| 214 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } | 198 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } |
| 215 | 199 |
| 216 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } | 200 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } |
| 217 | 201 |
| 202 // Defines layouts of an operand representing a (register) memory address, | |
| 203 // possibly modified by an immediate value. | |
| 204 enum EncodedImmAddress { | |
| 205 // Address modified by a rotated immediate 8-bit value. | |
| 206 RotatedImm8Address, | |
| 207 // Alternate encoding for RotatedImm8Address, where the offset is divided by 4 | |
|
Jim Stichnoth
2016/01/25 20:37:50
Optional: Consider adding a blank line after each
Karl
2016/01/25 23:59:16
Added blank lines. Did same for following enum Enc
| |
| 208 // before encoding. | |
| 209 RotatedImm8Div4Address, | |
| 210 // Address modified by an immediate 12-bit value. | |
| 211 Imm12Address, | |
| 212 // Alternate encoding 3, for an address modified by a rotated immediate 8-bit | |
| 213 // value. | |
| 214 RotatedImm8Enc3Address, | |
| 215 // Encoding where no immediate offset is used. | |
| 216 NoImmOffsetAddress | |
| 217 }; | |
| 218 | |
| 218 // The way an operand is encoded into a sequence of bits in functions | 219 // The way an operand is encoded into a sequence of bits in functions |
| 219 // encodeOperand and encodeAddress below. | 220 // encodeOperand and encodeAddress below. |
| 220 enum EncodedOperand { | 221 enum EncodedOperand { |
| 221 // Unable to encode, value left undefined. | 222 // Unable to encode, value left undefined. |
| 222 CantEncode = 0, | 223 CantEncode = 0, |
| 223 // Value is register found. | 224 // Value is register found. |
| 224 EncodedAsRegister, | 225 EncodedAsRegister, |
| 225 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 226 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
| 226 // value. | 227 // value. |
| 227 EncodedAsRotatedImm8, | 228 EncodedAsRotatedImm8, |
| 228 // EncodedAsImmRegOffset is a memory operand that can take three forms, based | 229 // EncodedAsImmRegOffset is a memory operand that can take three forms, based |
| 229 // on OpEncoding: | 230 // on type EncodedImmAddress: |
| 230 // | 231 // |
| 231 // ***** DefaultOpEncoding ***** | 232 // ***** RotatedImm8Address ***** |
| 232 // | 233 // |
| 233 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 234 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
| 234 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 235 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
| 235 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. | 236 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
| 236 // | 237 // |
| 237 // ***** OpEncoding3 ***** | 238 // ***** RotatedImm8Div4Address ***** |
| 238 // | 239 // |
| 239 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 | 240 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 |
| 240 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to | 241 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to |
| 241 // Rn. | 242 // Rn. |
| 242 // | 243 // |
| 243 // ***** OpEncodingMemEx ***** | 244 // ***** Imm12Address ***** |
| 244 // | 245 // |
| 245 // Value=00000000U000nnnn00000000xxxxxxxx where nnnn=Rn, xxxxxxxx=abs(Offset), | 246 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
| 246 // and U=1 Offset>=0. | 247 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
| 248 // Rn should be used, and iiiiiiiiiiii defines the immediate 12-bit value. | |
| 249 // | |
| 250 // ***** NoImmOffsetAddress ***** | |
| 251 // | |
| 252 // Value=000000001000nnnn0000000000000000 where nnnn=Rn. | |
| 247 EncodedAsImmRegOffset, | 253 EncodedAsImmRegOffset, |
| 248 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 254 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, |
| 249 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift | 255 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift |
| 250 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if | 256 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
| 251 // writeback to Rn. | 257 // writeback to Rn. |
| 252 EncodedAsShiftRotateImm5, | 258 EncodedAsShiftRotateImm5, |
| 253 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value | 259 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value |
| 254 // to shift. | 260 // to shift. |
| 255 EncodedAsShiftImm5, | 261 EncodedAsShiftImm5, |
| 256 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift | 262 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 } | 355 } |
| 350 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { | 356 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { |
| 351 const IValueT Immed5 = ShImm->getShAmtImm(); | 357 const IValueT Immed5 = ShImm->getShAmtImm(); |
| 352 assert(Immed5 < (1 << kShiftImmBits)); | 358 assert(Immed5 < (1 << kShiftImmBits)); |
| 353 Value = (Immed5 << kShiftImmShift); | 359 Value = (Immed5 << kShiftImmShift); |
| 354 return EncodedAsShiftImm5; | 360 return EncodedAsShiftImm5; |
| 355 } | 361 } |
| 356 return CantEncode; | 362 return CantEncode; |
| 357 } | 363 } |
| 358 | 364 |
| 359 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, | 365 inline IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, |
|
Jim Stichnoth
2016/01/25 20:37:50
Why inline here? This seems inconsistent with the
Karl
2016/01/25 23:59:16
Removed.
| |
| 360 OperandARM32Mem::AddrMode Mode, | 366 OperandARM32Mem::AddrMode Mode, |
| 361 IValueT OffsetShift = 0) { | 367 IOffsetT MaxOffset, IValueT OffsetShift) { |
| 362 IValueT Value = Mode | (Reg << kRnShift); | 368 IValueT Value = Mode | (Reg << kRnShift); |
| 363 if (Offset < 0) { | 369 if (Offset < 0) { |
| 364 Offset = -Offset; | 370 Offset = -Offset; |
| 365 Value ^= U; // Flip U to adjust sign. | 371 Value ^= U; // Flip U to adjust sign. |
| 366 } | 372 } |
| 373 assert(Offset <= MaxOffset); | |
| 374 (void)MaxOffset; | |
| 367 return Value | (Offset >> OffsetShift); | 375 return Value | (Offset >> OffsetShift); |
| 368 } | 376 } |
| 369 | 377 |
| 370 // Encodes immediate register offset using encoding 3. | 378 // Encodes immediate register offset using encoding 3. |
| 371 IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8, | 379 IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8, |
| 372 OperandARM32Mem::AddrMode Mode) { | 380 OperandARM32Mem::AddrMode Mode) { |
| 373 IValueT Value = Mode | (Rn << kRnShift); | 381 IValueT Value = Mode | (Rn << kRnShift); |
| 374 if (Imm8 < 0) { | 382 if (Imm8 < 0) { |
| 375 Imm8 = -Imm8; | 383 Imm8 = -Imm8; |
| 376 Value = (Value ^ U); | 384 Value = (Value ^ U); |
| 377 } | 385 } |
| 378 assert(Imm8 < (1 << 8)); | 386 assert(Imm8 < (1 << 8)); |
| 379 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); | 387 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); |
| 380 return Value; | 388 return Value; |
| 381 } | 389 } |
| 382 | 390 |
| 383 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, | 391 IValueT encodeImmRegOffset(EncodedImmAddress ImmEncoding, IValueT Reg, |
| 384 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { | 392 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { |
| 385 switch (AddressEncoding) { | 393 switch (ImmEncoding) { |
| 386 case DefaultOpEncoding: | 394 case RotatedImm8Address: { |
| 387 return encodeImmRegOffset(Reg, Offset, Mode); | 395 constexpr IOffsetT MaxOffset = (1 << 8) - 1; |
| 388 case ImmRegOffsetDiv4: { | 396 constexpr IValueT NoRightShift = 0; |
| 397 return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift); | |
| 398 } | |
| 399 case RotatedImm8Div4Address: { | |
| 389 assert((Offset & 0x3) == 0); | 400 assert((Offset & 0x3) == 0); |
| 401 constexpr IOffsetT MaxOffset = (1 << 8) - 1; | |
| 390 constexpr IValueT RightShift2 = 2; | 402 constexpr IValueT RightShift2 = 2; |
| 391 return encodeImmRegOffset(Reg, Offset, Mode, RightShift2); | 403 return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, RightShift2); |
| 392 } | 404 } |
| 393 case OpEncoding3: | 405 case Imm12Address: { |
| 406 constexpr IOffsetT MaxOffset = (1 << 12) - 1; | |
| 407 constexpr IValueT NoRightShift = 0; | |
| 408 return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift); | |
| 409 } | |
| 410 case RotatedImm8Enc3Address: | |
| 394 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); | 411 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); |
| 395 case OpEncodingMemEx: | 412 case NoImmOffsetAddress: { |
| 396 assert(Offset == 0); | 413 assert(Offset == 0); |
| 397 assert(Mode == OperandARM32Mem::Offset); | 414 assert(Mode == OperandARM32Mem::Offset); |
| 398 return Reg << kRnShift; | 415 return Reg << kRnShift; |
| 399 } | 416 } |
| 417 } | |
| 400 llvm_unreachable("(silence g++ warning)"); | 418 llvm_unreachable("(silence g++ warning)"); |
| 401 } | 419 } |
| 402 | 420 |
| 403 // Encodes memory address Opnd, and encodes that information into Value, based | 421 // Encodes memory address Opnd, and encodes that information into Value, based |
| 404 // on how ARM represents the address. Returns how the value was encoded. | 422 // on how ARM represents the address. Returns how the value was encoded. |
| 405 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, | 423 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
| 406 const AssemblerARM32::TargetInfo &TInfo, | 424 const AssemblerARM32::TargetInfo &TInfo, |
| 407 OpEncoding AddressEncoding = DefaultOpEncoding) { | 425 EncodedImmAddress ImmEncoding) { |
| 408 Value = 0; // Make sure initialized. | 426 Value = 0; // Make sure initialized. |
| 409 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 427 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
| 410 // Should be a stack variable, with an offset. | 428 // Should be a stack variable, with an offset. |
| 411 if (Var->hasReg()) | 429 if (Var->hasReg()) |
| 412 return CantEncode; | 430 return CantEncode; |
| 413 IOffsetT Offset = Var->getStackOffset(); | 431 IOffsetT Offset = Var->getStackOffset(); |
| 414 if (!Utils::IsAbsoluteUint(12, Offset)) | 432 if (!Utils::IsAbsoluteUint(12, Offset)) |
| 415 return CantEncode; | 433 return CantEncode; |
| 416 int32_t BaseRegNum = Var->getBaseRegNum(); | 434 int32_t BaseRegNum = Var->getBaseRegNum(); |
| 417 if (BaseRegNum == Variable::NoRegister) | 435 if (BaseRegNum == Variable::NoRegister) |
| 418 BaseRegNum = TInfo.FrameOrStackReg; | 436 BaseRegNum = TInfo.FrameOrStackReg; |
| 419 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset, | 437 Value = encodeImmRegOffset(ImmEncoding, BaseRegNum, Offset, |
| 420 OperandARM32Mem::Offset); | 438 OperandARM32Mem::Offset); |
| 421 return EncodedAsImmRegOffset; | 439 return EncodedAsImmRegOffset; |
| 422 } | 440 } |
| 423 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 441 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
| 424 Variable *Var = Mem->getBase(); | 442 Variable *Var = Mem->getBase(); |
| 425 if (!Var->hasReg()) | 443 if (!Var->hasReg()) |
| 426 return CantEncode; | 444 return CantEncode; |
| 427 IValueT Rn = getEncodedGPRegNum(Var); | 445 IValueT Rn = getEncodedGPRegNum(Var); |
| 428 if (Mem->isRegReg()) { | 446 if (Mem->isRegReg()) { |
| 429 const Variable *Index = Mem->getIndex(); | 447 const Variable *Index = Mem->getIndex(); |
| 430 if (Var == nullptr) | 448 if (Var == nullptr) |
| 431 return CantEncode; | 449 return CantEncode; |
| 432 Value = (Rn << kRnShift) | Mem->getAddrMode() | | 450 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
| 433 encodeShiftRotateImm5(getEncodedGPRegNum(Index), | 451 encodeShiftRotateImm5(getEncodedGPRegNum(Index), |
| 434 Mem->getShiftOp(), Mem->getShiftAmt()); | 452 Mem->getShiftOp(), Mem->getShiftAmt()); |
| 435 return EncodedAsShiftRotateImm5; | 453 return EncodedAsShiftRotateImm5; |
| 436 } | 454 } |
| 437 // Encoded as immediate register offset. | 455 // Encoded as immediate register offset. |
| 438 ConstantInteger32 *Offset = Mem->getOffset(); | 456 ConstantInteger32 *Offset = Mem->getOffset(); |
| 439 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(), | 457 Value = encodeImmRegOffset(ImmEncoding, Rn, Offset->getValue(), |
| 440 Mem->getAddrMode()); | 458 Mem->getAddrMode()); |
| 441 return EncodedAsImmRegOffset; | 459 return EncodedAsImmRegOffset; |
| 442 } | 460 } |
| 443 return CantEncode; | 461 return CantEncode; |
| 444 } | 462 } |
| 445 | 463 |
| 446 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 464 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
| 447 bool canEncodeBranchOffset(IOffsetT Offset) { | 465 bool canEncodeBranchOffset(IOffsetT Offset) { |
| 448 return Utils::IsAligned(Offset, 4) && | 466 return Utils::IsAligned(Offset, 4) && |
| 449 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 467 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | | 813 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 796 (InstType << kTypeShift) | (IsLoad ? L : 0) | | 814 (InstType << kTypeShift) | (IsLoad ? L : 0) | |
| 797 (IsByte ? B : 0) | (Rt << kRdShift) | Address; | 815 (IsByte ? B : 0) | (Rt << kRdShift) | Address; |
| 798 emitInst(Encoding); | 816 emitInst(Encoding); |
| 799 } | 817 } |
| 800 | 818 |
| 801 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, | 819 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, |
| 802 IValueT Rt, const Operand *OpAddress, | 820 IValueT Rt, const Operand *OpAddress, |
| 803 const TargetInfo &TInfo, const char *InstName) { | 821 const TargetInfo &TInfo, const char *InstName) { |
| 804 IValueT Address; | 822 IValueT Address; |
| 805 switch (encodeAddress(OpAddress, Address, TInfo)) { | 823 switch (encodeAddress(OpAddress, Address, TInfo, Imm12Address)) { |
| 806 default: | 824 default: |
| 807 llvm::report_fatal_error(std::string(InstName) + | 825 llvm::report_fatal_error(std::string(InstName) + |
| 808 ": Memory address not understood"); | 826 ": Memory address not understood"); |
| 809 case EncodedAsImmRegOffset: { | 827 case EncodedAsImmRegOffset: { |
| 810 // XXX{B} (immediate): | 828 // XXX{B} (immediate): |
| 811 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 829 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 812 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 830 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 813 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 831 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 814 // | 832 // |
| 815 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 833 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 return; | 871 return; |
| 854 } | 872 } |
| 855 } | 873 } |
| 856 } | 874 } |
| 857 | 875 |
| 858 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, | 876 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
| 859 IValueT Rt, const Operand *OpAddress, | 877 IValueT Rt, const Operand *OpAddress, |
| 860 const TargetInfo &TInfo, | 878 const TargetInfo &TInfo, |
| 861 const char *InstName) { | 879 const char *InstName) { |
| 862 IValueT Address; | 880 IValueT Address; |
| 863 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { | 881 switch (encodeAddress(OpAddress, Address, TInfo, RotatedImm8Enc3Address)) { |
| 864 default: | 882 default: |
| 865 llvm::report_fatal_error(std::string(InstName) + | 883 llvm::report_fatal_error(std::string(InstName) + |
| 866 ": Memory address not understood"); | 884 ": Memory address not understood"); |
| 867 case EncodedAsImmRegOffset: { | 885 case EncodedAsImmRegOffset: { |
| 868 // XXXH (immediate) | 886 // XXXH (immediate) |
| 869 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] | 887 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] |
| 870 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] | 888 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] |
| 871 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 889 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 872 // | 890 // |
| 873 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, | 891 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1349 break; | 1367 break; |
| 1350 case IceType_i16: | 1368 case IceType_i16: |
| 1351 MemExOpcode |= B2 | B1; | 1369 MemExOpcode |= B2 | B1; |
| 1352 break; | 1370 break; |
| 1353 case IceType_i32: | 1371 case IceType_i32: |
| 1354 break; | 1372 break; |
| 1355 case IceType_i64: | 1373 case IceType_i64: |
| 1356 MemExOpcode |= B1; | 1374 MemExOpcode |= B1; |
| 1357 } | 1375 } |
| 1358 IValueT AddressRn; | 1376 IValueT AddressRn; |
| 1359 if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) != | 1377 if (encodeAddress(OpAddress, AddressRn, TInfo, NoImmOffsetAddress) != |
| 1360 EncodedAsImmRegOffset) | 1378 EncodedAsImmRegOffset) |
| 1361 llvm::report_fatal_error(std::string(InstName) + | 1379 llvm::report_fatal_error(std::string(InstName) + |
| 1362 ": Can't extract Rn from address"); | 1380 ": Can't extract Rn from address"); |
| 1363 assert(Utils::IsAbsoluteUint(3, MemExOpcode)); | 1381 assert(Utils::IsAbsoluteUint(3, MemExOpcode)); |
| 1364 assert(Rd < RegARM32::getNumGPRegs()); | 1382 assert(Rd < RegARM32::getNumGPRegs()); |
| 1365 assert(Rt < RegARM32::getNumGPRegs()); | 1383 assert(Rt < RegARM32::getNumGPRegs()); |
| 1366 assert(CondARM32::isDefined(Cond)); | 1384 assert(CondARM32::isDefined(Cond)); |
| 1367 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 | | 1385 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 | |
| 1368 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) | | 1386 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) | |
| 1369 AddressRn | (Rd << kRdShift) | (Rt << kRmShift); | 1387 AddressRn | (Rd << kRdShift) | (Rt << kRmShift); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1723 // POP - ARM section A8.8.132, encoding A2: | 1741 // POP - ARM section A8.8.132, encoding A2: |
| 1724 // pop<c> {Rt} | 1742 // pop<c> {Rt} |
| 1725 // | 1743 // |
| 1726 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. | 1744 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1727 constexpr const char *Pop = "pop"; | 1745 constexpr const char *Pop = "pop"; |
| 1728 IValueT Rt = encodeGPRegister(OpRt, "Rt", Pop); | 1746 IValueT Rt = encodeGPRegister(OpRt, "Rt", Pop); |
| 1729 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); | 1747 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); |
| 1730 // Same as load instruction. | 1748 // Same as load instruction. |
| 1731 constexpr bool IsLoad = true; | 1749 constexpr bool IsLoad = true; |
| 1732 constexpr bool IsByte = false; | 1750 constexpr bool IsByte = false; |
| 1733 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | 1751 constexpr IOffsetT MaxOffset = (1 << 8) - 1; |
| 1734 OperandARM32Mem::PostIndex); | 1752 constexpr IValueT NoShiftRight = 0; |
| 1753 IValueT Address = | |
| 1754 encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | |
| 1755 OperandARM32Mem::PostIndex, MaxOffset, NoShiftRight); | |
| 1735 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); | 1756 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
| 1736 } | 1757 } |
| 1737 | 1758 |
| 1738 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { | 1759 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1739 // POP - ARM section A8.*.131, encoding A1: | 1760 // POP - ARM section A8.*.131, encoding A1: |
| 1740 // pop<c> <registers> | 1761 // pop<c> <registers> |
| 1741 // | 1762 // |
| 1742 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and | 1763 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1743 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1764 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1744 constexpr bool IsLoad = true; | 1765 constexpr bool IsLoad = true; |
| 1745 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); | 1766 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); |
| 1746 } | 1767 } |
| 1747 | 1768 |
| 1748 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { | 1769 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { |
| 1749 // PUSH - ARM section A8.8.133, encoding A2: | 1770 // PUSH - ARM section A8.8.133, encoding A2: |
| 1750 // push<c> {Rt} | 1771 // push<c> {Rt} |
| 1751 // | 1772 // |
| 1752 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. | 1773 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1753 constexpr const char *Push = "push"; | 1774 constexpr const char *Push = "push"; |
| 1754 IValueT Rt = encodeGPRegister(OpRt, "Rt", Push); | 1775 IValueT Rt = encodeGPRegister(OpRt, "Rt", Push); |
| 1755 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push); | 1776 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push); |
| 1756 // Same as store instruction. | 1777 // Same as store instruction. |
| 1757 constexpr bool isLoad = false; | 1778 constexpr bool isLoad = false; |
| 1758 constexpr bool isByte = false; | 1779 constexpr bool isByte = false; |
| 1759 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, | 1780 constexpr IOffsetT MaxOffset = (1 << 8) - 1; |
| 1760 OperandARM32Mem::PreIndex); | 1781 constexpr IValueT NoShiftRight = 0; |
| 1782 IValueT Address = | |
| 1783 encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, | |
| 1784 OperandARM32Mem::PreIndex, MaxOffset, NoShiftRight); | |
| 1761 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); | 1785 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); |
| 1762 } | 1786 } |
| 1763 | 1787 |
| 1764 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { | 1788 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { |
| 1765 // PUSH - ARM section A8.8.133, encoding A1: | 1789 // PUSH - ARM section A8.8.133, encoding A1: |
| 1766 // push<c> <Registers> | 1790 // push<c> <Registers> |
| 1767 // | 1791 // |
| 1768 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and | 1792 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1769 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1793 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1770 constexpr bool IsLoad = false; | 1794 constexpr bool IsLoad = false; |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2315 // VLDR - ARM section A8.8.333, encoding A1. | 2339 // VLDR - ARM section A8.8.333, encoding A1. |
| 2316 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] | 2340 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] |
| 2317 // | 2341 // |
| 2318 // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, | 2342 // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, |
| 2319 // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0. | 2343 // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0. |
| 2320 constexpr const char *Vldrd = "vldrd"; | 2344 constexpr const char *Vldrd = "vldrd"; |
| 2321 IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); | 2345 IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); |
| 2322 assert(CondARM32::isDefined(Cond)); | 2346 assert(CondARM32::isDefined(Cond)); |
| 2323 IValueT Address; | 2347 IValueT Address; |
| 2324 EncodedOperand AddressEncoding = | 2348 EncodedOperand AddressEncoding = |
| 2325 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2349 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
| 2326 (void)AddressEncoding; | 2350 (void)AddressEncoding; |
| 2327 assert(AddressEncoding == EncodedAsImmRegOffset); | 2351 assert(AddressEncoding == EncodedAsImmRegOffset); |
| 2328 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | | 2352 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | |
| 2329 (encodeCondition(Cond) << kConditionShift) | | 2353 (encodeCondition(Cond) << kConditionShift) | |
| 2330 (getYInRegYXXXX(Dd) << 22) | | 2354 (getYInRegYXXXX(Dd) << 22) | |
| 2331 (getXXXXInRegYXXXX(Dd) << 12) | Address; | 2355 (getXXXXInRegYXXXX(Dd) << 12) | Address; |
| 2332 emitInst(Encoding); | 2356 emitInst(Encoding); |
| 2333 } | 2357 } |
| 2334 | 2358 |
| 2335 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, | 2359 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, |
| 2336 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 2360 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 2337 // VDLR - ARM section A8.8.333, encoding A2. | 2361 // VDLR - ARM section A8.8.333, encoding A2. |
| 2338 // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]] | 2362 // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]] |
| 2339 // | 2363 // |
| 2340 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, | 2364 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, |
| 2341 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; | 2365 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; |
| 2342 constexpr const char *Vldrs = "vldrs"; | 2366 constexpr const char *Vldrs = "vldrs"; |
| 2343 IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); | 2367 IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); |
| 2344 assert(CondARM32::isDefined(Cond)); | 2368 assert(CondARM32::isDefined(Cond)); |
| 2345 IValueT Address; | 2369 IValueT Address; |
| 2346 EncodedOperand AddressEncoding = | 2370 EncodedOperand AddressEncoding = |
| 2347 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2371 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
| 2348 (void)AddressEncoding; | 2372 (void)AddressEncoding; |
| 2349 assert(AddressEncoding == EncodedAsImmRegOffset); | 2373 assert(AddressEncoding == EncodedAsImmRegOffset); |
| 2350 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | | 2374 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | |
| 2351 (encodeCondition(Cond) << kConditionShift) | | 2375 (encodeCondition(Cond) << kConditionShift) | |
| 2352 (getYInRegXXXXY(Sd) << 22) | | 2376 (getYInRegXXXXY(Sd) << 22) | |
| 2353 (getXXXXInRegXXXXY(Sd) << 12) | Address; | 2377 (getXXXXInRegXXXXY(Sd) << 12) | Address; |
| 2354 emitInst(Encoding); | 2378 emitInst(Encoding); |
| 2355 } | 2379 } |
| 2356 | 2380 |
| 2357 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt, | 2381 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2422 // VSTR - ARM section A8.8.413, encoding A1: | 2446 // VSTR - ARM section A8.8.413, encoding A1: |
| 2423 // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}] | 2447 // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}] |
| 2424 // | 2448 // |
| 2425 // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, | 2449 // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, |
| 2426 // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0. | 2450 // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0. |
| 2427 constexpr const char *Vstrd = "vstrd"; | 2451 constexpr const char *Vstrd = "vstrd"; |
| 2428 IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); | 2452 IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); |
| 2429 assert(CondARM32::isDefined(Cond)); | 2453 assert(CondARM32::isDefined(Cond)); |
| 2430 IValueT Address; | 2454 IValueT Address; |
| 2431 IValueT AddressEncoding = | 2455 IValueT AddressEncoding = |
| 2432 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2456 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
| 2433 (void)AddressEncoding; | 2457 (void)AddressEncoding; |
| 2434 assert(AddressEncoding == EncodedAsImmRegOffset); | 2458 assert(AddressEncoding == EncodedAsImmRegOffset); |
| 2435 IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | | 2459 IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | |
| 2436 (encodeCondition(Cond) << kConditionShift) | | 2460 (encodeCondition(Cond) << kConditionShift) | |
| 2437 (getYInRegYXXXX(Dd) << 22) | | 2461 (getYInRegYXXXX(Dd) << 22) | |
| 2438 (getXXXXInRegYXXXX(Dd) << 12) | Address; | 2462 (getXXXXInRegYXXXX(Dd) << 12) | Address; |
| 2439 emitInst(Encoding); | 2463 emitInst(Encoding); |
| 2440 } | 2464 } |
| 2441 | 2465 |
| 2442 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, | 2466 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, |
| 2443 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 2467 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 2444 // VSTR - ARM section A8.8.413, encoding A2: | 2468 // VSTR - ARM section A8.8.413, encoding A2: |
| 2445 // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]] | 2469 // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]] |
| 2446 // | 2470 // |
| 2447 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, | 2471 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, |
| 2448 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; | 2472 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; |
| 2449 constexpr const char *Vstrs = "vstrs"; | 2473 constexpr const char *Vstrs = "vstrs"; |
| 2450 IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); | 2474 IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); |
| 2451 assert(CondARM32::isDefined(Cond)); | 2475 assert(CondARM32::isDefined(Cond)); |
| 2452 IValueT Address; | 2476 IValueT Address; |
| 2453 IValueT AddressEncoding = | 2477 IValueT AddressEncoding = |
| 2454 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2478 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); |
| 2455 (void)AddressEncoding; | 2479 (void)AddressEncoding; |
| 2456 assert(AddressEncoding == EncodedAsImmRegOffset); | 2480 assert(AddressEncoding == EncodedAsImmRegOffset); |
| 2457 IValueT Encoding = | 2481 IValueT Encoding = |
| 2458 B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | | 2482 B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | |
| 2459 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address; | 2483 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address; |
| 2460 emitInst(Encoding); | 2484 emitInst(Encoding); |
| 2461 } | 2485 } |
| 2462 | 2486 |
| 2463 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn, | 2487 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn, |
| 2464 const Operand *OpSm, CondARM32::Cond Cond) { | 2488 const Operand *OpSm, CondARM32::Cond Cond) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2531 // | 2555 // |
| 2532 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and | 2556 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and |
| 2533 // iiiiiiii=NumConsecRegs. | 2557 // iiiiiiii=NumConsecRegs. |
| 2534 constexpr IValueT VpushOpcode = | 2558 constexpr IValueT VpushOpcode = |
| 2535 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; | 2559 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; |
| 2536 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs); | 2560 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs); |
| 2537 } | 2561 } |
| 2538 | 2562 |
| 2539 } // end of namespace ARM32 | 2563 } // end of namespace ARM32 |
| 2540 } // end of namespace Ice | 2564 } // end of namespace Ice |
| OLD | NEW |