| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   55 static constexpr uint32_t kRnShift = 16; |   55 static constexpr uint32_t kRnShift = 16; | 
|   56 static constexpr uint32_t kSShift = 20; |   56 static constexpr uint32_t kSShift = 20; | 
|   57 static constexpr uint32_t kTypeShift = 25; |   57 static constexpr uint32_t kTypeShift = 25; | 
|   58  |   58  | 
|   59 // Immediate instruction fields encoding. |   59 // Immediate instruction fields encoding. | 
|   60 static constexpr uint32_t kImmed8Bits = 8; |   60 static constexpr uint32_t kImmed8Bits = 8; | 
|   61 static constexpr uint32_t kImmed8Shift = 0; |   61 static constexpr uint32_t kImmed8Shift = 0; | 
|   62 static constexpr uint32_t kRotateBits = 4; |   62 static constexpr uint32_t kRotateBits = 4; | 
|   63 static constexpr uint32_t kRotateShift = 8; |   63 static constexpr uint32_t kRotateShift = 8; | 
|   64  |   64  | 
 |   65 // Shift instruction register fields encodings. | 
 |   66 static constexpr uint32_t kShiftImmShift = 7; | 
 |   67 static constexpr uint32_t kShiftImmBits = 5; | 
 |   68 static constexpr uint32_t kShiftShift = 5; | 
 |   69  | 
|   65 static constexpr uint32_t kImmed12Bits = 12; |   70 static constexpr uint32_t kImmed12Bits = 12; | 
|   66 static constexpr uint32_t kImm12Shift = 0; |   71 static constexpr uint32_t kImm12Shift = 0; | 
|   67  |   72  | 
|   68 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |   73 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } | 
|   69  |   74  | 
|   70 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |   75 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { | 
|   71   return static_cast<uint32_t>(Rn); |   76   return static_cast<uint32_t>(Rn); | 
|   72 } |   77 } | 
|   73  |   78  | 
|   74 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { |   79 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { | 
|   75   return R != RegARM32::Encoded_Not_GPR; |   80   return R != RegARM32::Encoded_Not_GPR; | 
|   76 } |   81 } | 
|   77  |   82  | 
|   78 inline bool isGPRRegisterDefined(uint32_t R) { |   83 inline bool isGPRRegisterDefined(uint32_t R) { | 
|   79   return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); |   84   return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); | 
|   80 } |   85 } | 
|   81  |   86  | 
|   82 inline bool isConditionDefined(CondARM32::Cond Cond) { |   87 inline bool isConditionDefined(CondARM32::Cond Cond) { | 
|   83   return Cond != CondARM32::kNone; |   88   return Cond != CondARM32::kNone; | 
|   84 } |   89 } | 
|   85  |   90  | 
|   86 inline uint32_t encodeCondition(CondARM32::Cond Cond) { |   91 inline uint32_t encodeCondition(CondARM32::Cond Cond) { | 
|   87   return static_cast<uint32_t>(Cond); |   92   return static_cast<uint32_t>(Cond); | 
|   88 } |   93 } | 
|   89  |   94  | 
 |   95 uint32_t encodeShift(OperandARM32::ShiftKind Shift) { | 
 |   96   // Follows encoding in ARM section A8.4.1 "Constant shifts". | 
 |   97   switch (Shift) { | 
 |   98   case OperandARM32::kNoShift: | 
 |   99   case OperandARM32::LSL: | 
 |  100     return 0; // 0b00 | 
 |  101   case OperandARM32::LSR: | 
 |  102     return 1; // 0b01 | 
 |  103   case OperandARM32::ASR: | 
 |  104     return 2; // 0b10 | 
 |  105   case OperandARM32::ROR: | 
 |  106   case OperandARM32::RRX: | 
 |  107     return 3; // 0b11 | 
 |  108   } | 
 |  109 } | 
 |  110  | 
