1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
|
| `AArch64TMStart t ->
sprintf "TSTART %s" (pp_regzr Set64 t)
| `AArch64TMCommit -> "TCOMMIT"
| `AArch64TMAbort (retry,reason) ->
sprintf "TABORT %s" (pp_imm (if retry then 32 + reason else reason))
| `AArch64TMTest -> "TTEST"
| `AArch64ImplementationDefinedStopFetching ->
"_STOP_FETCHING"
| `AArch64ImplementationDefinedThreadStart ->
"_THREAD_START"
| `AArch64ImplementationDefinedTestBeginEnd (isEnd) ->
if isEnd then
"_TEST_ENDS"
else
"_TEST_BEGINS"
| `AArch64AddSubCarry (d,n,m,datasize,sub_op,setflags) ->
if sub_op && is_zero_reg n then
sprintf "%s %s,%s" (pp_withflags "NGC" setflags) (pp_regzr datasize d) (pp_regzr datasize m)
else if sub_op then
sprintf "%s %s,%s,%s" (pp_withflags "SBC" setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
else
sprintf "%s %s,%s,%s" (pp_withflags "ADC" setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
| `AArch64AddSubExtendRegister (d,n,m,datasize,sub_op,setflags,extend_type,shift) ->
if setflags && is_zero_reg d then
begin
if (is_sp_reg n) && ((datasize = Set32 && extend_type = ExtendType_UXTW) || (datasize = Set64 && extend_type = ExtendType_UXTX)) then
sprintf "%s %s,%s%s" (if sub_op then "CMP" else "CMN") (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m)
(if shift = 0 then "" else (",LSL " ^ (pp_imm shift)))
else
sprintf "%s %s,%s%s" (if sub_op then "CMP" else "CMN") (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m) (pp_addsub_regext datasize extend_type shift)
end
else if (is_sp_reg d || is_sp_reg n) && ((datasize = Set32 && extend_type = ExtendType_UXTW) || (datasize = Set64 && extend_type = ExtendType_UXTX)) then
sprintf "%s %s,%s,%s%s" (pp_addsub sub_op setflags) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m)
(if shift = 0 then "" else (",LSL " ^ (pp_imm shift)))
else
sprintf "%s %s,%s,%s%s" (pp_addsub sub_op setflags) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regsp datasize n) (pp_regzrbyext datasize extend_type m) (pp_addsub_regext datasize extend_type shift)
| `AArch64AddSubImmediate (d,n,datasize,sub_op,setflags,imm) ->
let (imm12,shift) =
if reg_size_bits_iskbituimm 12 imm then (reg_size_bits_to_int imm, 0)
else (reg_size_bits_to_int (reg_size_bits_shift_right imm 12), 12)
in
if (sub_op,setflags) = (false,false) && (is_sp_reg d || is_sp_reg n) && (shift = 0 && imm12 = 0) then
sprintf "MOV %s,%s" (pp_regsp datasize d) (pp_regsp datasize n)
else if setflags && is_zero_reg d then
sprintf "%s %s,%s%s" (if sub_op then "CMP" else "CMN") (pp_regsp datasize n) (pp_imm imm12) (if shift = 0 then "" else ",LSL #12")
else
sprintf "%s %s,%s,%s%s" (pp_addsub sub_op setflags) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regsp datasize n) (pp_imm imm12) (if shift = 0 then "" else ",LSL #12")
| `AArch64AddSubShiftedRegister (d,n,m,datasize,sub_op,setflags,shift_type,shift_amount) ->
if setflags && is_zero_reg d then
begin
if shift_type = ShiftType_LSL && shift_amount = 0 then
sprintf "%s %s,%s" (if sub_op then "CMP" else "CMN") (pp_regzr datasize n) (pp_regzr datasize m)
else
sprintf "%s %s,%s,%s %s" (if sub_op then "CMP" else "CMN") (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
end
else if sub_op && is_zero_reg n then
begin
if shift_type = ShiftType_LSL && shift_amount = 0 then
sprintf "%s %s,%s" (pp_withflags "NEG" setflags) (pp_regzr datasize d) (pp_regzr datasize m)
else
sprintf "%s %s,%s,%s %s" (pp_withflags "NEG" setflags) (pp_regzr datasize d) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
end
else if shift_type = ShiftType_LSL && shift_amount = 0 then
sprintf "%s %s,%s,%s" (pp_addsub sub_op setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
else
sprintf "%s %s,%s,%s,%s %s" (pp_addsub sub_op setflags) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
| `AArch64Address (d,page,imm) ->
sprintf "%s %s,%s" (if page then "ADRP" else "ADR") (pp_regzr Set64 d) (pp_offset page imm)
| `AArch64LogicalImmediate (d,n,datasize,setflags,op,imm) ->
if op = LogicalOp_AND && setflags && is_zero_reg d then
sprintf "TST %s,%s" (pp_regzr datasize n) (pp_reg_size_imm imm)
else if op = LogicalOp_ORR && not setflags && is_zero_reg n && not (moveWidePreferred datasize imm) then (* ARM: missing the check of n=ZR *)
sprintf "MOV %s,%s" (pp_regsp datasize d) (pp_reg_size_imm imm)
else sprintf "%s %s,%s,%s" (pp_logop op setflags false) (if setflags then pp_regzr datasize d else pp_regsp datasize d) (pp_regzr datasize n) (pp_reg_size_imm imm)
| `AArch64LogicalShiftedRegister (d,n,m,datasize,setflags,op,shift_type,shift_amount,invert) ->
if op = LogicalOp_AND && setflags && not invert && is_zero_reg d then
begin
if shift_type = ShiftType_LSL && shift_amount = 0 then
sprintf "TST %s,%s" (pp_regzr datasize n) (pp_regzr datasize m)
else
sprintf "TST %s,%s,%s %s" (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
end
else if op = LogicalOp_ORR && not setflags && invert && is_zero_reg n then
begin
if shift_type = ShiftType_LSL && shift_amount = 0 then
sprintf "MVN %s,%s" (pp_regzr datasize d) (pp_regzr datasize m)
else
sprintf "MVN %s,%s,%s %s" (pp_regzr datasize d) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
end
else if op = LogicalOp_ORR && not setflags && not invert && is_zero_reg n && shift_type = ShiftType_LSL && shift_amount = 0 then
sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_regzr datasize m)
else
begin
if shift_type = ShiftType_LSL && shift_amount = 0 then
sprintf "%s %s,%s,%s" (pp_logop op setflags invert) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
else
sprintf "%s %s,%s,%s,%s %s" (pp_logop op setflags invert) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_shift shift_type) (pp_imm shift_amount)
end
| `AArch64Shift (d,n,m,datasize,shift_type) ->
sprintf "%s %s,%s,%s" (pp_shiftop shift_type) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
| `AArch64BranchConditional (offset,condition) ->
sprintf "B.%s %s" (pp_cond condition) (pp_offset false offset)
| `AArch64BranchImmediate (branch_type,offset) ->
sprintf "%s %s" (pp_branchimmediate branch_type) (pp_offset false offset)
| `AArch64BitfieldMove (d,n,datasize,inzero,extend,_R,_S,wmask,tmask) ->
if (inzero,extend) = (false,false) && _S < _R then
sprintf "BFI %s,%s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S+1)) (* FIXME: I'm not sure this is the right translation of imms and immr *)
else if (inzero,extend) = (false,false) && _S >= _R then
sprintf "BFXIL %s,%s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S-_R+1))
else if (inzero,extend) = (true,false) && datasize = Set32 && _S <> 0b011111 && _S+1 = _R then
sprintf "LSL %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm (31-_S))
else if (inzero,extend) = (true,false) && datasize = Set64 && _S <> 0b111111 && _S+1 = _R then
sprintf "LSL %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm (63-_S))
else if inzero && datasize = Set32 && _S = 0b011111 then
sprintf "%s %s,%s,%s" (if extend then "ASR" else "LSR") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R)
else if inzero && datasize = Set64 && _S = 0b111111 then
sprintf "%s %s,%s,%s" (if extend then "ASR" else "LSR") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R)
else if inzero && _S < _R then
sprintf "%s %s,%s,%s,%s" (if extend then "SBFIZ" else "UBFIZ") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S+1)) (* FIXME: -<lsb> MOD 32/64 *)
else if inzero && bFXPreferred datasize (if extend then 0 else 1) _S _R then
sprintf "%s %s,%s,%s,%s" (if extend then "SBFX" else "UBFX") (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm (_S - _R + 1))
else if inzero && _R = 0 && _S = 0b000111 then
sprintf "%s %s,%s" (if extend then "SXTB" else "UXTB") (pp_regzr datasize d) (pp_regzr Set32 n)
else if inzero && _R = 0 && _S = 0b001111 then
sprintf "%s %s,%s" (if extend then "SXTH" else "UXTH") (pp_regzr datasize d) (pp_regzr Set32 n)
else if (inzero,extend) = (true,true) && _R = 0 && _S = 0b011111 then (* implicitly datasize = Set64 *)
sprintf "SXTW %s,%s" (pp_regzr datasize d) (pp_regzr Set32 n)
else
sprintf "%s %s,%s,%s,%s" (pp_bfm inzero extend) (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm _R) (pp_imm _S)
| `AArch64BranchRegister (n,branch_type) ->
if branch_type = BranchType_RET && n = X (Ireg R30) then
"RET"
else
sprintf "%s %s" (pp_branchregister branch_type) (pp_regzr Set64 n)
| `AArch64CompareAndBranch (t,datasize,iszero,offset) ->
sprintf "%s %s,%s" (if iszero then "CBZ" else "CBNZ") (pp_regzr datasize t) (pp_offset false offset)
| `AArch64ConditionalCompareImmediate (n,datasize,sub_op,condition,flags,imm) ->
sprintf "%s %s,%s,%s,%s" (if sub_op then "CCMP" else "CCMN") (pp_regzr datasize n) (pp_reg_size_imm imm) (pp_imm flags) (pp_cond condition)
| `AArch64ConditionalCompareRegister (n,m,datasize,sub_op,condition,flags) ->
sprintf "%s %s,%s,%s,%s" (if sub_op then "CCMP" else "CCMN") (pp_regzr datasize n) (pp_regzr datasize m) (pp_imm flags) (pp_cond condition)
| `AArch64ClearExclusiveMonitor (imm) ->
if imm = 15 then
sprintf "CLREX"
else
sprintf "CLREX %s" (pp_imm imm)
| `AArch64CountLeading (d,n,datasize,opcode) ->
sprintf "%s %s,%s" (pp_countop opcode) (pp_regzr datasize d) (pp_regzr datasize n)
| `AArch64CRC (d,n,m,size,crc32c) ->
sprintf "%s %s,%s,%s" (pp_crc size crc32c) (pp_regzr Set32 d) (pp_regzr Set32 n) (pp_regzr (if size = DataSize64 then Set64 else Set32) m)
| `AArch64ConditionalSelect (d,n,m,datasize,condition,else_inv,else_inc) ->
if not else_inv && else_inc && n = m && not (is_zero_reg n) && not (condition = 0b1110 || condition = 0b1111) then
sprintf "CINC %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_cond condition)
else if not else_inv && else_inc && n = m && is_zero_reg n && not (condition = 0b1110 || condition = 0b1111) then
sprintf "CSET %s,%s" (pp_regzr datasize d) (pp_cond condition)
else if else_inv && not else_inc && n = m && not (is_zero_reg n) && not (condition = 0b1110 || condition = 0b1111) then
sprintf "CINV %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_cond condition)
else if else_inv && not else_inc && n = m && is_zero_reg n && not (condition = 0b1110 || condition = 0b1111) then
sprintf "CSETM %s,%s" (pp_regzr datasize d) (pp_cond condition)
else if else_inv && else_inc && n = m && not (condition = 0b1110 || condition = 0b1111) then
sprintf "CNEG %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_cond condition)
else
sprintf "%s %s,%s,%s,%s" (pp_csel else_inv else_inc) (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_cond condition)
| `AArch64Barrier (op,domain,types) ->
if op = MemBarrierOp_ISB && domain = MBReqDomain_FullSystem && types = MBReqTypes_All then
pp_barr op
else
sprintf "%s %s" (pp_barr op) (pp_barroption domain types)
| `AArch64ExtractRegister (d,n,m,datasize,lsb) ->
if n = m then
sprintf "ROR %s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_imm lsb)
else
sprintf "EXTR %s,%s,%s,%s" (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m) (pp_imm lsb)
| `AArch64Hint (op) ->
begin
match op with
| SystemHintOp_NOP -> "NOP"
| SystemHintOp_YIELD -> "YIELD"
| SystemHintOp_WFE -> "WFE"
| SystemHintOp_WFI -> "WFI"
| SystemHintOp_SEV -> "SEV"
| SystemHintOp_SEVL -> "SEVL"
end
| `AArch64LoadStoreAcqExc (n,t,t2,s,acctype,excl,pair,memop,elsize,regsize,datasize) ->
if pair && memop = MemOp_LOAD then
sprintf "%s %s,%s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n)
else if pair && memop = MemOp_STORE then
sprintf "%s %s,%s,%s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr Set32 s) (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n)
else if not pair && memop = MemOp_STORE && excl then
sprintf "%s %s,%s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr Set32 s) (pp_regzr regsize t) (pp_regsp Set64 n)
else
sprintf "%s %s,[%s]" (pp_ldaxstlxp memop acctype excl pair datasize) (pp_regzr regsize t) (pp_regsp Set64 n)
| `AArch64LoadStorePair (wback,postindex,n,t,t2,acctype,memop,signed,datasize,offset) ->
begin
let inst = if signed then "LDPSW" else if memop = MemOp_LOAD then "LDP" else "STP" in
let regsize = if signed then Set64 else (match datasize with DataSize32 -> Set32 | DataSize64 -> Set64 | DataSize16 | DataSize8 -> failwith "unexpected value") in
match (wback,postindex) with
| (true,true) ->
sprintf "%s %s,%s,[%s],%s" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n) (pp_big_imm offset)
| (true,false) ->
sprintf "%s %s,%s,[%s,%s]!" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n) (pp_big_imm offset)
| (false,false) ->
if eq_bit64 offset (bit64_of_int 0) then
sprintf "%s %s,%s,[%s]" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n)
else
sprintf "%s %s,%s,[%s,%s]" inst (pp_regzr regsize t) (pp_regzr regsize t2) (pp_regsp Set64 n) (pp_big_imm offset)
| (false,true) -> failwith "unexpected value"
end
| `AArch64LoadImmediate (n,t,acctype,memop,signed,wback,postindex,offset,regsize,datasize) ->
begin
if memop = MemOp_PREFETCH then
begin
(* the ast does not hold enough information to distinguish PRFM and PRFUM in some cases.
PRFM: <pimm> is a multiple of 8 in the range 0 to 32760
PRFUM: <simm> is in the range -256 to 255 *)
if eq_bit64 offset (bit64_of_int 0) then
sprintf "PRFM %s,[%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n)
else if big_in_range offset (-256) 255 then
sprintf "PRFUM %s,[%s,%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_big_imm offset)
else
sprintf "PRFM %s,[%s,%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_big_imm offset)
end
else
let inst =
(if memop = MemOp_LOAD then "LD" else "ST") ^
(if not wback && not postindex &&
not begin match datasize with
| DataSize8 ->
Nat_big_num.less_equal Nat_big_num.zero offset &&
Nat_big_num.less_equal offset (Nat_big_num.of_int 4095)
| DataSize16 ->
Nat_big_num.less_equal Nat_big_num.zero offset &&
Nat_big_num.less_equal offset (Nat_big_num.of_int 8190) &&
Nat_big_num.equal
(Nat_big_num.modulus offset (Nat_big_num.of_int 2))
Nat_big_num.zero
| DataSize32 ->
Nat_big_num.less_equal Nat_big_num.zero offset &&
Nat_big_num.less_equal offset (Nat_big_num.of_int 16380) &&
Nat_big_num.equal
(Nat_big_num.modulus offset (Nat_big_num.of_int 4))
Nat_big_num.zero
| DataSize64 ->
Nat_big_num.less_equal Nat_big_num.zero offset &&
Nat_big_num.less_equal offset (Nat_big_num.of_int 32760) &&
Nat_big_num.equal
(Nat_big_num.modulus offset (Nat_big_num.of_int 8))
Nat_big_num.zero
end
then
begin
if acctype=AccType_UNPRIV then "TR"
else "UR"
end
else "R") ^
(if signed then "S" else "") ^
(match datasize with
| DataSize8 -> "B"
| DataSize16 -> "H"
| DataSize32 -> if regsize = Set32 then "" else "W"
| DataSize64 -> "") in
match (wback,postindex) with
| (true,true) ->
sprintf "%s %s,[%s],%s" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_big_imm offset)
| (true,false) ->
sprintf "%s %s,[%s,%s]!" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_big_imm offset)
| (false,false) ->
if eq_bit64 offset (bit64_of_int 0) then
sprintf "%s %s,[%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n)
else
sprintf "%s %s,[%s,%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_big_imm offset)
| (false,true) -> failwith "unexpected value"
end
| `AArch64LoadLiteral (t,memop,signed,size,offset,datasize) ->
if memop = MemOp_PREFETCH then
sprintf "PRFM %s,%s" (pp_prfop (inst_reg_to_int t)) (pp_offset false offset)
else
let datasize =
if signed then Set64
else
begin match datasize with
| DataSize64 -> Set64
| DataSize32 -> Set32
| DataSize16 | DataSize8 -> failwith "unexpected value"
end
in
sprintf "%s %s,%s" (if signed then "LDRSW" else "LDR") (pp_regzr datasize t) (pp_offset false offset)
| `AArch64LoadRegister (n,t,m,acctype,memop,signed,wback,postindex,extend_type,shift,regsize,datasize) ->
begin
if memop = MemOp_PREFETCH then
begin
if extend_type = ExtendType_UXTX && shift = 0 then
sprintf "PRFM %s,[%s,%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m)
else if extend_type = ExtendType_UXTX (* && shift <> 0 *) then
sprintf "PRFM %s,[%s,%s,LSL %s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_imm shift)
else
sprintf "PRFM %s,[%s,%s%s]" (pp_prfop (inst_reg_to_int t)) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_ldrstr_regext extend_type shift)
end
else
let inst =
(if memop = MemOp_LOAD then "LDR" else "STR") ^
(if signed then "S" else "") ^
(match datasize with
| DataSize8 -> "B"
| DataSize16 -> "H"
| DataSize32 -> if regsize = Set32 then "" else "W"
| DataSize64 -> "") in
if extend_type = ExtendType_UXTX && shift = 0 then
sprintf "%s %s,[%s,%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m)
else if extend_type = ExtendType_UXTX (* && shift <> 0 *) then
sprintf "%s %s,[%s,%s,LSL %s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_imm shift)
else
sprintf "%s %s,[%s,%s%s]" inst (pp_regzr regsize t) (pp_regsp Set64 n) (pp_regzrbyext Set64 extend_type m) (pp_ldrstr_regext extend_type shift)
end
| `AArch64MultiplyAddSub (d,n,m,a,destsize,datasize,sub_op) ->
if is_zero_reg a then
sprintf "%s %s,%s,%s" (if sub_op then "MNEG" else "MUL") (pp_regzr destsize d) (pp_regzr destsize n) (pp_regzr destsize m)
else
sprintf "%s %s,%s,%s,%s" (if sub_op then "MSUB" else "MADD") (pp_regzr destsize d) (pp_regzr destsize n) (pp_regzr destsize m) (pp_regzr destsize a)
| `AArch64MoveWide (d,datasize,imm,pos,opcode) ->
if opcode = MoveWideOp_N && datasize = Set32 && (not (imm = 0 && pos <> 0)) && not (imm = 0xffff) then
sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_imm (lnot (imm lsl (pos*16))))
else if opcode = MoveWideOp_N && datasize = Set64 && (not (imm = 0 && pos <> 0)) then
sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_imm (lnot (imm lsl (pos*16))))
else if opcode = MoveWideOp_Z && (not (imm = 0 && pos <> 0)) then
sprintf "MOV %s,%s" (pp_regzr datasize d) (pp_imm (imm lsl (pos*16)))
else if pos = 0 then
sprintf "%s %s,%s" (pp_movwide opcode) (pp_regzr datasize d) (pp_imm imm)
else
sprintf "%s %s,%s,LSL %s" (pp_movwide opcode) (pp_regzr datasize d) (pp_imm imm) (pp_imm pos)
| `AArch64Reverse (d,n,datasize,op) ->
sprintf "%s %s,%s" (pp_reverse datasize op) (pp_regzr datasize d) (pp_regzr datasize n)
| `AArch64Division (d,n,m,datasize,unsigned) ->
sprintf "%s %s,%s,%s" (if unsigned then "UDIV" else "SDIV") (pp_regzr datasize d) (pp_regzr datasize n) (pp_regzr datasize m)
| `AArch64MultiplyAddSubLong (d,n,m,a,destsize,datasize,sub_op,unsigned) ->
if sub_op && is_zero_reg a then
sprintf "%s %s,%s,%s" (if unsigned then "UMNEGL" else "SMNEGL") (pp_regzr Set64 d) (pp_regzr Set32 n) (pp_regzr Set32 m)
else if not sub_op && is_zero_reg a then
sprintf "%s %s,%s,%s" (if unsigned then "UMULL" else "SMULL") (pp_regzr Set64 d) (pp_regzr Set32 n) (pp_regzr Set32 m)
else
sprintf "%s %s,%s,%s,%s" (pp_maddsubl sub_op unsigned) (pp_regzr Set64 d) (pp_regzr Set32 n) (pp_regzr Set32 m) (pp_regzr Set64 a)
| `AArch64MultiplyHigh (d,n,m,a,destsize,datasize,unsigned) ->
sprintf "%s %s,%s,%s" (if unsigned then "UMULH" else "SMULH") (pp_regzr Set64 d) (pp_regzr Set64 n) (pp_regzr Set64 m)
| `AArch64TestBitAndBranch (t,datasize,bit_pos,bit_val,offset) ->
sprintf "%s %s,%s,%s" (if bit_pos = 1 then "TBNZ" else "TBZ") (pp_regzr datasize t) (pp_imm bit_pos) (pp_offset false offset)
| `AArch64MoveSystemRegister (t,sys_op0,sys_op1,sys_op2,sys_crn,sys_crm,read) ->
if read then
sprintf "MRS %s,%s" (pp_regzr Set64 t) (pp_sysreg (sys_op0,sys_op1,sys_op2,sys_crn,sys_crm))
else
sprintf "MSR %s,%s" (pp_sysreg (sys_op0,sys_op1,sys_op2,sys_crn,sys_crm)) (pp_regzr Set64 t)
| `AArch64MoveSystemImmediate (operand,field) ->
sprintf "MSR %s,%s" (pp_pstatefield field) (pp_imm operand)
|