summaryrefslogtreecommitdiff
path: root/aarch64_small/gen/pretty.hgen
blob: b412fdda07fe5d60dbdc05d083208130ac239e21 (plain)
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
394
395
396
| `AArch64Unallocated ->
      "UNALLOCATED"

| `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)