podman

Форк
0
257 строк · 6.2 Кб
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 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/twitchyliquid64/golang-asm/obj"
15
	"github.com/twitchyliquid64/golang-asm/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
// IsARMCMP reports whether the op (as defined by an arm.A* constant) is
91
// one of the comparison instructions that require special handling.
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
// IsARMSTREX reports whether the op (as defined by an arm.A* constant) is
101
// one of the STREX-like instructions that require special handling.
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
// MCR is not defined by the obj/arm; instead we define it privately here.
111
// It is encoded as an MRC with a bit inside the instruction word,
112
// passed to arch.ARMMRCOffset.
113
const aMCR = arm.ALAST + 1
114

115
// IsARMMRC reports whether the op (as defined by an arm.A* constant) is
116
// MRC or MCR
117
func IsARMMRC(op obj.As) bool {
118
	switch op {
119
	case arm.AMRC, aMCR: // Note: aMCR is defined in this package.
120
		return true
121
	}
122
	return false
123
}
124

125
// IsARMBFX reports whether the op (as defined by an arm.A* constant) is one the
126
// BFX-like instructions which are in the form of "op $width, $LSB, (Reg,) Reg".
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
// IsARMFloatCmp reports whether the op is a floating comparison instruction.
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
// ARMMRCOffset implements the peculiar encoding of the MRC and MCR instructions.
145
// The difference between MRC and MCR is represented by a bit high in the word, not
146
// in the usual way by the opcode itself. Asm must use AMRC for both instructions, so
147
// we return the opcode for MRC so that asm doesn't need to import obj/arm.
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) | // opcode
158
		(op1 << 20) | // MCR/MRC
159
		((int64(bits) ^ arm.C_SCOND_XOR) << 28) | // scond
160
		((x0 & 15) << 8) | //coprocessor number
161
		((x1 & 7) << 21) | // coprocessor operation
162
		((x2 & 15) << 12) | // ARM register
163
		((x3 & 15) << 16) | // Crn
164
		((x4 & 15) << 0) | // Crm
165
		((x5 & 7) << 5) | // coprocessor information
166
		(1 << 4) /* must be set */
167
	return offset, arm.AMRC, true
168
}
169

170
// IsARMMULA reports whether the op (as defined by an arm.A* constant) is
171
// MULA, MULS, MMULA, MMULS, MULABB, MULAWB or MULAWT, the 4-operand instructions.
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
// ARMConditionCodes handles the special condition code situation for the ARM.
200
// It returns a boolean to indicate success; failure means cond was unrecognized.
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
	/* hack to make B.NE etc. work: turn it into the corresponding conditional */
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
// ParseARMCondition parses the conditions attached to an ARM instruction.
219
// The input is a single string consisting of period-separated condition
220
// codes, such as ".P.W". An initial period is ignored.
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.