1import random
2
3AARCH64_AS = "<PATH-TO-AS>"
4AARCH64_OBJDUMP = "<PATH-TO-OBJDUMP>"
5AARCH64_OBJCOPY = "<PATH-TO-OBJCOPY>"
6
7class Operand(object):
8
9     def generate(self):
10        return self
11
12class Register(Operand):
13
14    def generate(self):
15        self.number = random.randint(0, 30)
16        return self
17
18    def astr(self, prefix):
19        return prefix + str(self.number)
20
21class FloatRegister(Register):
22
23    def __str__(self):
24        return self.astr("v")
25
26    def nextReg(self):
27        next = FloatRegister()
28        next.number = (self.number + 1) % 32
29        return next
30
31class GeneralRegister(Register):
32
33    def __str__(self):
34        return self.astr("r")
35
36class GeneralRegisterOrZr(Register):
37
38    def generate(self):
39        self.number = random.randint(0, 31)
40        return self
41
42    def astr(self, prefix = ""):
43        if (self.number == 31):
44            return prefix + "zr"
45        else:
46            return prefix + str(self.number)
47
48    def __str__(self):
49        if (self.number == 31):
50            return self.astr()
51        else:
52            return self.astr("r")
53
54class GeneralRegisterOrSp(Register):
55    def generate(self):
56        self.number = random.randint(0, 31)
57        return self
58
59    def astr(self, prefix = ""):
60        if (self.number == 31):
61            return "sp"
62        else:
63            return prefix + str(self.number)
64
65    def __str__(self):
66        if (self.number == 31):
67            return self.astr()
68        else:
69            return self.astr("r")
70
71class FloatZero(Operand):
72
73    def __str__(self):
74        return "0.0"
75
76    def astr(self, ignored):
77        return "#0.0"
78
79class OperandFactory:
80
81    _modes = {'x' : GeneralRegister,
82              'w' : GeneralRegister,
83              's' : FloatRegister,
84              'd' : FloatRegister,
85              'z' : FloatZero}
86
87    @classmethod
88    def create(cls, mode):
89        return OperandFactory._modes[mode]()
90
91class ShiftKind:
92
93    def generate(self):
94        self.kind = ["LSL", "LSR", "ASR"][random.randint(0,2)]
95        return self
96
97    def cstr(self):
98        return self.kind
99
100class Instruction(object):
101
102    def __init__(self, name):
103        self._name = name
104        self.isWord = name.endswith("w") | name.endswith("wi")
105        self.asmRegPrefix = ["x", "w"][self.isWord]
106
107    def aname(self):
108        if (self._name.endswith("wi")):
109            return self._name[:len(self._name)-2]
110        else:
111            if (self._name.endswith("i") | self._name.endswith("w")):
112                return self._name[:len(self._name)-1]
113            else:
114                return self._name
115
116    def emit(self) :
117        pass
118
119    def compare(self) :
120        pass
121
122    def generate(self) :
123        return self
124
125    def cstr(self):
126        return '__ %s(' % self.name()
127
128    def astr(self):
129        return '%s\t' % self.aname()
130
131    def name(self):
132        name = self._name
133        if name == "and":
134            name = "andr" # Special case: the name "and" can't be used
135                          # in HotSpot, even for a member.
136        return name
137
138    def multipleForms(self):
139         return 0
140
141class InstructionWithModes(Instruction):
142
143    def __init__(self, name, mode):
144        Instruction.__init__(self, name)
145        self.mode = mode
146        self.isFloat = (mode == 'd') | (mode == 's')
147        if self.isFloat:
148            self.isWord = mode != 'd'
149            self.asmRegPrefix = ["d", "s"][self.isWord]
150        else:
151            self.isWord = mode != 'x'
152            self.asmRegPrefix = ["x", "w"][self.isWord]
153
154    def name(self):
155        return self._name + (self.mode if self.mode != 'x' else '')
156
157    def aname(self):
158        return (self._name+mode if (mode == 'b' or mode == 'h')
159            else self._name)
160
161class ThreeRegInstruction(Instruction):
162
163    def generate(self):
164        self.reg = [GeneralRegister().generate(), GeneralRegister().generate(),
165                    GeneralRegister().generate()]
166        return self
167
168
169    def cstr(self):
170        return (super(ThreeRegInstruction, self).cstr()
171                + ('%s, %s, %s'
172                   % (self.reg[0],
173                      self.reg[1], self.reg[2])))
174
175    def astr(self):
176        prefix = self.asmRegPrefix
177        return (super(ThreeRegInstruction, self).astr()
178                + ('%s, %s, %s'
179                   % (self.reg[0].astr(prefix),
180                      self.reg[1].astr(prefix), self.reg[2].astr(prefix))))
181
182class FourRegInstruction(ThreeRegInstruction):
183
184    def generate(self):
185        self.reg = ThreeRegInstruction.generate(self).reg + [GeneralRegister().generate()]
186        return self
187
188
189    def cstr(self):
190        return (super(FourRegInstruction, self).cstr()
191                + (', %s' % self.reg[3]))
192
193    def astr(self):
194        prefix = self.asmRegPrefix
195        return (super(FourRegInstruction, self).astr()
196                + (', %s' % self.reg[3].astr(prefix)))
197
198class TwoRegInstruction(Instruction):
199
200    def generate(self):
201        self.reg = [GeneralRegister().generate(), GeneralRegister().generate()]
202        return self
203
204    def cstr(self):
205        return (super(TwoRegInstruction, self).cstr()
206                + '%s, %s' % (self.reg[0],
207                              self.reg[1]))
208
209    def astr(self):
210        prefix = self.asmRegPrefix
211        return (super(TwoRegInstruction, self).astr()
212                + ('%s, %s'
213                   % (self.reg[0].astr(prefix),
214                      self.reg[1].astr(prefix))))
215
216class TwoRegImmedInstruction(TwoRegInstruction):
217
218    def generate(self):
219        super(TwoRegImmedInstruction, self).generate()
220        self.immed = random.randint(0, 1<<11 -1)
221        return self
222
223    def cstr(self):
224        return (super(TwoRegImmedInstruction, self).cstr()
225                + ', %su' % self.immed)
226
227    def astr(self):
228        return (super(TwoRegImmedInstruction, self).astr()
229                + ', #%s' % self.immed)
230
231class OneRegOp(Instruction):
232
233    def generate(self):
234        self.reg = GeneralRegister().generate()
235        return self
236
237    def cstr(self):
238        return (super(OneRegOp, self).cstr()
239                + '%s);' % self.reg)
240
241    def astr(self):
242        return (super(OneRegOp, self).astr()
243                + '%s' % self.reg.astr(self.asmRegPrefix))
244
245class ArithOp(ThreeRegInstruction):
246
247    def generate(self):
248        super(ArithOp, self).generate()
249        self.kind = ShiftKind().generate()
250        self.distance = random.randint(0, (1<<5)-1 if self.isWord else (1<<6)-1)
251        return self
252
253    def cstr(self):
254        return ('%s, Assembler::%s, %s);'
255                % (ThreeRegInstruction.cstr(self),
256                   self.kind.cstr(), self.distance))
257
258    def astr(self):
259        return ('%s, %s #%s'
260                % (ThreeRegInstruction.astr(self),
261                   self.kind.cstr(),
262                   self.distance))
263
264class AddSubCarryOp(ThreeRegInstruction):
265
266    def cstr(self):
267        return ('%s);'
268                % (ThreeRegInstruction.cstr(self)))
269
270class AddSubExtendedOp(ThreeRegInstruction):
271
272    uxtb, uxth, uxtw, uxtx, sxtb, sxth, sxtw, sxtx = range(8)
273    optNames = ["uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"]
274
275    def generate(self):
276        super(AddSubExtendedOp, self).generate()
277        self.amount = random.randint(1, 4)
278        self.option = random.randint(0, 7)
279        return self
280
281    def cstr(self):
282        return (super(AddSubExtendedOp, self).cstr()
283                + (", ext::" + AddSubExtendedOp.optNames[self.option]
284                   + ", " + str(self.amount) + ");"))
285
286    def astr(self):
287        return (super(AddSubExtendedOp, self).astr()
288                + (", " + AddSubExtendedOp.optNames[self.option]
289                   + " #" + str(self.amount)))
290
291class AddSubImmOp(TwoRegImmedInstruction):
292
293    def cstr(self):
294         return super(AddSubImmOp, self).cstr() + ");"
295
296class LogicalImmOp(AddSubImmOp):
297
298     # These tables are legal immediate logical operands
299     immediates32 \
300         = [0x1, 0x3f, 0x1f0, 0x7e0,
301            0x1c00, 0x3ff0, 0x8000, 0x1e000,
302            0x3e000, 0x78000, 0xe0000, 0x100000,
303            0x1fffe0, 0x3fe000, 0x780000, 0x7ffff8,
304            0xff8000, 0x1800180, 0x1fffc00, 0x3c003c0,
305            0x3ffff00, 0x7c00000, 0x7fffe00, 0xf000f00,
306            0xfffe000, 0x18181818, 0x1ffc0000, 0x1ffffffe,
307            0x3f003f00, 0x3fffe000, 0x60006000, 0x7f807f80,
308            0x7ffffc00, 0x800001ff, 0x803fffff, 0x9f9f9f9f,
309            0xc0000fff, 0xc0c0c0c0, 0xe0000000, 0xe003e003,
310            0xe3ffffff, 0xf0000fff, 0xf0f0f0f0, 0xf80000ff,
311            0xf83ff83f, 0xfc00007f, 0xfc1fffff, 0xfe0001ff,
312            0xfe3fffff, 0xff003fff, 0xff800003, 0xff87ff87,
313            0xffc00fff, 0xffe0000f, 0xffefffef, 0xfff1fff1,
314            0xfff83fff, 0xfffc0fff, 0xfffe0fff, 0xffff3fff,
315            0xffffc007, 0xffffe1ff, 0xfffff80f, 0xfffffe07,
316            0xffffffbf, 0xfffffffd]
317
318     immediates \
319         = [0x1, 0x1f80, 0x3fff0, 0x3ffffc,
320            0x3fe0000, 0x1ffc0000, 0xf8000000, 0x3ffffc000,
321            0xffffffe00, 0x3ffffff800, 0xffffc00000, 0x3f000000000,
322            0x7fffffff800, 0x1fe000001fe0, 0x3ffffff80000, 0xc00000000000,
323            0x1ffc000000000, 0x3ffff0003ffff, 0x7ffffffe00000, 0xfffffffffc000,
324            0x1ffffffffffc00, 0x3fffffffffff00, 0x7ffffffffffc00, 0xffffffffff8000,
325            0x1ffffffff800000, 0x3fffffc03fffffc, 0x7fffc0000000000, 0xff80ff80ff80ff8,
326            0x1c00000000000000, 0x1fffffffffff0000, 0x3fffff803fffff80, 0x7fc000007fc00000,
327            0x8000000000000000, 0x803fffff803fffff, 0xc000007fc000007f, 0xe00000000000ffff,
328            0xe3ffffffffffffff, 0xf007f007f007f007, 0xf80003ffffffffff, 0xfc000003fc000003,
329            0xfe000000007fffff, 0xff00000000007fff, 0xff800000000003ff, 0xffc00000000000ff,
330            0xffe00000000003ff, 0xfff0000000003fff, 0xfff80000001fffff, 0xfffc0000fffc0000,
331            0xfffe003fffffffff, 0xffff3fffffffffff, 0xffffc0000007ffff, 0xffffe01fffffe01f,
332            0xfffff800000007ff, 0xfffffc0fffffffff, 0xffffff00003fffff, 0xffffffc0000007ff,
333            0xfffffff0000001ff, 0xfffffffc00003fff, 0xffffffff07ffffff, 0xffffffffe003ffff,
334            0xfffffffffc01ffff, 0xffffffffffc00003, 0xfffffffffffc000f, 0xffffffffffffe07f]
335
336     def generate(self):
337          AddSubImmOp.generate(self)
338          self.immed = \
339              self.immediates32[random.randint(0, len(self.immediates32)-1)] \
340              	if self.isWord \
341              else \
342              	self.immediates[random.randint(0, len(self.immediates)-1)]
343
344          return self
345
346     def astr(self):
347          return (super(TwoRegImmedInstruction, self).astr()
348                  + ', #0x%x' % self.immed)
349
350     def cstr(self):
351          return super(AddSubImmOp, self).cstr() + "l);"
352
353class MultiOp():
354
355    def multipleForms(self):
356         return 3
357
358    def forms(self):
359         return ["__ pc()", "back", "forth"]
360
361    def aforms(self):
362         return [".", "back", "forth"]
363
364class AbsOp(MultiOp, Instruction):
365
366    def cstr(self):
367        return super(AbsOp, self).cstr() + "%s);"
368
369    def astr(self):
370        return Instruction.astr(self) + "%s"
371
372class RegAndAbsOp(MultiOp, Instruction):
373
374    def multipleForms(self):
375        if self.name() == "adrp":
376            # We can only test one form of adrp because anything other
377            # than "adrp ." requires relocs in the assembler output
378            return 1
379        return 3
380
381    def generate(self):
382        Instruction.generate(self)
383        self.reg = GeneralRegister().generate()
384        return self
385
386    def cstr(self):
387        if self.name() == "adrp":
388            return "__ _adrp(" + "%s, %s);" % (self.reg, "%s")
389        return (super(RegAndAbsOp, self).cstr()
390                + "%s, %s);" % (self.reg, "%s"))
391
392    def astr(self):
393        return (super(RegAndAbsOp, self).astr()
394                + self.reg.astr(self.asmRegPrefix) + ", %s")
395
396class RegImmAbsOp(RegAndAbsOp):
397
398    def cstr(self):
399        return (Instruction.cstr(self)
400                + "%s, %s, %s);" % (self.reg, self.immed, "%s"))
401
402    def astr(self):
403        return (Instruction.astr(self)
404                + ("%s, #%s, %s"
405                   % (self.reg.astr(self.asmRegPrefix), self.immed, "%s")))
406
407    def generate(self):
408        super(RegImmAbsOp, self).generate()
409        self.immed = random.randint(0, 1<<5 -1)
410        return self
411
412class MoveWideImmOp(RegImmAbsOp):
413
414    def multipleForms(self):
415         return 0
416
417    def cstr(self):
418        return (Instruction.cstr(self)
419                + "%s, %s, %s);" % (self.reg, self.immed, self.shift))
420
421    def astr(self):
422        return (Instruction.astr(self)
423                + ("%s, #%s, lsl %s"
424                   % (self.reg.astr(self.asmRegPrefix),
425                      self.immed, self.shift)))
426
427    def generate(self):
428        super(RegImmAbsOp, self).generate()
429        self.immed = random.randint(0, 1<<16 -1)
430        if self.isWord:
431            self.shift = random.randint(0, 1) * 16
432        else:
433            self.shift = random.randint(0, 3) * 16
434        return self
435
436class BitfieldOp(TwoRegInstruction):
437
438    def cstr(self):
439        return (Instruction.cstr(self)
440                + ("%s, %s, %s, %s);"
441                   % (self.reg[0], self.reg[1], self.immr, self.imms)))
442
443    def astr(self):
444        return (TwoRegInstruction.astr(self)
445                + (", #%s, #%s"
446                   % (self.immr, self.imms)))
447
448    def generate(self):
449        TwoRegInstruction.generate(self)
450        self.immr = random.randint(0, 31)
451        self.imms = random.randint(0, 31)
452        return self
453
454class ExtractOp(ThreeRegInstruction):
455
456    def generate(self):
457        super(ExtractOp, self).generate()
458        self.lsb = random.randint(0, (1<<5)-1 if self.isWord else (1<<6)-1)
459        return self
460
461    def cstr(self):
462        return (ThreeRegInstruction.cstr(self)
463                + (", %s);" % self.lsb))
464
465    def astr(self):
466        return (ThreeRegInstruction.astr(self)
467                + (", #%s" % self.lsb))
468
469class CondBranchOp(MultiOp, Instruction):
470
471    def cstr(self):
472        return "__ br(Assembler::" + self.name() + ", %s);"
473
474    def astr(self):
475        return "b." + self.name() + "\t%s"
476
477class ImmOp(Instruction):
478
479    def cstr(self):
480        return "%s%s);" % (Instruction.cstr(self), self.immed)
481
482    def astr(self):
483        return Instruction.astr(self) + "#" + str(self.immed)
484
485    def generate(self):
486        self.immed = random.randint(0, 1<<16 -1)
487        return self
488
489class Op(Instruction):
490
491    def cstr(self):
492        return Instruction.cstr(self) + ");"
493
494class SystemOp(Instruction):
495
496     def __init__(self, op):
497          Instruction.__init__(self, op[0])
498          self.barriers = op[1]
499
500     def generate(self):
501          Instruction.generate(self)
502          self.barrier \
503              = self.barriers[random.randint(0, len(self.barriers)-1)]
504          return self
505
506     def cstr(self):
507          return Instruction.cstr(self) + "Assembler::" + self.barrier + ");"
508
509     def astr(self):
510          return Instruction.astr(self) + self.barrier
511
512conditionCodes = ["EQ", "NE", "HS", "CS", "LO", "CC", "MI", "PL", "VS", \
513                       "VC", "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV"]
514
515class ConditionalCompareOp(TwoRegImmedInstruction):
516
517    def generate(self):
518        TwoRegImmedInstruction.generate(self)
519        self.cond = random.randint(0, 15)
520        self.immed = random.randint(0, 15)
521        return self
522
523    def cstr(self):
524        return (super(ConditionalCompareOp, self).cstr() + ", "
525                + "Assembler::" + conditionCodes[self.cond] + ");")
526
527    def astr(self):
528        return (super(ConditionalCompareOp, self).astr() +
529                 ", " + conditionCodes[self.cond])
530
531class ConditionalCompareImmedOp(Instruction):
532
533    def generate(self):
534        self.reg = GeneralRegister().generate()
535        self.cond = random.randint(0, 15)
536        self.immed2 = random.randint(0, 15)
537        self.immed = random.randint(0, 31)
538        return self
539
540    def cstr(self):
541        return (Instruction.cstr(self) + str(self.reg) + ", "
542                + str(self.immed) + ", "
543                + str(self.immed2) + ", "
544                + "Assembler::" + conditionCodes[self.cond] + ");")
545
546    def astr(self):
547        return (Instruction.astr(self)
548                + self.reg.astr(self.asmRegPrefix)
549                + ", #" + str(self.immed)
550                + ", #" + str(self.immed2)
551                + ", " + conditionCodes[self.cond])
552
553class TwoRegOp(TwoRegInstruction):
554
555    def cstr(self):
556        return TwoRegInstruction.cstr(self) + ");"
557
558class ThreeRegOp(ThreeRegInstruction):
559
560    def cstr(self):
561        return ThreeRegInstruction.cstr(self) + ");"
562
563class FourRegMulOp(FourRegInstruction):
564
565    def cstr(self):
566        return FourRegInstruction.cstr(self) + ");"
567
568    def astr(self):
569        isMaddsub = self.name().startswith("madd") | self.name().startswith("msub")
570        midPrefix = self.asmRegPrefix if isMaddsub else "w"
571        return (Instruction.astr(self)
572                + self.reg[0].astr(self.asmRegPrefix)
573                + ", " + self.reg[1].astr(midPrefix)
574                + ", " + self.reg[2].astr(midPrefix)
575                + ", " + self.reg[3].astr(self.asmRegPrefix))
576
577class ConditionalSelectOp(ThreeRegInstruction):
578
579    def generate(self):
580        ThreeRegInstruction.generate(self)
581        self.cond = random.randint(0, 15)
582        return self
583
584    def cstr(self):
585        return (ThreeRegInstruction.cstr(self) + ", "
586                + "Assembler::" + conditionCodes[self.cond] + ");")
587
588    def astr(self):
589        return (ThreeRegInstruction.astr(self)
590                + ", " + conditionCodes[self.cond])
591
592class LoadStoreExclusiveOp(InstructionWithModes):
593
594    def __init__(self, op): # op is a tuple of ["name", "mode", registers]
595        InstructionWithModes.__init__(self, op[0], op[1])
596        self.num_registers = op[2]
597
598    def astr(self):
599        result = self.aname() + '\t'
600        regs = list(self.regs)
601        index = regs.pop() # The last reg is the index register
602        prefix = ('x' if (self.mode == 'x')
603                  & ((self.name().startswith("ld"))
604                     | (self.name().startswith("stlr"))) # Ewww :-(
605                  else 'w')
606        result = result + regs.pop(0).astr(prefix) + ", "
607        for s in regs:
608            result = result + s.astr(self.asmRegPrefix) + ", "
609        result = result + "[" + index.astr("x") + "]"
610        return result
611
612    def cstr(self):
613        result = InstructionWithModes.cstr(self)
614        regs = list(self.regs)
615        index = regs.pop() # The last reg is the index register
616        for s in regs:
617            result = result + str(s) + ", "
618        result = result + str(index) + ");"
619        return result
620
621    def appendUniqueReg(self):
622        result = 0
623        while result == 0:
624            newReg = GeneralRegister().generate()
625            result = 1
626            for i in self.regs:
627                result = result and (i.number != newReg.number)
628        self.regs.append(newReg)
629
630    def generate(self):
631        self.regs = []
632        for i in range(self.num_registers):
633            self.appendUniqueReg()
634        return self
635
636    def name(self):
637        if self.mode == 'x':
638            return self._name
639        else:
640            return self._name + self.mode
641
642    def aname(self):
643        if (self.mode == 'b') | (self.mode == 'h'):
644            return self._name + self.mode
645        else:
646            return self._name
647
648class Address(object):
649
650    base_plus_unscaled_offset, pre, post, base_plus_reg, \
651        base_plus_scaled_offset, pcrel, post_reg, base_only = range(8)
652    kinds = ["base_plus_unscaled_offset", "pre", "post", "base_plus_reg",
653             "base_plus_scaled_offset", "pcrel", "post_reg", "base_only"]
654    extend_kinds = ["uxtw", "lsl", "sxtw", "sxtx"]
655
656    @classmethod
657    def kindToStr(cls, i):
658         return cls.kinds[i]
659
660    def generate(self, kind, shift_distance):
661        self.kind = kind
662        self.base = GeneralRegister().generate()
663        self.index = GeneralRegister().generate()
664        self.offset = {
665            Address.base_plus_unscaled_offset: random.randint(-1<<8, 1<<8-1) | 1,
666            Address.pre: random.randint(-1<<8, 1<<8-1),
667            Address.post: random.randint(-1<<8, 1<<8-1),
668            Address.pcrel: random.randint(0, 2),
669            Address.base_plus_reg: 0,
670            Address.base_plus_scaled_offset: (random.randint(0, 1<<11-1) | (3 << 9))*8,
671            Address.post_reg: 0,
672            Address.base_only: 0} [kind]
673        self.offset >>= (3 - shift_distance)
674        self.extend_kind = Address.extend_kinds[random.randint(0, 3)]
675        self.shift_distance = random.randint(0, 1) * shift_distance
676        return self
677
678    def __str__(self):
679        result = {
680            Address.base_plus_unscaled_offset: "Address(%s, %s)" \
681                % (str(self.base), self.offset),
682            Address.pre: "Address(__ pre(%s, %s))" % (str(self.base), self.offset),
683            Address.post: "Address(__ post(%s, %s))" % (str(self.base), self.offset),
684            Address.post_reg: "Address(__ post(%s, %s))" % (str(self.base), self.index),
685            Address.base_only: "Address(%s)" % (str(self.base)),
686            Address.pcrel: "",
687            Address.base_plus_reg: "Address(%s, %s, Address::%s(%s))" \
688                % (self.base, self.index, self.extend_kind, self.shift_distance),
689            Address.base_plus_scaled_offset:
690            "Address(%s, %s)" % (self.base, self.offset) } [self.kind]
691        if (self.kind == Address.pcrel):
692            result = ["__ pc()", "back", "forth"][self.offset]
693        return result
694
695    def astr(self, prefix):
696        extend_prefix = prefix
697        if self.kind == Address.base_plus_reg:
698            if self.extend_kind.endswith("w"):
699                extend_prefix = "w"
700        result = {
701            Address.base_plus_unscaled_offset: "[%s, %s]" \
702                 % (self.base.astr(prefix), self.offset),
703            Address.pre: "[%s, %s]!" % (self.base.astr(prefix), self.offset),
704            Address.post: "[%s], %s" % (self.base.astr(prefix), self.offset),
705            Address.post_reg: "[%s], %s" % (self.base.astr(prefix), self.index.astr(prefix)),
706            Address.base_only: "[%s]" %  (self.base.astr(prefix)),
707            Address.pcrel: "",
708            Address.base_plus_reg: "[%s, %s, %s #%s]" \
709                % (self.base.astr(prefix), self.index.astr(extend_prefix),
710                   self.extend_kind, self.shift_distance),
711            Address.base_plus_scaled_offset: \
712                "[%s, %s]" \
713                % (self.base.astr(prefix), self.offset)
714            } [self.kind]
715        if (self.kind == Address.pcrel):
716            result = [".", "back", "forth"][self.offset]
717        return result
718
719class LoadStoreOp(InstructionWithModes):
720
721    def __init__(self, args):
722        name, self.asmname, self.kind, mode = args
723        InstructionWithModes.__init__(self, name, mode)
724
725    def generate(self):
726
727        # This is something of a kludge, but the offset needs to be
728        # scaled by the memory datamode somehow.
729        shift = 3
730        if (self.mode == 'b') | (self.asmname.endswith("b")):
731            shift = 0
732        elif (self.mode == 'h') | (self.asmname.endswith("h")):
733            shift = 1
734        elif (self.mode == 'w') | (self.asmname.endswith("w")) \
735                | (self.mode == 's') :
736            shift = 2
737
738        self.adr = Address().generate(self.kind, shift)
739
740        isFloat = (self.mode == 'd') | (self.mode == 's')
741
742        regMode = FloatRegister if isFloat else GeneralRegister
743        self.reg = regMode().generate()
744        return self
745
746    def cstr(self):
747        if not(self._name.startswith("prfm")):
748            return "%s%s, %s);" % (Instruction.cstr(self), str(self.reg), str(self.adr))
749        else: # No target register for a prefetch
750            return "%s%s);" % (Instruction.cstr(self), str(self.adr))
751
752    def astr(self):
753        if not(self._name.startswith("prfm")):
754            return "%s\t%s, %s" % (self.aname(), self.reg.astr(self.asmRegPrefix),
755                                     self.adr.astr("x"))
756        else: # No target register for a prefetch
757            return "%s %s" % (self.aname(),
758                                     self.adr.astr("x"))
759
760    def aname(self):
761         result = self.asmname
762         # if self.kind == Address.base_plus_unscaled_offset:
763         #      result = result.replace("ld", "ldu", 1)
764         #      result = result.replace("st", "stu", 1)
765         return result
766
767class LoadStorePairOp(InstructionWithModes):
768
769     numRegs = 2
770
771     def __init__(self, args):
772          name, self.asmname, self.kind, mode = args
773          InstructionWithModes.__init__(self, name, mode)
774          self.offset = random.randint(-1<<4, 1<<4-1) << 4
775
776     def generate(self):
777          self.reg = [OperandFactory.create(self.mode).generate()
778                      for i in range(self.numRegs)]
779          self.base = OperandFactory.create('x').generate()
780          return self
781
782     def astr(self):
783          address = ["[%s, #%s]", "[%s, #%s]!", "[%s], #%s"][self.kind]
784          address = address % (self.base.astr('x'), self.offset)
785          result = "%s\t%s, %s, %s" \
786              % (self.asmname,
787                 self.reg[0].astr(self.asmRegPrefix),
788                 self.reg[1].astr(self.asmRegPrefix), address)
789          return result
790
791     def cstr(self):
792          address = {
793               Address.base_plus_unscaled_offset: "Address(%s, %s)" \
794                    % (str(self.base), self.offset),
795               Address.pre: "Address(__ pre(%s, %s))" % (str(self.base), self.offset),
796               Address.post: "Address(__ post(%s, %s))" % (str(self.base), self.offset),
797               } [self.kind]
798          result = "__ %s(%s, %s, %s);" \
799              % (self.name(), self.reg[0], self.reg[1], address)
800          return result
801
802class FloatInstruction(Instruction):
803
804    def aname(self):
805        if (self._name.endswith("s") | self._name.endswith("d")):
806            return self._name[:len(self._name)-1]
807        else:
808            return self._name
809
810    def __init__(self, args):
811        name, self.modes = args
812        Instruction.__init__(self, name)
813
814    def generate(self):
815        self.reg = [OperandFactory.create(self.modes[i]).generate()
816                    for i in range(self.numRegs)]
817        return self
818
819    def cstr(self):
820        formatStr = "%s%s" + ''.join([", %s" for i in range(1, self.numRegs)] + [");"])
821        return (formatStr
822                % tuple([Instruction.cstr(self)] +
823                        [str(self.reg[i]) for i in range(self.numRegs)])) # Yowza
824
825    def astr(self):
826        formatStr = "%s%s" + ''.join([", %s" for i in range(1, self.numRegs)])
827        return (formatStr
828                % tuple([Instruction.astr(self)] +
829                        [(self.reg[i].astr(self.modes[i])) for i in range(self.numRegs)]))
830
831class LdStSIMDOp(Instruction):
832    def __init__(self, args):
833        self._name, self.regnum, self.arrangement, self.addresskind = args
834
835    def generate(self):
836        self.address = Address().generate(self.addresskind, 0)
837        self._firstSIMDreg = FloatRegister().generate()
838        if (self.addresskind  == Address.post):
839            if (self._name in ["ld1r", "ld2r", "ld3r", "ld4r"]):
840                elem_size = {"8B" : 1, "16B" : 1, "4H" : 2, "8H" : 2, "2S" : 4, "4S" : 4, "1D" : 8, "2D" : 8} [self.arrangement]
841                self.address.offset = self.regnum * elem_size
842            else:
843                if (self.arrangement in ["8B", "4H", "2S", "1D"]):
844                    self.address.offset = self.regnum * 8
845                else:
846                    self.address.offset = self.regnum * 16
847        return self
848
849    def cstr(self):
850        buf = super(LdStSIMDOp, self).cstr() + str(self._firstSIMDreg)
851        current = self._firstSIMDreg
852        for cnt in range(1, self.regnum):
853            buf = '%s, %s' % (buf, current.nextReg())
854            current = current.nextReg()
855        return '%s, __ T%s, %s);' % (buf, self.arrangement, str(self.address))
856
857    def astr(self):
858        buf = '%s\t{%s.%s' % (self._name, self._firstSIMDreg, self.arrangement)
859        current = self._firstSIMDreg
860        for cnt in range(1, self.regnum):
861            buf = '%s, %s.%s' % (buf, current.nextReg(), self.arrangement)
862            current = current.nextReg()
863        return  '%s}, %s' % (buf, self.address.astr("x"))
864
865    def aname(self):
866         return self._name
867
868class LSEOp(Instruction):
869    def __init__(self, args):
870        self._name, self.asmname, self.size, self.suffix = args
871
872    def generate(self):
873        self._name = "%s%s" % (self._name, self.suffix)
874        self.asmname = "%s%s" % (self.asmname, self.suffix)
875        self.srcReg = GeneralRegisterOrZr().generate()
876        self.tgtReg = GeneralRegisterOrZr().generate()
877        self.adrReg = GeneralRegisterOrSp().generate()
878
879        return self
880
881    def cstr(self):
882        sizeSpec = {"x" : "Assembler::xword", "w" : "Assembler::word"} [self.size]
883        return super(LSEOp, self).cstr() + "%s, %s, %s, %s);" % (sizeSpec, self.srcReg, self.tgtReg, self.adrReg)
884
885    def astr(self):
886        return "%s\t%s, %s, [%s]" % (self.asmname, self.srcReg.astr(self.size), self.tgtReg.astr(self.size), self.adrReg.astr("x"))
887
888    def aname(self):
889         return self.asmname
890
891class TwoRegFloatOp(FloatInstruction):
892    numRegs = 2
893
894class ThreeRegFloatOp(TwoRegFloatOp):
895    numRegs = 3
896
897class FourRegFloatOp(TwoRegFloatOp):
898    numRegs = 4
899
900class FloatConvertOp(TwoRegFloatOp):
901
902    def __init__(self, args):
903        self._cname, self._aname, modes = args
904        TwoRegFloatOp.__init__(self, [self._cname, modes])
905
906    def aname(self):
907        return self._aname
908
909    def cname(self):
910        return self._cname
911
912class SpecialCases(Instruction):
913    def __init__(self, data):
914        self._name = data[0]
915        self._cstr = data[1]
916        self._astr = data[2]
917
918    def cstr(self):
919        return self._cstr
920
921    def astr(self):
922        return self._astr
923
924def generate(kind, names):
925    outfile.write("# " + kind.__name__ + "\n");
926    print "\n// " + kind.__name__
927    for name in names:
928        for i in range(1):
929             op = kind(name).generate()
930             if op.multipleForms():
931                  forms = op.forms()
932                  aforms = op.aforms()
933                  for i in range(op.multipleForms()):
934                       cstr = op.cstr() % forms[i]
935                       astr = op.astr() % aforms[i]
936                       print "    %-50s //\t%s" % (cstr, astr)
937                       outfile.write("\t" + astr + "\n")
938             else:
939                  print "    %-50s //\t%s" % (op.cstr(), op.astr())
940                  outfile.write("\t" + op.astr() + "\n")
941
942outfile = open("aarch64ops.s", "w")
943
944print "// BEGIN  Generated code -- do not edit"
945print "// Generated by aarch64-asmtest.py"
946
947print "    Label back, forth;"
948print "    __ bind(back);"
949
950outfile.write("back:\n")
951
952generate (ArithOp,
953          [ "add", "sub", "adds", "subs",
954            "addw", "subw", "addsw", "subsw",
955            "and", "orr", "eor", "ands",
956            "andw", "orrw", "eorw", "andsw",
957            "bic", "orn", "eon", "bics",
958            "bicw", "ornw", "eonw", "bicsw" ])
959
960generate (AddSubImmOp,
961          [ "addw", "addsw", "subw", "subsw",
962            "add", "adds", "sub", "subs"])
963generate (LogicalImmOp,
964          [ "andw", "orrw", "eorw", "andsw",
965            "and", "orr", "eor", "ands"])
966
967generate (AbsOp, [ "b", "bl" ])
968
969generate (RegAndAbsOp, ["cbzw", "cbnzw", "cbz", "cbnz", "adr", "adrp"])
970
971generate (RegImmAbsOp, ["tbz", "tbnz"])
972
973generate (MoveWideImmOp, ["movnw", "movzw", "movkw", "movn", "movz", "movk"])
974
975generate (BitfieldOp, ["sbfm", "bfmw", "ubfmw", "sbfm", "bfm", "ubfm"])
976
977generate (ExtractOp, ["extrw", "extr"])
978
979generate (CondBranchOp, ["EQ", "NE", "HS", "CS", "LO", "CC", "MI", "PL", "VS", "VC",
980                        "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV" ])
981
982generate (ImmOp, ["svc", "hvc", "smc", "brk", "hlt", # "dpcs1",  "dpcs2",  "dpcs3"
983               ])
984
985generate (Op, ["nop", "eret", "drps", "isb"])
986
987barriers = ["OSHLD", "OSHST", "OSH", "NSHLD", "NSHST", "NSH",
988            "ISHLD", "ISHST", "ISH", "LD", "ST", "SY"]
989
990generate (SystemOp, [["dsb", barriers], ["dmb", barriers]])
991
992generate (OneRegOp, ["br", "blr"])
993
994for mode in 'xwhb':
995    generate (LoadStoreExclusiveOp, [["stxr", mode, 3], ["stlxr", mode, 3],
996                                     ["ldxr", mode, 2], ["ldaxr", mode, 2],
997                                     ["stlr", mode, 2], ["ldar", mode, 2]])
998
999for mode in 'xw':
1000    generate (LoadStoreExclusiveOp, [["ldxp", mode, 3], ["ldaxp", mode, 3],
1001                                     ["stxp", mode, 4], ["stlxp", mode, 4]])
1002
1003for kind in range(6):
1004    print "\n// " + Address.kindToStr(kind),
1005    if kind != Address.pcrel:
1006        generate (LoadStoreOp,
1007                  [["str", "str", kind, "x"], ["str", "str", kind, "w"],
1008                   ["str", "strb", kind, "b"], ["str", "strh", kind, "h"],
1009                   ["ldr", "ldr", kind, "x"], ["ldr", "ldr", kind, "w"],
1010                   ["ldr", "ldrb", kind, "b"], ["ldr", "ldrh", kind, "h"],
1011                   ["ldrsb", "ldrsb", kind, "x"], ["ldrsh", "ldrsh", kind, "x"],
1012                   ["ldrsh", "ldrsh", kind, "w"], ["ldrsw", "ldrsw", kind, "x"],
1013                   ["ldr", "ldr", kind, "d"], ["ldr", "ldr", kind, "s"],
1014                   ["str", "str", kind, "d"], ["str", "str", kind, "s"],
1015                   ])
1016    else:
1017        generate (LoadStoreOp,
1018                  [["ldr", "ldr", kind, "x"], ["ldr", "ldr", kind, "w"]])
1019
1020
1021for kind in (Address.base_plus_unscaled_offset, Address.pcrel, Address.base_plus_reg, \
1022                 Address.base_plus_scaled_offset):
1023    generate (LoadStoreOp,
1024              [["prfm", "prfm\tPLDL1KEEP,", kind, "x"]])
1025
1026generate(AddSubCarryOp, ["adcw", "adcsw", "sbcw", "sbcsw", "adc", "adcs", "sbc", "sbcs"])
1027
1028generate(AddSubExtendedOp, ["addw", "addsw", "sub", "subsw", "add", "adds", "sub", "subs"])
1029
1030generate(ConditionalCompareOp, ["ccmnw", "ccmpw", "ccmn", "ccmp"])
1031generate(ConditionalCompareImmedOp, ["ccmnw", "ccmpw", "ccmn", "ccmp"])
1032generate(ConditionalSelectOp,
1033         ["cselw", "csincw", "csinvw", "csnegw", "csel", "csinc", "csinv", "csneg"])
1034
1035generate(TwoRegOp,
1036         ["rbitw", "rev16w", "revw", "clzw", "clsw", "rbit",
1037          "rev16", "rev32", "rev", "clz", "cls"])
1038generate(ThreeRegOp,
1039         ["udivw", "sdivw", "lslvw", "lsrvw", "asrvw", "rorvw", "udiv", "sdiv",
1040          "lslv", "lsrv", "asrv", "rorv", "umulh", "smulh"])
1041generate(FourRegMulOp,
1042         ["maddw", "msubw", "madd", "msub", "smaddl", "smsubl", "umaddl", "umsubl"])
1043
1044generate(ThreeRegFloatOp,
1045         [["fmuls", "sss"], ["fdivs", "sss"], ["fadds", "sss"], ["fsubs", "sss"],
1046          ["fmuls", "sss"],
1047          ["fmuld", "ddd"], ["fdivd", "ddd"], ["faddd", "ddd"], ["fsubd", "ddd"],
1048          ["fmuld", "ddd"]])
1049
1050generate(FourRegFloatOp,
1051         [["fmadds", "ssss"], ["fmsubs", "ssss"], ["fnmadds", "ssss"], ["fnmadds", "ssss"],
1052          ["fmaddd", "dddd"], ["fmsubd", "dddd"], ["fnmaddd", "dddd"], ["fnmaddd", "dddd"],])
1053
1054generate(TwoRegFloatOp,
1055         [["fmovs", "ss"], ["fabss", "ss"], ["fnegs", "ss"], ["fsqrts", "ss"],
1056          ["fcvts", "ds"],
1057          ["fmovd", "dd"], ["fabsd", "dd"], ["fnegd", "dd"], ["fsqrtd", "dd"],
1058          ["fcvtd", "sd"],
1059          ])
1060
1061generate(FloatConvertOp, [["fcvtzsw", "fcvtzs", "ws"], ["fcvtzs", "fcvtzs", "xs"],
1062                          ["fcvtzdw", "fcvtzs", "wd"], ["fcvtzd", "fcvtzs", "xd"],
1063                          ["scvtfws", "scvtf", "sw"], ["scvtfs", "scvtf", "sx"],
1064                          ["scvtfwd", "scvtf", "dw"], ["scvtfd", "scvtf", "dx"],
1065                          ["fmovs", "fmov", "ws"], ["fmovd", "fmov", "xd"],
1066                          ["fmovs", "fmov", "sw"], ["fmovd", "fmov", "dx"]])
1067
1068generate(TwoRegFloatOp, [["fcmps", "ss"], ["fcmpd", "dd"],
1069                         ["fcmps", "sz"], ["fcmpd", "dz"]])
1070
1071for kind in range(3):
1072     generate(LoadStorePairOp, [["stp", "stp", kind, "w"], ["ldp", "ldp", kind, "w"],
1073                                ["ldpsw", "ldpsw", kind, "x"],
1074                                ["stp", "stp", kind, "x"], ["ldp", "ldp", kind, "x"]
1075                                ])
1076generate(LoadStorePairOp, [["stnp", "stnp", 0, "w"], ["ldnp", "ldnp", 0, "w"],
1077                           ["stnp", "stnp", 0, "x"], ["ldnp", "ldnp", 0, "x"]])
1078
1079generate(LdStSIMDOp, [["ld1",  1, "8B",  Address.base_only],
1080                      ["ld1",  2, "16B", Address.post],
1081                      ["ld1",  3, "1D",  Address.post_reg],
1082                      ["ld1",  4, "8H",  Address.post],
1083                      ["ld1r", 1, "8B",  Address.base_only],
1084                      ["ld1r", 1, "4S",  Address.post],
1085                      ["ld1r", 1, "1D",  Address.post_reg],
1086                      ["ld2",  2, "2D",  Address.base_only],
1087                      ["ld2",  2, "4H",  Address.post],
1088                      ["ld2r", 2, "16B", Address.base_only],
1089                      ["ld2r", 2, "2S",  Address.post],
1090                      ["ld2r", 2, "2D",  Address.post_reg],
1091                      ["ld3",  3, "4S",  Address.post_reg],
1092                      ["ld3",  3, "2S",  Address.base_only],
1093                      ["ld3r", 3, "8H",  Address.base_only],
1094                      ["ld3r", 3, "4S",  Address.post],
1095                      ["ld3r", 3, "1D",  Address.post_reg],
1096                      ["ld4",  4, "8H",  Address.post],
1097                      ["ld4",  4, "8B",  Address.post_reg],
1098                      ["ld4r", 4, "8B",  Address.base_only],
1099                      ["ld4r", 4, "4H",  Address.post],
1100                      ["ld4r", 4, "2S",  Address.post_reg],
1101])
1102
1103generate(SpecialCases, [["ccmn",   "__ ccmn(zr, zr, 3u, Assembler::LE);",                "ccmn\txzr, xzr, #3, LE"],
1104                        ["ccmnw",  "__ ccmnw(zr, zr, 5u, Assembler::EQ);",               "ccmn\twzr, wzr, #5, EQ"],
1105                        ["ccmp",   "__ ccmp(zr, 1, 4u, Assembler::NE);",                 "ccmp\txzr, 1, #4, NE"],
1106                        ["ccmpw",  "__ ccmpw(zr, 2, 2, Assembler::GT);",                 "ccmp\twzr, 2, #2, GT"],
1107                        ["extr",   "__ extr(zr, zr, zr, 0);",                            "extr\txzr, xzr, xzr, 0"],
1108                        ["stlxp",  "__ stlxp(r0, zr, zr, sp);",                          "stlxp\tw0, xzr, xzr, [sp]"],
1109                        ["stlxpw", "__ stlxpw(r2, zr, zr, r3);",                         "stlxp\tw2, wzr, wzr, [x3]"],
1110                        ["stxp",   "__ stxp(r4, zr, zr, r5);",                           "stxp\tw4, xzr, xzr, [x5]"],
1111                        ["stxpw",  "__ stxpw(r6, zr, zr, sp);",                          "stxp\tw6, wzr, wzr, [sp]"],
1112                        ["dup",    "__ dup(v0, __ T16B, zr);",                           "dup\tv0.16b, wzr"],
1113                        ["mov",    "__ mov(v1, __ T1D, 0, zr);",                         "mov\tv1.d[0], xzr"],
1114                        ["mov",    "__ mov(v1, __ T2S, 1, zr);",                         "mov\tv1.s[1], wzr"],
1115                        ["mov",    "__ mov(v1, __ T4H, 2, zr);",                         "mov\tv1.h[2], wzr"],
1116                        ["mov",    "__ mov(v1, __ T8B, 3, zr);",                         "mov\tv1.b[3], wzr"],
1117                        ["ld1",    "__ ld1(v31, v0, __ T2D, Address(__ post(r1, r0)));", "ld1\t{v31.2d, v0.2d}, [x1], x0"]])
1118
1119print "\n// FloatImmediateOp"
1120for float in ("2.0", "2.125", "4.0", "4.25", "8.0", "8.5", "16.0", "17.0", "0.125",
1121              "0.1328125", "0.25", "0.265625", "0.5", "0.53125", "1.0", "1.0625",
1122              "-2.0", "-2.125", "-4.0", "-4.25", "-8.0", "-8.5", "-16.0", "-17.0",
1123              "-0.125", "-0.1328125", "-0.25", "-0.265625", "-0.5", "-0.53125", "-1.0", "-1.0625"):
1124    astr = "fmov d0, #" + float
1125    cstr = "__ fmovd(v0, " + float + ");"
1126    print "    %-50s //\t%s" % (cstr, astr)
1127    outfile.write("\t" + astr + "\n")
1128
1129# ARMv8.1A
1130for size in ("x", "w"):
1131    for suffix in ("", "a", "al", "l"):
1132        generate(LSEOp, [["swp", "swp", size, suffix],
1133                         ["ldadd", "ldadd", size, suffix],
1134                         ["ldbic", "ldclr", size, suffix],
1135                         ["ldeor", "ldeor", size, suffix],
1136                         ["ldorr", "ldset", size, suffix],
1137                         ["ldsmin", "ldsmin", size, suffix],
1138                         ["ldsmax", "ldsmax", size, suffix],
1139                         ["ldumin", "ldumin", size, suffix],
1140                         ["ldumax", "ldumax", size, suffix]]);
1141
1142print "\n    __ bind(forth);"
1143outfile.write("forth:\n")
1144
1145outfile.close()
1146
1147import subprocess
1148import sys
1149
1150# compile for 8.1 because of lse atomics
1151subprocess.check_call([AARCH64_AS, "-march=armv8.1-a", "aarch64ops.s", "-o", "aarch64ops.o"])
1152
1153print
1154print "/*",
1155sys.stdout.flush()
1156subprocess.check_call([AARCH64_OBJDUMP, "-d", "aarch64ops.o"])
1157print "*/"
1158
1159subprocess.check_call([AARCH64_OBJCOPY, "-O", "binary", "-j", ".text", "aarch64ops.o", "aarch64ops.bin"])
1160
1161infile = open("aarch64ops.bin", "r")
1162bytes = bytearray(infile.read())
1163
1164print
1165print "  static const unsigned int insns[] ="
1166print "  {"
1167
1168i = 0
1169while i < len(bytes):
1170     print "    0x%02x%02x%02x%02x," % (bytes[i+3], bytes[i+2], bytes[i+1], bytes[i]),
1171     i += 4
1172     if i%16 == 0:
1173          print
1174print "\n  };"
1175print "// END  Generated code -- do not edit"
1176
1177
1178