|   90 // Returns the bits in the corresponding masked value. |  111 // Returns the bits in the corresponding masked value. | 
|   91 inline uint32_t mask(uint32_t Value, uint32_t Shift, uint32_t Bits) { |  112 inline uint32_t mask(uint32_t Value, uint32_t Shift, uint32_t Bits) { | 
|   92   return (Value >> Shift) & ((1 << Bits) - 1); |  113   return (Value >> Shift) & ((1 << Bits) - 1); | 
|   93 } |  114 } | 
|   94  |  115  | 
|   95 // Extract out a Bit in Value. |  116 // Extract out a Bit in Value. | 
|   96 inline bool isBitSet(uint32_t Bit, uint32_t Value) { |  117 inline bool isBitSet(uint32_t Bit, uint32_t Value) { | 
|   97   return (Value & Bit) == Bit; |  118   return (Value & Bit) == Bit; | 
|   98 } |  119 } | 
|   99  |  120  | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  111   DecodedAsRegister, |  132   DecodedAsRegister, | 
|  112   // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |  133   // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 
|  113   // value. |  134   // value. | 
|  114   DecodedAsRotatedImm8, |  135   DecodedAsRotatedImm8, | 
|  115   // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |  136   // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 
|  116   // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |  137   // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 
|  117   // Rn should be used, and iiiiiiiiiiii is the offset. |  138   // Rn should be used, and iiiiiiiiiiii is the offset. | 
|  118   DecodedAsImmRegOffset |  139   DecodedAsImmRegOffset | 
|  119 }; |  140 }; | 
|  120  |  141  | 
 |  142 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, | 
 |  143 // tt=Shift, and mmmm=Rm. | 
 |  144 uint32_t encodeShiftRotateImm5(uint32_t Rm, OperandARM32::ShiftKind Shift, | 
 |  145                                uint32_t imm5) { | 
 |  146   (void)kShiftImmBits; | 
 |  147   assert(imm5 < (1 << kShiftImmBits)); | 
 |  148   return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; | 
 |  149 } | 
 |  150  | 
