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