1 import random
   2 
   3 AARCH64_AS = "<PATH-TO-AS>"
   4 AARCH64_OBJDUMP = "<PATH-TO-OBJDUMP>"
   5 AARCH64_OBJCOPY = "<PATH-TO-OBJCOPY>"
   6 
   7 class Operand(object):
   8 
   9      def generate(self):
  10         return self
  11 
  12 class 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 
  21 class 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 
  31 class GeneralRegister(Register):
  32 
  33     def __str__(self):
  34         return self.astr("r")
  35 
  36 class 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 
  54 class 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 
  71 class FloatZero(Operand):
  72 
  73     def __str__(self):
  74         return "0.0"
  75 
  76     def astr(self, ignored):
  77         return "#0.0"
  78 
  79 class 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 
  91 class 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 
 100 class 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 
 141 class 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 
 161 class 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                 
 182 class 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                 
 198 class 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                 
 216 class 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 
 231 class 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 
 245 class 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 
 264 class AddSubCarryOp(ThreeRegInstruction):
 265     
 266     def cstr(self):
 267         return ('%s);' 
 268                 % (ThreeRegInstruction.cstr(self)))
 269 
 270 class 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 
 291 class AddSubImmOp(TwoRegImmedInstruction):
 292 
 293     def cstr(self):
 294          return super(AddSubImmOp, self).cstr() + ");"
 295     
 296 class 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     
 353 class 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 
 364 class 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 
 372 class 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 
 396 class 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 
 412 class 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 
 436 class 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 
 454 class 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     
 469 class 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 
 477 class 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 
 489 class Op(Instruction):
 490 
 491     def cstr(self):
 492         return Instruction.cstr(self) + ");"
 493 
 494 class 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 
 512 conditionCodes = ["EQ", "NE", "HS", "CS", "LO", "CC", "MI", "PL", "VS", \
 513                        "VC", "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV"]
 514 
 515 class 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 
 531 class 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 
 553 class TwoRegOp(TwoRegInstruction):
 554     
 555     def cstr(self):
 556         return TwoRegInstruction.cstr(self) + ");"
 557 
 558 class ThreeRegOp(ThreeRegInstruction):
 559     
 560     def cstr(self):
 561         return ThreeRegInstruction.cstr(self) + ");"
 562 
 563 class 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 
 577 class 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 
 592 class 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 
 648 class 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         
 719 class 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 
 767 class 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 
 802 class 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 
 831 class 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 
 868 class 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 
 891 class TwoRegFloatOp(FloatInstruction):
 892     numRegs = 2
 893 
 894 class ThreeRegFloatOp(TwoRegFloatOp):
 895     numRegs = 3
 896 
 897 class FourRegFloatOp(TwoRegFloatOp):
 898     numRegs = 4
 899 
 900 class 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 
 912 class 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 
 924 def 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 
 942 outfile = open("aarch64ops.s", "w")
 943 
 944 print "// BEGIN  Generated code -- do not edit"
 945 print "// Generated by aarch64-asmtest.py"
 946 
 947 print "    Label back, forth;"
 948 print "    __ bind(back);"
 949 
 950 outfile.write("back:\n")
 951 
 952 generate (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 
 960 generate (AddSubImmOp, 
 961           [ "addw", "addsw", "subw", "subsw",
 962             "add", "adds", "sub", "subs"])
 963 generate (LogicalImmOp, 
 964           [ "andw", "orrw", "eorw", "andsw",
 965             "and", "orr", "eor", "ands"])
 966 
 967 generate (AbsOp, [ "b", "bl" ])
 968 
 969 generate (RegAndAbsOp, ["cbzw", "cbnzw", "cbz", "cbnz", "adr", "adrp"])
 970 
 971 generate (RegImmAbsOp, ["tbz", "tbnz"])
 972 
 973 generate (MoveWideImmOp, ["movnw", "movzw", "movkw", "movn", "movz", "movk"])
 974 
 975 generate (BitfieldOp, ["sbfm", "bfmw", "ubfmw", "sbfm", "bfm", "ubfm"])
 976 
 977 generate (ExtractOp, ["extrw", "extr"])
 978 
 979 generate (CondBranchOp, ["EQ", "NE", "HS", "CS", "LO", "CC", "MI", "PL", "VS", "VC",
 980                         "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV" ])
 981 
 982 generate (ImmOp, ["svc", "hvc", "smc", "brk", "hlt", # "dcps1",  "dcps2",  "dcps3"
 983                ])
 984 
 985 generate (Op, ["nop", "eret", "drps", "isb"])
 986 
 987 barriers = ["OSHLD", "OSHST", "OSH", "NSHLD", "NSHST", "NSH",
 988             "ISHLD", "ISHST", "ISH", "LD", "ST", "SY"]
 989 
 990 generate (SystemOp, [["dsb", barriers], ["dmb", barriers]])
 991 
 992 generate (OneRegOp, ["br", "blr"])
 993 
 994 for 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 
 999 for mode in 'xw':
1000     generate (LoadStoreExclusiveOp, [["ldxp", mode, 3], ["ldaxp", mode, 3],
1001                                      ["stxp", mode, 4], ["stlxp", mode, 4]])
1002 
1003 for 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 
1021 for 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 
1026 generate(AddSubCarryOp, ["adcw", "adcsw", "sbcw", "sbcsw", "adc", "adcs", "sbc", "sbcs"])
1027 
1028 generate(AddSubExtendedOp, ["addw", "addsw", "sub", "subsw", "add", "adds", "sub", "subs"])
1029 
1030 generate(ConditionalCompareOp, ["ccmnw", "ccmpw", "ccmn", "ccmp"])
1031 generate(ConditionalCompareImmedOp, ["ccmnw", "ccmpw", "ccmn", "ccmp"])
1032 generate(ConditionalSelectOp, 
1033          ["cselw", "csincw", "csinvw", "csnegw", "csel", "csinc", "csinv", "csneg"])
1034 
1035 generate(TwoRegOp, 
1036          ["rbitw", "rev16w", "revw", "clzw", "clsw", "rbit", 
1037           "rev16", "rev32", "rev", "clz", "cls"])
1038 generate(ThreeRegOp, 
1039          ["udivw", "sdivw", "lslvw", "lsrvw", "asrvw", "rorvw", "udiv", "sdiv", 
1040           "lslv", "lsrv", "asrv", "rorv", "umulh", "smulh"])
1041 generate(FourRegMulOp, 
1042          ["maddw", "msubw", "madd", "msub", "smaddl", "smsubl", "umaddl", "umsubl"])
1043 
1044 generate(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 
1050 generate(FourRegFloatOp, 
1051          [["fmadds", "ssss"], ["fmsubs", "ssss"], ["fnmadds", "ssss"], ["fnmadds", "ssss"], 
1052           ["fmaddd", "dddd"], ["fmsubd", "dddd"], ["fnmaddd", "dddd"], ["fnmaddd", "dddd"],])
1053 
1054 generate(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 
1061 generate(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 
1068 generate(TwoRegFloatOp, [["fcmps", "ss"], ["fcmpd", "dd"], 
1069                          ["fcmps", "sz"], ["fcmpd", "dz"]])
1070 
1071 for 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                                 ])
1076 generate(LoadStorePairOp, [["stnp", "stnp", 0, "w"], ["ldnp", "ldnp", 0, "w"],
1077                            ["stnp", "stnp", 0, "x"], ["ldnp", "ldnp", 0, "x"]])
1078 
1079 generate(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 
1103 generate(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 
1119 print "\n// FloatImmediateOp"
1120 for 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
1130 for 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 
1142 print "\n    __ bind(forth);"
1143 outfile.write("forth:\n")
1144 
1145 outfile.close()
1146 
1147 import subprocess
1148 import sys
1149 
1150 # compile for 8.1 because of lse atomics
1151 subprocess.check_call([AARCH64_AS, "-march=armv8.1-a", "aarch64ops.s", "-o", "aarch64ops.o"])
1152 
1153 print
1154 print "/*",
1155 sys.stdout.flush()
1156 subprocess.check_call([AARCH64_OBJDUMP, "-d", "aarch64ops.o"])
1157 print "*/"
1158 
1159 subprocess.check_call([AARCH64_OBJCOPY, "-O", "binary", "-j", ".text", "aarch64ops.o", "aarch64ops.bin"])
1160 
1161 infile = open("aarch64ops.bin", "r")
1162 bytes = bytearray(infile.read())
1163 
1164 print
1165 print "  static const unsigned int insns[] ="
1166 print "  {"
1167 
1168 i = 0
1169 while 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
1174 print "\n  };"
1175 print "// END  Generated code -- do not edit"
1176 
1177