1 import random
   2 
   3 AARCH64_AS = "as"
   4 AARCH64_OBJDUMP = "objdump"
   5 AARCH64_OBJCOPY = "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() + "ll);"
 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         kindStr = Address.kindToStr(self.kind);
 745         if (not isFloat) and (kindStr is "pre" or kindStr is "post"):
 746             (self.reg.number, self.adr.base.number) = random.sample(range(31), 2)
 747         return self
 748 
 749     def cstr(self):
 750         if not(self._name.startswith("prfm")):
 751             return "%s%s, %s);" % (Instruction.cstr(self), str(self.reg), str(self.adr))
 752         else: # No target register for a prefetch
 753             return "%s%s);" % (Instruction.cstr(self), str(self.adr))
 754 
 755     def astr(self):
 756         if not(self._name.startswith("prfm")):
 757             return "%s\t%s, %s" % (self.aname(), self.reg.astr(self.asmRegPrefix),
 758                                      self.adr.astr("x"))
 759         else: # No target register for a prefetch
 760             return "%s %s" % (self.aname(),
 761                                      self.adr.astr("x"))
 762 
 763     def aname(self):
 764          result = self.asmname
 765          # if self.kind == Address.base_plus_unscaled_offset:
 766          #      result = result.replace("ld", "ldu", 1)
 767          #      result = result.replace("st", "stu", 1)
 768          return result
 769 
 770 class LoadStorePairOp(InstructionWithModes):
 771 
 772      numRegs = 2
 773      
 774      def __init__(self, args):
 775           name, self.asmname, self.kind, mode = args
 776           InstructionWithModes.__init__(self, name, mode)
 777           self.offset = random.randint(-1<<4, 1<<4-1) << 4
 778           
 779      def generate(self):
 780           self.reg = [OperandFactory.create(self.mode).generate() 
 781                       for i in range(self.numRegs)]
 782           self.base = OperandFactory.create('x').generate()
 783           kindStr = Address.kindToStr(self.kind);
 784           if kindStr is "pre" or kindStr is "post":
 785               if self._name.startswith("ld"):
 786                   (self.reg[0].number, self.reg[1].number, self.base.number) = random.sample(range(31), 3)
 787               if self._name.startswith("st"):
 788                   self.base.number = random.choice(list(set(range(31)) - set([self.reg[0].number, self.reg[1].number])))
 789           elif self._name.startswith("ld"):
 790               (self.reg[0].number, self.reg[1].number) = random.sample(range(31), 2)
 791           return self
 792 
 793      def astr(self):
 794           address = ["[%s, #%s]", "[%s, #%s]!", "[%s], #%s"][self.kind]
 795           address = address % (self.base.astr('x'), self.offset)
 796           result = "%s\t%s, %s, %s" \
 797               % (self.asmname, 
 798                  self.reg[0].astr(self.asmRegPrefix), 
 799                  self.reg[1].astr(self.asmRegPrefix), address)
 800           return result
 801 
 802      def cstr(self):
 803           address = {
 804                Address.base_plus_unscaled_offset: "Address(%s, %s)" \
 805                     % (str(self.base), self.offset),
 806                Address.pre: "Address(__ pre(%s, %s))" % (str(self.base), self.offset),
 807                Address.post: "Address(__ post(%s, %s))" % (str(self.base), self.offset),
 808                } [self.kind]
 809           result = "__ %s(%s, %s, %s);" \
 810               % (self.name(), self.reg[0], self.reg[1], address)
 811           return result
 812 
 813 class FloatInstruction(Instruction):
 814 
 815     def aname(self):
 816         if (self._name.endswith("s") | self._name.endswith("d")):
 817             return self._name[:len(self._name)-1]
 818         else:
 819             return self._name
 820 
 821     def __init__(self, args):
 822         name, self.modes = args
 823         Instruction.__init__(self, name)
 824 
 825     def generate(self):
 826         self.reg = [OperandFactory.create(self.modes[i]).generate() 
 827                     for i in range(self.numRegs)]
 828         return self
 829 
 830     def cstr(self):
 831         formatStr = "%s%s" + ''.join([", %s" for i in range(1, self.numRegs)] + [");"])
 832         return (formatStr
 833                 % tuple([Instruction.cstr(self)] +
 834                         [str(self.reg[i]) for i in range(self.numRegs)])) # Yowza
 835     
 836     def astr(self):
 837         formatStr = "%s%s" + ''.join([", %s" for i in range(1, self.numRegs)])
 838         return (formatStr
 839                 % tuple([Instruction.astr(self)] +
 840                         [(self.reg[i].astr(self.modes[i])) for i in range(self.numRegs)]))
 841 
 842 class LdStSIMDOp(Instruction):
 843     def __init__(self, args):
 844         self._name, self.regnum, self.arrangement, self.addresskind = args
 845 
 846     def generate(self):
 847         self.address = Address().generate(self.addresskind, 0)
 848         self._firstSIMDreg = FloatRegister().generate()
 849         if (self.addresskind  == Address.post):
 850             if (self._name in ["ld1r", "ld2r", "ld3r", "ld4r"]):
 851                 elem_size = {"8B" : 1, "16B" : 1, "4H" : 2, "8H" : 2, "2S" : 4, "4S" : 4, "1D" : 8, "2D" : 8} [self.arrangement]
 852                 self.address.offset = self.regnum * elem_size
 853             else:
 854                 if (self.arrangement in ["8B", "4H", "2S", "1D"]):
 855                     self.address.offset = self.regnum * 8
 856                 else:
 857                     self.address.offset = self.regnum * 16
 858         return self
 859 
 860     def cstr(self):
 861         buf = super(LdStSIMDOp, self).cstr() + str(self._firstSIMDreg)
 862         current = self._firstSIMDreg
 863         for cnt in range(1, self.regnum):
 864             buf = '%s, %s' % (buf, current.nextReg())
 865             current = current.nextReg()
 866         return '%s, __ T%s, %s);' % (buf, self.arrangement, str(self.address))
 867 
 868     def astr(self):
 869         buf = '%s\t{%s.%s' % (self._name, self._firstSIMDreg, self.arrangement)
 870         current = self._firstSIMDreg
 871         for cnt in range(1, self.regnum):
 872             buf = '%s, %s.%s' % (buf, current.nextReg(), self.arrangement)
 873             current = current.nextReg()
 874         return  '%s}, %s' % (buf, self.address.astr("x"))
 875 
 876     def aname(self):
 877          return self._name
 878 
 879 class SHA512SIMDOp(Instruction):
 880 
 881     def generate(self):
 882         if (self._name == 'sha512su0'):
 883             self.reg = [FloatRegister().generate(), FloatRegister().generate()]
 884         else:
 885             self.reg = [FloatRegister().generate(), FloatRegister().generate(),
 886                         FloatRegister().generate()]
 887         return self
 888 
 889     def cstr(self):
 890         if (self._name == 'sha512su0'):
 891             return (super(SHA512SIMDOp, self).cstr()
 892                     + ('%s, __ T2D, %s);' % (self.reg[0], self.reg[1])))
 893         else:
 894             return (super(SHA512SIMDOp, self).cstr()
 895                     + ('%s, __ T2D, %s, %s);' % (self.reg[0], self.reg[1], self.reg[2])))
 896 
 897     def astr(self):
 898         if (self._name == 'sha512su0'):
 899             return (super(SHA512SIMDOp, self).astr()
 900                     + ('\t%s.2D, %s.2D' % (self.reg[0].astr("v"), self.reg[1].astr("v"))))
 901         elif (self._name == 'sha512su1'):
 902             return (super(SHA512SIMDOp, self).astr()
 903                     + ('\t%s.2D, %s.2D, %s.2D' % (self.reg[0].astr("v"),
 904                        self.reg[1].astr("v"), self.reg[2].astr("v"))))
 905         else:
 906             return (super(SHA512SIMDOp, self).astr()
 907                     + ('\t%s, %s, %s.2D' % (self.reg[0].astr("q"),
 908                        self.reg[1].astr("q"), self.reg[2].astr("v"))))
 909 
 910 class LSEOp(Instruction):
 911     def __init__(self, args):
 912         self._name, self.asmname, self.size, self.suffix = args
 913 
 914     def generate(self):
 915         self._name = "%s%s" % (self._name, self.suffix)
 916         self.asmname = "%s%s" % (self.asmname, self.suffix)
 917         self.srcReg = GeneralRegisterOrZr().generate()
 918         self.tgtReg = GeneralRegisterOrZr().generate()
 919         self.adrReg = GeneralRegisterOrSp().generate()
 920 
 921         return self
 922 
 923     def cstr(self):
 924         sizeSpec = {"x" : "Assembler::xword", "w" : "Assembler::word"} [self.size]
 925         return super(LSEOp, self).cstr() + "%s, %s, %s, %s);" % (sizeSpec, self.srcReg, self.tgtReg, self.adrReg)
 926 
 927     def astr(self):
 928         return "%s\t%s, %s, [%s]" % (self.asmname, self.srcReg.astr(self.size), self.tgtReg.astr(self.size), self.adrReg.astr("x"))
 929 
 930     def aname(self):
 931          return self.asmname
 932 
 933 class TwoRegFloatOp(FloatInstruction):
 934     numRegs = 2
 935 
 936 class ThreeRegFloatOp(TwoRegFloatOp):
 937     numRegs = 3
 938 
 939 class FourRegFloatOp(TwoRegFloatOp):
 940     numRegs = 4
 941 
 942 class FloatConvertOp(TwoRegFloatOp):
 943 
 944     def __init__(self, args):
 945         self._cname, self._aname, modes = args
 946         TwoRegFloatOp.__init__(self, [self._cname, modes])
 947 
 948     def aname(self):
 949         return self._aname
 950 
 951     def cname(self):
 952         return self._cname
 953 
 954 class SpecialCases(Instruction):
 955     def __init__(self, data):
 956         self._name = data[0]
 957         self._cstr = data[1]
 958         self._astr = data[2]
 959 
 960     def cstr(self):
 961         return self._cstr
 962 
 963     def astr(self):
 964         return self._astr
 965 
 966 def generate(kind, names):
 967     outfile.write("# " + kind.__name__ + "\n");
 968     print "\n// " + kind.__name__
 969     for name in names:
 970         for i in range(1):
 971              op = kind(name).generate()
 972              if op.multipleForms():
 973                   forms = op.forms()
 974                   aforms = op.aforms()
 975                   for i in range(op.multipleForms()):
 976                        cstr = op.cstr() % forms[i]
 977                        astr = op.astr() % aforms[i]
 978                        print "    %-50s //\t%s" % (cstr, astr)
 979                        outfile.write("\t" + astr + "\n")
 980              else:
 981                   print "    %-50s //\t%s" % (op.cstr(), op.astr())
 982                   outfile.write("\t" + op.astr() + "\n")
 983 
 984 outfile = open("aarch64ops.s", "w")
 985 
 986 random.seed(0)
 987 
 988 print "// BEGIN  Generated code -- do not edit"
 989 print "// Generated by aarch64-asmtest.py"
 990 
 991 print "    Label back, forth;"
 992 print "    __ bind(back);"
 993 
 994 outfile.write("back:\n")
 995 
 996 generate (ArithOp, 
 997           [ "add", "sub", "adds", "subs",
 998             "addw", "subw", "addsw", "subsw",
 999             "and", "orr", "eor", "ands",
1000             "andw", "orrw", "eorw", "andsw", 
1001             "bic", "orn", "eon", "bics", 
1002             "bicw", "ornw", "eonw", "bicsw" ])
1003 
1004 generate (AddSubImmOp, 
1005           [ "addw", "addsw", "subw", "subsw",
1006             "add", "adds", "sub", "subs"])
1007 generate (LogicalImmOp, 
1008           [ "andw", "orrw", "eorw", "andsw",
1009             "and", "orr", "eor", "ands"])
1010 
1011 generate (AbsOp, [ "b", "bl" ])
1012 
1013 generate (RegAndAbsOp, ["cbzw", "cbnzw", "cbz", "cbnz", "adr", "adrp"])
1014 
1015 generate (RegImmAbsOp, ["tbz", "tbnz"])
1016 
1017 generate (MoveWideImmOp, ["movnw", "movzw", "movkw", "movn", "movz", "movk"])
1018 
1019 generate (BitfieldOp, ["sbfm", "bfmw", "ubfmw", "sbfm", "bfm", "ubfm"])
1020 
1021 generate (ExtractOp, ["extrw", "extr"])
1022 
1023 generate (CondBranchOp, ["EQ", "NE", "HS", "CS", "LO", "CC", "MI", "PL", "VS", "VC",
1024                         "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV" ])
1025 
1026 generate (ImmOp, ["svc", "hvc", "smc", "brk", "hlt", # "dcps1",  "dcps2",  "dcps3"
1027                ])
1028 
1029 generate (Op, ["nop", "eret", "drps", "isb"])
1030 
1031 barriers = ["OSHLD", "OSHST", "OSH", "NSHLD", "NSHST", "NSH",
1032             "ISHLD", "ISHST", "ISH", "LD", "ST", "SY"]
1033 
1034 generate (SystemOp, [["dsb", barriers], ["dmb", barriers]])
1035 
1036 generate (OneRegOp, ["br", "blr"])
1037 
1038 for mode in 'xwhb':
1039     generate (LoadStoreExclusiveOp, [["stxr", mode, 3], ["stlxr", mode, 3],
1040                                      ["ldxr", mode, 2], ["ldaxr", mode, 2],
1041                                      ["stlr", mode, 2], ["ldar", mode, 2]])
1042 
1043 for mode in 'xw':
1044     generate (LoadStoreExclusiveOp, [["ldxp", mode, 3], ["ldaxp", mode, 3],
1045                                      ["stxp", mode, 4], ["stlxp", mode, 4]])
1046 
1047 for kind in range(6):
1048     print "\n// " + Address.kindToStr(kind),
1049     if kind != Address.pcrel:
1050         generate (LoadStoreOp, 
1051                   [["str", "str", kind, "x"], ["str", "str", kind, "w"], 
1052                    ["str", "strb", kind, "b"], ["str", "strh", kind, "h"],
1053                    ["ldr", "ldr", kind, "x"], ["ldr", "ldr", kind, "w"], 
1054                    ["ldr", "ldrb", kind, "b"], ["ldr", "ldrh", kind, "h"],
1055                    ["ldrsb", "ldrsb", kind, "x"], ["ldrsh", "ldrsh", kind, "x"], 
1056                    ["ldrsh", "ldrsh", kind, "w"], ["ldrsw", "ldrsw", kind, "x"],
1057                    ["ldr", "ldr", kind, "d"], ["ldr", "ldr", kind, "s"], 
1058                    ["str", "str", kind, "d"], ["str", "str", kind, "s"], 
1059                    ])
1060     else:
1061         generate (LoadStoreOp, 
1062                   [["ldr", "ldr", kind, "x"], ["ldr", "ldr", kind, "w"]])
1063         
1064 
1065 for kind in (Address.base_plus_unscaled_offset, Address.pcrel, Address.base_plus_reg, \
1066                  Address.base_plus_scaled_offset):
1067     generate (LoadStoreOp, 
1068               [["prfm", "prfm\tPLDL1KEEP,", kind, "x"]])
1069 
1070 generate(AddSubCarryOp, ["adcw", "adcsw", "sbcw", "sbcsw", "adc", "adcs", "sbc", "sbcs"])
1071 
1072 generate(AddSubExtendedOp, ["addw", "addsw", "sub", "subsw", "add", "adds", "sub", "subs"])
1073 
1074 generate(ConditionalCompareOp, ["ccmnw", "ccmpw", "ccmn", "ccmp"])
1075 generate(ConditionalCompareImmedOp, ["ccmnw", "ccmpw", "ccmn", "ccmp"])
1076 generate(ConditionalSelectOp, 
1077          ["cselw", "csincw", "csinvw", "csnegw", "csel", "csinc", "csinv", "csneg"])
1078 
1079 generate(TwoRegOp, 
1080          ["rbitw", "rev16w", "revw", "clzw", "clsw", "rbit", 
1081           "rev16", "rev32", "rev", "clz", "cls"])
1082 generate(ThreeRegOp, 
1083          ["udivw", "sdivw", "lslvw", "lsrvw", "asrvw", "rorvw", "udiv", "sdiv", 
1084           "lslv", "lsrv", "asrv", "rorv", "umulh", "smulh"])
1085 generate(FourRegMulOp, 
1086          ["maddw", "msubw", "madd", "msub", "smaddl", "smsubl", "umaddl", "umsubl"])
1087 
1088 generate(ThreeRegFloatOp, 
1089          [["fmuls", "sss"], ["fdivs", "sss"], ["fadds", "sss"], ["fsubs", "sss"], 
1090           ["fmuls", "sss"],
1091           ["fmuld", "ddd"], ["fdivd", "ddd"], ["faddd", "ddd"], ["fsubd", "ddd"], 
1092           ["fmuld", "ddd"]])
1093 
1094 generate(FourRegFloatOp, 
1095          [["fmadds", "ssss"], ["fmsubs", "ssss"], ["fnmadds", "ssss"], ["fnmadds", "ssss"], 
1096           ["fmaddd", "dddd"], ["fmsubd", "dddd"], ["fnmaddd", "dddd"], ["fnmaddd", "dddd"],])
1097 
1098 generate(TwoRegFloatOp, 
1099          [["fmovs", "ss"], ["fabss", "ss"], ["fnegs", "ss"], ["fsqrts", "ss"], 
1100           ["fcvts", "ds"],
1101           ["fmovd", "dd"], ["fabsd", "dd"], ["fnegd", "dd"], ["fsqrtd", "dd"], 
1102           ["fcvtd", "sd"],
1103           ])
1104 
1105 generate(FloatConvertOp, [["fcvtzsw", "fcvtzs", "ws"], ["fcvtzs", "fcvtzs", "xs"],
1106                           ["fcvtzdw", "fcvtzs", "wd"], ["fcvtzd", "fcvtzs", "xd"],
1107                           ["scvtfws", "scvtf", "sw"], ["scvtfs", "scvtf", "sx"],
1108                           ["scvtfwd", "scvtf", "dw"], ["scvtfd", "scvtf", "dx"],
1109                           ["fmovs", "fmov", "ws"], ["fmovd", "fmov", "xd"],
1110                           ["fmovs", "fmov", "sw"], ["fmovd", "fmov", "dx"]])
1111 
1112 generate(TwoRegFloatOp, [["fcmps", "ss"], ["fcmpd", "dd"], 
1113                          ["fcmps", "sz"], ["fcmpd", "dz"]])
1114 
1115 for kind in range(3):
1116      generate(LoadStorePairOp, [["stp", "stp", kind, "w"], ["ldp", "ldp", kind, "w"],
1117                                 ["ldpsw", "ldpsw", kind, "x"], 
1118                                 ["stp", "stp", kind, "x"], ["ldp", "ldp", kind, "x"]
1119                                 ])
1120 generate(LoadStorePairOp, [["stnp", "stnp", 0, "w"], ["ldnp", "ldnp", 0, "w"],
1121                            ["stnp", "stnp", 0, "x"], ["ldnp", "ldnp", 0, "x"]])
1122 
1123 generate(LdStSIMDOp, [["ld1",  1, "8B",  Address.base_only],
1124                       ["ld1",  2, "16B", Address.post],
1125                       ["ld1",  3, "1D",  Address.post_reg],
1126                       ["ld1",  4, "8H",  Address.post],
1127                       ["ld1r", 1, "8B",  Address.base_only],
1128                       ["ld1r", 1, "4S",  Address.post],
1129                       ["ld1r", 1, "1D",  Address.post_reg],
1130                       ["ld2",  2, "2D",  Address.base_only],
1131                       ["ld2",  2, "4H",  Address.post],
1132                       ["ld2r", 2, "16B", Address.base_only],
1133                       ["ld2r", 2, "2S",  Address.post],
1134                       ["ld2r", 2, "2D",  Address.post_reg],
1135                       ["ld3",  3, "4S",  Address.post_reg],
1136                       ["ld3",  3, "2S",  Address.base_only],
1137                       ["ld3r", 3, "8H",  Address.base_only],
1138                       ["ld3r", 3, "4S",  Address.post],
1139                       ["ld3r", 3, "1D",  Address.post_reg],
1140                       ["ld4",  4, "8H",  Address.post],
1141                       ["ld4",  4, "8B",  Address.post_reg],
1142                       ["ld4r", 4, "8B",  Address.base_only],
1143                       ["ld4r", 4, "4H",  Address.post],
1144                       ["ld4r", 4, "2S",  Address.post_reg],
1145 ])
1146 
1147 generate(SHA512SIMDOp, ["sha512h", "sha512h2", "sha512su0", "sha512su1"])
1148 
1149 generate(SpecialCases, [["ccmn",   "__ ccmn(zr, zr, 3u, Assembler::LE);",                "ccmn\txzr, xzr, #3, LE"],
1150                         ["ccmnw",  "__ ccmnw(zr, zr, 5u, Assembler::EQ);",               "ccmn\twzr, wzr, #5, EQ"],
1151                         ["ccmp",   "__ ccmp(zr, 1, 4u, Assembler::NE);",                 "ccmp\txzr, 1, #4, NE"],
1152                         ["ccmpw",  "__ ccmpw(zr, 2, 2, Assembler::GT);",                 "ccmp\twzr, 2, #2, GT"],
1153                         ["extr",   "__ extr(zr, zr, zr, 0);",                            "extr\txzr, xzr, xzr, 0"],
1154                         ["stlxp",  "__ stlxp(r0, zr, zr, sp);",                          "stlxp\tw0, xzr, xzr, [sp]"],
1155                         ["stlxpw", "__ stlxpw(r2, zr, zr, r3);",                         "stlxp\tw2, wzr, wzr, [x3]"],
1156                         ["stxp",   "__ stxp(r4, zr, zr, r5);",                           "stxp\tw4, xzr, xzr, [x5]"],
1157                         ["stxpw",  "__ stxpw(r6, zr, zr, sp);",                          "stxp\tw6, wzr, wzr, [sp]"],
1158                         ["dup",    "__ dup(v0, __ T16B, zr);",                           "dup\tv0.16b, wzr"],
1159                         ["mov",    "__ mov(v1, __ T1D, 0, zr);",                         "mov\tv1.d[0], xzr"],
1160                         ["mov",    "__ mov(v1, __ T2S, 1, zr);",                         "mov\tv1.s[1], wzr"],
1161                         ["mov",    "__ mov(v1, __ T4H, 2, zr);",                         "mov\tv1.h[2], wzr"],
1162                         ["mov",    "__ mov(v1, __ T8B, 3, zr);",                         "mov\tv1.b[3], wzr"],
1163                         ["ld1",    "__ ld1(v31, v0, __ T2D, Address(__ post(r1, r0)));", "ld1\t{v31.2d, v0.2d}, [x1], x0"]])
1164 
1165 print "\n// FloatImmediateOp"
1166 for float in ("2.0", "2.125", "4.0", "4.25", "8.0", "8.5", "16.0", "17.0", "0.125", 
1167               "0.1328125", "0.25", "0.265625", "0.5", "0.53125", "1.0", "1.0625", 
1168               "-2.0", "-2.125", "-4.0", "-4.25", "-8.0", "-8.5", "-16.0", "-17.0", 
1169               "-0.125", "-0.1328125", "-0.25", "-0.265625", "-0.5", "-0.53125", "-1.0", "-1.0625"):
1170     astr = "fmov d0, #" + float
1171     cstr = "__ fmovd(v0, " + float + ");"
1172     print "    %-50s //\t%s" % (cstr, astr)
1173     outfile.write("\t" + astr + "\n")
1174 
1175 # ARMv8.1A
1176 for size in ("x", "w"):
1177     for suffix in ("", "a", "al", "l"):
1178         generate(LSEOp, [["swp", "swp", size, suffix],
1179                          ["ldadd", "ldadd", size, suffix],
1180                          ["ldbic", "ldclr", size, suffix],
1181                          ["ldeor", "ldeor", size, suffix],
1182                          ["ldorr", "ldset", size, suffix],
1183                          ["ldsmin", "ldsmin", size, suffix],
1184                          ["ldsmax", "ldsmax", size, suffix],
1185                          ["ldumin", "ldumin", size, suffix],
1186                          ["ldumax", "ldumax", size, suffix]]);
1187 
1188 print "\n    __ bind(forth);"
1189 outfile.write("forth:\n")
1190 
1191 outfile.close()
1192 
1193 import subprocess
1194 import sys
1195 
1196 # compile for 8.1 and sha2 because of lse atomics and sha512 crypto extension.
1197 subprocess.check_call([AARCH64_AS, "-march=armv8.1-a+sha2", "aarch64ops.s", "-o", "aarch64ops.o"])
1198 
1199 print
1200 print "/*",
1201 sys.stdout.flush()
1202 subprocess.check_call([AARCH64_OBJDUMP, "-d", "aarch64ops.o"])
1203 print "*/"
1204 
1205 subprocess.check_call([AARCH64_OBJCOPY, "-O", "binary", "-j", ".text", "aarch64ops.o", "aarch64ops.bin"])
1206 
1207 infile = open("aarch64ops.bin", "r")
1208 bytes = bytearray(infile.read())
1209 
1210 print
1211 print "  static const unsigned int insns[] ="
1212 print "  {"
1213 
1214 i = 0
1215 while i < len(bytes):
1216      print "    0x%02x%02x%02x%02x," % (bytes[i+3], bytes[i+2], bytes[i+1], bytes[i]),
1217      i += 4
1218      if i%16 == 0:
1219           print
1220 print "\n  };"
1221 print "// END  Generated code -- do not edit"
1222 
1223