github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/asm/arch/arm.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE.assembler file. 4 5 // This file encapsulates some of the odd characteristics of the ARM 6 // instruction set, to minimize its interaction with the core of the 7 // assembler. 8 9 package arch 10 11 import ( 12 "strings" 13 14 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/obj" 15 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/obj/arm" 16 ) 17 18 var armLS = map[string]uint8{ 19 "U": arm.C_UBIT, 20 "S": arm.C_SBIT, 21 "W": arm.C_WBIT, 22 "P": arm.C_PBIT, 23 "PW": arm.C_WBIT | arm.C_PBIT, 24 "WP": arm.C_WBIT | arm.C_PBIT, 25 } 26 27 var armSCOND = map[string]uint8{ 28 "EQ": arm.C_SCOND_EQ, 29 "NE": arm.C_SCOND_NE, 30 "CS": arm.C_SCOND_HS, 31 "HS": arm.C_SCOND_HS, 32 "CC": arm.C_SCOND_LO, 33 "LO": arm.C_SCOND_LO, 34 "MI": arm.C_SCOND_MI, 35 "PL": arm.C_SCOND_PL, 36 "VS": arm.C_SCOND_VS, 37 "VC": arm.C_SCOND_VC, 38 "HI": arm.C_SCOND_HI, 39 "LS": arm.C_SCOND_LS, 40 "GE": arm.C_SCOND_GE, 41 "LT": arm.C_SCOND_LT, 42 "GT": arm.C_SCOND_GT, 43 "LE": arm.C_SCOND_LE, 44 "AL": arm.C_SCOND_NONE, 45 "U": arm.C_UBIT, 46 "S": arm.C_SBIT, 47 "W": arm.C_WBIT, 48 "P": arm.C_PBIT, 49 "PW": arm.C_WBIT | arm.C_PBIT, 50 "WP": arm.C_WBIT | arm.C_PBIT, 51 "F": arm.C_FBIT, 52 "IBW": arm.C_WBIT | arm.C_PBIT | arm.C_UBIT, 53 "IAW": arm.C_WBIT | arm.C_UBIT, 54 "DBW": arm.C_WBIT | arm.C_PBIT, 55 "DAW": arm.C_WBIT, 56 "IB": arm.C_PBIT | arm.C_UBIT, 57 "IA": arm.C_UBIT, 58 "DB": arm.C_PBIT, 59 "DA": 0, 60 } 61 62 var armJump = map[string]bool{ 63 "B": true, 64 "BL": true, 65 "BX": true, 66 "BEQ": true, 67 "BNE": true, 68 "BCS": true, 69 "BHS": true, 70 "BCC": true, 71 "BLO": true, 72 "BMI": true, 73 "BPL": true, 74 "BVS": true, 75 "BVC": true, 76 "BHI": true, 77 "BLS": true, 78 "BGE": true, 79 "BLT": true, 80 "BGT": true, 81 "BLE": true, 82 "CALL": true, 83 "JMP": true, 84 } 85 86 func jumpArm(word string) bool { 87 return armJump[word] 88 } 89 90 91 92 func IsARMCMP(op obj.As) bool { 93 switch op { 94 case arm.ACMN, arm.ACMP, arm.ATEQ, arm.ATST: 95 return true 96 } 97 return false 98 } 99 100 101 102 func IsARMSTREX(op obj.As) bool { 103 switch op { 104 case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU: 105 return true 106 } 107 return false 108 } 109 110 111 112 113 const aMCR = arm.ALAST + 1 114 115 116 117 func IsARMMRC(op obj.As) bool { 118 switch op { 119 case arm.AMRC, aMCR: 120 return true 121 } 122 return false 123 } 124 125 126 127 func IsARMBFX(op obj.As) bool { 128 switch op { 129 case arm.ABFX, arm.ABFXU, arm.ABFC, arm.ABFI: 130 return true 131 } 132 return false 133 } 134 135 136 func IsARMFloatCmp(op obj.As) bool { 137 switch op { 138 case arm.ACMPF, arm.ACMPD: 139 return true 140 } 141 return false 142 } 143 144 145 146 147 148 func ARMMRCOffset(op obj.As, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, op0 obj.As, ok bool) { 149 op1 := int64(0) 150 if op == arm.AMRC { 151 op1 = 1 152 } 153 bits, ok := ParseARMCondition(cond) 154 if !ok { 155 return 156 } 157 offset = (0xe << 24) | 158 (op1 << 20) | 159 ((int64(bits) ^ arm.C_SCOND_XOR) << 28) | 160 ((x0 & 15) << 8) | 161 ((x1 & 7) << 21) | 162 ((x2 & 15) << 12) | 163 ((x3 & 15) << 16) | 164 ((x4 & 15) << 0) | 165 ((x5 & 7) << 5) | 166 (1 << 4) 167 return offset, arm.AMRC, true 168 } 169 170 171 172 func IsARMMULA(op obj.As) bool { 173 switch op { 174 case arm.AMULA, arm.AMULS, arm.AMMULA, arm.AMMULS, arm.AMULABB, arm.AMULAWB, arm.AMULAWT: 175 return true 176 } 177 return false 178 } 179 180 var bcode = []obj.As{ 181 arm.ABEQ, 182 arm.ABNE, 183 arm.ABCS, 184 arm.ABCC, 185 arm.ABMI, 186 arm.ABPL, 187 arm.ABVS, 188 arm.ABVC, 189 arm.ABHI, 190 arm.ABLS, 191 arm.ABGE, 192 arm.ABLT, 193 arm.ABGT, 194 arm.ABLE, 195 arm.AB, 196 obj.ANOP, 197 } 198 199 200 201 func ARMConditionCodes(prog *obj.Prog, cond string) bool { 202 if cond == "" { 203 return true 204 } 205 bits, ok := ParseARMCondition(cond) 206 if !ok { 207 return false 208 } 209 210 if prog.As == arm.AB { 211 prog.As = bcode[(bits^arm.C_SCOND_XOR)&0xf] 212 bits = (bits &^ 0xf) | arm.C_SCOND_NONE 213 } 214 prog.Scond = bits 215 return true 216 } 217 218 219 220 221 func ParseARMCondition(cond string) (uint8, bool) { 222 return parseARMCondition(cond, armLS, armSCOND) 223 } 224 225 func parseARMCondition(cond string, ls, scond map[string]uint8) (uint8, bool) { 226 cond = strings.TrimPrefix(cond, ".") 227 if cond == "" { 228 return arm.C_SCOND_NONE, true 229 } 230 names := strings.Split(cond, ".") 231 bits := uint8(0) 232 for _, name := range names { 233 if b, present := ls[name]; present { 234 bits |= b 235 continue 236 } 237 if b, present := scond[name]; present { 238 bits = (bits &^ arm.C_SCOND) | b 239 continue 240 } 241 return 0, false 242 } 243 return bits, true 244 } 245 246 func armRegisterNumber(name string, n int16) (int16, bool) { 247 if n < 0 || 15 < n { 248 return 0, false 249 } 250 switch name { 251 case "R": 252 return arm.REG_R0 + n, true 253 case "F": 254 return arm.REG_F0 + n, true 255 } 256 return 0, false 257 }