|  121 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { |  151 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { | 
|  122   if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |  152   if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 
|  123     if (Var->hasReg()) { |  153     if (Var->hasReg()) { | 
|  124       Value = Var->getRegNum(); |  154       Value = Var->getRegNum(); | 
|  125       return DecodedAsRegister; |  155       return DecodedAsRegister; | 
|  126     } |  156     } | 
|  127   } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |  157   } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 
|  128     const uint32_t Immed8 = FlexImm->getImm(); |  158     const uint32_t Immed8 = FlexImm->getImm(); | 
|  129     const uint32_t Rotate = FlexImm->getRotateAmt(); |  159     const uint32_t Rotate = FlexImm->getRotateAmt(); | 
|  130     assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); |  160     assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); | 
|  131     // TODO(kschimpf): Remove void casts when MINIMAL build allows. |  161     // TODO(kschimpf): Remove void casts when MINIMAL build allows. | 
|  132     (void) kRotateBits; |  162     (void)kRotateBits; | 
|  133     (void) kImmed8Bits; |  163     (void)kImmed8Bits; | 
|  134     Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |  164     Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 
|  135     return DecodedAsRotatedImm8; |  165     return DecodedAsRotatedImm8; | 
|  136   } |  166   } | 
|  137   return CantDecode; |  167   return CantDecode; | 
|  138 } |  168 } | 
|  139  |  169  | 
|  140 uint32_t decodeImmRegOffset(RegARM32::GPRRegister Reg, int32_t Offset, |  170 uint32_t decodeImmRegOffset(RegARM32::GPRRegister Reg, int32_t Offset, | 
|  141                             OperandARM32Mem::AddrMode Mode) { |  171                             OperandARM32Mem::AddrMode Mode) { | 
|  142   uint32_t Value = Mode | (encodeGPRRegister(Reg) << kRnShift); |  172   uint32_t Value = Mode | (encodeGPRRegister(Reg) << kRnShift); | 
|  143   if (Offset < 0) { |  173   if (Offset < 0) { | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  199   } |  229   } | 
|  200   // TODO(kschimpf) Decide if we have near jumps. |  230   // TODO(kschimpf) Decide if we have near jumps. | 
|  201   label->bindTo(bound); |  231   label->bindTo(bound); | 
|  202 } |  232 } | 
|  203  |  233  | 
|  204 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |  234 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, | 
|  205                                        uint32_t Opcode, bool SetCc, uint32_t Rn, |  235                                        uint32_t Opcode, bool SetCc, uint32_t Rn, | 
|  206                                        uint32_t Rd, uint32_t Imm12) { |  236                                        uint32_t Rd, uint32_t Imm12) { | 
|  207   assert(isGPRRegisterDefined(Rd)); |  237   assert(isGPRRegisterDefined(Rd)); | 
|  208   // TODO(kschimpf): Remove void cast when MINIMAL build allows. |  238   // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 
|  209   (void) isGPRRegisterDefined(Rd); |  239   (void)isGPRRegisterDefined(Rd); | 
|  210   assert(Cond != CondARM32::kNone); |  240   assert(Cond != CondARM32::kNone); | 
|  211   AssemblerBuffer::EnsureCapacity ensured(&Buffer); |  241   AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 
|  212   const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | |  242   const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | | 
|  213                             (Type << kTypeShift) | (Opcode << kOpcodeShift) | |  243                             (Type << kTypeShift) | (Opcode << kOpcodeShift) | | 
|  214                             (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | |  244                             (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | | 
|  215                             (Rd << kRdShift) | Imm12; |  245                             (Rd << kRdShift) | Imm12; | 
|  216   emitInst(Encoding); |  246   emitInst(Encoding); | 
|  217 } |  247 } | 
|  218  |  248  | 
|  219 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, |  249 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  232                                 const Operand *OpSrc1, bool SetFlags, |  262                                 const Operand *OpSrc1, bool SetFlags, | 
|  233                                 CondARM32::Cond Cond) { |  263                                 CondARM32::Cond Cond) { | 
|  234   // Note: Loop is used so that we can short circuit using break; |  264   // Note: Loop is used so that we can short circuit using break; | 
|  235   do { |  265   do { | 
|  236     uint32_t Rd; |  266     uint32_t Rd; | 
|  237     if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |  267     if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 
|  238       break; |  268       break; | 
|  239     uint32_t Rn; |  269     uint32_t Rn; | 
|  240     if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |  270     if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 
|  241       break; |  271       break; | 
 |  272     constexpr uint32_t Add = B2; // 0100 | 
|  242     uint32_t Src1Value; |  273     uint32_t Src1Value; | 
|  243     // TODO(kschimpf) Other possible decodings of add. |  274     // TODO(kschimpf) Other possible decodings of add. | 
|  244     if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { |  275     switch (decodeOperand(OpSrc1, Src1Value)) { | 
|  245       // ADD (Immediate): See ARM section A8.8.5, rule A1. |  276     default: | 
|  246       // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |  277       break; | 
|  247       // s=SetFlags and iiiiiiiiiiii=Src1Value |  278     case DecodedAsRegister: { | 
|  248       if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || |  279       // ADD (register) - ARM section A8.8.7, encoding A1: | 
|  249           (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) |  280       //   add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 
 |  281       // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: | 
 |  282       //   add{s}<c> sp, <Rn>, <Rm>{, <shiff>} | 
 |  283       // | 
 |  284       // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 
 |  285       // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags | 
 |  286       Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | 
 |  287       if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | 
|  250         // Conditions of rule violated. |  288         // Conditions of rule violated. | 
|  251         break; |  289         break; | 
|  252       constexpr uint32_t Add = B2; // 0100 |  290       constexpr uint32_t InstTypeRegister = 0; | 
|  253       constexpr uint32_t InstType = 1; |  291       emitType01(Cond, InstTypeRegister, Add, SetFlags, Rn, Rd, Src1Value); | 
|  254       emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); |  | 
|  255       return; |  292       return; | 
|  256     } |  293     } | 
 |  294     case DecodedAsRotatedImm8: { | 
 |  295       // ADD (Immediate) - ARM section A8.8.5, encoding A1: | 
 |  296       //   add{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 
 |  297       // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. | 
 |  298       //   add{s}<c> <Rd>, sp, #<RotatedImm8> | 
 |  299       // | 
 |  300       // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 
 |  301       // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. | 
 |  302       if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 
 |  303         // Conditions of rule violated. | 
 |  304         break; | 
 |  305       constexpr uint32_t InstTypeImmediate = 1; | 
 |  306       emitType01(Cond, InstTypeImmediate, Add, SetFlags, Rn, Rd, Src1Value); | 
 |  307       return; | 
 |  308     } | 
 |  309     } | 
|  257   } while (0); |  310   } while (0); | 
|  258   UnimplementedError(Ctx->getFlags()); |  311   UnimplementedError(Ctx->getFlags()); | 
|  259 } |  312 } | 
|  260  |  313  | 
|  261 void ARM32::AssemblerARM32::bkpt(uint16_t imm16) { |  314 void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { | 
 |  315   // BKPT - ARM section A*.8.24 - encoding A1: | 
 |  316   //   bkpt #<Imm16> | 
 |  317   // | 
 |  318   // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 | 
|  262   AssemblerBuffer::EnsureCapacity ensured(&Buffer); |  319   AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 
|  263   const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | |  320   const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | | 
|  264                             ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); |  321                             ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); | 
|  265   emitInst(Encoding); |  322   emitInst(Encoding); | 
|  266 } |  323 } | 
|  267  |  324  | 
|  268 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |  325 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { | 
 |  326   // BX - ARM section A8.8.27, encoding A1: | 
 |  327   //   bx<c> <Rm> | 
 |  328   // | 
|  269   // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |  329   // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 
|  270   // (ARM section A8.8.27, encoding A1). |  | 
|  271   assert(isGPRRegisterDefined(Rm)); |  330   assert(isGPRRegisterDefined(Rm)); | 
|  272   // TODO(kschimpf): Remove void cast when MINIMAL build allows. |  331   // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 
|  273   (void) isGPRRegisterDefined(Rm); |  332   (void)isGPRRegisterDefined(Rm); | 
|  274   assert(isConditionDefined(Cond)); |  333   assert(isConditionDefined(Cond)); | 
 |  334   (void)isConditionDefined(Cond); | 
|  275   AssemblerBuffer::EnsureCapacity ensured(&Buffer); |  335   AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 
|  276   const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | |  336   const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | | 
|  277                             B21 | (0xfff << 8) | B4 | |  337                             B21 | (0xfff << 8) | B4 | | 
|  278                             (encodeGPRRegister(Rm) << kRmShift); |  338                             (encodeGPRRegister(Rm) << kRmShift); | 
|  279   emitInst(Encoding); |  339   emitInst(Encoding); | 
|  280 } |  340 } | 
|  281  |  341  | 
|  282 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |  342 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 
|  283                                 CondARM32::Cond Cond) { |  343                                 CondARM32::Cond Cond) { | 
|  284   // Note: Loop is used so that we can short ciruit using break; |  344   // Note: Loop is used so that we can short ciruit using break; | 
|  285   do { |  345   do { | 
|  286     uint32_t Rt; |  346     uint32_t Rt; | 
|  287     if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |  347     if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 
|  288       break; |  348       break; | 
|  289     uint32_t Address; |  349     uint32_t Address; | 
|  290     if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |  350     if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 
|  291       break; |  351       break; | 
|  292     // cccc010pu0w1nnnnttttiiiiiiiiiiii (ARM section A8.8.63, encoding A1; and |  352     // LDR (immediate) - ARM section A8.8.63, encoding A1: | 
|  293     // section A8.6.68, encoding A1). |  353     //   ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}]      ; p=1, w=0 | 
 |  354     //   ldr<c> <Rt>, [<Rn>], #+/-<imm12>        ; p=1, w=1 | 
 |  355     //   ldr<c> <Rt>, [<Rn>, #+/-<imm12>]!       ; p=0, w=1 | 
 |  356     // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 
 |  357     //   ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}]     ; p=1, w=0 | 
 |  358     //   ldrb<c> <Rt>, [<Rn>], #+/-<imm12>       ; p=1, w=1 | 
 |  359     //   ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]!      ; p=0, w=1 | 
 |  360     // | 
 |  361     // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 
 |  362     // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | 
|  294     constexpr uint32_t InstType = B1; // 010 |  363     constexpr uint32_t InstType = B1; // 010 | 
|  295     constexpr bool IsLoad = true; |  364     constexpr bool IsLoad = true; | 
|  296     const Type Ty = OpRt->getType(); |  365     const Type Ty = OpRt->getType(); | 
|  297     if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |  366     if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 
|  298       break; |  367       break; | 
|  299     const bool IsByte = typeWidthInBytes(Ty) == 1; |  368     const bool IsByte = typeWidthInBytes(Ty) == 1; | 
|  300     if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |  369     if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 
|  301         (!IsByte && !isBitSet(P, Address) && isBitSet(W, Address)) || |  370         (!isBitSet(P, Address) && isBitSet(W, Address)) || | 
|  302         ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |  371         (!IsByte && | 
 |  372          (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 
|  303          !isBitSet(P, Address) && |  373          !isBitSet(P, Address) && | 
|  304          isBitSet(U, Address) & !isBitSet(W, Address) && |  374          isBitSet(U, Address) & !isBitSet(W, Address) && | 
|  305          (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |  375          (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 
|  306       break; |  376       break; | 
|  307     emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |  377     emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | 
|  308     return; |  378     return; | 
|  309   } while (0); |  379   } while (0); | 
|  310   UnimplementedError(Ctx->getFlags()); |  380   UnimplementedError(Ctx->getFlags()); | 
|  311 } |  381 } | 
|  312  |  382  | 
|  313 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |  383 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 
|  314                                 CondARM32::Cond Cond) { |  384                                 CondARM32::Cond Cond) { | 
|  315   // Note: Loop is used so that we can short ciruit using break; |  385   // Note: Loop is used so that we can short ciruit using break; | 
|  316   do { |  386   do { | 
|  317     uint32_t Rd; |  387     uint32_t Rd; | 
|  318     if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |  388     if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 
|  319       break; |  389       break; | 
|  320     uint32_t Src; |  390     uint32_t Src; | 
|  321     // TODO(kschimpf) Handle other forms of mov. |  391     // TODO(kschimpf) Handle other forms of mov. | 
|  322     if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { |  392     if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { | 
|  323       // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) |  393       // MOV (immediate) - ARM section A8.8.102, encoding A1: | 
|  324       // Note: We don't use movs in this assembler. |  394       //   mov{S}<c> <Rd>, #<RotatedImm8> | 
 |  395       // | 
 |  396       // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, | 
 |  397       // and iiiiiiiiiiii=RotatedImm8=Src.  Note: We don't use movs in this | 
 |  398       // assembler. | 
|  325       constexpr bool SetFlags = false; |  399       constexpr bool SetFlags = false; | 
|  326       if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags)) |  400       if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 
|  327         // Conditions of rule violated. |  401         // Conditions of rule violated. | 
|  328         break; |  402         break; | 
|  329       constexpr uint32_t Rn = 0; |  403       constexpr uint32_t Rn = 0; | 
|  330       constexpr uint32_t Mov = B3 | B2 | B0; // 1101. |  404       constexpr uint32_t Mov = B3 | B2 | B0; // 1101. | 
|  331       constexpr uint32_t InstType = 1; |  405       constexpr uint32_t InstType = 1; | 
|  332       emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); |  406       emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); | 
|  333       return; |  407       return; | 
|  334     } |  408     } | 
|  335   } while (0); |  409   } while (0); | 
|  336   UnimplementedError(Ctx->getFlags()); |  410   UnimplementedError(Ctx->getFlags()); | 
|  337 } |  411 } | 
|  338  |  412  | 
|  339 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |  413 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 
|  340                                 CondARM32::Cond Cond) { |  414                                 CondARM32::Cond Cond) { | 
|  341   // Note: Loop is used so that we can short ciruit using break; |  415   // Note: Loop is used so that we can short ciruit using break; | 
|  342   do { |  416   do { | 
|  343     uint32_t Rt; |  417     uint32_t Rt; | 
|  344     if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |  418     if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 
|  345       break; |  419       break; | 
|  346     uint32_t Address; |  420     uint32_t Address; | 
|  347     if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |  421     if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 
|  348       break; |  422       break; | 
|  349     // cccc010pub0nnnnttttiiiiiiiiiiii (ARM section A8.8.204, encoding A1; and |  423     // STR (immediate) - ARM section A8.8.204, encoding A1: | 
|  350     // section 18.8.207, encoding A1). |  424     //   str<c> <Rt>, [<Rn>{, #+/-<imm12>}]      ; p=1, w=0 | 
 |  425     //   str<c> <Rt>, [<Rn>], #+/-<imm12>        ; p=1, w=1 | 
 |  426     //   str<c> <Rt>, [<Rn>, #+/-<imm12>]!       ; p=0, w=1 | 
 |  427     // STRB (immediate) - ARM section A8.8.207, encoding A1: | 
 |  428     //   strb<c> <Rt>, [<Rn>{, #+/-<imm12>}]     ; p=1, w=0 | 
 |  429     //   strb<c> <Rt>, [<Rn>], #+/-<imm12>       ; p=1, w=1 | 
 |  430     //   strb<c> <Rt>, [<Rn>, #+/-<imm12>]!      ; p=0, w=1 | 
 |  431     // | 
 |  432     // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 
 |  433     // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | 
|  351     constexpr uint32_t InstType = B1; // 010 |  434     constexpr uint32_t InstType = B1; // 010 | 
|  352     constexpr bool IsLoad = false; |  435     constexpr bool IsLoad = false; | 
|  353     const Type Ty = OpRt->getType(); |  436     const Type Ty = OpRt->getType(); | 
|  354     if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |  437     if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 
|  355       break; |  438       break; | 
|  356     const bool IsByte = typeWidthInBytes(Ty) == 1; |  439     const bool IsByte = typeWidthInBytes(Ty) == 1; | 
|  357     // Check for rule violations. |  440     // Check for rule violations. | 
|  358     if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |  441     if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 
|  359         (!isBitSet(P, Address) && isBitSet(W, Address)) || |  442         (!isBitSet(P, Address) && isBitSet(W, Address)) || | 
|  360         (!IsByte && |  443         (!IsByte && | 
|  361          (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |  444          (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 
|  362          isBitSet(P, Address) && !isBitSet(U, Address) && |  445          isBitSet(P, Address) && !isBitSet(U, Address) && | 
|  363          isBitSet(W, Address) && |  446          isBitSet(W, Address) && | 
|  364          (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |  447          (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 
 |  448       // Conditions of rule violated. | 
|  365       break; |  449       break; | 
|  366     emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |  450     emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | 
|  367     return; |  451     return; | 
|  368   } while (0); |  452   } while (0); | 
|  369   UnimplementedError(Ctx->getFlags()); |  453   UnimplementedError(Ctx->getFlags()); | 
|  370 } |  454 } | 
|  371  |  455  | 
|  372 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |  456 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 
|  373                                 const Operand *OpSrc1, bool SetFlags, |  457                                 const Operand *OpSrc1, bool SetFlags, | 
|  374                                 CondARM32::Cond Cond) { |  458                                 CondARM32::Cond Cond) { | 
|  375   // Note: Loop is used so that we can short circuit using break; |  459   // Note: Loop is used so that we can short circuit using break; | 
|  376   do { |  460   do { | 
|  377     uint32_t Rd; |  461     uint32_t Rd; | 
|  378     if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |  462     if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 
|  379       break; |  463       break; | 
|  380     uint32_t Rn; |  464     uint32_t Rn; | 
|  381     if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |  465     if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 
|  382       break; |  466       break; | 
 |  467     constexpr uint32_t Sub = B1; // 0010 | 
|  383     uint32_t Src1Value; |  468     uint32_t Src1Value; | 
|  384     // TODO(kschimpf) Other possible decodings of add. |  469     // TODO(kschimpf) Other possible decodings of sub. | 
|  385     if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { |  470     switch (decodeOperand(OpSrc1, Src1Value)) { | 
|  386       // Sub (Immediate): See ARM section A8.8.222, rule A1. |  471     default: | 
|  387       // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |  472       break; | 
|  388       // s=SetFlags and iiiiiiiiiiii=Src1Value |  473     case DecodedAsRegister: { | 
|  389       if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || |  474       // SUB (register) - ARM section A8.8.223, encoding A1: | 
|  390           (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) |  475       //   sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 
 |  476       // SUB (SP minus register): See ARM section 8.8.226, encoding A1: | 
 |  477       //   sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} | 
 |  478       // | 
 |  479       // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 
 |  480       // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. | 
 |  481       Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | 
 |  482       constexpr uint32_t InstType = 0; // i.e. register | 
 |  483       if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | 
|  391         // Conditions of rule violated. |  484         // Conditions of rule violated. | 
|  392         break; |  485         break; | 
|  393       constexpr uint32_t Add = B1; // 0010 |  486       emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); | 
 |  487       return; | 
 |  488     } | 
 |  489     case DecodedAsRotatedImm8: { | 
 |  490       // Sub (Immediate) - ARM section A8.8.222, encoding A1: | 
 |  491       //    sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 
 |  492       // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: | 
 |  493       //    sub{s}<c> sp, <Rn>, #<RotatedImm8> | 
 |  494       // | 
 |  495       // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 
 |  496       // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 | 
 |  497       if (Rd == RegARM32::Encoded_Reg_pc) | 
 |  498         // Conditions of rule violated. | 
 |  499         break; | 
|  394       constexpr uint32_t InstType = 1; |  500       constexpr uint32_t InstType = 1; | 
|  395       emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); |  501       emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); | 
|  396       return; |  502       return; | 
|  397     } |  503     } | 
 |  504     } | 
|  398   } while (0); |  505   } while (0); | 
|  399   UnimplementedError(Ctx->getFlags()); |  506   UnimplementedError(Ctx->getFlags()); | 
|  400 } |  507 } | 
|  401  |  508  | 
|  402 } // end of namespace Ice |  509 } // end of namespace Ice | 
| OLD | NEW |