1
2
3
4
5
6
7
8
9 package arch
10
11 import (
12 "strings"
13
14 "cmd/internal/obj"
15 "cmd/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.ASTREXB, 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 }
258
View as plain text