aarch64 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +42 -0
  3. data/.github/workflows/release.yml +62 -0
  4. data/Rakefile +2 -8
  5. data/aarch64.gemspec +0 -1
  6. data/lib/aarch64/instructions/add/addsub_ext.rb +37 -0
  7. data/lib/aarch64/instructions/add/addsub_imm.rb +34 -0
  8. data/lib/aarch64/instructions/add/addsub_shift.rb +37 -0
  9. data/lib/aarch64/instructions/add.rb +9 -0
  10. data/lib/aarch64/instructions/adds/addsub_ext.rb +37 -0
  11. data/lib/aarch64/instructions/adds/addsub_imm.rb +35 -0
  12. data/lib/aarch64/instructions/adds/addsub_shift.rb +37 -0
  13. data/lib/aarch64/instructions/adds.rb +9 -0
  14. data/lib/aarch64/instructions/and/log_imm.rb +37 -0
  15. data/lib/aarch64/instructions/and/log_shift.rb +37 -0
  16. data/lib/aarch64/instructions/and.rb +8 -0
  17. data/lib/aarch64/instructions/ands/log_imm.rb +37 -0
  18. data/lib/aarch64/instructions/ands/log_shift.rb +37 -0
  19. data/lib/aarch64/instructions/ands.rb +8 -0
  20. data/lib/aarch64/instructions/eor/log_imm.rb +37 -0
  21. data/lib/aarch64/instructions/eor/log_shift.rb +37 -0
  22. data/lib/aarch64/instructions/eor.rb +8 -0
  23. data/lib/aarch64/instructions/orn/log_shift.rb +37 -0
  24. data/lib/aarch64/instructions/orn.rb +7 -0
  25. data/lib/aarch64/instructions/orr/log_imm.rb +37 -0
  26. data/lib/aarch64/instructions/orr/log_shift.rb +37 -0
  27. data/lib/aarch64/instructions/orr.rb +8 -0
  28. data/lib/aarch64/instructions/sub/addsub_ext.rb +37 -0
  29. data/lib/aarch64/instructions/sub/addsub_imm.rb +35 -0
  30. data/lib/aarch64/instructions/sub/addsub_shift.rb +37 -0
  31. data/lib/aarch64/instructions/sub.rb +9 -0
  32. data/lib/aarch64/instructions/subs/addsub_ext.rb +37 -0
  33. data/lib/aarch64/instructions/subs/addsub_imm.rb +35 -0
  34. data/lib/aarch64/instructions/subs/addsub_shift.rb +37 -0
  35. data/lib/aarch64/instructions/subs.rb +9 -0
  36. data/lib/aarch64/instructions.rb +9 -21
  37. data/lib/aarch64/parser.rb +1886 -552
  38. data/lib/aarch64/system_registers/mrs_msr_64.rb +6 -3
  39. data/lib/aarch64/tokenizer.rb +460 -0
  40. data/lib/aarch64/version.rb +1 -1
  41. data/lib/aarch64.rb +54 -54
  42. data/test/base_instructions_test.rb +13 -3
  43. data/test/helper.rb +3 -3
  44. data/test/parser_test.rb +16 -3
  45. metadata +36 -41
  46. data/lib/aarch64/instructions/add_addsub_ext.rb +0 -35
  47. data/lib/aarch64/instructions/add_addsub_imm.rb +0 -32
  48. data/lib/aarch64/instructions/add_addsub_shift.rb +0 -35
  49. data/lib/aarch64/instructions/adds_addsub_ext.rb +0 -35
  50. data/lib/aarch64/instructions/adds_addsub_imm.rb +0 -33
  51. data/lib/aarch64/instructions/adds_addsub_shift.rb +0 -35
  52. data/lib/aarch64/instructions/and_log_imm.rb +0 -35
  53. data/lib/aarch64/instructions/and_log_shift.rb +0 -35
  54. data/lib/aarch64/instructions/ands_log_imm.rb +0 -35
  55. data/lib/aarch64/instructions/ands_log_shift.rb +0 -35
  56. data/lib/aarch64/instructions/eor_log_imm.rb +0 -35
  57. data/lib/aarch64/instructions/eor_log_shift.rb +0 -35
  58. data/lib/aarch64/instructions/orn_log_shift.rb +0 -35
  59. data/lib/aarch64/instructions/orr_log_imm.rb +0 -35
  60. data/lib/aarch64/instructions/orr_log_shift.rb +0 -35
  61. data/lib/aarch64/instructions/sub_addsub_ext.rb +0 -35
  62. data/lib/aarch64/instructions/sub_addsub_imm.rb +0 -33
  63. data/lib/aarch64/instructions/sub_addsub_shift.rb +0 -35
  64. data/lib/aarch64/instructions/subs_addsub_ext.rb +0 -35
  65. data/lib/aarch64/instructions/subs_addsub_imm.rb +0 -33
  66. data/lib/aarch64/instructions/subs_addsub_shift.rb +0 -35
@@ -2,629 +2,1963 @@
2
2
 
3
3
  require "strscan"
4
4
  require "aarch64/system_registers/mrs_msr_64"
5
- require "aarch64/parser.tab"
6
5
  require "aarch64"
6
+ require "aarch64/tokenizer"
7
7
 
8
8
  module AArch64
9
- class Parser < Racc::Parser
10
- class RegsWithShift
11
- attr_reader :d, :n, :m, :shift, :amount
9
+ class Parser
10
+ include Instructions
12
11
 
