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