LLVM API Documentation
00001 //===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains the ARM addressing mode implementation stuff. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H 00015 #define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H 00016 00017 #include "llvm/CodeGen/SelectionDAGNodes.h" 00018 #include "llvm/Support/MathExtras.h" 00019 #include <cassert> 00020 00021 namespace llvm { 00022 00023 /// ARM_AM - ARM Addressing Mode Stuff 00024 namespace ARM_AM { 00025 enum ShiftOpc { 00026 no_shift = 0, 00027 asr, 00028 lsl, 00029 lsr, 00030 ror, 00031 rrx 00032 }; 00033 00034 enum AddrOpc { 00035 add = '+', sub = '-' 00036 }; 00037 00038 static inline const char *getShiftOpcStr(ShiftOpc Op) { 00039 switch (Op) { 00040 default: assert(0 && "Unknown shift opc!"); 00041 case ARM_AM::asr: return "asr"; 00042 case ARM_AM::lsl: return "lsl"; 00043 case ARM_AM::lsr: return "lsr"; 00044 case ARM_AM::ror: return "ror"; 00045 case ARM_AM::rrx: return "rrx"; 00046 } 00047 } 00048 00049 static inline ShiftOpc getShiftOpcForNode(SDValue N) { 00050 switch (N.getOpcode()) { 00051 default: return ARM_AM::no_shift; 00052 case ISD::SHL: return ARM_AM::lsl; 00053 case ISD::SRL: return ARM_AM::lsr; 00054 case ISD::SRA: return ARM_AM::asr; 00055 case ISD::ROTR: return ARM_AM::ror; 00056 //case ISD::ROTL: // Only if imm -> turn into ROTR. 00057 // Can't handle RRX here, because it would require folding a flag into 00058 // the addressing mode. :( This causes us to miss certain things. 00059 //case ARMISD::RRX: return ARM_AM::rrx; 00060 } 00061 } 00062 00063 enum AMSubMode { 00064 bad_am_submode = 0, 00065 ia, 00066 ib, 00067 da, 00068 db 00069 }; 00070 00071 static inline const char *getAMSubModeStr(AMSubMode Mode) { 00072 switch (Mode) { 00073 default: assert(0 && "Unknown addressing sub-mode!"); 00074 case ARM_AM::ia: return "ia"; 00075 case ARM_AM::ib: return "ib"; 00076 case ARM_AM::da: return "da"; 00077 case ARM_AM::db: return "db"; 00078 } 00079 } 00080 00081 static inline const char *getAMSubModeAltStr(AMSubMode Mode, bool isLD) { 00082 switch (Mode) { 00083 default: assert(0 && "Unknown addressing sub-mode!"); 00084 case ARM_AM::ia: return isLD ? "fd" : "ea"; 00085 case ARM_AM::ib: return isLD ? "ed" : "fa"; 00086 case ARM_AM::da: return isLD ? "fa" : "ed"; 00087 case ARM_AM::db: return isLD ? "ea" : "fd"; 00088 } 00089 } 00090 00091 /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. 00092 /// 00093 static inline unsigned rotr32(unsigned Val, unsigned Amt) { 00094 assert(Amt < 32 && "Invalid rotate amount"); 00095 return (Val >> Amt) | (Val << ((32-Amt)&31)); 00096 } 00097 00098 /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. 00099 /// 00100 static inline unsigned rotl32(unsigned Val, unsigned Amt) { 00101 assert(Amt < 32 && "Invalid rotate amount"); 00102 return (Val << Amt) | (Val >> ((32-Amt)&31)); 00103 } 00104 00105 //===--------------------------------------------------------------------===// 00106 // Addressing Mode #1: shift_operand with registers 00107 //===--------------------------------------------------------------------===// 00108 // 00109 // This 'addressing mode' is used for arithmetic instructions. It can 00110 // represent things like: 00111 // reg 00112 // reg [asr|lsl|lsr|ror|rrx] reg 00113 // reg [asr|lsl|lsr|ror|rrx] imm 00114 // 00115 // This is stored three operands [rega, regb, opc]. The first is the base 00116 // reg, the second is the shift amount (or reg0 if not present or imm). The 00117 // third operand encodes the shift opcode and the imm if a reg isn't present. 00118 // 00119 static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { 00120 return ShOp | (Imm << 3); 00121 } 00122 static inline unsigned getSORegOffset(unsigned Op) { 00123 return Op >> 3; 00124 } 00125 static inline ShiftOpc getSORegShOp(unsigned Op) { 00126 return (ShiftOpc)(Op & 7); 00127 } 00128 00129 /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return 00130 /// the 8-bit imm value. 00131 static inline unsigned getSOImmValImm(unsigned Imm) { 00132 return Imm & 0xFF; 00133 } 00134 /// getSOImmValRotate - Given an encoded imm field for the reg/imm form, return 00135 /// the rotate amount. 00136 static inline unsigned getSOImmValRot(unsigned Imm) { 00137 return (Imm >> 8) * 2; 00138 } 00139 00140 /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, 00141 /// computing the rotate amount to use. If this immediate value cannot be 00142 /// handled with a single shifter-op, determine a good rotate amount that will 00143 /// take a maximal chunk of bits out of the immediate. 00144 static inline unsigned getSOImmValRotate(unsigned Imm) { 00145 // 8-bit (or less) immediates are trivially shifter_operands with a rotate 00146 // of zero. 00147 if ((Imm & ~255U) == 0) return 0; 00148 00149 // Use CTZ to compute the rotate amount. 00150 unsigned TZ = CountTrailingZeros_32(Imm); 00151 00152 // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, 00153 // not 9. 00154 unsigned RotAmt = TZ & ~1; 00155 00156 // If we can handle this spread, return it. 00157 if ((rotr32(Imm, RotAmt) & ~255U) == 0) 00158 return (32-RotAmt)&31; // HW rotates right, not left. 00159 00160 // For values like 0xF000000F, we should skip the first run of ones, then 00161 // retry the hunt. 00162 if (Imm & 1) { 00163 unsigned TrailingOnes = CountTrailingZeros_32(~Imm); 00164 if (TrailingOnes != 32) { // Avoid overflow on 0xFFFFFFFF 00165 // Restart the search for a high-order bit after the initial seconds of 00166 // ones. 00167 unsigned TZ2 = CountTrailingZeros_32(Imm & ~((1 << TrailingOnes)-1)); 00168 00169 // Rotate amount must be even. 00170 unsigned RotAmt2 = TZ2 & ~1; 00171 00172 // If this fits, use it. 00173 if (RotAmt2 != 32 && (rotr32(Imm, RotAmt2) & ~255U) == 0) 00174 return (32-RotAmt2)&31; // HW rotates right, not left. 00175 } 00176 } 00177 00178 // Otherwise, we have no way to cover this span of bits with a single 00179 // shifter_op immediate. Return a chunk of bits that will be useful to 00180 // handle. 00181 return (32-RotAmt)&31; // HW rotates right, not left. 00182 } 00183 00184 /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit 00185 /// into an shifter_operand immediate operand, return the 12-bit encoding for 00186 /// it. If not, return -1. 00187 static inline int getSOImmVal(unsigned Arg) { 00188 // 8-bit (or less) immediates are trivially shifter_operands with a rotate 00189 // of zero. 00190 if ((Arg & ~255U) == 0) return Arg; 00191 00192 unsigned RotAmt = getSOImmValRotate(Arg); 00193 00194 // If this cannot be handled with a single shifter_op, bail out. 00195 if (rotr32(~255U, RotAmt) & Arg) 00196 return -1; 00197 00198 // Encode this correctly. 00199 return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); 00200 } 00201 00202 /// isSOImmTwoPartVal - Return true if the specified value can be obtained by 00203 /// or'ing together two SOImmVal's. 00204 static inline bool isSOImmTwoPartVal(unsigned V) { 00205 // If this can be handled with a single shifter_op, bail out. 00206 V = rotr32(~255U, getSOImmValRotate(V)) & V; 00207 if (V == 0) 00208 return false; 00209 00210 // If this can be handled with two shifter_op's, accept. 00211 V = rotr32(~255U, getSOImmValRotate(V)) & V; 00212 return V == 0; 00213 } 00214 00215 /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, 00216 /// return the first chunk of it. 00217 static inline unsigned getSOImmTwoPartFirst(unsigned V) { 00218 return rotr32(255U, getSOImmValRotate(V)) & V; 00219 } 00220 00221 /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, 00222 /// return the second chunk of it. 00223 static inline unsigned getSOImmTwoPartSecond(unsigned V) { 00224 // Mask out the first hunk. 00225 V = rotr32(~255U, getSOImmValRotate(V)) & V; 00226 00227 // Take what's left. 00228 assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); 00229 return V; 00230 } 00231 00232 /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed 00233 /// by a left shift. Returns the shift amount to use. 00234 static inline unsigned getThumbImmValShift(unsigned Imm) { 00235 // 8-bit (or less) immediates are trivially immediate operand with a shift 00236 // of zero. 00237 if ((Imm & ~255U) == 0) return 0; 00238 00239 // Use CTZ to compute the shift amount. 00240 return CountTrailingZeros_32(Imm); 00241 } 00242 00243 /// isThumbImmShiftedVal - Return true if the specified value can be obtained 00244 /// by left shifting a 8-bit immediate. 00245 static inline bool isThumbImmShiftedVal(unsigned V) { 00246 // If this can be handled with 00247 V = (~255U << getThumbImmValShift(V)) & V; 00248 return V == 0; 00249 } 00250 00251 /// getThumbImmNonShiftedVal - If V is a value that satisfies 00252 /// isThumbImmShiftedVal, return the non-shiftd value. 00253 static inline unsigned getThumbImmNonShiftedVal(unsigned V) { 00254 return V >> getThumbImmValShift(V); 00255 } 00256 00257 //===--------------------------------------------------------------------===// 00258 // Addressing Mode #2 00259 //===--------------------------------------------------------------------===// 00260 // 00261 // This is used for most simple load/store instructions. 00262 // 00263 // addrmode2 := reg +/- reg shop imm 00264 // addrmode2 := reg +/- imm12 00265 // 00266 // The first operand is always a Reg. The second operand is a reg if in 00267 // reg/reg form, otherwise it's reg#0. The third field encodes the operation 00268 // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. 00269 // 00270 // If this addressing mode is a frame index (before prolog/epilog insertion 00271 // and code rewriting), this operand will have the form: FI#, reg0, <offs> 00272 // with no shift amount for the frame offset. 00273 // 00274 static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) { 00275 assert(Imm12 < (1 << 12) && "Imm too large!"); 00276 bool isSub = Opc == sub; 00277 return Imm12 | ((int)isSub << 12) | (SO << 13); 00278 } 00279 static inline unsigned getAM2Offset(unsigned AM2Opc) { 00280 return AM2Opc & ((1 << 12)-1); 00281 } 00282 static inline AddrOpc getAM2Op(unsigned AM2Opc) { 00283 return ((AM2Opc >> 12) & 1) ? sub : add; 00284 } 00285 static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { 00286 return (ShiftOpc)(AM2Opc >> 13); 00287 } 00288 00289 00290 //===--------------------------------------------------------------------===// 00291 // Addressing Mode #3 00292 //===--------------------------------------------------------------------===// 00293 // 00294 // This is used for sign-extending loads, and load/store-pair instructions. 00295 // 00296 // addrmode3 := reg +/- reg 00297 // addrmode3 := reg +/- imm8 00298 // 00299 // The first operand is always a Reg. The second operand is a reg if in 00300 // reg/reg form, otherwise it's reg#0. The third field encodes the operation 00301 // in bit 8, the immediate in bits 0-7. 00302 00303 /// getAM3Opc - This function encodes the addrmode3 opc field. 00304 static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) { 00305 bool isSub = Opc == sub; 00306 return ((int)isSub << 8) | Offset; 00307 } 00308 static inline unsigned char getAM3Offset(unsigned AM3Opc) { 00309 return AM3Opc & 0xFF; 00310 } 00311 static inline AddrOpc getAM3Op(unsigned AM3Opc) { 00312 return ((AM3Opc >> 8) & 1) ? sub : add; 00313 } 00314 00315 //===--------------------------------------------------------------------===// 00316 // Addressing Mode #4 00317 //===--------------------------------------------------------------------===// 00318 // 00319 // This is used for load / store multiple instructions. 00320 // 00321 // addrmode4 := reg, <mode> 00322 // 00323 // The four modes are: 00324 // IA - Increment after 00325 // IB - Increment before 00326 // DA - Decrement after 00327 // DB - Decrement before 00328 // 00329 // If the 4th bit (writeback)is set, then the base register is updated after 00330 // the memory transfer. 00331 00332 static inline AMSubMode getAM4SubMode(unsigned Mode) { 00333 return (AMSubMode)(Mode & 0x7); 00334 } 00335 00336 static inline unsigned getAM4ModeImm(AMSubMode SubMode, bool WB = false) { 00337 return (int)SubMode | ((int)WB << 3); 00338 } 00339 00340 static inline bool getAM4WBFlag(unsigned Mode) { 00341 return (Mode >> 3) & 1; 00342 } 00343 00344 //===--------------------------------------------------------------------===// 00345 // Addressing Mode #5 00346 //===--------------------------------------------------------------------===// 00347 // 00348 // This is used for coprocessor instructions, such as FP load/stores. 00349 // 00350 // addrmode5 := reg +/- imm8*4 00351 // 00352 // The first operand is always a Reg. The third field encodes the operation 00353 // in bit 8, the immediate in bits 0-7. 00354 // 00355 // This can also be used for FP load/store multiple ops. The third field encodes 00356 // writeback mode in bit 8, the number of registers (or 2 times the number of 00357 // registers for DPR ops) in bits 0-7. In addition, bit 9-11 encodes one of the 00358 // following two sub-modes: 00359 // 00360 // IA - Increment after 00361 // DB - Decrement before 00362 00363 /// getAM5Opc - This function encodes the addrmode5 opc field. 00364 static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { 00365 bool isSub = Opc == sub; 00366 return ((int)isSub << 8) | Offset; 00367 } 00368 static inline unsigned char getAM5Offset(unsigned AM5Opc) { 00369 return AM5Opc & 0xFF; 00370 } 00371 static inline AddrOpc getAM5Op(unsigned AM5Opc) { 00372 return ((AM5Opc >> 8) & 1) ? sub : add; 00373 } 00374 00375 /// getAM5Opc - This function encodes the addrmode5 opc field for FLDM and 00376 /// FSTM instructions. 00377 static inline unsigned getAM5Opc(AMSubMode SubMode, bool WB, 00378 unsigned char Offset) { 00379 assert((SubMode == ia || SubMode == db) && 00380 "Illegal addressing mode 5 sub-mode!"); 00381 return ((int)SubMode << 9) | ((int)WB << 8) | Offset; 00382 } 00383 static inline AMSubMode getAM5SubMode(unsigned AM5Opc) { 00384 return (AMSubMode)((AM5Opc >> 9) & 0x7); 00385 } 00386 static inline bool getAM5WBFlag(unsigned AM5Opc) { 00387 return ((AM5Opc >> 8) & 1); 00388 } 00389 00390 } // end namespace ARM_AM 00391 } // end namespace llvm 00392 00393 #endif 00394