import os
import random
import subprocess
import sys
AARCH64_AS = "as"
AARCH64_OBJDUMP = "objdump"
AARCH64_OBJCOPY = "objcopy"
# These tables are legal immediate logical operands
immediates8 \
= [0x1, 0x0c, 0x3e, 0x60, 0x7c, 0x80, 0x83,
0xe1, 0xbf, 0xef, 0xf3, 0xfe]
immediates16 \
= [0x1, 0x38, 0x7e, 0xff, 0x1fc, 0x1ff, 0x3f0,
0x7e0, 0xfc0, 0x1f80, 0x3ff0, 0x7e00, 0x7e00,
0x8000, 0x81ff, 0xc1ff, 0xc003, 0xc7ff, 0xdfff,
0xe03f, 0xe10f, 0xe1ff, 0xf801, 0xfc00, 0xfc07,
0xff03, 0xfffe]
immediates32 \
= [0x1, 0x3f, 0x1f0, 0x7e0,
0x1c00, 0x3ff0, 0x8000, 0x1e000,
0x3e000, 0x78000, 0xe0000, 0x100000,
0x1fffe0, 0x3fe000, 0x780000, 0x7ffff8,
0xff8000, 0x1800180, 0x1fffc00, 0x3c003c0,
0x3ffff00, 0x7c00000, 0x7fffe00, 0xf000f00,
0xfffe000, 0x18181818, 0x1ffc0000, 0x1ffffffe,
0x3f003f00, 0x3fffe000, 0x60006000, 0x7f807f80,
0x7ffffc00, 0x800001ff, 0x803fffff, 0x9f9f9f9f,
0xc0000fff, 0xc0c0c0c0, 0xe0000000, 0xe003e003,
0xe3ffffff, 0xf0000fff, 0xf0f0f0f0, 0xf80000ff,
0xf83ff83f, 0xfc00007f, 0xfc1fffff, 0xfe0001ff,
0xfe3fffff, 0xff003fff, 0xff800003, 0xff87ff87,
0xffc00fff, 0xffe0000f, 0xffefffef, 0xfff1fff1,
0xfff83fff, 0xfffc0fff, 0xfffe0fff, 0xffff3fff,
0xffffc007, 0xffffe1ff, 0xfffff80f, 0xfffffe07,
0xffffffbf, 0xfffffffd]
immediates64 \
= [0x1, 0x1f80, 0x3fff0, 0x3ffffc,
0x3fe0000, 0x1ffc0000, 0xf8000000, 0x3ffffc000,
0xffffffe00, 0x3ffffff800, 0xffffc00000, 0x3f000000000,
0x7fffffff800, 0x1fe000001fe0, 0x3ffffff80000, 0xc00000000000,
0x1ffc000000000, 0x3ffff0003ffff, 0x7ffffffe00000, 0xfffffffffc000,
0x1ffffffffffc00, 0x3fffffffffff00, 0x7ffffffffffc00, 0xffffffffff8000,
0x1ffffffff800000, 0x3fffffc03fffffc, 0x7fffc0000000000, 0xff80ff80ff80ff8,
0x1c00000000000000, 0x1fffffffffff0000, 0x3fffff803fffff80, 0x7fc000007fc00000,
0x8000000000000000, 0x803fffff803fffff, 0xc000007fc000007f, 0xe00000000000ffff,
0xe3ffffffffffffff, 0xf007f007f007f007, 0xf80003ffffffffff, 0xfc000003fc000003,
0xfe000000007fffff, 0xff00000000007fff, 0xff800000000003ff, 0xffc00000000000ff,
0xffe00000000003ff, 0xfff0000000003fff, 0xfff80000001fffff, 0xfffc0000fffc0000,
0xfffe003fffffffff, 0xffff3fffffffffff, 0xffffc0000007ffff, 0xffffe01fffffe01f,
0xfffff800000007ff, 0xfffffc0fffffffff, 0xffffff00003fffff, 0xffffffc0000007ff,
0xfffffff0000001ff, 0xfffffffc00003fff, 0xffffffff07ffffff, 0xffffffffe003ffff,
0xfffffffffc01ffff, 0xffffffffffc00003, 0xfffffffffffc000f, 0xffffffffffffe07f]
class Operand(object):
def generate(self):
return self
class Register(Operand):
def generate(self):
self.number = random.randint(0, 30)
if self.number == 18:
self.number = 17
return self
def astr(self, prefix):
return prefix + str(self.number)
class FloatRegister(Register):
def __str__(self):
return self.astr("v" )
def nextReg(self):
next = FloatRegister()
next.number = (self.number + 1) % 32
return next
class GeneralRegister(Register):
def __str__(self):
return self.astr("r" )
class GeneralRegisterOrZr(Register):
def generate(self):
self.number = random.randint(0, 31)
if self.number == 18:
self.number = 16
return self
def astr(self, prefix = "" ):
if (self.number == 31):
return prefix + "zr"
else :
return prefix + str(self.number)
def __str__(self):
if (self.number == 31):
return self.astr()
else :
return self.astr("r" )
class GeneralRegisterOrSp(Register):
def generate(self):
self.number = random.randint(0, 31)
if self.number == 18:
self.number = 15
return self
def astr(self, prefix = "" ):
if (self.number == 31):
return "sp"
else :
return prefix + str(self.number)
def __str__(self):
if (self.number == 31):
return self.astr()
else :
return self.astr("r" )
class SVEVectorRegister(FloatRegister):
def __str__(self):
return self.astr("z" )
class SVEPRegister(Register):
def __str__(self):
return self.astr("p" )
def generate(self):
self.number = random.randint(0, 15)
return self
class SVEGoverningPRegister(Register):
def __str__(self):
return self.astr("p" )
def generate(self):
self.number = random.randint(0, 7)
return self
class RegVariant(object):
def __init__(self, low, high):
self.number = random.randint(low, high)
def astr(self):
nameMap = {
0: ".b" ,
1: ".h" ,
2: ".s" ,
3: ".d" ,
4: ".q"
}
return nameMap.get(self.number)
def cstr(self):
nameMap = {
0: "__ B" ,
1: "__ H" ,
2: "__ S" ,
3: "__ D" ,
4: "__ Q"
}
return nameMap.get(self.number)
class FloatZero(Operand):
def __str__(self):
return "0.0"
def astr(self, ignored):
return "#0.0"
class OperandFactory:
_modes = {'x' : GeneralRegister,
'w' : GeneralRegister,
'b' : FloatRegister,
'h' : FloatRegister,
's' : FloatRegister,
'd' : FloatRegister,
'z' : FloatZero,
'p' : SVEPRegister,
'P' : SVEGoverningPRegister,
'Z' : SVEVectorRegister}
@classmethod
def create(cls, mode):
return OperandFactory._modes[mode]()
class ShiftKind:
def generate(self):
self.kind = ["LSL" , "LSR" , "ASR" ][random.randint(0,2)]
return self
def cstr(self):
return self.kind
class Instruction(object):
def __init__(self, name):
self._name = name
self.isWord = name.endswith("w" ) | name.endswith("wi" )
self.asmRegPrefix = ["x" , "w" ][self.isWord]
self.isPostfixException = False
def aname(self):
if self.isPostfixException:
return self._name
elif (self._name.endswith("wi" )):
return self._name[:len(self._name)-2]
elif (self._name.endswith("i" ) | self._name.endswith("w" )):
return self._name[:len(self._name)-1]
else :
return self._name
def emit(self) :
pass
def compare(self) :
pass
def generate(self) :
return self
def cstr(self):
return '__ %s(' % self.name()
def astr(self):
return '%s\t' % self.aname()
def name(self):
name = self._name
if name == "and" :
name = "andr" # Special case: the name "and" can't be used
# in HotSpot, even for a member.
return name
def multipleForms(self):
return 0
class InstructionWithModes(Instruction):
def __init__(self, name, mode):
Instruction.__init__(self, name)
self.mode = mode
self.isFloat = (mode == 'd' ) | (mode == 's' )
if self.isFloat:
self.isWord = mode != 'd'
self.asmRegPrefix = ["d" , "s" ][self.isWord]
else :
self.isWord = mode != 'x'
self.asmRegPrefix = ["x" , "w" ][self.isWord]
def name(self):
return self._name + (self.mode if self.mode != 'x' else '' )
def aname(self):
return (self._name+mode if (mode == 'b' or mode == 'h' )
else self._name)
class ThreeRegInstruction(Instruction):
def generate(self):
self.reg = [GeneralRegister().generate(), GeneralRegister().generate(),
GeneralRegister().generate()]
return self
def cstr(self):
return (super(ThreeRegInstruction, self).cstr()
+ ('%s, %s, %s'
% (self.reg[0],
self.reg[1], self.reg[2])))
def astr(self):
prefix = self.asmRegPrefix
return (super(ThreeRegInstruction, self).astr()
+ ('%s, %s, %s'
% (self.reg[0].astr(prefix),
self.reg[1].astr(prefix), self.reg[2].astr(prefix))))
class FourRegInstruction(ThreeRegInstruction):
def generate(self):
self.reg = ThreeRegInstruction.generate(self).reg + [GeneralRegister().generate()]
return self
def cstr(self):
return (super(FourRegInstruction, self).cstr()
+ (', %s' % self.reg[3]))
def astr(self):
prefix = self.asmRegPrefix
return (super(FourRegInstruction, self).astr()
+ (', %s' % self.reg[3].astr(prefix)))
class TwoRegInstruction(Instruction):
def generate(self):
self.reg = [GeneralRegister().generate(), GeneralRegister().generate()]
return self
def cstr(self):
return (super(TwoRegInstruction, self).cstr()
+ '%s, %s' % (self.reg[0],
self.reg[1]))
def astr(self):
prefix = self.asmRegPrefix
return (super(TwoRegInstruction, self).astr()
+ ('%s, %s'
% (self.reg[0].astr(prefix),
self.reg[1].astr(prefix))))
class TwoRegImmedInstruction(TwoRegInstruction):
def generate(self):
super(TwoRegImmedInstruction, self).generate()
self.immed = random.randint(0, 1<<11 -1)
return self
def cstr(self):
return (super(TwoRegImmedInstruction, self).cstr()
+ ', %su' % self.immed)
def astr(self):
return (super(TwoRegImmedInstruction, self).astr()
+ ', #%s' % self.immed)
class OneRegOp(Instruction):
def generate(self):
self.reg = GeneralRegister().generate()
return self
def cstr(self):
return (super(OneRegOp, self).cstr()
+ '%s);' % self.reg)
def astr(self):
return (super(OneRegOp, self).astr()
+ '%s' % self.reg.astr(self.asmRegPrefix))
class PostfixExceptionOneRegOp(OneRegOp):
def __init__(self, op):
OneRegOp.__init__(self, op)
self.isPostfixException=True
class ArithOp(ThreeRegInstruction):
def generate(self):
super(ArithOp, self).generate()
self.kind = ShiftKind().generate()
self.distance = random.randint(0, (1<<5)-1 if self.isWord else (1<<6)-1)
return self
def cstr(self):
return ('%s, Assembler::%s, %s);'
% (ThreeRegInstruction.cstr(self),
self.kind.cstr(), self.distance))
def astr(self):
return ('%s, %s #%s'
% (ThreeRegInstruction.astr(self),
self.kind.cstr(),
self.distance))
class AddSubCarryOp(ThreeRegInstruction):
def cstr(self):
return ('%s);'
% (ThreeRegInstruction.cstr(self)))
class AddSubExtendedOp(ThreeRegInstruction):
uxtb, uxth, uxtw, uxtx, sxtb, sxth, sxtw, sxtx = range(8)
optNames = ["uxtb" , "uxth" , "uxtw" , "uxtx" , "sxtb" , "sxth" , "sxtw" , "sxtx" ]
def generate(self):
super(AddSubExtendedOp, self).generate()
self.amount = random.randint(1, 4)
self.option = random.randint(0, 7)
return self
def cstr(self):
return (super(AddSubExtendedOp, self).cstr()
+ (", ext::" + AddSubExtendedOp.optNames[self.option]
+ ", " + str(self.amount) + ");" ))
def astr(self):
return (super(AddSubExtendedOp, self).astr()
+ (", " + AddSubExtendedOp.optNames[self.option]
+ " #" + str(self.amount)))
class AddSubImmOp(TwoRegImmedInstruction):
def cstr(self):
return super(AddSubImmOp, self).cstr() + ");"
class LogicalImmOp(AddSubImmOp):
def generate(self):
AddSubImmOp.generate(self)
self.immed = \
immediates32[random.randint(0, len(immediates32)-1)] \
if self.isWord else \
immediates64[random.randint(0, len(immediates64)-1)]
return self
def astr(self):
return (super(TwoRegImmedInstruction, self).astr()
+ ', #0x%x' % self.immed)
def cstr(self):
return super(AddSubImmOp, self).cstr() + "ll);"
class SVEBinaryImmOp(Instruction):
def __init__(self, name):
reg = SVEVectorRegister().generate()
self.reg = [reg, reg]
self.numRegs = len(self.reg)
self._width = RegVariant(0, 3)
self._isLogical = False
if name in ["and" , "eor" , "orr" ]:
self._isLogical = True
Instruction.__init__(self, name)
def generate(self):
Instruction.generate(self)
self.immed = random.randint(0, (1<<8)-1)
if self._isLogical:
vectype = self._width.cstr()
if vectype == "__ B" :
self.immed = immediates8[random.randint(0, len(immediates8)-1)]
elif vectype == "__ H" :
self.immed = immediates16[random.randint(0, len(immediates16)-1)]
elif vectype == "__ S" :
self.immed = immediates32[random.randint(0, len(immediates32)-1)]
elif vectype == "__ D" :
self.immed = immediates64[random.randint(0, len(immediates64)-1)]
return self
def cstr(self):
formatStr = "%s%s, %s, %su);"
return (formatStr
% tuple(["__ sve_" + self._name + "(" ] +
[str(self.reg[0]), self._width.cstr(), self.immed]))
def astr(self):
formatStr = "%s%s, %s, #0x%x"
Regs = [str(self.reg[i]) + self._width.astr() for i in range(0, self.numRegs)]
return (formatStr
% tuple([Instruction.astr(self)] + Regs + [self.immed]))
class SVEComparisonWithZero(Instruction):
def __init__(self, arg):
Instruction.__init__(self, "fcm" )
self.condition = arg
self.dest = OperandFactory.create('p' ).generate()
self.reg = SVEVectorRegister().generate()
self._width = RegVariant(2, 3)
self.preg = OperandFactory.create('P' ).generate()
def generate(self):
return Instruction.generate(self)
def cstr(self):
return ("%s(%s, %s, %s, %s, %s, 0.0);"
% ("__ sve_" + self._name, "Assembler::" + self.condition,
str(self.dest), self._width.cstr(), str(self.preg), str(self.reg)))
def astr(self):
val = ("%s%s\t%s%s, %s/z, %s%s, #0.0"
% (self._name, self.condition.lower(), str(self.dest), self._width.astr(),
str(self.preg), str(self.reg), self._width.astr()))
return val
class MultiOp():
def multipleForms(self):
return 3
def forms(self):
return ["__ pc()" , "back" , "forth" ]
def aforms(self):
return ["." , "back" , "forth" ]
class AbsOp(MultiOp, Instruction):
def cstr(self):
return super(AbsOp, self).cstr() + "%s);"
def astr(self):
return Instruction.astr(self) + "%s"
class RegAndAbsOp(MultiOp, Instruction):
def multipleForms(self):
if self.name() == "adrp" :
# We can only test one form of adrp because anything other
# than "adrp ." requires relocs in the assembler output
return 1
return 3
def generate(self):
Instruction.generate(self)
self.reg = GeneralRegister().generate()
return self
def cstr(self):
if self.name() == "adrp" :
return "__ _adrp(" + "%s, %s);" % (self.reg, "%s" )
return (super(RegAndAbsOp, self).cstr()
+ "%s, %s);" % (self.reg, "%s" ))
def astr(self):
return (super(RegAndAbsOp, self).astr()
+ self.reg.astr(self.asmRegPrefix) + ", %s" )
class RegImmAbsOp(RegAndAbsOp):
def cstr(self):
return (Instruction.cstr(self)
+ "%s, %s, %s);" % (self.reg, self.immed, "%s" ))
def astr(self):
return (Instruction.astr(self)
+ ("%s, #%s, %s"
% (self.reg.astr(self.asmRegPrefix), self.immed, "%s" )))
def generate(self):
super(RegImmAbsOp, self).generate()
self.immed = random.randint(0, 1<<5 -1)
return self
class MoveWideImmOp(RegImmAbsOp):
def multipleForms(self):
return 0
def cstr(self):
return (Instruction.cstr(self)
+ "%s, %s, %s);" % (self.reg, self.immed, self.shift))
def astr(self):
return (Instruction.astr(self)
+ ("%s, #%s, lsl %s"
% (self.reg.astr(self.asmRegPrefix),
self.immed, self.shift)))
def generate(self):
super(RegImmAbsOp, self).generate()
self.immed = random.randint(0, 1<<16 -1)
if self.isWord:
self.shift = random.randint(0, 1) * 16
else :
self.shift = random.randint(0, 3) * 16
return self
class BitfieldOp(TwoRegInstruction):
def cstr(self):
return (Instruction.cstr(self)
+ ("%s, %s, %s, %s);"
% (self.reg[0], self.reg[1], self.immr, self.imms)))
def astr(self):
return (TwoRegInstruction.astr(self)
+ (", #%s, #%s"
% (self.immr, self.imms)))
def generate(self):
TwoRegInstruction.generate(self)
self.immr = random.randint(0, 31)
self.imms = random.randint(0, 31)
return self
class ExtractOp(ThreeRegInstruction):
def generate(self):
super(ExtractOp, self).generate()
self.lsb = random.randint(0, (1<<5)-1 if self.isWord else (1<<6)-1)
return self
def cstr(self):
return (ThreeRegInstruction.cstr(self)
+ (", %s);" % self.lsb))
def astr(self):
return (ThreeRegInstruction.astr(self)
+ (", #%s" % self.lsb))
class CondBranchOp(MultiOp, Instruction):
def cstr(self):
return "__ br(Assembler::" + self.name() + ", %s);"
def astr(self):
return "b." + self.name() + "\t%s"
class ImmOp(Instruction):
def cstr(self):
return "%s%s);" % (Instruction.cstr(self), self.immed)
def astr(self):
return Instruction.astr(self) + "#" + str(self.immed)
def generate(self):
self.immed = random.randint(0, 1<<16 -1)
return self
class Op(Instruction):
def cstr(self):
return Instruction.cstr(self) + ");"
def astr(self):
return self.aname();
class PostfixExceptionOp(Op):
def __init__(self, op):
Op.__init__(self, op)
self.isPostfixException=True
class SystemOp(Instruction):
def __init__(self, op):
Instruction.__init__(self, op[0])
self.barriers = op[1]
def generate(self):
Instruction.generate(self)
self.barrier \
= self.barriers[random.randint(0, len(self.barriers)-1)]
return self
def cstr(self):
return Instruction.cstr(self) + "Assembler::" + self.barrier + ");"
def astr(self):
return Instruction.astr(self) + self.barrier
conditionCodes = ["EQ" , "NE" , "HS" , "CS" , "LO" , "CC" , "MI" , "PL" , "VS" , \
"VC" , "HI" , "LS" , "GE" , "LT" , "GT" , "LE" , "AL" , "NV" ]
class ConditionalCompareOp(TwoRegImmedInstruction):
def generate(self):
TwoRegImmedInstruction.generate(self)
self.cond = random.randint(0, 15)
self.immed = random.randint(0, 15)
return self
def cstr(self):
return (super(ConditionalCompareOp, self).cstr() + ", "
+ "Assembler::" + conditionCodes[self.cond] + ");" )
def astr(self):
return (super(ConditionalCompareOp, self).astr() +
", " + conditionCodes[self.cond])
class ConditionalCompareImmedOp(Instruction):
def generate(self):
self.reg = GeneralRegister().generate()
self.cond = random.randint(0, 15)
self.immed2 = random.randint(0, 15)
self.immed = random.randint(0, 31)
return self
def cstr(self):
return (Instruction.cstr(self) + str(self.reg) + ", "
+ str(self.immed) + ", "
+ str(self.immed2) + ", "
+ "Assembler::" + conditionCodes[self.cond] + ");" )
def astr(self):
return (Instruction.astr(self)
+ self.reg.astr(self.asmRegPrefix)
+ ", #" + str(self.immed)
+ ", #" + str(self.immed2)
+ ", " + conditionCodes[self.cond])
class TwoRegOp(TwoRegInstruction):
def cstr(self):
return TwoRegInstruction.cstr(self) + ");"
class ThreeRegOp(ThreeRegInstruction):
def cstr(self):
return ThreeRegInstruction.cstr(self) + ");"
class FourRegMulOp(FourRegInstruction):
def cstr(self):
return FourRegInstruction.cstr(self) + ");"
def astr(self):
isMaddsub = self.name().startswith("madd" ) | self.name().startswith("msub" )
midPrefix = self.asmRegPrefix if isMaddsub else "w"
return (Instruction.astr(self)
+ self.reg[0].astr(self.asmRegPrefix)
+ ", " + self.reg[1].astr(midPrefix)
+ ", " + self.reg[2].astr(midPrefix)
+ ", " + self.reg[3].astr(self.asmRegPrefix))
class ConditionalSelectOp(ThreeRegInstruction):
def generate(self):
ThreeRegInstruction.generate(self)
self.cond = random.randint(0, 15)
return self
def cstr(self):
return (ThreeRegInstruction.cstr(self) + ", "
+ "Assembler::" + conditionCodes[self.cond] + ");" )
def astr(self):
return (ThreeRegInstruction.astr(self)
+ ", " + conditionCodes[self.cond])
class LoadStoreExclusiveOp(InstructionWithModes):
def __init__(self, op): # op is a tuple of ["name", "mode", registers]
InstructionWithModes.__init__(self, op[0], op[1])
self.num_registers = op[2]
def astr(self):
result = self.aname() + '\t'
regs = list(self.regs)
index = regs.pop() # The last reg is the index register
prefix = ('x' if (self.mode == 'x' )
& ((self.name().startswith("ld" ))
| (self.name().startswith("stlr" ))) # Ewww :-(
else 'w' )
result = result + regs.pop(0).astr(prefix) + ", "
for s in regs:
result = result + s.astr(self.asmRegPrefix) + ", "
result = result + "[" + index.astr("x" ) + "]"
return result
def cstr(self):
result = InstructionWithModes.cstr(self)
regs = list(self.regs)
index = regs.pop() # The last reg is the index register
for s in regs:
result = result + str(s) + ", "
result = result + str(index) + ");"
return result
def appendUniqueReg(self):
result = 0
while result == 0:
newReg = GeneralRegister().generate()
result = 1
for i in self.regs:
result = result and (i.number != newReg.number)
self.regs.append(newReg)
def generate(self):
self.regs = []
for i in range(self.num_registers):
self.appendUniqueReg()
return self
def name(self):
if self.mode == 'x' :
return self._name
else :
return self._name + self.mode
def aname(self):
if (self.mode == 'b' ) | (self.mode == 'h' ):
return self._name + self.mode
else :
return self._name
class Address(object):
base_plus_unscaled_offset, pre, post, base_plus_reg, \
base_plus_scaled_offset, pcrel, post_reg, base_only = range(8)
kinds = ["base_plus_unscaled_offset" , "pre" , "post" , "base_plus_reg" ,
"base_plus_scaled_offset" , "pcrel" , "post_reg" , "base_only" ]
extend_kinds = ["uxtw" , "lsl" , "sxtw" , "sxtx" ]
@classmethod
def kindToStr(cls, i):
return cls.kinds[i]
def generate(self, kind, shift_distance):
self.kind = kind
self.base = GeneralRegister().generate()
self.index = GeneralRegister().generate()
self.offset = {
Address.base_plus_unscaled_offset: random.randint(-1<<8, 1<<8-1) | 1,
Address.pre: random.randint(-1<<8, 1<<8-1),
Address.post: random.randint(-1<<8, 1<<8-1),
Address.pcrel: random.randint(0, 2),
Address.base_plus_reg: 0,
Address.base_plus_scaled_offset: (random.randint(0, 1<<11-1) | (3 << 9))*8,
Address.post_reg: 0,
Address.base_only: 0} [kind]
self.offset >>= (3 - shift_distance)
self.extend_kind = Address.extend_kinds[random.randint(0, 3)]
self.shift_distance = random.randint(0, 1) * shift_distance
return self
def __str__(self):
result = {
Address.base_plus_unscaled_offset: "Address(%s, %s)" \
% (str(self.base), self.offset),
Address.pre: "Address(__ pre(%s, %s))" % (str(self.base), self.offset),
Address.post: "Address(__ post(%s, %s))" % (str(self.base), self.offset),
Address.post_reg: "Address(__ post(%s, %s))" % (str(self.base), self.index),
Address.base_only: "Address(%s)" % (str(self.base)),
Address.pcrel: "" ,
Address.base_plus_reg: "Address(%s, %s, Address::%s(%s))" \
% (self.base, self.index, self.extend_kind, self.shift_distance),
Address.base_plus_scaled_offset:
"Address(%s, %s)" % (self.base, self.offset) } [self.kind]
if (self.kind == Address.pcrel):
result = ["__ pc()" , "back" , "forth" ][self.offset]
return result
def astr(self, prefix):
extend_prefix = prefix
if self.kind == Address.base_plus_reg:
if self.extend_kind.endswith("w" ):
extend_prefix = "w"
result = {
Address.base_plus_unscaled_offset: "[%s, %s]" \
% (self.base.astr(prefix), self.offset),
Address.pre: "[%s, %s]!" % (self.base.astr(prefix), self.offset),
Address.post: "[%s], %s" % (self.base.astr(prefix), self.offset),
Address.post_reg: "[%s], %s" % (self.base.astr(prefix), self.index.astr(prefix)),
Address.base_only: "[%s]" % (self.base.astr(prefix)),
Address.pcrel: "" ,
Address.base_plus_reg: "[%s, %s, %s #%s]" \
% (self.base.astr(prefix), self.index.astr(extend_prefix),
self.extend_kind, self.shift_distance),
Address.base_plus_scaled_offset: \
"[%s, %s]" \
% (self.base.astr(prefix), self.offset)
} [self.kind]
if (self.kind == Address.pcrel):
result = ["." , "back" , "forth" ][self.offset]
return result
class LoadStoreOp(InstructionWithModes):
def __init__(self, args):
name, self.asmname, self.kind, mode = args
InstructionWithModes.__init__(self, name, mode)
def generate(self):
# This is something of a kludge, but the offset needs to be
# scaled by the memory datamode somehow.
shift = 3
if (self.mode == 'b' ) | (self.asmname.endswith("b" )):
shift = 0
elif (self.mode == 'h' ) | (self.asmname.endswith("h" )):
shift = 1
elif (self.mode == 'w' ) | (self.asmname.endswith("w" )) \
| (self.mode == 's' ) :
shift = 2
self.adr = Address().generate(self.kind, shift)
isFloat = (self.mode == 'd' ) | (self.mode == 's' )
regMode = FloatRegister if isFloat else GeneralRegister
self.reg = regMode().generate()
kindStr = Address.kindToStr(self.kind);
if (not isFloat) and (kindStr is "pre" or kindStr is "post" ):
(self.reg.number, self.adr.base.number) = random.sample(list(set(range(31)) - set([18])), 2)
return self
def cstr(self):
if not (self._name.startswith("prfm" )):
return "%s%s, %s);" % (Instruction.cstr(self), str(self.reg), str(self.adr))
else : # No target register for a prefetch
return "%s%s);" % (Instruction.cstr(self), str(self.adr))
def astr(self):
if not (self._name.startswith("prfm" )):
return "%s\t%s, %s" % (self.aname(), self.reg.astr(self.asmRegPrefix),
self.adr.astr("x" ))
else : # No target register for a prefetch
return "%s %s" % (self.aname(),
self.adr.astr("x" ))
def aname(self):
result = self.asmname
# if self.kind == Address.base_plus_unscaled_offset:
# result = result.replace("ld", "ldu", 1)
# result = result.replace("st", "stu", 1)
return result
class LoadStorePairOp(InstructionWithModes):
numRegs = 2
def __init__(self, args):
name, self.asmname, self.kind, mode = args
InstructionWithModes.__init__(self, name, mode)
self.offset = random.randint(-1<<4, 1<<4-1) << 4
def generate(self):
self.reg = [OperandFactory.create(self.mode).generate()
for i in range(self.numRegs)]
self.base = OperandFactory.create('x' ).generate()
kindStr = Address.kindToStr(self.kind);
if kindStr is "pre" or kindStr is "post" :
if self._name.startswith("ld" ):
(self.reg[0].number, self.reg[1].number, self.base.number) = random.sample(list(set(range(31)) - set([18])), 3)
if self._name.startswith("st" ):
self.base.number = random.choice(list(set(range(31)) - set([self.reg[0].number, self.reg[1].number, 18])))
elif self._name.startswith("ld" ):
(self.reg[0].number, self.reg[1].number) = random.sample(list(set(range(31)) - set([18])), 2)
return self
def astr(self):
address = ["[%s, #%s]", "[%s, #%s]!", "[%s], #%s"][self.kind]
address = address % (self.base.astr('x' ), self.offset)
result = "%s\t%s, %s, %s" \
% (self.asmname,
self.reg[0].astr(self.asmRegPrefix),
self.reg[1].astr(self.asmRegPrefix), address)
return result
def cstr(self):
address = {
Address.base_plus_unscaled_offset: "Address(%s, %s)" \
% (str(self.base), self.offset),
Address.pre: "Address(__ pre(%s, %s))" % (str(self.base), self.offset),
Address.post: "Address(__ post(%s, %s))" % (str(self.base), self.offset),
} [self.kind]
result = "__ %s(%s, %s, %s);" \
% (self.name(), self.reg[0], self.reg[1], address)
return result
class FloatInstruction(Instruction):
def aname(self):
if (self._name in ["fcvtsh" , "fcvths" ]):
return self._name[:len(self._name)-2]
elif (self._name.endswith("s" ) | self._name.endswith("d" )):
return self._name[:len(self._name)-1]
else :
return self._name
def __init__(self, args):
name, self.modes = args
Instruction.__init__(self, name)
def generate(self):
self.reg = [OperandFactory.create(self.modes[i]).generate()
for i in range(self.numRegs)]
return self
def cstr(self):
formatStr = "%s%s" + '' .join([", %s" for i in range(1, self.numRegs)] + [");" ])
return (formatStr
% tuple([Instruction.cstr(self)] +
[str(self.reg[i]) for i in range(self.numRegs)])) # Yowza
def astr(self):
formatStr = "%s%s" + '' .join([", %s" for i in range(1, self.numRegs)])
return (formatStr
% tuple([Instruction.astr(self)] +
[(self.reg[i].astr(self.modes[i])) for i in range(self.numRegs)]))
class SVEVectorOp(Instruction):
def __init__(self, args):
name = args[0]
regTypes = args[1]
regs = []
for c in regTypes:
regs.append(OperandFactory.create(c).generate())
self.reg = regs
self.numRegs = len(regs)
if regTypes[0] != "p" and regTypes[1] == 'P' :
self._isPredicated = True
assert len(args) > 2, "Must specify predicate type"
for arg in args[2:]:
if arg == 'm' :
self._merge = "/m"
elif arg == 'z' :
self._merge = "/z"
else :
assert arg == "dn" , "Unknown predicate type"
else :
self._isPredicated = False
self._merge = ""
self._bitwiseop = False
if name[0] == 'f' :
self._width = RegVariant(2, 3)
elif not self._isPredicated and (name in ["and" , "eor" , "orr" , "bic" , "eor3" ]):
self._width = RegVariant(3, 3)
self._bitwiseop = True
elif name == "revb" :
self._width = RegVariant(1, 3)
else :
self._width = RegVariant(0, 3)
self._dnm = None
if len(args) > 2:
for arg in args[2:]:
if arg == "dn" :
self._dnm = arg
Instruction.__init__(self, name)
def cstr(self):
formatStr = "%s%s" + '' .join([", %s" for i in range(0, self.numRegs)] + [");" ])
if self._bitwiseop:
width = []
formatStr = "%s%s" + '' .join([", %s" for i in range(1, self.numRegs)] + [");" ])
else :
width = [self._width.cstr()]
return (formatStr
% tuple(["__ sve_" + self._name + "(" ] +
[str(self.reg[0])] +
width +
[str(self.reg[i]) for i in range(1, self.numRegs)]))
def astr(self):
firstArg = 0 if self._name == "eor3" else 1
formatStr = "%s%s" + '' .join([", %s" for i in range(firstArg, self.numRegs)])
if self._dnm == 'dn' :
formatStr += ", %s"
dnReg = [str(self.reg[0]) + self._width.astr()]
else :
dnReg = []
if self._isPredicated:
restRegs = [str(self.reg[1]) + self._merge] + dnReg + [str(self.reg[i]) + self._width.astr() for i in range(2, self.numRegs)]
else :
restRegs = dnReg + [str(self.reg[i]) + self._width.astr() for i in range(firstArg, self.numRegs)]
return (formatStr
% tuple([Instruction.astr(self)] +
[str(self.reg[0]) + self._width.astr()] +
restRegs))
def generate(self):
return self
class SVEReductionOp(Instruction):
def __init__(self, args):
name = args[0]
lowRegType = args[1]
self.reg = []
Instruction.__init__(self, name)
self.reg.append(OperandFactory.create('s' ).generate())
self.reg.append(OperandFactory.create('P' ).generate())
self.reg.append(OperandFactory.create('Z' ).generate())
self._width = RegVariant(lowRegType, 3)
def cstr(self):
return "__ sve_%s(%s, %s, %s, %s);" % (self.name(),
str(self.reg[0]),
self._width.cstr(),
str(self.reg[1]),
str(self.reg[2]))
def astr(self):
if self.name() == "uaddv" :
dstRegName = "d" + str(self.reg[0].number)
else :
dstRegName = self._width.astr()[1] + str(self.reg[0].number)
formatStr = "%s %s, %s, %s"
if self.name() == "fadda" :
formatStr += ", %s"
moreReg = [dstRegName]
else :
moreReg = []
return formatStr % tuple([self.name()] +
[dstRegName] +
[str(self.reg[1])] +
moreReg +
[str(self.reg[2]) + self._width.astr()])
class LdStNEONOp(Instruction):
def __init__(self, args):
self._name, self.regnum, self.arrangement, self.addresskind = args
def generate(self):
self.address = Address().generate(self.addresskind, 0)
self._firstSIMDreg = FloatRegister().generate()
if (self.addresskind == Address.post):
if (self._name in ["ld1r" , "ld2r" , "ld3r" , "ld4r" ]):
elem_size = {"8B" : 1, "16B" : 1, "4H" : 2, "8H" : 2, "2S" : 4, "4S" : 4, "1D" : 8, "2D" : 8} [self.arrangement]
self.address.offset = self.regnum * elem_size
else :
if (self.arrangement in ["8B" , "4H" , "2S" , "1D" ]):
self.address.offset = self.regnum * 8
else :
self.address.offset = self.regnum * 16
return self
def cstr(self):
buf = super(LdStNEONOp, self).cstr() + str(self._firstSIMDreg)
current = self._firstSIMDreg
for cnt in range(1, self.regnum):
buf = '%s, %s' % (buf, current.nextReg())
current = current.nextReg()
return '%s, __ T%s, %s);' % (buf, self.arrangement, str(self.address))
def astr(self):
buf = '%s\t{%s.%s' % (self._name, self._firstSIMDreg, self.arrangement)
current = self._firstSIMDreg
for cnt in range(1, self.regnum):
buf = '%s, %s.%s' % (buf, current.nextReg(), self.arrangement)
current = current.nextReg()
return '%s}, %s' % (buf, self.address.astr("x" ))
def aname(self):
return self._name
class NEONReduceInstruction(Instruction):
def __init__(self, args):
self._name, self.insname, self.arrangement = args
def generate(self):
current = FloatRegister().generate()
self.dstSIMDreg = current
self.srcSIMDreg = current.nextReg()
return self
def cstr(self):
buf = Instruction.cstr(self) + str(self.dstSIMDreg)
if self._name == "fmaxp" or self._name == "fminp" :
buf = '%s, %s, __ %s);' % (buf, self.srcSIMDreg, self.arrangement[1:])
else :
buf = '%s, __ T%s, %s);' % (buf, self.arrangement, self.srcSIMDreg)
return buf
def astr(self):
buf = '%s\t%s' % (self.insname, self.dstSIMDreg.astr(self.arrangement[-1].lower()))
buf = '%s, %s.%s' % (buf, self.srcSIMDreg, self.arrangement)
return buf
def aname(self):
return self._name
class CommonNEONInstruction(Instruction):
def __init__(self, args):
self._name, self.insname, self.arrangement = args
def generate(self):
self._firstSIMDreg = FloatRegister().generate()
return self
def cstr(self):
buf = Instruction.cstr(self) + str(self._firstSIMDreg)
buf = '%s, __ T%s' % (buf, self.arrangement)
current = self._firstSIMDreg
for cnt in range(1, self.numRegs):
buf = '%s, %s' % (buf, current.nextReg())
current = current.nextReg()
return '%s);' % (buf)
def astr(self):
buf = '%s\t%s.%s' % (self.insname, self._firstSIMDreg, self.arrangement)
current = self._firstSIMDreg
for cnt in range(1, self.numRegs):
buf = '%s, %s.%s' % (buf, current.nextReg(), self.arrangement)
current = current.nextReg()
return buf
def aname(self):
return self._name
class SHA512SIMDOp(Instruction):
def generate(self):
if (self._name == 'sha512su0' ):
self.reg = [FloatRegister().generate(), FloatRegister().generate()]
else :
self.reg = [FloatRegister().generate(), FloatRegister().generate(),
FloatRegister().generate()]
return self
def cstr(self):
if (self._name == 'sha512su0' ):
return (super(SHA512SIMDOp, self).cstr()
+ ('%s, __ T2D, %s);' % (self.reg[0], self.reg[1])))
else :
return (super(SHA512SIMDOp, self).cstr()
+ ('%s, __ T2D, %s, %s);' % (self.reg[0], self.reg[1], self.reg[2])))
def astr(self):
if (self._name == 'sha512su0' ):
return (super(SHA512SIMDOp, self).astr()
+ ('\t%s.2D, %s.2D' % (self.reg[0].astr("v" ), self.reg[1].astr("v" ))))
elif (self._name == 'sha512su1' ):
return (super(SHA512SIMDOp, self).astr()
+ ('\t%s.2D, %s.2D, %s.2D' % (self.reg[0].astr("v" ),
self.reg[1].astr("v" ), self.reg[2].astr("v" ))))
else :
return (super(SHA512SIMDOp, self).astr()
+ ('\t%s, %s, %s.2D' % (self.reg[0].astr("q" ),
self.reg[1].astr("q" ), self.reg[2].astr("v" ))))
class SHA3SIMDOp(Instruction):
def generate(self):
if ((self._name == 'eor3' ) or (self._name == 'bcax' )):
self.reg = [FloatRegister().generate(), FloatRegister().generate(),
FloatRegister().generate(), FloatRegister().generate()]
else :
self.reg = [FloatRegister().generate(), FloatRegister().generate(),
FloatRegister().generate()]
if (self._name == 'xar' ):
self.imm6 = random.randint(0, 63)
return self
def cstr(self):
if ((self._name == 'eor3' ) or (self._name == 'bcax' )):
return (super(SHA3SIMDOp, self).cstr()
+ ('%s, __ T16B, %s, %s, %s);' % (self.reg[0], self.reg[1], self.reg[2], self.reg[3])))
elif (self._name == 'rax1' ):
return (super(SHA3SIMDOp, self).cstr()
+ ('%s, __ T2D, %s, %s);' % (self.reg[0], self.reg[1], self.reg[2])))
else :
return (super(SHA3SIMDOp, self).cstr()
+ ('%s, __ T2D, %s, %s, %s);' % (self.reg[0], self.reg[1], self.reg[2], self.imm6)))
def astr(self):
if ((self._name == 'eor3' ) or (self._name == 'bcax' )):
return (super(SHA3SIMDOp, self).astr()
+ ('\t%s.16B, %s.16B, %s.16B, %s.16B' % (self.reg[0].astr("v" ), self.reg[1].astr("v" ),
self.reg[2].astr("v" ), self.reg[3].astr("v" ))))
elif (self._name == 'rax1' ):
return (super(SHA3SIMDOp, self).astr()
+ ('\t%s.2D, %s.2D, %s.2D' ) % (self.reg[0].astr("v" ), self.reg[1].astr("v" ),
self.reg[2].astr("v" )))
else :
return (super(SHA3SIMDOp, self).astr()
+ ('\t%s.2D, %s.2D, %s.2D, #%s') % (self.reg[0].astr("v"), self.reg[1].astr("v"),
self.reg[2].astr("v" ), self.imm6))
class LSEOp(Instruction):
def __init__(self, args):
self._name, self.asmname, self.size, self.suffix = args
def generate(self):
self._name = "%s%s" % (self._name, self.suffix)
self.asmname = "%s%s" % (self.asmname, self.suffix)
self.srcReg = GeneralRegisterOrZr().generate()
self.tgtReg = GeneralRegisterOrZr().generate()
self.adrReg = GeneralRegisterOrSp().generate()
return self
def cstr(self):
sizeSpec = {"x" : "Assembler::xword" , "w" : "Assembler::word" } [self.size]
return super(LSEOp, self).cstr() + "%s, %s, %s, %s);" % (sizeSpec, self.srcReg, self.tgtReg, self.adrReg)
def astr(self):
return "%s\t%s, %s, [%s]" % (self.asmname, self.srcReg.astr(self.size), self.tgtReg.astr(self.size), self.adrReg.astr("x" ))
def aname(self):
return self.asmname
class TwoRegFloatOp(FloatInstruction):
numRegs = 2
class ThreeRegFloatOp(TwoRegFloatOp):
numRegs = 3
class FourRegFloatOp(TwoRegFloatOp):
numRegs = 4
class FloatConvertOp(TwoRegFloatOp):
def __init__(self, args):
self._cname, self._aname, modes = args
TwoRegFloatOp.__init__(self, [self._cname, modes])
def aname(self):
return self._aname
def cname(self):
return self._cname
class TwoRegNEONOp(CommonNEONInstruction):
numRegs = 2
class ThreeRegNEONOp(TwoRegNEONOp):
numRegs = 3
class SpecialCases(Instruction):
def __init__(self, data):
self._name = data[0]
self._cstr = data[1]
self._astr = data[2]
def cstr(self):
return self._cstr
def astr(self):
return self._astr
def generate(kind, names):
outfile.write("# " + kind.__name__ + "\n");
print "\n// " + kind.__name__
for name in names:
for i in range(1):
op = kind(name).generate()
if op.multipleForms():
forms = op.forms()
aforms = op.aforms()
for i in range(op.multipleForms()):
cstr = op.cstr() % forms[i]
astr = op.astr() % aforms[i]
print " %-50s //\t%s" % (cstr, astr)
outfile.write("\t" + astr + "\n" )
else :
print " %-50s //\t%s" % (op.cstr(), op.astr())
outfile.write("\t" + op.astr() + "\n" )
outfile = open("aarch64ops.s" , "w" )
# To minimize the changes of assembler test code
random.seed(0)
print "// BEGIN Generated code -- do not edit"
print "// Generated by aarch64-asmtest.py"
print " Label back, forth;"
print " __ bind(back);"
outfile.write("back:\n" )
generate (ArithOp,
[ "add" , "sub" , "adds" , "subs" ,
"addw" , "subw" , "addsw" , "subsw" ,
"and" , "orr" , "eor" , "ands" ,
"andw" , "orrw" , "eorw" , "andsw" ,
"bic" , "orn" , "eon" , "bics" ,
"bicw" , "ornw" , "eonw" , "bicsw" ])
generate (AddSubImmOp,
[ "addw" , "addsw" , "subw" , "subsw" ,
"add" , "adds" , "sub" , "subs" ])
generate (LogicalImmOp,
[ "andw" , "orrw" , "eorw" , "andsw" ,
"and" , "orr" , "eor" , "ands" ])
generate (AbsOp, [ "b" , "bl" ])
generate (RegAndAbsOp, ["cbzw" , "cbnzw" , "cbz" , "cbnz" , "adr" , "adrp" ])
generate (RegImmAbsOp, ["tbz" , "tbnz" ])
generate (MoveWideImmOp, ["movnw" , "movzw" , "movkw" , "movn" , "movz" , "movk" ])
generate (BitfieldOp, ["sbfm" , "bfmw" , "ubfmw" , "sbfm" , "bfm" , "ubfm" ])
generate (ExtractOp, ["extrw" , "extr" ])
generate (CondBranchOp, ["EQ" , "NE" , "HS" , "CS" , "LO" , "CC" , "MI" , "PL" , "VS" , "VC" ,
"HI" , "LS" , "GE" , "LT" , "GT" , "LE" , "AL" , "NV" ])
generate (ImmOp, ["svc" , "hvc" , "smc" , "brk" , "hlt" , # "dcps1", "dcps2", "dcps3"
])
generate (Op, ["nop" , "yield" , "wfe" , "sev" , "sevl" ,
"autia1716" , "autiasp" , "autiaz" , "autib1716" , "autibsp" , "autibz" ,
"pacia1716" , "paciasp" , "paciaz" , "pacib1716" , "pacibsp" , "pacibz" ,
"eret" , "drps" , "isb" ,])
# Ensure the "i" is not stripped off the end of the instruction
generate (PostfixExceptionOp, ["wfi" , "xpaclri" ])
barriers = ["OSHLD" , "OSHST" , "OSH" , "NSHLD" , "NSHST" , "NSH" ,
"ISHLD" , "ISHST" , "ISH" , "LD" , "ST" , "SY" ]
generate (SystemOp, [["dsb" , barriers], ["dmb" , barriers]])
generate (OneRegOp, ["br" , "blr" ,
"paciza" , "pacizb" , "pacdza" , "pacdzb" ,
"autiza" , "autizb" , "autdza" , "autdzb" , "xpacd" ,
"braaz" , "brabz" , "blraaz" , "blrabz" ])
# Ensure the "i" is not stripped off the end of the instruction
generate (PostfixExceptionOneRegOp, ["xpaci" ])
for mode in 'xwhb' :
generate (LoadStoreExclusiveOp, [["stxr" , mode, 3], ["stlxr" , mode, 3],
["ldxr" , mode, 2], ["ldaxr" , mode, 2],
["stlr" , mode, 2], ["ldar" , mode, 2]])
for mode in 'xw' :
generate (LoadStoreExclusiveOp, [["ldxp" , mode, 3], ["ldaxp" , mode, 3],
["stxp" , mode, 4], ["stlxp" , mode, 4]])
for kind in range(6):
sys.stdout.write("\n// " + Address.kindToStr(kind))
if kind != Address.pcrel:
generate (LoadStoreOp,
[["str" , "str" , kind, "x" ], ["str" , "str" , kind, "w" ],
["str" , "strb" , kind, "b" ], ["str" , "strh" , kind, "h" ],
["ldr" , "ldr" , kind, "x" ], ["ldr" , "ldr" , kind, "w" ],
["ldr" , "ldrb" , kind, "b" ], ["ldr" , "ldrh" , kind, "h" ],
["ldrsb" , "ldrsb" , kind, "x" ], ["ldrsh" , "ldrsh" , kind, "x" ],
["ldrsh" , "ldrsh" , kind, "w" ], ["ldrsw" , "ldrsw" , kind, "x" ],
["ldr" , "ldr" , kind, "d" ], ["ldr" , "ldr" , kind, "s" ],
["str" , "str" , kind, "d" ], ["str" , "str" , kind, "s" ],
])
else :
generate (LoadStoreOp,
[["ldr" , "ldr" , kind, "x" ], ["ldr" , "ldr" , kind, "w" ]])
for kind in (Address.base_plus_unscaled_offset, Address.pcrel, Address.base_plus_reg, \
Address.base_plus_scaled_offset):
generate (LoadStoreOp,
[["prfm" , "prfm\tPLDL1KEEP," , kind, "x" ]])
generate(AddSubCarryOp, ["adcw" , "adcsw" , "sbcw" , "sbcsw" , "adc" , "adcs" , "sbc" , "sbcs" ])
generate(AddSubExtendedOp, ["addw" , "addsw" , "sub" , "subsw" , "add" , "adds" , "sub" , "subs" ])
generate(ConditionalCompareOp, ["ccmnw" , "ccmpw" , "ccmn" , "ccmp" ])
generate(ConditionalCompareImmedOp, ["ccmnw" , "ccmpw" , "ccmn" , "ccmp" ])
generate(ConditionalSelectOp,
["cselw" , "csincw" , "csinvw" , "csnegw" , "csel" , "csinc" , "csinv" , "csneg" ])
generate(TwoRegOp,
["rbitw" , "rev16w" , "revw" , "clzw" , "clsw" , "rbit" ,
"rev16" , "rev32" , "rev" , "clz" , "cls" ,
"pacia" , "pacib" , "pacda" , "pacdb" , "autia" , "autib" , "autda" , "autdb" ,
"braa" , "brab" , "blraa" , "blrab" ])
generate(ThreeRegOp,
["udivw" , "sdivw" , "lslvw" , "lsrvw" , "asrvw" , "rorvw" , "udiv" , "sdiv" ,
"lslv" , "lsrv" , "asrv" , "rorv" , "umulh" , "smulh" ])
generate(FourRegMulOp,
["maddw" , "msubw" , "madd" , "msub" , "smaddl" , "smsubl" , "umaddl" , "umsubl" ])
generate(ThreeRegFloatOp,
[["fabds" , "sss" ], ["fmuls" , "sss" ], ["fdivs" , "sss" ], ["fadds" , "sss" ], ["fsubs" , "sss" ],
["fabdd" , "ddd" ], ["fmuld" , "ddd" ], ["fdivd" , "ddd" ], ["faddd" , "ddd" ], ["fsubd" , "ddd" ],
])
generate(FourRegFloatOp,
[["fmadds" , "ssss" ], ["fmsubs" , "ssss" ], ["fnmadds" , "ssss" ], ["fnmadds" , "ssss" ],
["fmaddd" , "dddd" ], ["fmsubd" , "dddd" ], ["fnmaddd" , "dddd" ], ["fnmaddd" , "dddd" ],])
generate(TwoRegFloatOp,
[["fmovs" , "ss" ], ["fabss" , "ss" ], ["fnegs" , "ss" ], ["fsqrts" , "ss" ],
["fcvts" , "ds" ], ["fcvtsh" , "hs" ], ["fcvths" , "sh" ],
["fmovd" , "dd" ], ["fabsd" , "dd" ], ["fnegd" , "dd" ], ["fsqrtd" , "dd" ],
["fcvtd" , "sd" ],
])
generate(FloatConvertOp, [["fcvtzsw" , "fcvtzs" , "ws" ], ["fcvtzs" , "fcvtzs" , "xs" ],
["fcvtzdw" , "fcvtzs" , "wd" ], ["fcvtzd" , "fcvtzs" , "xd" ],
["scvtfws" , "scvtf" , "sw" ], ["scvtfs" , "scvtf" , "sx" ],
["scvtfwd" , "scvtf" , "dw" ], ["scvtfd" , "scvtf" , "dx" ],
["fcvtassw" , "fcvtas" , "ws" ], ["fcvtasd" , "fcvtas" , "xd" ],
["fcvtmssw" , "fcvtms" , "ws" ], ["fcvtmsd" , "fcvtms" , "xd" ],
["fmovs" , "fmov" , "ws" ], ["fmovd" , "fmov" , "xd" ],
["fmovs" , "fmov" , "sw" ], ["fmovd" , "fmov" , "dx" ]])
generate(TwoRegFloatOp, [["fcmps" , "ss" ], ["fcmpd" , "dd" ],
["fcmps" , "sz" ], ["fcmpd" , "dz" ]])
for kind in range(3):
generate(LoadStorePairOp, [["stp" , "stp" , kind, "w" ], ["ldp" , "ldp" , kind, "w" ],
["ldpsw" , "ldpsw" , kind, "x" ],
["stp" , "stp" , kind, "x" ], ["ldp" , "ldp" , kind, "x" ]
])
generate(LoadStorePairOp, [["stnp" , "stnp" , 0, "w" ], ["ldnp" , "ldnp" , 0, "w" ],
["stnp" , "stnp" , 0, "x" ], ["ldnp" , "ldnp" , 0, "x" ]])
generate(LdStNEONOp, [["ld1" , 1, "8B" , Address.base_only],
["ld1" , 2, "16B" , Address.post],
["ld1" , 3, "1D" , Address.post_reg],
["ld1" , 4, "8H" , Address.post],
["ld1r" , 1, "8B" , Address.base_only],
["ld1r" , 1, "4S" , Address.post],
["ld1r" , 1, "1D" , Address.post_reg],
["ld2" , 2, "2D" , Address.base_only],
["ld2" , 2, "4H" , Address.post],
["ld2r" , 2, "16B" , Address.base_only],
["ld2r" , 2, "2S" , Address.post],
["ld2r" , 2, "2D" , Address.post_reg],
["ld3" , 3, "4S" , Address.post_reg],
["ld3" , 3, "2S" , Address.base_only],
["ld3r" , 3, "8H" , Address.base_only],
["ld3r" , 3, "4S" , Address.post],
["ld3r" , 3, "1D" , Address.post_reg],
["ld4" , 4, "8H" , Address.post],
["ld4" , 4, "8B" , Address.post_reg],
["ld4r" , 4, "8B" , Address.base_only],
["ld4r" , 4, "4H" , Address.post],
["ld4r" , 4, "2S" , Address.post_reg],
])
generate(NEONReduceInstruction,
[["addv" , "addv" , "8B" ], ["addv" , "addv" , "16B" ],
["addv" , "addv" , "4H" ], ["addv" , "addv" , "8H" ],
["addv" , "addv" , "4S" ],
["smaxv" , "smaxv" , "8B" ], ["smaxv" , "smaxv" , "16B" ],
["smaxv" , "smaxv" , "4H" ], ["smaxv" , "smaxv" , "8H" ],
["smaxv" , "smaxv" , "4S" ], ["fmaxv" , "fmaxv" , "4S" ],
["sminv" , "sminv" , "8B" ], ["uminv" , "uminv" , "8B" ],
["sminv" , "sminv" , "16B" ],["uminv" , "uminv" , "16B" ],
["sminv" , "sminv" , "4H" ], ["uminv" , "uminv" , "4H" ],
["sminv" , "sminv" , "8H" ], ["uminv" , "uminv" , "8H" ],
["sminv" , "sminv" , "4S" ], ["uminv" , "uminv" , "4S" ],
["fminv" , "fminv" , "4S" ],
["fmaxp" , "fmaxp" , "2S" ], ["fmaxp" , "fmaxp" , "2D" ],
["fminp" , "fminp" , "2S" ], ["fminp" , "fminp" , "2D" ],
])
generate(TwoRegNEONOp,
[["absr" , "abs" , "8B" ], ["absr" , "abs" , "16B" ],
["absr" , "abs" , "4H" ], ["absr" , "abs" , "8H" ],
["absr" , "abs" , "2S" ], ["absr" , "abs" , "4S" ],
["absr" , "abs" , "2D" ],
["fabs" , "fabs" , "2S" ], ["fabs" , "fabs" , "4S" ],
["fabs" , "fabs" , "2D" ],
["fneg" , "fneg" , "2S" ], ["fneg" , "fneg" , "4S" ],
["fneg" , "fneg" , "2D" ],
["fsqrt" , "fsqrt" , "2S" ], ["fsqrt" , "fsqrt" , "4S" ],
["fsqrt" , "fsqrt" , "2D" ],
["notr" , "not" , "8B" ], ["notr" , "not" , "16B" ],
])
generate(ThreeRegNEONOp,
[["andr" , "and" , "8B" ], ["andr" , "and" , "16B" ],
["orr" , "orr" , "8B" ], ["orr" , "orr" , "16B" ],
["eor" , "eor" , "8B" ], ["eor" , "eor" , "16B" ],
["addv" , "add" , "8B" ], ["addv" , "add" , "16B" ],
["addv" , "add" , "4H" ], ["addv" , "add" , "8H" ],
["addv" , "add" , "2S" ], ["addv" , "add" , "4S" ],
["addv" , "add" , "2D" ],
["fadd" , "fadd" , "2S" ], ["fadd" , "fadd" , "4S" ],
["fadd" , "fadd" , "2D" ],
["subv" , "sub" , "8B" ], ["subv" , "sub" , "16B" ],
["subv" , "sub" , "4H" ], ["subv" , "sub" , "8H" ],
["subv" , "sub" , "2S" ], ["subv" , "sub" , "4S" ],
["subv" , "sub" , "2D" ],
["fsub" , "fsub" , "2S" ], ["fsub" , "fsub" , "4S" ],
["fsub" , "fsub" , "2D" ],
["mulv" , "mul" , "8B" ], ["mulv" , "mul" , "16B" ],
["mulv" , "mul" , "4H" ], ["mulv" , "mul" , "8H" ],
["mulv" , "mul" , "2S" ], ["mulv" , "mul" , "4S" ],
["fabd" , "fabd" , "2S" ], ["fabd" , "fabd" , "4S" ],
["fabd" , "fabd" , "2D" ],
["fmul" , "fmul" , "2S" ], ["fmul" , "fmul" , "4S" ],
["fmul" , "fmul" , "2D" ],
["mlav" , "mla" , "4H" ], ["mlav" , "mla" , "8H" ],
["mlav" , "mla" , "2S" ], ["mlav" , "mla" , "4S" ],
["fmla" , "fmla" , "2S" ], ["fmla" , "fmla" , "4S" ],
["fmla" , "fmla" , "2D" ],
["mlsv" , "mls" , "4H" ], ["mlsv" , "mls" , "8H" ],
["mlsv" , "mls" , "2S" ], ["mlsv" , "mls" , "4S" ],
["fmls" , "fmls" , "2S" ], ["fmls" , "fmls" , "4S" ],
["fmls" , "fmls" , "2D" ],
["fdiv" , "fdiv" , "2S" ], ["fdiv" , "fdiv" , "4S" ],
["fdiv" , "fdiv" , "2D" ],
["maxv" , "smax" , "8B" ], ["maxv" , "smax" , "16B" ],
["maxv" , "smax" , "4H" ], ["maxv" , "smax" , "8H" ],
["maxv" , "smax" , "2S" ], ["maxv" , "smax" , "4S" ],
["smaxp" , "smaxp" , "8B" ], ["smaxp" , "smaxp" , "16B" ],
["smaxp" , "smaxp" , "4H" ], ["smaxp" , "smaxp" , "8H" ],
["smaxp" , "smaxp" , "2S" ], ["smaxp" , "smaxp" , "4S" ],
["fmax" , "fmax" , "2S" ], ["fmax" , "fmax" , "4S" ],
["fmax" , "fmax" , "2D" ],
["minv" , "smin" , "8B" ], ["minv" , "smin" , "16B" ],
["minv" , "smin" , "4H" ], ["minv" , "smin" , "8H" ],
["minv" , "smin" , "2S" ], ["minv" , "smin" , "4S" ],
["sminp" , "sminp" , "8B" ], ["sminp" , "sminp" , "16B" ],
["sminp" , "sminp" , "4H" ], ["sminp" , "sminp" , "8H" ],
["sminp" , "sminp" , "2S" ], ["sminp" , "sminp" , "4S" ],
["fmin" , "fmin" , "2S" ], ["fmin" , "fmin" , "4S" ],
["fmin" , "fmin" , "2D" ],
["cmeq" , "cmeq" , "8B" ], ["cmeq" , "cmeq" , "16B" ],
["cmeq" , "cmeq" , "4H" ], ["cmeq" , "cmeq" , "8H" ],
["cmeq" , "cmeq" , "2S" ], ["cmeq" , "cmeq" , "4S" ],
["cmeq" , "cmeq" , "2D" ],
["fcmeq" , "fcmeq" , "2S" ], ["fcmeq" , "fcmeq" , "4S" ],
["fcmeq" , "fcmeq" , "2D" ],
["cmgt" , "cmgt" , "8B" ], ["cmgt" , "cmgt" , "16B" ],
["cmgt" , "cmgt" , "4H" ], ["cmgt" , "cmgt" , "8H" ],
["cmgt" , "cmgt" , "2S" ], ["cmgt" , "cmgt" , "4S" ],
["cmgt" , "cmgt" , "2D" ],
["cmhi" , "cmhi" , "8B" ], ["cmhi" , "cmhi" , "16B" ],
["cmhi" , "cmhi" , "4H" ], ["cmhi" , "cmhi" , "8H" ],
["cmhi" , "cmhi" , "2S" ], ["cmhi" , "cmhi" , "4S" ],
["cmhi" , "cmhi" , "2D" ],
["cmhs" , "cmhs" , "8B" ], ["cmhs" , "cmhs" , "16B" ],
["cmhs" , "cmhs" , "4H" ], ["cmhs" , "cmhs" , "8H" ],
["cmhs" , "cmhs" , "2S" ], ["cmhs" , "cmhs" , "4S" ],
["cmhs" , "cmhs" , "2D" ],
["fcmgt" , "fcmgt" , "2S" ], ["fcmgt" , "fcmgt" , "4S" ],
["fcmgt" , "fcmgt" , "2D" ],
["cmge" , "cmge" , "8B" ], ["cmge" , "cmge" , "16B" ],
["cmge" , "cmge" , "4H" ], ["cmge" , "cmge" , "8H" ],
["cmge" , "cmge" , "2S" ], ["cmge" , "cmge" , "4S" ],
["cmge" , "cmge" , "2D" ],
["fcmge" , "fcmge" , "2S" ], ["fcmge" , "fcmge" , "4S" ],
["fcmge" , "fcmge" , "2D" ],
["facgt" , "facgt" , "2S" ], ["facgt" , "facgt" , "4S" ],
["facgt" , "facgt" , "2D" ],
])
generate(SVEComparisonWithZero, ["EQ" , "GT" , "GE" , "LT" , "LE" , "NE" ])
generate(SpecialCases, [["ccmn" , "__ ccmn(zr, zr, 3u, Assembler::LE);" , "ccmn\txzr, xzr, #3, LE"],
["ccmnw" , "__ ccmnw(zr, zr, 5u, Assembler::EQ);" , "ccmn\twzr, wzr, #5, EQ"],
["ccmp" , "__ ccmp(zr, 1, 4u, Assembler::NE);" , "ccmp\txzr, 1, #4, NE"],
["ccmpw" , "__ ccmpw(zr, 2, 2, Assembler::GT);" , "ccmp\twzr, 2, #2, GT"],
["extr" , "__ extr(zr, zr, zr, 0);" , "extr\txzr, xzr, xzr, 0" ],
["stlxp" , "__ stlxp(r0, zr, zr, sp);" , "stlxp\tw0, xzr, xzr, [sp]" ],
["stlxpw" , "__ stlxpw(r2, zr, zr, r3);" , "stlxp\tw2, wzr, wzr, [x3]" ],
["stxp" , "__ stxp(r4, zr, zr, r5);" , "stxp\tw4, xzr, xzr, [x5]" ],
["stxpw" , "__ stxpw(r6, zr, zr, sp);" , "stxp\tw6, wzr, wzr, [sp]" ],
["dup" , "__ dup(v0, __ T16B, zr);" , "dup\tv0.16b, wzr" ],
["dup" , "__ dup(v0, __ S, v1);" , "dup\ts0, v1.s[0]" ],
["mov" , "__ mov(v1, __ D, 0, zr);" , "mov\tv1.d[0], xzr" ],
["mov" , "__ mov(v1, __ S, 1, zr);" , "mov\tv1.s[1], wzr" ],
["mov" , "__ mov(v1, __ H, 2, zr);" , "mov\tv1.h[2], wzr" ],
["mov" , "__ mov(v1, __ B, 3, zr);" , "mov\tv1.b[3], wzr" ],
["smov" , "__ smov(r0, v1, __ S, 0);" , "smov\tx0, v1.s[0]" ],
["smov" , "__ smov(r0, v1, __ H, 1);" , "smov\tx0, v1.h[1]" ],
["smov" , "__ smov(r0, v1, __ B, 2);" , "smov\tx0, v1.b[2]" ],
["umov" , "__ umov(r0, v1, __ D, 0);" , "umov\tx0, v1.d[0]" ],
["umov" , "__ umov(r0, v1, __ S, 1);" , "umov\tw0, v1.s[1]" ],
["umov" , "__ umov(r0, v1, __ H, 2);" , "umov\tw0, v1.h[2]" ],
["umov" , "__ umov(r0, v1, __ B, 3);" , "umov\tw0, v1.b[3]" ],
["fmov" , "__ fmovhid(r0, v1);" , "fmov\tx0, v1.d[1]" ],
["fmov" , "__ fmovs(v9, __ T2S, 0.5f);" , "fmov\tv9.2s, 0.5" ],
["fmov" , "__ fmovd(v14, __ T2D, 0.5f);" , "fmov\tv14.2d, 0.5" ],
["ld1" , "__ ld1(v31, v0, __ T2D, Address(__ post(r1, r0)));" , "ld1\t{v31.2d, v0.2d}, [x1], x0" ],
["fcvtzs" , "__ fcvtzs(v0, __ T2S, v1);" , "fcvtzs\tv0.2s, v1.2s" ],
["fcvtas" , "__ fcvtas(v2, __ T4S, v3);" , "fcvtas\tv2.4s, v3.4s" ],
["fcvtms" , "__ fcvtms(v4, __ T2D, v5);" , "fcvtms\tv4.2d, v5.2d" ],
# SVE instructions
["cpy" , "__ sve_cpy(z0, __ S, p0, v1);" , "mov\tz0.s, p0/m, s1" ],
["cpy" , "__ sve_cpy(z0, __ B, p0, 127, true);" , "mov\tz0.b, p0/m, 127" ],
["cpy" , "__ sve_cpy(z1, __ H, p0, -128, true);" , "mov\tz1.h, p0/m, -128" ],
["cpy" , "__ sve_cpy(z2, __ S, p0, 32512, true);" , "mov\tz2.s, p0/m, 32512" ],
["cpy" , "__ sve_cpy(z5, __ D, p0, -32768, false);" , "mov\tz5.d, p0/z, -32768" ],
["cpy" , "__ sve_cpy(z10, __ B, p0, -1, false);" , "mov\tz10.b, p0/z, -1" ],
["cpy" , "__ sve_cpy(z11, __ S, p0, -1, false);" , "mov\tz11.s, p0/z, -1" ],
["inc" , "__ sve_inc(r0, __ S);" , "incw\tx0" ],
["dec" , "__ sve_dec(r1, __ H);" , "dech\tx1" ],
["lsl" , "__ sve_lsl(z0, __ B, z1, 7);" , "lsl\tz0.b, z1.b, #7"],
["lsl" , "__ sve_lsl(z21, __ H, z1, 15);" , "lsl\tz21.h, z1.h, #15"],
["lsl" , "__ sve_lsl(z0, __ S, z1, 31);" , "lsl\tz0.s, z1.s, #31"],
["lsl" , "__ sve_lsl(z0, __ D, z1, 63);" , "lsl\tz0.d, z1.d, #63"],
["lsr" , "__ sve_lsr(z0, __ B, z1, 7);" , "lsr\tz0.b, z1.b, #7"],
["asr" , "__ sve_asr(z0, __ H, z11, 15);" , "asr\tz0.h, z11.h, #15"],
["lsr" , "__ sve_lsr(z30, __ S, z1, 31);" , "lsr\tz30.s, z1.s, #31"],
["asr" , "__ sve_asr(z0, __ D, z1, 63);" , "asr\tz0.d, z1.d, #63"],
["lsl" , "__ sve_lsl(z0, __ B, p0, 0);" , "lsl\tz0.b, p0/m, z0.b, #0"],
["lsl" , "__ sve_lsl(z0, __ B, p0, 5);" , "lsl\tz0.b, p0/m, z0.b, #5"],
["lsl" , "__ sve_lsl(z1, __ H, p1, 15);" , "lsl\tz1.h, p1/m, z1.h, #15"],
["lsl" , "__ sve_lsl(z2, __ S, p2, 31);" , "lsl\tz2.s, p2/m, z2.s, #31"],
["lsl" , "__ sve_lsl(z3, __ D, p3, 63);" , "lsl\tz3.d, p3/m, z3.d, #63"],
["lsr" , "__ sve_lsr(z0, __ B, p0, 1);" , "lsr\tz0.b, p0/m, z0.b, #1"],
["lsr" , "__ sve_lsr(z0, __ B, p0, 8);" , "lsr\tz0.b, p0/m, z0.b, #8"],
["lsr" , "__ sve_lsr(z1, __ H, p1, 15);" , "lsr\tz1.h, p1/m, z1.h, #15"],
["lsr" , "__ sve_lsr(z2, __ S, p2, 7);" , "lsr\tz2.s, p2/m, z2.s, #7"],
["lsr" , "__ sve_lsr(z2, __ S, p2, 31);" , "lsr\tz2.s, p2/m, z2.s, #31"],
["lsr" , "__ sve_lsr(z3, __ D, p3, 63);" , "lsr\tz3.d, p3/m, z3.d, #63"],
--> --------------------
--> maximum size reached
--> --------------------
quality 90%
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.47Angebot
¤
*Eine klare Vorstellung vom Zielzustand