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