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