13
- def initialize d, n, m, shift: :lsl, amount: 0
14
- @d = d
15
- @n = n
16
- @m = m
17
- @shift = shift
18
- @amount = amount
12
+ def parse str
13
+ str += "\n" unless str.end_with?("\n")
14
+ @scan = Tokenizer.new(str)
15
+ @asm = AArch64::Assembler.new
16
+ @labels = {}
17
+ @defined_labels = {}
18
+ instructions
19
+ end
20
+
21
+ private
22
+
23
+ def instructions
24
+ while !@scan.eof?
25
+ tok = @scan.peek
26
+ name = tok.first.to_s
27
+
28
+ if respond_to?("parse_#{name}", true)
29
+ if tok.first != :LABEL_CREATE
30
+ expect tok.first
31
+ end
32
+ if node = send("parse_#{name}")
33
+ @asm << node
34
+ end
35
+ expect :EOL
36
+ else
37
+ string = @scan.string
38
+ line_number = string.byteslice(0, @scan.pos).count("\n") + 1
39
+ val = tok.last
40
+ raise AArch64::ParseError, "parse error on value #{val.inspect} (#{name}) on line #{line_number} at pos #{@scan.pos}/#{string.bytesize}"
41
+ end
42
+ end
43
+
44
+ @labels.each do |name, label|
45
+ unless @defined_labels[name]
46
+ raise "Label #{name.inspect} not defined"
47
+ end
48
+ end
49
+
50
+ @asm
51
+ end
52
+
53
+ def parse_LABEL_CREATE
54
+ label_name = next_token
55
+ label = if @defined_labels[label_name]
56
+ raise "symbol '#{label_name}' is already defined"
57
+ else
58
+ @defined_labels[label_name] = (@labels[label_name] ||= @asm.make_label(label_name))
59
+ end
60
+ @asm.put_label(label)
61
+ false
62
+ end
63
+
64
+ def parse_ADC
65
+ if @scan.peek.last.x?
66
+ xd_xd_xd Instructions::ADC
67
+ else
68
+ wd_wd_wd Instructions::ADC
69
+ end
70
+ end
71
+
72
+ def parse_ADCS
73
+ if @scan.peek.last.x?
74
+ xd_xd_xd ADCS
75
+ else
76
+ wd_wd_wd ADCS
77
+ end
78
+ end
79
+
80
+ def parse_ADD
81
+ add_body ADD
82
+ end
83
+
84
+ def parse_ADDG
85
+ d = next_token
86
+ expect(:COMMA)
87
+ n = next_token
88
+ expect(:COMMA)
89
+ imm6 = expect(:NUMBER)
90
+ expect(:COMMA)
91
+ imm4 = expect(:NUMBER)
92
+ ADDG.new(d, n, imm6 / 16, imm4)
93
+ end
94
+
95
+ def parse_ADDS
96
+ add_body ADDS
97
+ end
98
+
99
+ def parse_ADR
100
+ adr_body ADR
101
+ end
102
+
103
+ def parse_ADRP
104
+ adr_body ADRP
105
+ end
106
+
107
+ def parse_AND
108
+ and_body AND
109
+ end
110
+
111
+ def parse_ANDS
112
+ and_body ANDS
113
+ end
114
+
115
+ def parse_ASR
116
+ d = next_token
117
+ expect(:COMMA)
118
+ n = d.x? ? expect_x : expect_w
119
+ expect(:COMMA)
120
+
121
+ m = if at(:NUMBER)
122
+ next_token
123
+ else
124
+ d.x? ? expect_x : expect_w
125
+ end
126
+ @asm.asr d, n, m
127
+ false
128
+ end
129
+
130
+ def parse_AT
131
+ op = next_token.to_sym
132
+ comma
133
+ d = next_token
134
+ @asm.at op, d
135
+ false
136
+ end
137
+
138
+ def parse_B
139
+
140
+ cond = nil
141
+ if at(:DOT)
142
+ expect :DOT
143
+ cond = next_token.to_sym
144
+ label = if at(:NUMBER)
145
+ next_token
146
+ else
147
+ label_name = next_token
148
+ @labels[label_name] ||= @asm.make_label(label_name)
149
+ end
150
+ else
151
+ label = if at(:NUMBER)
152
+ next_token
153
+ else
154
+ label_name = next_token
155
+ @labels[label_name] ||= @asm.make_label(label_name)
156
+ end
157
+ end
158
+
159
+ @asm.b label, cond: cond
160
+ false
161
+ end
162
+
163
+ def parse_BFI
164
+ bfi_body { |d, n, lsb, width| @asm.bfi d, n, lsb, width }
165
+ false
166
+ end
167
+
168
+ def parse_BFXIL
169
+ bfi_body { |d, n, lsb, width| @asm.bfxil d, n, lsb, width }
170
+ false
171
+ end
172
+
173
+ def parse_BIC
174
+ shifted BIC_log_shift
175
+ end
176
+
177
+ def parse_BICS
178
+ shifted BICS
179
+ end
180
+
181
+ def parse_BL
182
+ val = if at(:NUMBER)
183
+ next_token
184
+ else
185
+ label_name = next_token
186
+ @labels[label_name] ||= @asm.make_label(label_name)
187
+ end
188
+
189
+ @asm.bl val
190
+ false
191
+ end
192
+
193
+ def parse_BLR
194
+ @asm.blr(next_token)
195
+ false
196
+ end
197
+
198
+ def parse_BR
199
+ @asm.br(next_token)
200
+ false
201
+ end
202
+
203
+ def parse_BRK
204
+ @asm.brk(expect(:NUMBER))
205
+ false
206
+ end
207
+
208
+ def parse_CBNZ
209
+ reg_imm_or_label { |rt, where| @asm.cbnz rt, where }
210
+ end
211
+
212
+ def parse_CBZ
213
+ reg_imm_or_label { |rt, where| @asm.cbz rt, where }
214
+ end
215
+
216
+ def parse_CINC
217
+ cond_three { |d, n, cond| @asm.cinc d, n, cond }
218
+ end
219
+
220
+ def parse_CINV
221
+ cond_three { |d, n, cond| @asm.cinv d, n, cond }
222
+ end
223
+
224
+ def parse_CLREX
225
+ if at(:NUMBER)
226
+ @asm.clrex(next_token)
227
+ else
228
+ @asm.clrex(15)
229
+ end
230
+ false
231
+ end
232
+
233
+ def parse_CLS
234
+ reg_reg { |d, n| @asm.cls d, n }
235
+ end
236
+
237
+ def parse_CLZ
238
+ reg_reg { |d, n| @asm.clz d, n }
239
+ end
240
+
241
+ def parse_CMN
242
+ cmn_body ADDS
243
+ end
244
+
245
+ def parse_CMP
246
+ cmn_body SUBS
247
+ end
248
+
249
+ def parse_CNEG
250
+ cond_three { |d, n, cond| @asm.cneg d, n, cond }
251
+ end
252
+
253
+ class_eval %w{ CSEL CSINV CSINC CCMN CCMP CSNEG }.map { |n|
254
+ <<-eorb
255
+ def parse_#{n}
256
+ cond_four { |d, n, m, cond| @asm.#{n.downcase} d, n, m, cond }
257
+ end
258
+ eorb
259
+ }.join("\n")
260
+
261
+ def parse_CSET
262
+ cond_two { |d, cond| @asm.cset d, cond }
263
+ end
264
+
265
+ def parse_CSETM
266
+ cond_two { |d, cond| @asm.csetm d, cond }
267
+ end
268
+
269
+ class_eval %w{ CRC32B CRC32H CRC32W CRC32CB CRC32CH CRC32CW }.map { |n|
270
+ <<-eorb
271
+ def parse_#{n}
272
+ wd_wd_wd { |d, n, m| @asm.#{n.downcase} d, n, m }
273
+ end
274
+ eorb
275
+ }.join("\n")
276
+
277
+ def parse_CRC32X
278
+ rd = expect_w
279
+ comma
280
+ rn = expect_w
281
+ comma
282
+ rm = expect_x
283
+ @asm.crc32x rd, rn, rm
284
+ false
285
+ end
286
+
287
+ def parse_CRC32CX
288
+ rd = expect_w
289
+ comma
290
+ rn = expect_w
291
+ comma
292
+ rm = expect_x
293
+ @asm.crc32cx rd, rn, rm
294
+ false
295
+ end
296
+
297
+ def parse_DC
298
+ op = expect_any([:IVAC, :ISW, :IGVAC, :IGSW, :IGDVAC, :IGDSW, :CSW, :CGSW,
299
+ :CGDSW, :CISW, :CIGSW, :CIGDSW, :ZVA, :GVA, :GZVA, :CVAC, :CGVAC,
300
+ :CGDVAC, :CVAU, :CVAP, :CGVAP, :CGDVAP, :CVADP, :CGVADP, :CGDVADP,
301
+ :CIVAC, :CIGVAC, :CIGDVAC]).to_sym
302
+ comma
303
+ xt = expect_x
304
+ @asm.dc op, xt
305
+ false
306
+ end
307
+
308
+ class_eval 3.times.map { |i|
309
+ "def parse_DCPS#{i + 1}; DCPS.new(0, #{i + 1}); end"
310
+ }.join("\n")
311
+
312
+ def parse_DMB
313
+ dmb_body DMB
314
+ end
315
+
316
+ def parse_DSB
317
+ dmb_body DSB
318
+ end
319
+
320
+ def parse_EOR
321
+ and_body EOR
322
+ end
323
+
324
+ def parse_EON
325
+ shifted EON
326
+ end
327
+
328
+ def parse_EXTR
329
+ reg_reg_reg { |d, n, m|
330
+ comma
331
+ EXTR.new(d, n, m, expect(:NUMBER), d.sf)
332
+ }
333
+ end
334
+
335
+ def parse_AUTDA
336
+ xd = expect_x
337
+ comma
338
+ xn = next_token # can be Xd or SP
339
+ @asm.autda(xd, xn)
340
+ false
341
+ end
342
+
343
+ def parse_DRPS
344
+ @asm.drps
345
+ false
346
+ end
347
+
348
+ def parse_ERET
349
+ @asm.eret
350
+ false
351
+ end
352
+
353
+ def parse_HINT
354
+ @asm.hint(expect(:NUMBER))
355
+ false
356
+ end
357
+
358
+ def parse_HLT
359
+ @asm.hlt(expect(:NUMBER))
360
+ false
361
+ end
362
+
363
+ def parse_HVC
364
+ @asm.hvc(expect(:NUMBER))
365
+ false
366
+ end
367
+
368
+ def parse_LDAR
369
+ wd = next_token
370
+ comma
371
+ expect :LSQ
372
+ xn = expect_reg
373
+ expect :RSQ
374
+ @asm.ldar(wd, [xn])
375
+ false
376
+ end
377
+
378
+ def parse_LDARB
379
+ wd = expect_w
380
+ comma
381
+ expect :LSQ
382
+ xn = expect_reg
383
+ expect :RSQ
384
+ @asm.ldarb(wd, [xn])
385
+ false
386
+ end
387
+
388
+ def parse_LDARH
389
+ wd = expect_w
390
+ comma
391
+ expect :LSQ
392
+ xn = expect_reg
393
+ expect :RSQ
394
+ @asm.ldarh(wd, [xn])
395
+ false
396
+ end
397
+
398
+ def parse_LDAXR
399
+ rd = next_token
400
+ comma
401
+ expect :LSQ
402
+ xn = expect_reg
403
+ expect :RSQ
404
+ @asm.ldaxr(rd, [xn])
405
+ false
406
+ end
407
+
408
+ def parse_LDAXRB
409
+ wd = expect_w
410
+ comma
411
+ expect :LSQ
412
+ xn = expect_reg
413
+ expect :RSQ
414
+ @asm.ldaxrb(wd, [xn])
415
+ false
416
+ end
417
+
418
+ def parse_LDAXRH
419
+ wd = expect_w
420
+ comma
421
+ expect :LSQ
422
+ xn = expect_reg
423
+ expect :RSQ
424
+ @asm.ldaxrh(wd, [xn])
425
+ false
426
+ end
427
+
428
+ def parse_LDR
429
+ ldr_body { |rt, addr, imm| @asm.ldr(rt, addr, imm) }
430
+ end
431
+
432
+ def parse_LDRB
433
+ ldr_body { |rt, addr, imm| @asm.ldrb(rt, addr, imm) }
434
+ end
435
+
436
+ def parse_LDRH
437
+ ldr_body { |rt, addr, imm| @asm.ldrh(rt, addr, imm) }
438
+ end
439
+
440
+ def parse_LDRSB
441
+ ldr_body { |rt, addr, imm| @asm.ldrsb(rt, addr, imm) }
442
+ end
443
+
444
+ def parse_LDRSH
445
+ ldr_body { |rt, addr, imm| @asm.ldrsh(rt, addr, imm) }
446
+ end
447
+
448
+ def parse_LDRSW
449
+ ldr_body { |rt, addr, imm| @asm.ldrsw(rt, addr, imm) }
450
+ end
451
+
452
+ def parse_LDTR
453
+ ldtr_body { |rt, addr| @asm.ldtr(rt, addr) }
454
+ end
455
+
456
+ def parse_LDTRB
457
+ ldtr_body { |rt, addr| @asm.ldtrb(rt, addr) }
458
+ end
459
+
460
+ def parse_LDTRH
461
+ ldtr_body { |rt, addr| @asm.ldtrh(rt, addr) }
462
+ end
463
+
464
+ def parse_LDTRSB
465
+ ldtr_body { |rt, addr| @asm.ldtrsb(rt, addr) }
466
+ end
467
+
468
+ def parse_LDTRSH
469
+ ldtr_body { |rt, addr| @asm.ldtrsh(rt, addr) }
470
+ end
471
+
472
+ def parse_LDTRSW
473
+ ldtr_body { |rt, addr| @asm.ldtrsw(rt, addr) }
474
+ end
475
+
476
+ def parse_LDUR
477
+ ldtr_body { |rt, addr| @asm.ldur(rt, addr) }
478
+ end
479
+
480
+ def parse_LDURB
481
+ ldtr_body { |rt, addr| @asm.ldurb(rt, addr) }
482
+ end
483
+
484
+ def parse_LDURH
485
+ ldtr_body { |rt, addr| @asm.ldurh(rt, addr) }
486
+ end
487
+
488
+ def parse_LDURSB
489
+ ldtr_body { |rt, addr| @asm.ldursb(rt, addr) }
490
+ end
491
+
492
+ def parse_LDURSH
493
+ ldtr_body { |rt, addr| @asm.ldursh(rt, addr) }
494
+ end
495
+
496
+ def parse_LDURSW
497
+ ldtr_body { |rt, addr| @asm.ldursw(rt, addr) }
498
+ end
499
+
500
+ def parse_LDXP
501
+ rt1 = expect_reg
502
+ comma
503
+ rt2 = srt rt1
504
+ comma
505
+ expect :LSQ
506
+ xn = expect_reg
507
+ expect :RSQ
508
+ @asm.ldxp(rt1, rt2, [xn])
509
+ false
510
+ end
511
+
512
+ def parse_LDXR
513
+ rd = next_token
514
+ comma
515
+ expect :LSQ
516
+ xn = expect_reg
517
+ expect :RSQ
518
+ @asm.ldxr(rd, [xn])
519
+ false
520
+ end
521
+
522
+ def parse_LDXRB
523
+ wd = expect_w
524
+ comma
525
+ expect :LSQ
526
+ xn = expect_reg
527
+ expect :RSQ
528
+ @asm.ldxrb(wd, [xn])
529
+ false
530
+ end
531
+
532
+ def parse_LDXRH
533
+ wd = expect_w
534
+ comma
535
+ expect :LSQ
536
+ xn = expect_reg
537
+ expect :RSQ
538
+ @asm.ldxrh(wd, [xn])
539
+ false
540
+ end
541
+
542
+ def parse_LSL
543
+ d = next_token
544
+ comma
545
+ n = srt d
546
+ comma
547
+ m = if at(:NUMBER)
548
+ next_token
549
+ else
550
+ srt d
551
+ end
552
+ @asm.lsl d, n, m
553
+ false
554
+ end
555
+
556
+ def parse_LSR
557
+ d = next_token
558
+ comma
559
+ n = srt d
560
+ comma
561
+ m = if at(:NUMBER)
562
+ next_token
563
+ else
564
+ srt d
565
+ end
566
+ @asm.lsr d, n, m
567
+ false
568
+ end
569
+
570
+ def parse_MADD
571
+ reg_reg_reg { |d, n, m|
572
+ comma
573
+ ra = srt d
574
+ @asm.madd d, n, m, ra
575
+ }
576
+ false
577
+ end
578
+
579
+ def parse_MNEG
580
+ reg_reg_reg { |d, n, m| @asm.mneg d, n, m }
581
+ false
582
+ end
583
+
584
+ def parse_MOV
585
+ d = next_token
586
+ comma
587
+ if at(:NUMBER)
588
+ imm = next_token
589
+ @asm.mov d, imm
590
+ else
591
+ n = next_token
592
+ @asm.mov d, n
593
+ end
594
+ false
595
+ end
596
+
597
+ def parse_MOVK
598
+ movz_body { |d, imm, opts| @asm.movk(d, imm, **opts) }
599
+ end
600
+
601
+ def parse_MOVN
602
+ movz_body { |d, imm, opts| @asm.movn(d, imm, **opts) }
603
+ end
604
+
605
+ def parse_MOVZ
606
+ movz_body { |d, imm, opts| @asm.movz(d, imm, **opts) }
607
+ end
608
+
609
+ def parse_MRS
610
+ xd = expect_x
611
+ comma
612
+ sysreg = next_token
613
+ @asm.mrs(xd, sysreg)
614
+ false
615
+ end
616
+
617
+ def parse_MSR
618
+ sysreg = next_token
619
+ comma
620
+ if at(:NUMBER)
621
+ imm = next_token
622
+ @asm.msr(sysreg, imm)
623
+ else
624
+ xd = expect_x
625
+ @asm.msr(sysreg, xd)
626
+ end
627
+ false
628
+ end
629
+
630
+ def parse_MSUB
631
+ reg_reg_reg { |d, n, m|
632
+ comma
633
+ ra = srt d
634
+ @asm.msub d, n, m, ra
635
+ }
636
+ false
637
+ end
638
+
639
+ def parse_MUL
640
+ reg_reg_reg { |d, n, m| @asm.mul d, n, m }
641
+ false
642
+ end
643
+
644
+ def parse_MVN
645
+ d = next_token
646
+ comma
647
+ n = srt d
648
+ if at(:COMMA)
649
+ comma
650
+ shift = expect_any([:LSL, :LSR, :ASR, :ROR]).to_sym
651
+ amount = expect(:NUMBER)
652
+ @asm.mvn d, n, shift: shift, amount: amount
653
+ else
654
+ @asm.mvn d, n
655
+ end
656
+ false
657
+ end
658
+
659
+ def parse_NEG
660
+ d = next_token
661
+ comma
662
+ n = srt d
663
+ if at(:COMMA)
664
+ comma
665
+ shift = expect_any([:LSL, :LSR, :ASR]).to_sym
666
+ amount = expect(:NUMBER)
667
+ @asm.neg d, n, shift: shift, amount: amount
668
+ else
669
+ @asm.neg d, n
670
+ end
671
+ false
672
+ end
673
+
674
+ def parse_NEGS
675
+ d = next_token
676
+ comma
677
+ n = srt d
678
+ if at(:COMMA)
679
+ comma
680
+ shift = expect_any([:LSL, :LSR, :ASR]).to_sym
681
+ amount = expect(:NUMBER)
682
+ @asm.negs d, n, shift: shift, amount: amount
683
+ else
684
+ @asm.negs d, n
685
+ end
686
+ false
687
+ end
688
+
689
+ def parse_NGC
690
+ reg_reg { |d, n| @asm.ngc d, n }
691
+ end
692
+
693
+ def parse_NGCS
694
+ reg_reg { |d, n| @asm.ngcs d, n }
695
+ end
696
+
697
+ def parse_NOP
698
+ @asm.nop
699
+ false
700
+ end
701
+
702
+ def parse_ORN
703
+ shifted Instructions::ORN::LOG_shift
704
+ end
705
+
706
+ def parse_ORR
707
+ and_body Instructions::ORR
708
+ end
709
+
710
+ def parse_PRFM
711
+ op = if at(:PRFOP)
712
+ next_token.to_sym
713
+ else
714
+ expect(:NUMBER)
715
+ end
716
+ comma
717
+ if at(:LSQ)
718
+ expect :LSQ
719
+ xn = expect_reg
720
+ if at(:COMMA)
721
+ comma
722
+ if at(:NUMBER)
723
+ imm = next_token
724
+ expect :RSQ
725
+ @asm.prfm(op, [xn, imm])
726
+ else
727
+ # reg offset with optional extend
728
+ rm = next_token
729
+ if at(:COMMA)
730
+ comma
731
+ ext = expect_any([:LSL, :UXTW, :SXTW, :SXTX]).to_sym
732
+ amount = at(:NUMBER) ? next_token : nil
733
+ expect :RSQ
734
+ @asm.prfm(op, [xn, rm, Shifts::Shift.new(amount, 0, ext)])
735
+ else
736
+ expect :RSQ
737
+ @asm.prfm(op, [xn, rm])
738
+ end
739
+ end
740
+ else
741
+ expect :RSQ
742
+ @asm.prfm(op, [xn])
743
+ end
744
+ else
745
+ imm = expect(:NUMBER)
746
+ @asm.prfm(op, imm)
747
+ end
748
+ false
749
+ end
750
+
751
+ def parse_PRFUM
752
+ op = if at(:PRFOP)
753
+ next_token.to_sym
754
+ else
755
+ expect(:NUMBER)
756
+ end
757
+ comma
758
+ expect :LSQ
759
+ xn = expect_reg
760
+ if at(:COMMA)
761
+ comma
762
+ imm = expect(:NUMBER)
763
+ expect :RSQ
764
+ @asm.prfum(op, [xn, imm])
765
+ else
766
+ expect :RSQ
767
+ @asm.prfum(op, [xn])
768
+ end
769
+ false
770
+ end
771
+
772
+ def parse_PSSBB
773
+ @asm.pssbb
774
+ false
775
+ end
776
+
777
+ def parse_RBIT
778
+ reg_reg { |d, n| @asm.rbit d, n }
779
+ end
780
+
781
+ def parse_RET
782
+ if at(:EOL)
783
+ @asm.ret
784
+ else
785
+ @asm.ret(next_token)
786
+ end
787
+ false
788
+ end
789
+
790
+ def parse_REV
791
+ reg_reg { |d, n| @asm.rev d, n }
792
+ end
793
+
794
+ def parse_REV16
795
+ reg_reg { |d, n| @asm.rev16 d, n }
796
+ end
797
+
798
+ def parse_REV32
799
+ d = expect_x
800
+ comma
801
+ n = expect_x
802
+ @asm.rev32 d, n
803
+ false
804
+ end
805
+
806
+ def parse_ROR
807
+ d = next_token
808
+ comma
809
+ n = srt d
810
+ comma
811
+ m = if at(:NUMBER)
812
+ next_token
813
+ else
814
+ srt d
19
815
  end
816
+ @asm.ror d, n, m
817
+ false
818
+ end
819
+
820
+ def parse_SBC
821
+ reg_reg_reg { |d, n, m| @asm.sbc d, n, m }
822
+ false
823
+ end
824
+
825
+ def parse_SBCS
826
+ reg_reg_reg { |d, n, m| @asm.sbcs d, n, m }
827
+ false
828
+ end
829
+
830
+ def parse_SBFIZ
831
+ bfi_body { |d, n, lsb, width| @asm.sbfiz d, n, lsb, width }
832
+ false
833
+ end
834
+
835
+ def parse_SBFX
836
+ bfi_body { |d, n, lsb, width| @asm.sbfx d, n, lsb, width }
837
+ false
838
+ end
839
+
840
+ def parse_SDIV
841
+ reg_reg_reg { |d, n, m| @asm.sdiv d, n, m }
842
+ false
843
+ end
844
+
845
+ def parse_SEV
846
+ @asm.sev
847
+ false
848
+ end
849
+
850
+ def parse_SEVL
851
+ @asm.sevl
852
+ false
853
+ end
854
+
855
+ def parse_SMADDL
856
+ xd = expect_x
857
+ comma
858
+ wn = expect_w
859
+ comma
860
+ wm = expect_w
861
+ comma
862
+ xa = expect_x
863
+ @asm.smaddl xd, wn, wm, xa
864
+ false
865
+ end
866
+
867
+ def parse_SMC
868
+ @asm.smc(expect(:NUMBER))
869
+ false
870
+ end
871
+
872
+ def parse_SMNEGL
873
+ xd = expect_x
874
+ comma
875
+ wn = expect_w
876
+ comma
877
+ wm = expect_w
878
+ @asm.smnegl xd, wn, wm
879
+ false
880
+ end
881
+
882
+ def parse_SMSUBL
883
+ xd = expect_x
884
+ comma
885
+ wn = expect_w
886
+ comma
887
+ wm = expect_w
888
+ comma
889
+ xa = expect_x
890
+ @asm.smsubl xd, wn, wm, xa
891
+ false
892
+ end
20
893
 
21
- def apply asm, name
22
- asm.public_send(name, d, n, m, shift: shift, amount: amount)
894
+ def parse_SMULH
895
+ xd = expect_x
896
+ comma
897
+ xn = expect_x
898
+ comma
899
+ xm = expect_x
900
+ @asm.smulh xd, xn, xm
901
+ false
902
+ end
903
+
904
+ def parse_SMULL
905
+ xd = expect_x
906
+ comma
907
+ wn = expect_w
908
+ comma
909
+ wm = expect_w
910
+ @asm.smull xd, wn, wm
911
+ false
912
+ end
913
+
914
+ def parse_SSBB
915
+ @asm.ssbb
916
+ false
917
+ end
918
+
919
+ def parse_STLR
920
+ rt = next_token
921
+ comma
922
+ expect :LSQ
923
+ xn = expect_reg
924
+ expect :RSQ
925
+ @asm.stlr(rt, [xn])
926
+ false
927
+ end
928
+
929
+ def parse_STLRB
930
+ wd = expect_w
931
+ comma
932
+ expect :LSQ
933
+ xn = expect_reg
934
+ expect :RSQ
935
+ @asm.stlrb(wd, [xn])
936
+ false
937
+ end
938
+
939
+ def parse_STLRH
940
+ wd = expect_w
941
+ comma
942
+ expect :LSQ
943
+ xn = expect_reg
944
+ expect :RSQ
945
+ @asm.stlrh(wd, [xn])
946
+ false
947
+ end
948
+
949
+ def parse_STLXP
950
+ ws = expect_w
951
+ comma
952
+ rt1 = next_token
953
+ comma
954
+ rt2 = srt rt1
955
+ comma
956
+ expect :LSQ
957
+ xn = expect_reg
958
+ expect :RSQ
959
+ @asm.stlxp(ws, rt1, rt2, [xn])
960
+ false
961
+ end
962
+
963
+ def parse_STLXR
964
+ ws = expect_w
965
+ comma
966
+ rt = next_token
967
+ comma
968
+ expect :LSQ
969
+ xn = expect_reg
970
+ expect :RSQ
971
+ @asm.stlxr(ws, rt, [xn])
972
+ false
973
+ end
974
+
975
+ def parse_STLXRB
976
+ ws = expect_w
977
+ comma
978
+ wt = expect_w
979
+ comma
980
+ expect :LSQ
981
+ xn = expect_reg
982
+ expect :RSQ
983
+ @asm.stlxrb(ws, wt, [xn])
984
+ false
985
+ end
986
+
987
+ def parse_STLXRH
988
+ ws = expect_w
989
+ comma
990
+ wt = expect_w
991
+ comma
992
+ expect :LSQ
993
+ xn = expect_reg
994
+ expect :RSQ
995
+ @asm.stlxrh(ws, wt, [xn])
996
+ false
997
+ end
998
+
999
+ def parse_STNP
1000
+ rt1 = expect_reg
1001
+ comma
1002
+ rt2 = srt rt1
1003
+ comma
1004
+ expect :LSQ
1005
+ xn = expect_reg
1006
+ val = if at(:COMMA)
1007
+ comma
1008
+ expect(:NUMBER)
1009
+ else
1010
+ 0
23
1011
  end
1012
+ expect :RSQ
1013
+ @asm.stnp rt1, rt2, [xn, val]
1014
+ false
1015
+ end
1016
+
1017
+ def parse_STP
1018
+ stp_body { |rt1, rt2, rn, imm| @asm.stp(rt1, rt2, rn, imm) }
1019
+ end
1020
+
1021
+ def parse_STR
1022
+ str_body { |rt, addr, imm| @asm.str(rt, addr, imm) }
1023
+ end
1024
+
1025
+ def parse_STRB
1026
+ str_body { |rt, addr, imm| @asm.strb(rt, addr, imm) }
1027
+ end
1028
+
1029
+ def parse_STRH
1030
+ str_body { |rt, addr, imm| @asm.strh(rt, addr, imm) }
1031
+ end
1032
+
1033
+ def parse_STTR
1034
+ ldtr_body { |rt, addr| @asm.sttr(rt, addr) }
1035
+ end
1036
+
1037
+ def parse_STTRB
1038
+ ldtr_body { |rt, addr| @asm.sttrb(rt, addr) }
1039
+ end
1040
+
1041
+ def parse_STTRH
1042
+ ldtr_body { |rt, addr| @asm.sttrh(rt, addr) }
1043
+ end
1044
+
1045
+ def parse_STUR
1046
+ ldtr_body { |rt, addr| @asm.stur(rt, addr) }
1047
+ end
1048
+
1049
+ def parse_STURB
1050
+ ldtr_body { |rt, addr| @asm.sturb(rt, addr) }
1051
+ end
1052
+
1053
+ def parse_STURH
1054
+ ldtr_body { |rt, addr| @asm.sturh(rt, addr) }
1055
+ end
1056
+
1057
+ def parse_STXP
1058
+ ws = expect_w
1059
+ comma
1060
+ rt1 = next_token
1061
+ comma
1062
+ rt2 = srt rt1
1063
+ comma
1064
+ expect :LSQ
1065
+ xn = expect_reg
1066
+ expect :RSQ
1067
+ @asm.stxp(ws, rt1, rt2, [xn])
1068
+ false
1069
+ end
1070
+
1071
+ def parse_STXR
1072
+ ws = expect_w
1073
+ comma
1074
+ rt = next_token
1075
+ comma
1076
+ expect :LSQ
1077
+ xn = expect_reg
1078
+ expect :RSQ
1079
+ @asm.stxr(ws, rt, [xn])
1080
+ false
1081
+ end
1082
+
1083
+ def parse_STXRB
1084
+ ws = expect_w
1085
+ comma
1086
+ wt = expect_w
1087
+ comma
1088
+ expect :LSQ
1089
+ xn = expect_reg
1090
+ expect :RSQ
1091
+ @asm.stxrb(ws, wt, [xn])
1092
+ false
1093
+ end
1094
+
1095
+ def parse_STXRH
1096
+ ws = expect_w
1097
+ comma
1098
+ wt = expect_w
1099
+ comma
1100
+ expect :LSQ
1101
+ xn = expect_reg
1102
+ expect :RSQ
1103
+ @asm.stxrh(ws, wt, [xn])
1104
+ false
1105
+ end
1106
+
1107
+ def parse_SUB
1108
+ add_body Instructions::SUB
1109
+ end
1110
+
1111
+ def parse_SUBS
1112
+ add_body Instructions::SUBS
1113
+ end
1114
+
1115
+ def parse_SVC
1116
+ @asm.svc(expect(:NUMBER))
1117
+ false
1118
+ end
1119
+
1120
+ def parse_SXTB
1121
+ d = next_token
1122
+ comma
1123
+ n = expect_w
1124
+ @asm.sxtb d, n
1125
+ false
1126
+ end
1127
+
1128
+ def parse_SXTH
1129
+ d = next_token
1130
+ comma
1131
+ n = expect_w
1132
+ @asm.sxth d, n
1133
+ false
24
1134
  end
25
1135
 
26
- class RegRegShift
27
- attr_reader :d, :m, :shift, :amount
1136
+ def parse_SXTW
1137
+ d = expect_x
1138
+ comma
1139
+ n = expect_w
1140
+ @asm.sxtw d, n
1141
+ false
1142
+ end
28
1143
 
29
- def initialize d, m, shift: :lsl, amount: 0
30
- @d = d
31
- @m = m
32
- @shift = shift
33
- @amount = amount
1144
+ def parse_SYS
1145
+ op1 = expect(:NUMBER)
1146
+ comma
1147
+ cn = next_token
1148
+ comma
1149
+ cm = next_token
1150
+ comma
1151
+ op2 = expect(:NUMBER)
1152
+ if at(:COMMA)
1153
+ comma
1154
+ xt = expect_x
1155
+ @asm.sys(op1, cn, cm, op2, xt)
1156
+ else
1157
+ @asm.sys(op1, cn, cm, op2)
34
1158
  end
1159
+ false
1160
+ end
1161
+
1162
+ def parse_SYSL
1163
+ xd = expect_x
1164
+ comma
1165
+ op1 = expect(:NUMBER)
1166
+ comma
1167
+ cn = next_token
1168
+ comma
1169
+ cm = next_token
1170
+ comma
1171
+ op2 = expect(:NUMBER)
1172
+ @asm.sysl(xd, op1, cn, cm, op2)
1173
+ false
1174
+ end
35
1175
 
36
- def apply asm, name
37
- asm.public_send(name, d, m, shift: shift, amount: amount)
1176
+ def parse_TBZ
1177
+ rt = next_token
1178
+ comma
1179
+ imm = expect(:NUMBER)
1180
+ comma
1181
+ label = if at(:NUMBER)
1182
+ next_token
1183
+ else
1184
+ get_label next_token
38
1185
  end
1186
+ @asm.tbz rt, imm, label
1187
+ false
39
1188
  end
40
1189
 
41
- class TwoWithExtend
42
- attr_reader :n, :m, :extend, :amount
1190
+ def parse_TBNZ
1191
+ rt = next_token
1192
+ comma
1193
+ imm = expect(:NUMBER)
1194
+ comma
1195
+ label = if at(:NUMBER)
1196
+ next_token
1197
+ else
1198
+ get_label next_token
1199
+ end
1200
+ @asm.tbnz rt, imm, label
1201
+ false
1202
+ end
43
1203
 
44
- def initialize n, m, extend:, amount:
45
- @n = n
46
- @m = m
47
- @extend = extend
48
- @amount = amount
1204
+ def parse_TLBI
1205
+ op = next_token.to_sym
1206
+ if at(:COMMA)
1207
+ comma
1208
+ xt = next_token
1209
+ @asm.tlbi(op, xt)
1210
+ else
1211
+ @asm.tlbi(op)
49
1212
  end
1213
+ false
1214
+ end
50
1215
 
51
- def apply asm, name
52
- asm.public_send(name, n, m, extend: extend, amount: amount)
1216
+ def parse_TST
1217
+ rn = next_token
1218
+ comma
1219
+ if at(:NUMBER)
1220
+ imm = next_token
1221
+ @asm.tst rn, imm
1222
+ else
1223
+ rm = srt rn
1224
+ if at(:COMMA)
1225
+ comma
1226
+ shift = expect_any([:LSL, :LSR, :ASR, :ROR]).to_sym
1227
+ amount = expect(:NUMBER)
1228
+ @asm.tst rn, rm, shift: shift, amount: amount
1229
+ else
1230
+ @asm.tst rn, rm
1231
+ end
53
1232
  end
1233
+ false
1234
+ end
1235
+
1236
+ def parse_UBFIZ
1237
+ bfi_body { |d, n, lsb, width| @asm.ubfiz d, n, lsb, width }
1238
+ false
1239
+ end
1240
+
1241
+ def parse_UBFX
1242
+ bfi_body { |d, n, lsb, width| @asm.ubfx d, n, lsb, width }
1243
+ false
1244
+ end
1245
+
1246
+ def parse_UDIV
1247
+ reg_reg_reg { |d, n, m| @asm.udiv d, n, m }
1248
+ false
1249
+ end
1250
+
1251
+ def parse_UMADDL
1252
+ xd = expect_x
1253
+ comma
1254
+ wn = expect_w
1255
+ comma
1256
+ wm = expect_w
1257
+ comma
1258
+ xa = expect_x
1259
+ @asm.umaddl xd, wn, wm, xa
1260
+ false
1261
+ end
1262
+
1263
+ def parse_UMNEGL
1264
+ xd = expect_x
1265
+ comma
1266
+ wn = expect_w
1267
+ comma
1268
+ wm = expect_w
1269
+ @asm.umnegl xd, wn, wm
1270
+ false
1271
+ end
1272
+
1273
+ def parse_UMSUBL
1274
+ xd = expect_x
1275
+ comma
1276
+ wn = expect_w
1277
+ comma
1278
+ wm = expect_w
1279
+ comma
1280
+ xa = expect_x
1281
+ @asm.umsubl xd, wn, wm, xa
1282
+ false
1283
+ end
1284
+
1285
+ def parse_UMULH
1286
+ xd = expect_x
1287
+ comma
1288
+ xn = expect_x
1289
+ comma
1290
+ xm = expect_x
1291
+ @asm.umulh xd, xn, xm
1292
+ false
1293
+ end
1294
+
1295
+ def parse_UMULL
1296
+ xd = expect_x
1297
+ comma
1298
+ wn = expect_w
1299
+ comma
1300
+ wm = expect_w
1301
+ @asm.umull xd, wn, wm
1302
+ false
1303
+ end
1304
+
1305
+ def parse_UXTB
1306
+ wd = expect_w
1307
+ comma
1308
+ wn = expect_w
1309
+ @asm.uxtb wd, wn
1310
+ false
1311
+ end
1312
+
1313
+ def parse_UXTH
1314
+ wd = expect_w
1315
+ comma
1316
+ wn = expect_w
1317
+ @asm.uxth wd, wn
1318
+ false
1319
+ end
1320
+
1321
+ def parse_WFE
1322
+ @asm.wfe
1323
+ false
1324
+ end
1325
+
1326
+ def parse_WFI
1327
+ @asm.wfi
1328
+ false
54
1329
  end
55
1330
 
56
- class TwoWithShift
57
- attr_reader :n, :m, :shift, :amount
1331
+ def parse_YIELD
1332
+ @asm.yield
1333
+ false
1334
+ end
58
1335
 
59
- def initialize n, m, shift:, amount:
60
- @n = n
61
- @m = m
62
- @shift = shift
63
- @amount = amount
1336
+ def parse_IC
1337
+ op = expect_any([:IALLUIS, :IALLU, :IVAU]).to_sym
1338
+ xt = Registers::SP
1339
+ if at(:COMMA)
1340
+ comma
1341
+ xt = next_token
64
1342
  end
1343
+ @asm.ic(op, xt)
1344
+ false
1345
+ end
65
1346
 
66
- def apply asm, name
67
- asm.public_send(name, n, m, shift: shift, amount: amount)
1347
+ def parse_ISB
1348
+ if at(:NUMBER)
1349
+ @asm.isb(next_token)
1350
+ else
1351
+ @asm.isb
68
1352
  end
1353
+ false
69
1354
  end
70
1355
 
71
- class TwoWithLsl
72
- attr_reader :n, :m, :lsl
1356
+ def parse_LDAXP
1357
+ d = expect_reg
1358
+ comma
1359
+ n = srt d
1360
+ comma
1361
+ expect :LSQ
1362
+ xn = expect_reg
1363
+ expect :RSQ
1364
+ LDAXP.new d, n, xn, d.sf
1365
+ end
73
1366
 
74
- def initialize n, m, lsl:
75
- @n = n
76
- @m = m
77
- @lsl = lsl
1367
+ def parse_LDNP
1368
+ rt1 = expect_reg
1369
+ comma
1370
+ rt2 = srt rt1
1371
+ comma
1372
+ expect :LSQ
1373
+ rt3 = expect_reg
1374
+ val = if at(:COMMA)
1375
+ comma
1376
+ expect(:NUMBER)
1377
+ else
1378
+ 0
78
1379
  end
1380
+ expect :RSQ
1381
+ @asm.ldnp rt1, rt2, [rt3, val]
1382
+ false
1383
+ end
79
1384
 
80
- def apply asm, name
81
- asm.public_send(name, n, m, lsl: lsl)
82
- end
1385
+ def parse_LDP
1386
+ ldp_body { |rt1, rt2, rn, imm| @asm.ldp(rt1, rt2, rn, imm) }
83
1387
  end
84
1388
 
85
- class ThreeWithLsl
86
- attr_reader :d, :n, :m, :lsl
1389
+ def parse_LDPSW
1390
+ ldp_body { |rt1, rt2, rn, imm| @asm.ldpsw(rt1, rt2, rn, imm) }
1391
+ end
87
1392
 
88
- def initialize d, n, m, lsl:
89
- @d = d
90
- @n = n
91
- @m = m
92
- @lsl = lsl
1393
+ def ldp_body
1394
+ rt1 = expect_reg
1395
+ comma
1396
+ rt2 = srt rt1
1397
+ comma
1398
+ expect :LSQ
1399
+ rt3 = expect_reg
1400
+ if at(:COMMA)
1401
+ comma
1402
+ rt3 = [rt3, expect(:NUMBER)]
1403
+ else
1404
+ rt3 = [rt3]
93
1405
  end
1406
+ expect :RSQ
94
1407
 
95
- def apply asm, name
96
- asm.public_send(name, d, n, m, lsl: lsl)
1408
+ imm = if at(:COMMA)
1409
+ comma
1410
+ expect(:NUMBER)
1411
+ else
1412
+ if at(:BANG)
1413
+ expect :BANG
1414
+ :!
1415
+ else
1416
+ nil
1417
+ end
97
1418
  end
1419
+
1420
+ yield rt1, rt2, rt3, imm
1421
+
1422
+ false
98
1423
  end
99
1424
 
100
- class TwoArg
101
- attr_reader :n, :m
1425
+ def movz_body
1426
+ d = next_token
1427
+ comma
1428
+ imm = expect(:NUMBER)
1429
+ opts = {}
1430
+ if at(:COMMA)
1431
+ comma
1432
+ expect :LSL
1433
+ opts[:lsl] = expect(:NUMBER)
1434
+ end
1435
+ yield d, imm, opts
1436
+ false
1437
+ end
102
1438
 
103
- def initialize n, m
104
- @n = n
105
- @m = m
1439
+ def ldr_body
1440
+ rt = next_token
1441
+ comma
1442
+ if at(:LSQ)
1443
+ expect :LSQ
1444
+ xn = expect_reg
1445
+ if at(:COMMA)
1446
+ comma
1447
+ if at(:NUMBER)
1448
+ imm = next_token
1449
+ expect :RSQ
1450
+ if at(:BANG)
1451
+ expect :BANG
1452
+ # pre-index: ldr rt, [xn, imm]!
1453
+ yield rt, [xn, imm], :!
1454
+ else
1455
+ # signed/unsigned offset: ldr rt, [xn, imm]
1456
+ yield rt, [xn, imm]
1457
+ end
1458
+ else
1459
+ # register offset
1460
+ rm = next_token
1461
+ if at(:COMMA)
1462
+ comma
1463
+ ext = expect_any([:LSL, :UXTW, :SXTW, :SXTX]).to_sym
1464
+ amount = at(:NUMBER) ? next_token : nil
1465
+ expect :RSQ
1466
+ yield rt, [xn, rm, Shifts::Shift.new(amount, 0, ext)]
1467
+ else
1468
+ expect :RSQ
1469
+ yield rt, [xn, rm]
1470
+ end
1471
+ end
1472
+ else
1473
+ expect :RSQ
1474
+ if at(:COMMA)
1475
+ comma
1476
+ imm = expect(:NUMBER)
1477
+ # post-index: ldr rt, [xn], imm
1478
+ yield rt, [xn], imm
1479
+ else
1480
+ yield rt, [xn]
1481
+ end
1482
+ end
1483
+ else
1484
+ # literal
1485
+ imm = expect(:NUMBER)
1486
+ yield rt, imm
106
1487
  end
1488
+ false
1489
+ end
107
1490
 
108
- def apply asm, name
109
- asm.public_send(name, n, m)
1491
+ def ldtr_body
1492
+ rt = next_token
1493
+ comma
1494
+ expect :LSQ
1495
+ xn = expect_reg
1496
+ if at(:COMMA)
1497
+ comma
1498
+ imm = expect(:NUMBER)
1499
+ expect :RSQ
1500
+ yield rt, [xn, imm]
1501
+ else
1502
+ expect :RSQ
1503
+ yield rt, [xn]
110
1504
  end
1505
+ false
1506
+ end
111
1507
 
112
- def to_a; [n, m]; end
1508
+ def str_body
1509
+ rt = next_token
1510
+ comma
1511
+ expect :LSQ
1512
+ xn = expect_reg
1513
+ if at(:COMMA)
1514
+ comma
1515
+ if at(:NUMBER)
1516
+ imm = next_token
1517
+ expect :RSQ
1518
+ if at(:BANG)
1519
+ expect :BANG
1520
+ # pre-index
1521
+ yield rt, [xn, imm], :!
1522
+ else
1523
+ yield rt, [xn, imm]
1524
+ end
1525
+ else
1526
+ # register offset
1527
+ rm = next_token
1528
+ if at(:COMMA)
1529
+ comma
1530
+ ext = expect_any([:LSL, :UXTW, :SXTW, :SXTX]).to_sym
1531
+ amount = at(:NUMBER) ? next_token : nil
1532
+ expect :RSQ
1533
+ yield rt, [xn, rm, Shifts::Shift.new(amount, 0, ext)]
1534
+ else
1535
+ expect :RSQ
1536
+ yield rt, [xn, rm]
1537
+ end
1538
+ end
1539
+ else
1540
+ expect :RSQ
1541
+ if at(:COMMA)
1542
+ comma
1543
+ imm = expect(:NUMBER)
1544
+ # post-index
1545
+ yield rt, [xn], imm
1546
+ else
1547
+ yield rt, [xn]
1548
+ end
1549
+ end
1550
+ false
113
1551
  end
114
1552
 
115
- class ThreeArg
116
- attr_reader :d, :n, :m
1553
+ def stp_body
1554
+ rt1 = expect_reg
1555
+ comma
1556
+ rt2 = srt rt1
1557
+ comma
1558
+ expect :LSQ
1559
+ rt3 = expect_reg
1560
+ if at(:COMMA)
1561
+ comma
1562
+ rt3 = [rt3, expect(:NUMBER)]
1563
+ else
1564
+ rt3 = [rt3]
1565
+ end
1566
+ expect :RSQ
1567
+
1568
+ imm = if at(:COMMA)
1569
+ comma
1570
+ expect(:NUMBER)
1571
+ else
1572
+ if at(:BANG)
1573
+ expect :BANG
1574
+ :!
1575
+ else
1576
+ nil
1577
+ end
1578
+ end
117
1579
 
118
- def initialize d, n, m
119
- @d = d
120
- @n = n
121
- @m = m
1580
+ yield rt1, rt2, rt3, imm
1581
+
1582
+ false
1583
+ end
1584
+
1585
+ def dmb_body nm
1586
+ if at(:NUMBER)
1587
+ nm.new(next_token)
1588
+ else
1589
+ nm.new(Utils.dmb2imm(next_token))
122
1590
  end
1591
+ end
1592
+
1593
+ def cmn_body nm
1594
+ rn = next_token
1595
+ comma
1596
+ if at(:NUMBER)
1597
+ imm = next_token
1598
+ shift = 0
1599
+
1600
+ if at(:COMMA)
1601
+ comma
1602
+ expect :LSL
1603
+ shift = expect(:NUMBER)
1604
+ end
1605
+
1606
+ nm::ADDSUB_imm.new(rn.zr, rn, imm, shift / 12, rn.zr.sf)
1607
+ else
1608
+ rm = expect_reg
1609
+
1610
+ if rm.x? != rn.x? || rn.sp?
1611
+ # extended
1612
+ amount = 0
1613
+ ext = rn.x? ? :uxtx : :uxtw
1614
+
1615
+ if at(:COMMA)
1616
+ comma
123
1617
 
124
- def apply asm, name
125
- asm.public_send(name, d, n, m)
1618
+ if at_extend
1619
+ ext = self.extend
1620
+ if at(:NUMBER)
1621
+ amount = next_token
1622
+ end
1623
+ else
1624
+ shift = expect_any([:LSL, :LSR, :ASR]).to_sym
1625
+ amount = 0
1626
+
1627
+ if at(:NUMBER)
1628
+ amount = next_token
1629
+ end
1630
+ end
1631
+ end
1632
+
1633
+ extend = Utils.sub_decode_extend32(ext)
1634
+ nm::ADDSUB_ext.new(rn.zr, rn, rm, extend, amount, rn.zr.sf)
1635
+ else
1636
+ # shifted
1637
+ shift = :lsl
1638
+ amount = 0
1639
+
1640
+ if at(:COMMA)
1641
+ comma
1642
+ if at_extend
1643
+ ext = self.extend
1644
+
1645
+ if at(:NUMBER)
1646
+ amount = next_token
1647
+ end
1648
+
1649
+ extend = Utils.sub_decode_extend32(ext)
1650
+ return nm::ADDSUB_ext.new(rn.zr, rn, rm, extend, amount, rn.zr.sf)
1651
+ else
1652
+ shift = expect_any([:LSL, :LSR, :ASR]).to_sym
1653
+
1654
+ if at(:NUMBER)
1655
+ amount = next_token
1656
+ end
1657
+ end
1658
+ end
1659
+
1660
+ shift = [:lsl, :lsr, :asr].index(shift)
1661
+ nm::ADDSUB_shift.new(rn.zr, rn, rm, shift, amount, rn.zr.sf)
1662
+ end
126
1663
  end
1664
+ end
1665
+
1666
+ def reg
1667
+ d = expect_reg
1668
+ yield d
1669
+ end
1670
+
1671
+ def reg_reg
1672
+ d = next_token
1673
+ comma
1674
+ n = srt d
1675
+ yield d, n
1676
+ false
1677
+ end
1678
+
1679
+ def reg_reg_reg
1680
+ reg { |d|
1681
+ comma
1682
+ reg { |n|
1683
+ comma
1684
+ reg { |m| yield d, n, m }
1685
+ }
1686
+ }
1687
+ end
127
1688
 
128
- def to_a; [d, n, m]; end
1689
+ def cond_two
1690
+ d = next_token
1691
+ comma
1692
+ yield d, cond
1693
+ false
129
1694
  end
130
1695
 
131
- class ThreeWithExtend
132
- attr_reader :d, :n, :m, :extend, :amount
1696
+ def cond_three
1697
+ d = next_token
1698
+ comma
1699
+ n = d.x? ? expect_x : expect_w
1700
+ comma
1701
+ yield d, n, cond
1702
+ false
1703
+ end
133
1704
 
134
- def initialize d, n, m, extend:, amount:
135
- @d = d
136
- @n = n
137
- @m = m
138
- @extend = extend
139
- @amount = amount
1705
+ def cond_four
1706
+ d = next_token
1707
+ comma
1708
+ n = if at(:NUMBER)
1709
+ next_token
1710
+ else
1711
+ srt d
1712
+ end
1713
+ comma
1714
+ m = if at(:NUMBER)
1715
+ next_token
1716
+ else
1717
+ srt d
140
1718
  end
1719
+ comma
1720
+ yield d, n, m, cond
1721
+ false
1722
+ end
1723
+
1724
+ def cond
1725
+ expect_any([:EQ, :LO, :LT, :HS, :GT, :LE, :NE, :MI, :GE, :PL, :LS,
1726
+ :HI, :VC, :VS]).to_sym
1727
+ end
141
1728
 
142
- def apply asm, name
143
- asm.public_send(name, d, n, m, extend: extend, amount: amount)
1729
+ def reg_imm_or_label
1730
+ rt = next_token
1731
+ comma
1732
+ where = if at(:NUMBER)
1733
+ next_token
1734
+ else
1735
+ get_label next_token
144
1736
  end
1737
+ yield rt, where
1738
+ false
145
1739
  end
146
1740
 
147
- class FourArg < ClassGen.pos(:a, :b, :c, :d)
148
- def apply asm, name
149
- asm.public_send(name, a, b, c, d)
1741
+ def shifted nm
1742
+ d = next_token
1743
+ comma
1744
+ n = d.x? ? expect_x : expect_w
1745
+ comma
1746
+ m = d.x? ? expect_x : expect_w
1747
+
1748
+ shift = :lsl
1749
+ amount = 0
1750
+
1751
+ if at(:COMMA)
1752
+ comma
1753
+ shift = expect_any([:LSL, :LSR, :ASR, :ROR]).to_sym
1754
+ amount = expect :NUMBER
150
1755
  end
1756
+
1757
+ shift = [:lsl, :lsr, :asr, :ror].index(shift)
1758
+ nm.new(d, n, m, shift, amount, d.sf)
151
1759
  end
152
1760
 
153
- def parse str
154
- str += "\n" unless str.end_with?("\n")
155
- parse_states = [
156
- # First pass: Label parsing
157
- :first_pass,
158
- # Second pass: Code generation
159
- :second_pass
160
- ]
161
- @labels = {}
162
- parse_states.each do |state|
163
- @scan = StringScanner.new str
164
- @asm = AArch64::Assembler.new
165
- @state = state
166
- do_parse
1761
+ def bfi_body
1762
+ d = next_token
1763
+ comma
1764
+ n = d.x? ? expect_x : expect_w
1765
+ comma
1766
+ lsb = expect(:NUMBER)
1767
+ comma
1768
+ width = expect(:NUMBER)
1769
+ yield d, n, lsb, width
1770
+ end
1771
+
1772
+ def and_body nm
1773
+ d = next_token
1774
+ expect(:COMMA)
1775
+ n = d.x? ? expect_x : expect_w
1776
+ expect(:COMMA)
1777
+
1778
+ if at(:NUMBER)
1779
+ m = next_token
1780
+ enc = Utils.encode_mask(m, d.size) || raise("Can't encode mask #{m}")
1781
+ nm::LOG_imm.new(d, n, enc.immr, enc.imms, enc.n, d.sf)
1782
+ else
1783
+ m = d.x? ? expect_x : expect_w
1784
+ shift = :lsl
1785
+ amount = 0
1786
+
1787
+ if at(:COMMA)
1788
+ expect(:COMMA)
1789
+ shift = next_token.to_sym
1790
+ if at(:NUMBER)
1791
+ amount = next_token
1792
+ end
1793
+ end
1794
+ shift = [:lsl, :lsr, :asr, :ror].index(shift) || raise(NotImplementedError)
1795
+ nm::LOG_shift.new(d, n, m, shift, amount, d.sf)
167
1796
  end
1797
+ end
168
1798
 
169
- @asm
1799
+ def adr_body nm
1800
+ reg = next_token
1801
+ expect(:COMMA)
1802
+ label = if at(:NUMBER)
1803
+ Assembler::Immediate.new(next_token)
1804
+ else
1805
+ label_name = next_token
1806
+ @labels[label_name] ||= @asm.make_label(label_name)
1807
+ end
1808
+ nm.new(reg, label)
170
1809
  end
171
1810
 
172
- def next_token
173
- _next_token
174
- end
175
-
176
- SYS_REG_SCAN = Regexp.new(AArch64::SystemRegisters.constants.join("|"), true)
177
- SYS_REG_MAP = Hash[AArch64::SystemRegisters.constants.map { |k|
178
- [k.to_s.downcase, AArch64::SystemRegisters.const_get(k)]
179
- }]
180
- # Created with: puts File.read('./lib/aarch64/parser.y').scan(/\b[A-Z][A-Z\d]+\b/).sort.uniq - ['LABEL', 'LABEL_CREATE']
181
- KEYWORDS = %w[
182
- ADC
183
- ADCS
184
- ADD
185
- ADDS
186
- ADR
187
- ADRP
188
- ALLE1
189
- ALLE1IS
190
- ALLE1OS
191
- ALLE2
192
- ALLE2IS
193
- ALLE2OS
194
- ALLE3
195
- ALLE3IS
196
- ALLE3OS
197
- AND
198
- ANDS
199
- ASIDE1
200
- ASIDE1IS
201
- ASIDE1OS
202
- ASR
203
- AT
204
- AUTDA
205
- B
206
- BANG
207
- BFI
208
- BFXIL
209
- BIC
210
- BICS
211
- BL
212
- BLR
213
- BR
214
- BRK
215
- CBNZ
216
- CBZ
217
- CCMN
218
- CCMP
219
- CGDSW
220
- CGDVAC
221
- CGDVADP
222
- CGDVAP
223
- CGSW
224
- CGVAC
225
- CGVADP
226
- CGVAP
227
- CIGDSW
228
- CIGDVAC
229
- CIGSW
230
- CIGVAC
231
- CINC
232
- CINV
233
- CISW
234
- CIVAC
235
- CLREX
236
- CLS
237
- CLZ
238
- CMN
239
- CMP
240
- CNEG
241
- COMMA
242
- CRC32B
243
- CRC32CB
244
- CRC32CH
245
- CRC32CW
246
- CRC32CX
247
- CRC32H
248
- CRC32W
249
- CRC32X
250
- CSEL
251
- CSET
252
- CSETM
253
- CSINC
254
- CSINV
255
- CSNEG
256
- CSW
257
- CVAC
258
- CVADP
259
- CVAP
260
- CVAU
261
- DC
262
- DCPS1
263
- DCPS2
264
- DCPS3
265
- DMB
266
- DOT
267
- DRPS
268
- DSB
269
- EOL
270
- EON
271
- EOR
272
- EQ
273
- ERET
274
- EXTR
275
- GE
276
- GT
277
- GVA
278
- GZVA
279
- HI
280
- HINT
281
- HLT
282
- HS
283
- HVC
284
- IALLU
285
- IALLUIS
286
- IC
287
- IGDSW
288
- IGDVAC
289
- IGSW
290
- IGVAC
291
- IPAS2E1
292
- IPAS2E1IS
293
- IPAS2E1OS
294
- IPAS2LE1
295
- IPAS2LE1IS
296
- IPAS2LE1OS
297
- ISB
298
- ISH
299
- ISHLD
300
- ISHST
301
- ISW
302
- IVAC
303
- IVAU
304
- LD
305
- LDAR
306
- LDARB
307
- LDARH
308
- LDAXP
309
- LDAXR
310
- LDAXRB
311
- LDAXRH
312
- LDNP
313
- LDP
314
- LDPSW
315
- LDR
316
- LDRB
317
- LDRH
318
- LDRSB
319
- LDRSH
320
- LDRSW
321
- LDTR
322
- LDTRB
323
- LDTRH
324
- LDTRSB
325
- LDTRSH
326
- LDTRSW
327
- LDUR
328
- LDURB
329
- LDURH
330
- LDURSB
331
- LDURSH
332
- LDURSW
333
- LDXP
334
- LDXR
335
- LDXRB
336
- LDXRH
337
- LE
338
- LO
339
- LS
340
- LSL
341
- LSQ
342
- LSR
343
- LT
344
- MADD
345
- MI
346
- MNEG
347
- MOV
348
- MOVK
349
- MOVN
350
- MOVZ
351
- MRS
352
- MSR
353
- MSUB
354
- MUL
355
- MVN
356
- NE
357
- NEG
358
- NEGS
359
- NGC
360
- NGCS
361
- NOP
362
- NSH
363
- NSHLD
364
- NSHST
365
- NUMBER
366
- ORN
367
- ORR
368
- OSH
369
- OSHLD
370
- OSHST
371
- PL
372
- PRFM
373
- PRFOP
374
- PRFUM
375
- PSSBB
376
- RBIT
377
- RET
378
- REV
379
- REV16
380
- REV32
381
- RIPAS2E1
382
- RIPAS2E1IS
383
- RIPAS2E1OS
384
- RIPAS2LE1
385
- RIPAS2LE1IS
386
- RIPAS2LE1OS
387
- ROR
388
- RSQ
389
- RVAAE1
390
- RVAAE1IS
391
- RVAAE1OS
392
- RVAALE1
393
- RVAALE1IS
394
- RVAALE1OS
395
- RVAE1
396
- RVAE1IS
397
- RVAE1OS
398
- RVAE2
399
- RVAE2IS
400
- RVAE2OS
401
- RVAE3
402
- RVAE3IS
403
- RVAE3OS
404
- RVALE1
405
- RVALE1IS
406
- RVALE1OS
407
- RVALE2
408
- RVALE2IS
409
- RVALE2OS
410
- RVALE3
411
- RVALE3IS
412
- RVALE3OS
413
- S12E0R
414
- S12E0W
415
- S12E1R
416
- S12E1W
417
- S1E0R
418
- S1E0W
419
- S1E1R
420
- S1E1RP
421
- S1E1W
422
- S1E1WP
423
- S1E2R
424
- S1E2W
425
- S1E3R
426
- S1E3W
427
- SBC
428
- SBCS
429
- SBFIZ
430
- SBFX
431
- SDIV
432
- SEV
433
- SEVL
434
- SMADDL
435
- SMC
436
- SMNEGL
437
- SMSUBL
438
- SMULH
439
- SMULL
440
- SP
441
- SSBB
442
- ST
443
- STLR
444
- STLRB
445
- STLRH
446
- STLXP
447
- STLXR
448
- STLXRB
449
- STLXRH
450
- STNP
451
- STP
452
- STR
453
- STRB
454
- STRH
455
- STTR
456
- STTRB
457
- STTRH
458
- STUR
459
- STURB
460
- STURH
461
- STXP
462
- STXR
463
- STXRB
464
- STXRH
465
- SUB
466
- SUBS
467
- SVC
468
- SXTB
469
- SXTH
470
- SXTW
471
- SXTX
472
- SY
473
- SYS
474
- SYSL
475
- SYSTEMREG
476
- TBNZ
477
- TBZ
478
- TLBI
479
- TST
480
- UBFIZ
481
- UBFX
482
- UDIV
483
- UMADDL
484
- UMNEGL
485
- UMSUBL
486
- UMULH
487
- UMULL
488
- UXTB
489
- UXTH
490
- UXTW
491
- UXTX
492
- VAAE1
493
- VAAE1IS
494
- VAAE1OS
495
- VAALE1
496
- VAALE1IS
497
- VAALE1OS
498
- VAE1
499
- VAE1IS
500
- VAE1OS
501
- VAE2
502
- VAE2IS
503
- VAE2OS
504
- VAE3
505
- VAE3IS
506
- VAE3OS
507
- VALE1
508
- VALE1IS
509
- VALE1OS
510
- VALE2
511
- VALE2IS
512
- VALE2OS
513
- VALE3
514
- VALE3IS
515
- VALE3OS
516
- VC
517
- VMALLE1
518
- VMALLE1IS
519
- VMALLE1OS
520
- VMALLS12E1
521
- VMALLS12E1IS
522
- VMALLS12E1OS
523
- VS
524
- WFE
525
- WFI
526
- WSP
527
- XZR
528
- YIELD
529
- ZVA
530
- ].freeze
531
- KEYWORDS_SCAN = /(#{Regexp.union(KEYWORDS.sort).source})\b/i
532
- LABEL_SCAN = /[a-zA-Z_]\w+/
533
- LABEL_CREATE_SCAN = /#{LABEL_SCAN}:/
534
-
535
- def register_label str
536
- return unless @state == :first_pass
537
-
538
- if @labels.include?(str)
539
- raise "symbol '#{str}' is already defined"
540
- end
541
-
542
- label = @asm.make_label(str)
543
- @asm.put_label(label)
544
- @labels[str] = label
545
-
546
- nil
547
- end
548
-
549
- def label_for str
550
- # In the first pass, all valid labels are not known yet i.e. forward references
551
- # Return a placeholder value instead.
552
- if @state == :first_pass
553
- @asm.make_label(str)
554
- else
555
- raise("Label #{str.inspect} not defined") unless @labels.key?(str)
556
- @labels[str]
557
- end
558
- end
559
-
560
- def _next_token
561
- return _next_token if @scan.scan(/[\t ]+/) # skip whitespace
562
- return if @scan.eos?
563
-
564
- if str = @scan.scan(/\n/)
565
- return [:EOL, :EOL]
566
- elsif str = @scan.scan(LABEL_CREATE_SCAN)
567
- [:LABEL_CREATE, str[0...-1]]
568
- elsif str = @scan.scan(/x\d+/i)
569
- [:Xd, AArch64::Registers.const_get(str.upcase)]
570
- elsif str = @scan.scan(/w\d+/i)
571
- [:Wd, AArch64::Registers.const_get(str.upcase)]
572
- elsif str = @scan.scan(/c\d+/i)
573
- [:Cd, AArch64::Names.const_get(str.upcase)]
574
- elsif str = @scan.scan(/sp/i)
575
- [:SP, AArch64::Registers.const_get(str.upcase)]
576
- elsif str = @scan.scan(/xzr/i)
577
- [:Xd, AArch64::Registers.const_get(str.upcase)]
578
- elsif str = @scan.scan(/wzr/i)
579
- [:Wd, AArch64::Registers.const_get(str.upcase)]
580
- elsif str = @scan.scan(/wsp/i)
581
- [:WSP, AArch64::Registers.const_get(str.upcase)]
582
- elsif @scan.scan(/,/)
583
- [:COMMA, ","]
584
- elsif @scan.scan(/\./)
585
- [:DOT, "."]
586
- elsif @scan.scan(/\[/)
587
- [:LSQ, "["]
588
- elsif @scan.scan(/\]/)
589
- [:RSQ, "]"]
590
- elsif @scan.scan(/!/)
591
- [:BANG, "!"]
592
- elsif str = @scan.scan(/(?:pld|pli|pst)(?:l1|l2|l3)(?:keep|strm)/)
593
- [:PRFOP, str]
594
- elsif str = @scan.scan(/-?0x[0-9A-F]+/i)
595
- [:NUMBER, Integer(str)]
596
- elsif str = @scan.scan(/-?(?:0|[1-9][0-9]*)/i)
597
- [:NUMBER, Integer(str)]
598
- elsif str = @scan.scan(/LSL/i)
599
- [:LSL, str]
600
- elsif str = @scan.scan(/#/)
601
- ["#", "#"]
602
- elsif str = @scan.scan(/s\d_\d_c\d+_c\d+_\d/i)
603
- if str =~ /s(\d)_(\d)_(c\d+)_(c\d+)_(\d)/i
604
- [:SYSTEMREG, SystemRegisters::MRS_MSR_64.new($1.to_i,
605
- $2.to_i,
606
- Names.const_get($3.upcase),
607
- Names.const_get($4.upcase),
608
- $5.to_i)]
1811
+ def add_body nm
1812
+ d = next_token
1813
+ expect(:COMMA)
1814
+ n = next_token
1815
+ expect(:COMMA)
1816
+ if at(:NUMBER)
1817
+ m = next_token
1818
+ if at(:COMMA)
1819
+ expect(:COMMA)
1820
+ expect(:LSL)
1821
+ lsl = expect(:NUMBER)
1822
+ nm::ADDSUB_imm.new(d, n, m, lsl / 12, d.sf)
1823
+ else
1824
+ nm::ADDSUB_imm.new(d, n, m, 0, d.sf)
1825
+ end
1826
+ else
1827
+ m = next_token
1828
+ if at(:COMMA)
1829
+ expect(:COMMA)
1830
+ amount = 0
1831
+
1832
+ if d.sp? || n.sp? || m.sp?
1833
+ modifier = next_token.to_sym
1834
+ if at(:NUMBER)
1835
+ amount = next_token
1836
+ end
1837
+ extend = m.x? ? Utils.sub_decode_extend64(modifier) : Utils.sub_decode_extend32(modifier)
1838
+ nm::ADDSUB_ext.new(d, n, m, extend, amount, d.sf)
1839
+ else
1840
+ modifier = next_token.to_sym
1841
+
1842
+ case modifier
1843
+ when :uxtb, :uxth, :uxtw, :uxtx, :sxtb, :sxth, :sxtw, :sxtx
1844
+ # extend
1845
+ if at(:NUMBER)
1846
+ amount = next_token
1847
+ end
1848
+ extend = Utils.sub_decode_extend32(modifier)
1849
+ nm::ADDSUB_ext.new(d, n, m, extend, amount, d.sf)
1850
+ when :lsl, :lsr, :asr
1851
+ shift = [:lsl, :lsr, :asr].index(modifier)
1852
+
1853
+ amount = 0
1854
+ # shift
1855
+ if at(:NUMBER)
1856
+ amount = next_token
1857
+ end
1858
+ nm::ADDSUB_shift.new(d, n, m, shift, amount, d.sf)
1859
+ end
1860
+ end
609
1861
  else
610
- raise
1862
+ if d.sp? || n.sp? || m.sp?
1863
+ extend = m.x? ? Utils.sub_decode_extend64(:uxtx) : Utils.sub_decode_extend32(:uxtw)
1864
+ nm::ADDSUB_ext.new(d, n, m, extend, 0, d.sf)
1865
+ else
1866
+ nm::ADDSUB_shift.new(d, n, m, 0, 0, d.sf)
1867
+ end
611
1868
  end
612
- elsif str = @scan.scan(SYS_REG_SCAN)
613
- [:SYSTEMREG, SYS_REG_MAP[str.downcase]]
614
- elsif str = @scan.scan(KEYWORDS_SCAN)
615
- [str.upcase.to_sym, str]
616
- elsif str = @scan.scan(LABEL_SCAN)
617
- [:LABEL, str]
1869
+ end
1870
+ end
1871
+
1872
+ def wd_wd_wd nm = nil
1873
+ w1 = expect_w
1874
+ expect(:COMMA)
1875
+ w2 = expect_w
1876
+ expect(:COMMA)
1877
+ w3 = expect_w
1878
+ if block_given?
1879
+ yield w1, w2, w3
1880
+ false
618
1881
  else
619
- [:UNKNOWN_CHAR, @scan.getch]
1882
+ nm.new(w1, w2, w3, w1.sf)
1883
+ end
1884
+ end
1885
+
1886
+ def xd_xd_xd nm
1887
+ x1 = expect_x
1888
+ expect(:COMMA)
1889
+ x2 = expect_x
1890
+ expect(:COMMA)
1891
+ x3 = expect_x
1892
+ nm.new(x1, x2, x3, x1.sf)
1893
+ end
1894
+
1895
+ def expect tok
1896
+ unless @scan.peek&.first == tok
1897
+ string = @scan.string
1898
+ line_number = string.byteslice(0, @scan.pos).count("\n") + 1
1899
+ val = @scan.peek&.last
1900
+ name = @scan.peek&.first
1901
+ raise AArch64::ParseError, "parse error on value #{val.inspect} (#{name}) on line #{line_number} at pos #{@scan.pos}/#{string.bytesize}"
620
1902
  end
1903
+ next_token
1904
+ end
1905
+
1906
+ def expect_any toks
1907
+ tok = @scan.peek.first
1908
+ unless toks.include?(tok)
1909
+ p @scan.peek
1910
+ raise
1911
+ end
1912
+ next_token
1913
+ end
1914
+
1915
+ def at_any toks
1916
+ tok = @scan.peek.first
1917
+ toks.include?(tok)
1918
+ end
1919
+
1920
+ def expect_w
1921
+ raise if @scan.peek.last.x?
1922
+ next_token
1923
+ end
1924
+
1925
+ def expect_x
1926
+ raise unless @scan.peek.last.x?
1927
+ next_token
1928
+ end
1929
+
1930
+ def expect_reg
1931
+ raise unless @scan.peek.last.register?
1932
+ next_token
1933
+ end
1934
+
1935
+ def at tok
1936
+ @scan.peek.first == tok
1937
+ end
1938
+
1939
+ def next_token
1940
+ @scan.next_token.last
1941
+ end
1942
+
1943
+ def get_label name
1944
+ @labels[name] ||= @asm.make_label(name)
1945
+ end
1946
+
1947
+ # "same reg type"
1948
+ def srt n
1949
+ n.x? ? expect_x : expect_w
1950
+ end
1951
+
1952
+ def comma
1953
+ expect :COMMA
1954
+ end
1955
+
1956
+ def extend
1957
+ expect_any([:UXTB, :UXTH, :UXTW, :UXTX, :SXTB, :SXTH, :SXTW, :SXTX]).to_sym
621
1958
  end
622
1959
 
623
- def on_error(token_id, val, vstack)
624
- token_str = token_to_str(token_id) || '?'
625
- string = @scan.string
626
- line_number = string.byteslice(0, @scan.pos).count("\n") + 1
627
- raise ParseError, "parse error on value #{val.inspect} (#{token_str}) on line #{line_number} at pos #{@scan.pos}/#{string.bytesize}"
1960
+ def at_extend
1961
+ at_any([:UXTB, :UXTH, :UXTW, :UXTX, :SXTB, :SXTH, :SXTW, :SXTX])
628
1962
  end
629
1963
  end
630
1964
  end