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):
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):
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):
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
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"])
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",
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
|
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):
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):
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):
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
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"])
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",
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)
|