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)