1 // Do not edit. Bootstrap copy of /Volumes/Android/buildbot/src/android/build-tools/out/obj/go/src/cmd/asm/internal/arch/arm.go 2 3 //line /Volumes/Android/buildbot/src/android/build-tools/out/obj/go/src/cmd/asm/internal/arch/arm.go:1 4 // Copyright 2015 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 // This file encapsulates some of the odd characteristics of the ARM 9 // instruction set, to minimize its interaction with the core of the 10 // assembler. 11 12 package arch 13 14 import ( 15 "strings" 16 17 "bootstrap/internal/obj" 18 "bootstrap/internal/obj/arm" 19 ) 20 21 var armLS = map[string]uint8{ 22 "U": arm.C_UBIT, 23 "S": arm.C_SBIT, 24 "W": arm.C_WBIT, 25 "P": arm.C_PBIT, 26 "PW": arm.C_WBIT | arm.C_PBIT, 27 "WP": arm.C_WBIT | arm.C_PBIT, 28 } 29 30 var armSCOND = map[string]uint8{ 31 "EQ": arm.C_SCOND_EQ, 32 "NE": arm.C_SCOND_NE, 33 "CS": arm.C_SCOND_HS, 34 "HS": arm.C_SCOND_HS, 35 "CC": arm.C_SCOND_LO, 36 "LO": arm.C_SCOND_LO, 37 "MI": arm.C_SCOND_MI, 38 "PL": arm.C_SCOND_PL, 39 "VS": arm.C_SCOND_VS, 40 "VC": arm.C_SCOND_VC, 41 "HI": arm.C_SCOND_HI, 42 "LS": arm.C_SCOND_LS, 43 "GE": arm.C_SCOND_GE, 44 "LT": arm.C_SCOND_LT, 45 "GT": arm.C_SCOND_GT, 46 "LE": arm.C_SCOND_LE, 47 "AL": arm.C_SCOND_NONE, 48 "U": arm.C_UBIT, 49 "S": arm.C_SBIT, 50 "W": arm.C_WBIT, 51 "P": arm.C_PBIT, 52 "PW": arm.C_WBIT | arm.C_PBIT, 53 "WP": arm.C_WBIT | arm.C_PBIT, 54 "F": arm.C_FBIT, 55 "IBW": arm.C_WBIT | arm.C_PBIT | arm.C_UBIT, 56 "IAW": arm.C_WBIT | arm.C_UBIT, 57 "DBW": arm.C_WBIT | arm.C_PBIT, 58 "DAW": arm.C_WBIT, 59 "IB": arm.C_PBIT | arm.C_UBIT, 60 "IA": arm.C_UBIT, 61 "DB": arm.C_PBIT, 62 "DA": 0, 63 } 64 65 var armJump = map[string]bool{ 66 "B": true, 67 "BL": true, 68 "BEQ": true, 69 "BNE": true, 70 "BCS": true, 71 "BHS": true, 72 "BCC": true, 73 "BLO": true, 74 "BMI": true, 75 "BPL": true, 76 "BVS": true, 77 "BVC": true, 78 "BHI": true, 79 "BLS": true, 80 "BGE": true, 81 "BLT": true, 82 "BGT": true, 83 "BLE": true, 84 "CALL": true, 85 "JMP": true, 86 } 87 88 func jumpArm(word string) bool { 89 return armJump[word] 90 } 91 92 // IsARMCMP reports whether the op (as defined by an arm.A* constant) is 93 // one of the comparison instructions that require special handling. 94 func IsARMCMP(op int) bool { 95 switch op { 96 case arm.ACMN, arm.ACMP, arm.ATEQ, arm.ATST: 97 return true 98 } 99 return false 100 } 101 102 // IsARMSTREX reports whether the op (as defined by an arm.A* constant) is 103 // one of the STREX-like instructions that require special handling. 104 func IsARMSTREX(op int) bool { 105 switch op { 106 case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU: 107 return true 108 } 109 return false 110 } 111 112 // MCR is not defined by the obj/arm; instead we define it privately here. 113 // It is encoded as an MRC with a bit inside the instruction word, 114 // passed to arch.ARMMRCOffset. 115 const aMCR = arm.ALAST + 1 116 117 // IsARMMRC reports whether the op (as defined by an arm.A* constant) is 118 // MRC or MCR 119 func IsARMMRC(op int) bool { 120 switch op { 121 case arm.AMRC, aMCR: // Note: aMCR is defined in this package. 122 return true 123 } 124 return false 125 } 126 127 // IsARMFloatCmp reports whether the op is a floating comparison instruction. 128 func IsARMFloatCmp(op int) bool { 129 switch op { 130 case arm.ACMPF, arm.ACMPD: 131 return true 132 } 133 return false 134 } 135 136 // ARMMRCOffset implements the peculiar encoding of the MRC and MCR instructions. 137 // The difference between MRC and MCR is represented by a bit high in the word, not 138 // in the usual way by the opcode itself. Asm must use AMRC for both instructions, so 139 // we return the opcode for MRC so that asm doesn't need to import obj/arm. 140 func ARMMRCOffset(op int, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, op0 int16, ok bool) { 141 op1 := int64(0) 142 if op == arm.AMRC { 143 op1 = 1 144 } 145 bits, ok := ParseARMCondition(cond) 146 if !ok { 147 return 148 } 149 offset = (0xe << 24) | // opcode 150 (op1 << 20) | // MCR/MRC 151 ((int64(bits) ^ arm.C_SCOND_XOR) << 28) | // scond 152 ((x0 & 15) << 8) | //coprocessor number 153 ((x1 & 7) << 21) | // coprocessor operation 154 ((x2 & 15) << 12) | // ARM register 155 ((x3 & 15) << 16) | // Crn 156 ((x4 & 15) << 0) | // Crm 157 ((x5 & 7) << 5) | // coprocessor information 158 (1 << 4) /* must be set */ 159 return offset, arm.AMRC, true 160 } 161 162 // IsARMMULA reports whether the op (as defined by an arm.A* constant) is 163 // MULA, MULAWT or MULAWB, the 4-operand instructions. 164 func IsARMMULA(op int) bool { 165 switch op { 166 case arm.AMULA, arm.AMULAWB, arm.AMULAWT: 167 return true 168 } 169 return false 170 } 171 172 var bcode = []int{ 173 arm.ABEQ, 174 arm.ABNE, 175 arm.ABCS, 176 arm.ABCC, 177 arm.ABMI, 178 arm.ABPL, 179 arm.ABVS, 180 arm.ABVC, 181 arm.ABHI, 182 arm.ABLS, 183 arm.ABGE, 184 arm.ABLT, 185 arm.ABGT, 186 arm.ABLE, 187 arm.AB, 188 obj.ANOP, 189 } 190 191 // ARMConditionCodes handles the special condition code situation for the ARM. 192 // It returns a boolean to indicate success; failure means cond was unrecognized. 193 func ARMConditionCodes(prog *obj.Prog, cond string) bool { 194 if cond == "" { 195 return true 196 } 197 bits, ok := ParseARMCondition(cond) 198 if !ok { 199 return false 200 } 201 /* hack to make B.NE etc. work: turn it into the corresponding conditional */ 202 if prog.As == arm.AB { 203 prog.As = int16(bcode[(bits^arm.C_SCOND_XOR)&0xf]) 204 bits = (bits &^ 0xf) | arm.C_SCOND_NONE 205 } 206 prog.Scond = bits 207 return true 208 } 209 210 // ParseARMCondition parses the conditions attached to an ARM instruction. 211 // The input is a single string consisting of period-separated condition 212 // codes, such as ".P.W". An initial period is ignored. 213 func ParseARMCondition(cond string) (uint8, bool) { 214 return parseARMCondition(cond, armLS, armSCOND) 215 } 216 217 func parseARMCondition(cond string, ls, scond map[string]uint8) (uint8, bool) { 218 if strings.HasPrefix(cond, ".") { 219 cond = cond[1:] 220 } 221 if cond == "" { 222 return arm.C_SCOND_NONE, true 223 } 224 names := strings.Split(cond, ".") 225 bits := uint8(0) 226 for _, name := range names { 227 if b, present := ls[name]; present { 228 bits |= b 229 continue 230 } 231 if b, present := scond[name]; present { 232 bits = (bits &^ arm.C_SCOND) | b 233 continue 234 } 235 return 0, false 236 } 237 return bits, true 238 } 239 240 func armRegisterNumber(name string, n int16) (int16, bool) { 241 if n < 0 || 15 < n { 242 return 0, false 243 } 244 switch name { 245 case "R": 246 return arm.REG_R0 + n, true 247 case "F": 248 return arm.REG_F0 + n, true 249 } 250 return 0, false 251 } 252