jdk-24/test/hotspot/gtest/x86/x86-asmtest.py
2024-11-13 16:19:33 +00:00

1469 lines
56 KiB
Python

# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
import os
import sys
import platform
import random
import re
import subprocess
OBJDUMP = "objdump"
X86_AS = "as"
X86_OBJCOPY = "objcopy"
SEED = 1327
random.seed(SEED)
cond_to_suffix = {
'overflow': 'o',
'noOverflow': 'no',
'below': 'b',
'aboveEqual': 'ae',
'zero': 'z',
'notZero': 'nz',
'belowEqual': 'be',
'above': 'a',
'negative': 's',
'positive': 'ns',
'parity': 'p',
'noParity': 'np',
'less': 'l',
'greaterEqual': 'ge',
'lessEqual': 'le',
'greater': 'g',
}
shift_rot_ops = {'sarl', 'sarq', 'sall', 'salq', 'shll', 'shlq', 'shrl', 'shrq', 'shrdl', 'shrdq', 'shldl', 'shldq', 'rcrq', 'rorl', 'rorq', 'roll', 'rolq', 'rcll', 'rclq',
'esarl', 'esarq', 'esall', 'esalq', 'eshll', 'eshlq', 'eshrl', 'eshrq', 'eshrdl', 'eshrdq', 'eshldl', 'eshldq', 'ercrq', 'erorl', 'erorq', 'eroll', 'erolq', 'ercll', 'erclq'}
registers_mapping = {
# skip rax, rsi, rdi, rsp, rbp as they have special encodings
# 'rax': {64: 'rax', 32: 'eax', 16: 'ax', 8: 'al'},
'rcx': {64: 'rcx', 32: 'ecx', 16: 'cx', 8: 'cl'},
'rdx': {64: 'rdx', 32: 'edx', 16: 'dx', 8: 'dl'},
'rbx': {64: 'rbx', 32: 'ebx', 16: 'bx', 8: 'bl'},
# 'rsp': {64: 'rsp', 32: 'esp', 16: 'sp', 8: 'spl'},
# 'rbp': {64: 'rbp', 32: 'ebp', 16: 'bp', 8: 'bpl'},
# 'rsi': {64: 'rsi', 32: 'esi', 16: 'si', 8: 'sil'},
# 'rdi': {64: 'rdi', 32: 'edi', 16: 'di', 8: 'dil'},
'r8': {64: 'r8', 32: 'r8d', 16: 'r8w', 8: 'r8b'},
'r9': {64: 'r9', 32: 'r9d', 16: 'r9w', 8: 'r9b'},
'r10': {64: 'r10', 32: 'r10d', 16: 'r10w', 8: 'r10b'},
'r11': {64: 'r11', 32: 'r11d', 16: 'r11w', 8: 'r11b'},
'r12': {64: 'r12', 32: 'r12d', 16: 'r12w', 8: 'r12b'},
'r13': {64: 'r13', 32: 'r13d', 16: 'r13w', 8: 'r13b'},
'r14': {64: 'r14', 32: 'r14d', 16: 'r14w', 8: 'r14b'},
'r15': {64: 'r15', 32: 'r15d', 16: 'r15w', 8: 'r15b'},
'r16': {64: 'r16', 32: 'r16d', 16: 'r16w', 8: 'r16b'},
'r17': {64: 'r17', 32: 'r17d', 16: 'r17w', 8: 'r17b'},
'r18': {64: 'r18', 32: 'r18d', 16: 'r18w', 8: 'r18b'},
'r19': {64: 'r19', 32: 'r19d', 16: 'r19w', 8: 'r19b'},
'r20': {64: 'r20', 32: 'r20d', 16: 'r20w', 8: 'r20b'},
'r21': {64: 'r21', 32: 'r21d', 16: 'r21w', 8: 'r21b'},
'r22': {64: 'r22', 32: 'r22d', 16: 'r22w', 8: 'r22b'},
'r23': {64: 'r23', 32: 'r23d', 16: 'r23w', 8: 'r23b'},
'r24': {64: 'r24', 32: 'r24d', 16: 'r24w', 8: 'r24b'},
'r25': {64: 'r25', 32: 'r25d', 16: 'r25w', 8: 'r25b'},
'r26': {64: 'r26', 32: 'r26d', 16: 'r26w', 8: 'r26b'},
'r27': {64: 'r27', 32: 'r27d', 16: 'r27w', 8: 'r27b'},
'r28': {64: 'r28', 32: 'r28d', 16: 'r28w', 8: 'r28b'},
'r29': {64: 'r29', 32: 'r29d', 16: 'r29w', 8: 'r29b'},
'r30': {64: 'r30', 32: 'r30d', 16: 'r30w', 8: 'r30b'},
'r31': {64: 'r31', 32: 'r31d', 16: 'r31w', 8: 'r31b'},
}
class Operand(object):
def generate(self):
return self
class Register(Operand):
def generate(self, reg, width):
self.reg = reg
self.areg = registers_mapping.get(reg, {}).get(width, reg)
return self
def cstr(self):
return self.reg
def astr(self):
return self.areg
class Immediate(Operand):
def generate(self, value):
self._value = value
return self
def cstr(self):
return str(self._value)
def astr(self):
return str(self._value)
class Address(Operand):
width_to_ptr = {
8: "byte ptr",
16: "word ptr",
32: "dword ptr",
64: "qword ptr"
}
def generate(self, base, index, width):
self.base = Register().generate(base, 64)
self.index = Register().generate(index, 64)
self._width = width
self._scale_factor = random.choice([-1, 0, 1, 2, 3])
self._disp = random.randint(-2**31, 2**31 - 1)
return self
def cstr(self):
disp_str = "{0:+#x}".format(self._disp)
if self._scale_factor == -1:
return f"Address({self.base.cstr()}, {disp_str})"
else:
return f"Address({self.base.cstr()}, {self.index.cstr()}, (Address::ScaleFactor){self._scale_factor}, {disp_str})"
def astr(self):
ptr_str = self.width_to_ptr.get(self._width, "qword ptr")
disp_str = "{0:+#x}".format(self._disp)
if self._scale_factor == -1:
return f"{ptr_str} [{self.base.cstr() + disp_str}]"
else:
return f"{ptr_str} [{self.base.cstr()}+{self.index.cstr()}*{2 ** self._scale_factor}{disp_str}]"
class Instruction(object):
def __init__(self, name, aname):
self._name = name
self._aname = aname
def generate_operands(self, *operands):
self.operands = [operand for operand in operands]
def cstr(self):
return f'__ {self._name}(' + ', '.join([op.cstr() for op in self.operands]) + ');'
def astr(self):
# JDK assembler uses 'cl' for shift instructions with one operand by default
cl_str = (', cl' if self._name in shift_rot_ops and len(self.operands) == 1 else '')
return f'{self._aname} ' + ', '.join([op.astr() for op in self.operands]) + cl_str
class NFInstruction(Instruction):
def __init__(self, name, aname, no_flag):
super().__init__(name, aname)
self.no_flag = no_flag
def cstr(self):
return f'__ {self._name}(' + ', '.join([op.cstr() for op in self.operands]) + (f', {str(self.no_flag).lower()}' if self.no_flag is not None else '') + ');'
def astr(self):
# JDK assembler uses 'cl' for shift instructions with one operand by default
cl_str = (', cl' if self._name in shift_rot_ops and len(self.operands) == 2 else '')
# special case for shift instructions with three operands
if (self._name == 'eshldl' or self._name == 'eshldq' or self._name == 'eshrdl' or self._name == 'eshrdq') and all([isinstance(op, Register) for op in self.operands]):
cl_str = ', cl'
return ('{NF}' if self.no_flag else '{EVEX}') + f'{self._aname} ' + ', '.join([op.astr() for op in self.operands]) + cl_str
class RegInstruction(Instruction):
def __init__(self, name, aname, width, reg):
super().__init__(name, aname)
self.reg = Register().generate(reg, width)
self.generate_operands(self.reg)
class MemInstruction(Instruction):
def __init__(self, name, aname, width, mem_base, mem_idx):
super().__init__(name, aname)
self.mem = Address().generate(mem_base, mem_idx, width)
self.generate_operands(self.mem)
class TwoRegInstruction(Instruction):
def __init__(self, name, aname, width, reg1, reg2):
super().__init__(name, aname)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.generate_operands(self.reg1, self.reg2)
def astr(self):
return f'{{load}}' + super().astr()
class MemRegInstruction(Instruction):
def __init__(self, name, aname, width, reg, mem_base, mem_idx):
super().__init__(name, aname)
self.mem = Address().generate(mem_base, mem_idx, width)
self.reg = Register().generate(reg, width)
self.generate_operands(self.mem, self.reg)
class RegMemInstruction(Instruction):
def __init__(self, name, aname, width, reg, mem_base, mem_idx):
super().__init__(name, aname)
self.reg = Register().generate(reg, width)
self.mem = Address().generate(mem_base, mem_idx, width)
self.generate_operands(self.reg, self.mem)
class RegImmInstruction(Instruction):
def __init__(self, name, aname, width, reg, imm):
super().__init__(name, aname)
self.reg = Register().generate(reg, width)
self.imm = Immediate().generate(imm)
self.generate_operands(self.reg, self.imm)
class MemImmInstruction(Instruction):
def __init__(self, name, aname, width, imm, mem_base, mem_idx):
super().__init__(name, aname)
self.mem = Address().generate(mem_base, mem_idx, width)
self.imm = Immediate().generate(imm)
self.generate_operands(self.mem, self.imm)
class RegRegImmInstruction(Instruction):
def __init__(self, name, aname, width, reg1, reg2, imm):
super().__init__(name, aname)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.imm = Immediate().generate(imm)
self.generate_operands(self.reg1, self.reg2, self.imm)
class RegMemImmInstruction(Instruction):
def __init__(self, name, aname, width, reg, imm, mem_base, mem_idx):
super().__init__(name, aname)
self.reg = Register().generate(reg, width)
self.mem = Address().generate(mem_base, mem_idx, width)
self.imm = Immediate().generate(imm)
self.generate_operands(self.reg, self.mem, self.imm)
class Pop2Instruction(TwoRegInstruction):
def __init__(self, name, aname, width, reg1, reg2):
super().__init__(name, aname, width, reg1, reg2)
def cstr(self):
# reverse to match the order in OpenJDK
return f'__ {self._name}(' + ', '.join([reg.cstr() for reg in reversed(self.operands)]) + ');'
class Push2Instruction(TwoRegInstruction):
def __init__(self, name, aname, width, reg1, reg2):
super().__init__(name, aname, width, reg1, reg2)
def cstr(self):
# reverse to match the order in OpenJDK
return f'__ {self._name}(' + ', '.join([reg.cstr() for reg in reversed(self.operands)]) + ');'
class CmpxchgInstruction(MemRegInstruction):
def __init__(self, name, aname, width, reg, mem_base, mem_idx):
super().__init__(name, aname, width, reg, mem_base, mem_idx)
def cstr(self):
# reverse to match the order in OpenJDK
return f'__ {self._name}(' + ', '.join([reg.cstr() for reg in reversed(self.operands)]) + ');'
class CondRegMemInstruction(RegMemInstruction):
def __init__(self, name, aname, width, cond, reg, mem_base, mem_idx):
super().__init__(name, aname, width, reg, mem_base, mem_idx)
self.cond = cond
def cstr(self):
return f'__ {self._name}(' + 'Assembler::Condition::' + self.cond + ', ' + ', '.join([self.reg.cstr(), self.mem.cstr()]) + ');'
def astr(self):
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + ', '.join([self.reg.astr(), self.mem.astr()])
class CondRegInstruction(RegInstruction):
def __init__(self, name, aname, width, cond, reg):
super().__init__(name, aname, width, reg)
self.cond = cond
def cstr(self):
return f'__ {self._name}b(' + 'Assembler::Condition::' + self.cond + ', ' + self.reg.cstr() + ');'
def astr(self):
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + self.reg.astr()
class CondRegRegRegInstruction(Instruction):
def __init__(self, name, aname, width, cond, reg1, reg2, reg3):
super().__init__(name, aname)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.reg3 = Register().generate(reg3, width)
self.cond = cond
self.generate_operands(self.reg1, self.reg2, self.reg3)
def cstr(self):
return f'__ {self._name} (' + 'Assembler::Condition::' + self.cond + ', ' + ', '.join([reg.cstr() for reg in self.operands]) + ');'
def astr(self):
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + ', '.join([reg.astr() for reg in self.operands])
class CondRegRegMemInstruction(Instruction):
def __init__(self, name, aname, width, cond, reg1, reg2, mem_base, mem_idx):
super().__init__(name, aname)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.mem = Address().generate(mem_base, mem_idx, width)
self.cond = cond
self.generate_operands(self.reg1, self.reg2, self.mem)
def cstr(self):
return f'__ {self._name} (' + 'Assembler::Condition::' + self.cond + ', ' + ', '.join([reg.cstr() for reg in self.operands]) + ');'
def astr(self):
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + ', '.join([reg.astr() for reg in self.operands])
class MoveRegMemInstruction(Instruction):
def __init__(self, name, aname, width, mem_width, reg, mem_base, mem_idx):
super().__init__(name, aname)
self.reg = Register().generate(reg, width)
self.mem = Address().generate(mem_base, mem_idx, mem_width)
self.generate_operands(self.reg, self.mem)
class MoveRegRegInstruction(Instruction):
def __init__(self, name, aname, width, reg_width, reg1, reg2):
super().__init__(name, aname)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, reg_width)
self.generate_operands(self.reg1, self.reg2)
class RegNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg):
super().__init__(name, aname, no_flag)
self.reg = Register().generate(reg, width)
self.generate_operands(self.reg)
class MemNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, mem_base, mem_idx):
super().__init__(name, aname, no_flag)
self.mem = Address().generate(mem_base, mem_idx, width)
self.generate_operands(self.mem)
class RegRegNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg1, reg2):
super().__init__(name, aname, no_flag)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.generate_operands(self.reg1, self.reg2)
class RegMemNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg, mem_base, mem_idx):
super().__init__(name, aname, no_flag)
self.reg = Register().generate(reg, width)
self.mem = Address().generate(mem_base, mem_idx, width)
self.generate_operands(self.reg, self.mem)
class RegMemImmNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg, imm, mem_base, mem_idx):
super().__init__(name, aname, no_flag)
self.reg = Register().generate(reg, width)
self.mem = Address().generate(mem_base, mem_idx, width)
self.imm = Immediate().generate(imm)
self.generate_operands(self.reg, self.mem, self.imm)
class RegMemRegNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg1, mem_base, mem_idx, reg2):
super().__init__(name, aname, no_flag)
self.reg1 = Register().generate(reg1, width)
self.mem = Address().generate(mem_base, mem_idx, width)
self.reg2 = Register().generate(reg2, width)
self.generate_operands(self.reg1, self.mem, self.reg2)
class RegRegImmNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg1, reg2, imm):
super().__init__(name, aname, no_flag)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.imm = Immediate().generate(imm)
self.generate_operands(self.reg1, self.reg2, self.imm)
class RegRegMemNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg1, reg2, mem_base, mem_idx):
super().__init__(name, aname, no_flag)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.mem = Address().generate(mem_base, mem_idx, width)
self.generate_operands(self.reg1, self.reg2, self.mem)
class RegRegRegNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg1, reg2, reg3):
super().__init__(name, aname, no_flag)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.reg3 = Register().generate(reg3, width)
self.generate_operands(self.reg1, self.reg2, self.reg3)
def astr(self):
return f'{{load}}' + super().astr()
class RegRegRegImmNddInstruction(NFInstruction):
def __init__(self, name, aname, width, no_flag, reg1, reg2, reg3, imm):
super().__init__(name, aname, no_flag)
self.reg1 = Register().generate(reg1, width)
self.reg2 = Register().generate(reg2, width)
self.reg3 = Register().generate(reg3, width)
self.imm = Immediate().generate(imm)
self.generate_operands(self.reg1, self.reg2, self.reg3, self.imm)
test_regs = list(registers_mapping.keys())
immediates32 = [2 ** i for i in range(0, 32, 4)]
immediates16 = [2 ** i for i in range(0, 16, 2)]
immediates8 = [2 ** i for i in range(0, 8, 2)]
immediates5 = [2 ** i for i in range(0, 5, 1)]
immediate_values_8_to_16_bit = [2 ** i for i in range(8, 16, 2)]
immediate_values_16_to_32_bit = [2 ** i for i in range(16, 32, 2)]
immediate_values_32_to_64_bit = [2 ** i for i in range(32, 64, 2)]
negative_immediates32 = [-2 ** i for i in range(0, 32, 4)]
immediate_map = {
8: immediates8,
16: immediates16,
32: immediates32,
64: immediates32
}
def is_64_reg(reg):
return reg in {'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'r16', 'r17', 'r18', 'r19', 'r20', 'r21', 'r22', 'r23', 'r24', 'r25', 'r26', 'r27', 'r28', 'r29', 'r30', 'r31'}
def print_instruction(instr, lp64_flag, print_lp64_flag):
cstr = instr.cstr()
astr = instr.astr()
print(" %-75s // %s IID%s" % (cstr, astr, len(ifdef_flags)))
ifdef_flags.append(lp64_flag or not print_lp64_flag)
insns_strs.append(cstr)
outfile.write(f" {astr}\n")
def handle_lp64_flag(lp64_flag, print_lp64_flag, *regs):
for reg in regs:
if is_64_reg(reg):
if not lp64_flag and print_lp64_flag:
print("#ifdef _LP64")
return True
if lp64_flag and print_lp64_flag:
print("#endif // _LP64")
return False
return lp64_flag
def get_immediate_list(op_name, width):
# special cases
word_imm_ops = {'addw', 'cmpw'}
dword_imm_ops = {'subl_imm32', 'subq_imm32', 'orq_imm32', 'cmpl_imm32', 'esubl_imm32', 'esubq_imm32', 'eorq_imm32', 'testl'}
qword_imm_ops = {'mov64'}
neg_imm_ops = {'testq'}
bt_ops = {'btq'}
if op_name in shift_rot_ops:
return immediates5
elif op_name in bt_ops:
return immediate_map[8]
elif op_name in word_imm_ops:
return immediate_values_8_to_16_bit
elif op_name in dword_imm_ops:
return immediate_values_16_to_32_bit
elif op_name in qword_imm_ops:
return immediate_values_32_to_64_bit
elif op_name in neg_imm_ops:
return negative_immediates32
else:
return immediate_map[width]
lp64_flag = False
def generate(RegOp, ops, print_lp64_flag=True, full_set=False):
global lp64_flag
for op in ops:
op_name = op[0]
width = op[2]
if RegOp in [RegInstruction, CondRegInstruction, RegNddInstruction]:
if full_set:
for i in range(len(test_regs)):
test_reg = test_regs[i]
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg)
instr = RegOp(*op, reg=test_reg)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
test_reg = random.choice(test_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg)
instr = RegOp(*op, reg=test_reg)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [TwoRegInstruction, MoveRegRegInstruction, RegRegNddInstruction]:
if full_set:
for i in range(len(test_regs)):
test_reg1 = test_regs[i]
test_reg2 = test_regs[(i + 1) % len(test_regs)]
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
test_reg1 = random.choice(test_regs)
test_reg2 = random.choice(test_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [RegRegRegNddInstruction, CondRegRegRegInstruction]:
if full_set:
for i in range(len(test_regs)):
test_reg1 = test_regs[i]
test_reg2 = test_regs[(i + 1) % len(test_regs)]
test_reg3 = test_regs[(i + 2) % len(test_regs)]
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
test_reg1 = random.choice(test_regs)
test_reg2 = random.choice(test_regs)
test_reg3 = random.choice(test_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [MemRegInstruction, RegMemInstruction, MoveRegMemInstruction, CmpxchgInstruction, CondRegMemInstruction, RegMemNddInstruction]:
if full_set:
for i in range(len(test_regs)):
test_reg = test_regs[i]
test_mem_base = test_regs[(i + 1) % len(test_regs)]
test_mem_idx = test_regs[(i + 2) % len(test_regs)]
if test_mem_idx == 'rsp':
continue
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg, test_mem_base, test_mem_idx)
instr = RegOp(*op, reg=test_reg, mem_base=test_mem_base, mem_idx=test_mem_idx)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
filtered_regs = [reg for reg in test_regs if reg != 'rsp']
test_reg = random.choice(test_regs)
test_mem_base = random.choice(test_regs)
test_mem_idx = random.choice(filtered_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg, test_mem_base, test_mem_idx)
instr = RegOp(*op, reg=test_reg, mem_base=test_mem_base, mem_idx=test_mem_idx)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [RegImmInstruction]:
if full_set:
imm_list = get_immediate_list(op_name, width)
for i in range(len(test_regs)):
test_reg = test_regs[i]
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg)
for imm in imm_list:
instr = RegOp(*op, reg=test_reg, imm=imm)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
test_reg = random.choice(test_regs)
imm = random.choice(get_immediate_list(op_name, width))
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg)
instr = RegOp(*op, reg=test_reg, imm=imm)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [MemImmInstruction]:
if full_set:
imm_list = get_immediate_list(op_name, width)
for imm in imm_list:
for i in range(len(test_regs)):
test_mem_base = test_regs[i]
test_mem_idx = test_regs[(i + 1) % len(test_regs)]
if test_mem_idx == 'rsp':
continue
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_mem_base, test_mem_idx)
instr = RegOp(*op, imm=imm, mem_base=test_mem_base, mem_idx=test_mem_idx)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
filtered_regs = [reg for reg in test_regs if reg != 'rsp']
imm = random.choice(get_immediate_list(op_name, width))
test_mem_base = random.choice(test_regs)
test_mem_idx = random.choice(filtered_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_mem_base, test_mem_idx)
instr = RegOp(*op, imm=imm, mem_base=test_mem_base, mem_idx=test_mem_idx)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [MemInstruction, MemNddInstruction]:
if full_set:
for i in range(len(test_regs)):
test_mem_base = test_regs[i]
test_mem_idx = test_regs[(i + 1) % len(test_regs)]
if test_mem_idx == 'rsp':
continue
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_mem_base, test_mem_idx)
instr = RegOp(*op, mem_base=test_mem_base, mem_idx=test_mem_idx)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
filtered_regs = [reg for reg in test_regs if reg != 'rsp']
test_mem_base = random.choice(test_regs)
test_mem_idx = random.choice(filtered_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_mem_base, test_mem_idx)
instr = RegOp(*op, mem_base=test_mem_base, mem_idx=test_mem_idx)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [RegRegImmInstruction, RegRegImmNddInstruction]:
if full_set:
imm_list = get_immediate_list(op_name, width)
for i in range(len(test_regs)):
test_reg1 = test_regs[i]
test_reg2 = test_regs[(i + 1) % len(test_regs)]
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
for imm in imm_list:
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, imm=imm)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
imm = random.choice(get_immediate_list(op_name, width))
test_reg1 = random.choice(test_regs)
test_reg2 = random.choice(test_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, imm=imm)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [RegMemImmInstruction, RegMemImmNddInstruction]:
if full_set:
imm_list = get_immediate_list(op_name, width)
for i in range(len(test_regs)):
test_reg = test_regs[i]
test_mem_base = test_regs[(i + 1) % len(test_regs)]
test_mem_idx = test_regs[(i + 2) % len(test_regs)]
if test_mem_idx == 'rsp':
continue
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg, test_mem_base, test_mem_idx)
for imm in imm_list:
instr = RegOp(*op, reg=test_reg, mem_base=test_mem_base, mem_idx=test_mem_idx, imm=imm)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
imm = random.choice(get_immediate_list(op_name, width))
filtered_regs = [reg for reg in test_regs if reg != 'rsp']
test_reg = random.choice(test_regs)
test_mem_base = random.choice(test_regs)
test_mem_idx = random.choice(filtered_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg, test_mem_base, test_mem_idx)
instr = RegOp(*op, reg=test_reg, imm=imm, mem_base=test_mem_base, mem_idx=test_mem_idx)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [RegMemRegNddInstruction, RegRegMemNddInstruction, CondRegRegMemInstruction]:
if full_set:
for i in range(len(test_regs)):
test_reg1 = test_regs[i]
test_mem_base = test_regs[(i + 1) % len(test_regs)]
test_mem_idx = test_regs[(i + 2) % len(test_regs)]
test_reg2 = test_regs[(i + 3) % len(test_regs)]
if test_mem_idx == 'rsp':
continue
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_mem_base, test_mem_idx, test_reg2)
instr = RegOp(*op, reg1=test_reg1, mem_base=test_mem_base, mem_idx=test_mem_idx, reg2=test_reg2)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
filtered_regs = [reg for reg in test_regs if reg != 'rsp']
test_reg1 = random.choice(test_regs)
test_mem_base = random.choice(test_regs)
test_mem_idx = random.choice(filtered_regs)
test_reg2 = random.choice(test_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_mem_base, test_mem_idx, test_reg2)
instr = RegOp(*op, reg1=test_reg1, mem_base=test_mem_base, mem_idx=test_mem_idx, reg2=test_reg2)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [RegRegRegImmNddInstruction]:
if full_set:
imm_list = get_immediate_list(op_name, width)
for i in range(len(test_regs)):
test_reg1 = test_regs[i]
test_reg2 = test_regs[(i + 1) % len(test_regs)]
test_reg3 = test_regs[(i + 2) % len(test_regs)]
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
for imm in imm_list:
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3, imm=imm)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
imm = random.choice(get_immediate_list(op_name, width))
test_reg1 = random.choice(test_regs)
test_reg2 = random.choice(test_regs)
test_reg3 = random.choice(test_regs)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3, imm=imm)
print_instruction(instr, lp64_flag, print_lp64_flag)
elif RegOp in [Push2Instruction, Pop2Instruction]:
if full_set:
for i in range(len(test_regs)):
test_reg1 = test_regs[i]
test_reg2 = test_regs[(i + 1) % len(test_regs)]
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
if test_reg1 == 'rsp' or test_reg2 == 'rsp':
continue
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
filtered_regs = [reg for reg in test_regs if reg != 'rsp']
test_reg1, test_reg2 = random.sample(filtered_regs, 2)
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2)
print_instruction(instr, lp64_flag, print_lp64_flag)
else:
raise ValueError(f"Unsupported instruction type: {RegOp}")
def print_with_ifdef(ifdef_flags, items, item_formatter, width):
under_defined = False
iid = 0
for idx, item in enumerate(items):
if ifdef_flags[idx]:
if not under_defined:
print("#ifdef _LP64")
under_defined = True
else:
if under_defined:
print("#endif // _LP64")
under_defined = False
print(" %-*s // IID%s" % (width, item_formatter(item) + ",", iid))
iid += 1
if under_defined:
print("#endif // _LP64")
instruction_set = {
TwoRegInstruction: [
('shldl', 'shld', 32),
('shrdl', 'shrd', 32),
('adcl', 'adc', 32),
('cmpl', 'cmp', 32),
('imull', 'imul', 32),
('popcntl', 'popcnt', 32),
('sbbl', 'sbb', 32),
('subl', 'sub', 32),
('tzcntl', 'tzcnt', 32),
('lzcntl', 'lzcnt', 32),
('addl', 'add', 32),
('andl', 'and', 32),
('orl', 'or', 32),
('xorl', 'xor', 32),
('movl', 'mov', 32),
('bsfl', 'bsf', 32),
('bsrl', 'bsr', 32),
('xchgl', 'xchg', 32),
('testl', 'test', 32),
],
MemRegInstruction: [
('addb', 'add', 8),
('addw', 'add', 16),
('addl', 'add', 32),
('adcl', 'adc', 32),
('andb', 'and', 8),
('andl', 'and', 32),
('cmpb', 'cmp', 8),
('cmpw', 'cmp', 16),
('cmpl', 'cmp', 32),
('orb', 'or', 8),
('orl', 'or', 32),
('xorb', 'xor', 8),
('xorl', 'xor', 32),
('subl', 'sub', 32),
('movb', 'mov', 8),
('movl', 'mov', 32),
('xaddb', 'xadd', 8),
('xaddw', 'xadd', 16),
('xaddl', 'xadd', 32),
],
MemImmInstruction: [
('adcl', 'adc', 32),
('andl', 'and', 32),
('addb', 'add', 8),
('addw', 'add', 16),
('addl', 'add', 32),
('cmpb', 'cmp', 8),
('cmpw', 'cmp', 16),
('cmpl', 'cmp', 32),
('sarl', 'sar', 32),
('sall', 'sal', 32),
('sbbl', 'sbb', 32),
('shrl', 'shr', 32),
('subl', 'sub', 32),
('xorl', 'xor', 32),
('orb', 'or', 8),
('orl', 'or', 32),
('movb', 'mov', 8),
('movl', 'mov', 32),
('testb', 'test', 8),
('testl', 'test', 32),
('cmpl_imm32', 'cmp', 32),
],
RegMemInstruction: [
('addl', 'add', 32),
('andl', 'and', 32),
('cmpb', 'cmp', 8),
('cmpl', 'cmp', 32),
('lzcntl', 'lzcnt', 32),
('orl', 'or', 32),
('adcl', 'adc', 32),
('imull', 'imul', 32),
('popcntl', 'popcnt', 32),
('sbbl', 'sbb', 32),
('subl', 'sub', 32),
('tzcntl', 'tzcnt', 32),
('xorb', 'xor', 8),
('xorw', 'xor', 16),
('xorl', 'xor', 32),
('movb', 'mov', 8),
('movl', 'mov', 32),
('leal', 'lea', 32),
('xchgb', 'xchg', 8),
('xchgw', 'xchg', 16),
('xchgl', 'xchg', 32),
('testl', 'test', 32),
],
RegImmInstruction: [
('addb', 'add', 8),
('addl', 'add', 32),
('andl', 'and', 32),
('adcl', 'adc', 32),
('cmpb', 'cmp', 8),
('cmpl', 'cmp', 32),
('rcll', 'rcl', 32),
('roll', 'rol', 32),
('rorl', 'ror', 32),
('sarl', 'sar', 32),
('sall', 'sal', 32),
('sbbl', 'sbb', 32),
('shll', 'shl', 32),
('shrl', 'shr', 32),
('subl', 'sub', 32),
('xorl', 'xor', 32),
('movl', 'mov', 32),
('testb', 'test', 8),
('testl', 'test', 32),
('subl_imm32', 'sub', 32),
],
CondRegMemInstruction: [
('cmovl', 'cmov', 32, key) for key in cond_to_suffix.keys()
],
CondRegInstruction: [
('set', 'set', 8, key) for key in cond_to_suffix.keys()
],
RegInstruction: [
('divl', 'div', 32),
('idivl', 'idiv', 32),
('imull', 'imul', 32),
('mull', 'mul', 32),
('negl', 'neg', 32),
('notl', 'not', 32),
('roll', 'rol', 32),
('rorl', 'ror', 32),
('sarl', 'sar', 32),
('sall', 'sal', 32),
('shll', 'shl', 32),
('shrl', 'shr', 32),
('incrementl', 'inc', 32),
('decrementl', 'dec', 32),
],
MemInstruction: [
('mull', 'mul', 32),
('negl', 'neg', 32),
('sarl', 'sar', 32),
('sall', 'sal', 32),
('shrl', 'shr', 32),
('incrementl', 'inc', 32),
('decrementl', 'dec', 32),
],
RegMemImmInstruction: [
('imull', 'imul', 32),
],
RegRegImmInstruction: [
('imull', 'imul', 32),
('shldl', 'shld', 32),
('shrdl', 'shrd', 32),
],
MoveRegMemInstruction: [
('movzbl', 'movzx', 32, 8),
('movzwl', 'movzx', 32, 16),
('movsbl', 'movsx', 32, 8),
('movswl', 'movsx', 32, 16),
],
MoveRegRegInstruction: [
('movzbl', 'movzx', 32, 8),
('movzwl', 'movzx', 32, 16),
('movsbl', 'movsx', 32, 8),
('movswl', 'movsx', 32, 16),
],
CmpxchgInstruction: [
('cmpxchgb', 'cmpxchg', 8),
('cmpxchgw', 'cmpxchg', 16),
('cmpxchgl', 'cmpxchg', 32),
],
# --- NDD instructions ---
RegNddInstruction: [
('eidivl', 'idiv', 32, False),
('eidivl', 'idiv', 32, True),
('edivl', 'div', 32, False),
('edivl', 'div', 32, True),
('eimull', 'imul', 32, False),
('eimull', 'imul', 32, True),
('emull', 'mul', 32, False),
('emull', 'mul', 32, True),
],
MemNddInstruction: [
('emull', 'mul', 32, False),
('emull', 'mul', 32, True),
],
RegRegNddInstruction: [
('elzcntl', 'lzcnt', 32, False),
('elzcntl', 'lzcnt', 32, True),
('enegl', 'neg', 32, False),
('enegl', 'neg', 32, True),
('epopcntl', 'popcnt', 32, False),
('epopcntl', 'popcnt', 32, True),
('enotl', 'not', 32, None),
('eroll', 'rol', 32, False),
('eroll', 'rol', 32, True),
('erorl', 'ror', 32, False),
('erorl', 'ror', 32, True),
('esall', 'sal', 32, False),
('esall', 'sal', 32, True),
('esarl', 'sar', 32, False),
('esarl', 'sar', 32, True),
('edecl', 'dec', 32, False),
('edecl', 'dec', 32, True),
('eincl', 'inc', 32, False),
('eincl', 'inc', 32, True),
('eshll', 'shl', 32, False),
('eshll', 'shl', 32, True),
('eshrl', 'shr', 32, False),
('eshrl', 'shr', 32, True),
('etzcntl', 'tzcnt', 32, False),
('etzcntl', 'tzcnt', 32, True),
],
RegMemNddInstruction: [
('elzcntl', 'lzcnt', 32, False),
('elzcntl', 'lzcnt', 32, True),
('enegl', 'neg', 32, False),
('enegl', 'neg', 32, True),
('epopcntl', 'popcnt', 32, False),
('epopcntl', 'popcnt', 32, True),
('esall', 'sal', 32, False),
('esall', 'sal', 32, True),
('esarl', 'sar', 32, False),
('esarl', 'sar', 32, True),
('edecl', 'dec', 32, False),
('edecl', 'dec', 32, True),
('eincl', 'inc', 32, False),
('eincl', 'inc', 32, True),
('eshrl', 'shr', 32, False),
('eshrl', 'shr', 32, True),
('etzcntl', 'tzcnt', 32, False),
('etzcntl', 'tzcnt', 32, True),
],
RegMemImmNddInstruction: [
('eaddl', 'add', 32, False),
('eaddl', 'add', 32, True),
('eandl', 'and', 32, False),
('eandl', 'and', 32, True),
('eimull', 'imul', 32, False),
('eimull', 'imul', 32, True),
('eorl', 'or', 32, False),
('eorl', 'or', 32, True),
('eorb', 'or', 8, False),
('eorb', 'or', 8, True),
('esall', 'sal', 32, False),
('esall', 'sal', 32, True),
('esarl', 'sar', 32, False),
('esarl', 'sar', 32, True),
('eshrl', 'shr', 32, False),
('eshrl', 'shr', 32, True),
('esubl', 'sub', 32, False),
('esubl', 'sub', 32, True),
('exorl', 'xor', 32, False),
('exorl', 'xor', 32, True),
],
RegMemRegNddInstruction: [
('eaddl', 'add', 32, False),
('eaddl', 'add', 32, True),
('eorl', 'or', 32, False),
('eorl', 'or', 32, True),
('eorb', 'or', 8, False),
('eorb', 'or', 8, True),
('esubl', 'sub', 32, False),
('esubl', 'sub', 32, True),
('exorl', 'xor', 32, False),
('exorl', 'xor', 32, True),
('exorb', 'xor', 8, False),
('exorb', 'xor', 8, True),
],
RegRegImmNddInstruction: [
('eaddl', 'add', 32, False),
('eaddl', 'add', 32, True),
('eandl', 'and', 32, False),
('eandl', 'and', 32, True),
('eimull', 'imul', 32, False),
('eimull', 'imul', 32, True),
('eorl', 'or', 32, False),
('eorl', 'or', 32, True),
('ercll', 'rcl', 32, None),
('eroll', 'rol', 32, False),
('eroll', 'rol', 32, True),
('erorl', 'ror', 32, False),
('erorl', 'ror', 32, True),
('esall', 'sal', 32, False),
('esall', 'sal', 32, True),
('esarl', 'sar', 32, False),
('esarl', 'sar', 32, True),
('eshll', 'shl', 32, False),
('eshll', 'shl', 32, True),
('eshrl', 'shr', 32, False),
('eshrl', 'shr', 32, True),
('esubl', 'sub', 32, False),
('esubl', 'sub', 32, True),
('exorl', 'xor', 32, False),
('exorl', 'xor', 32, True),
('esubl_imm32', 'sub', 32, False),
('esubl_imm32', 'sub', 32, True),
],
RegRegMemNddInstruction: [
('eaddl', 'add', 32, False),
('eaddl', 'add', 32, True),
('eandl', 'and', 32, False),
('eandl', 'and', 32, True),
('eimull', 'imul', 32, False),
('eimull', 'imul', 32, True),
('eorl', 'or', 32, False),
('eorl', 'or', 32, True),
('esubl', 'sub', 32, False),
('esubl', 'sub', 32, True),
('exorl', 'xor', 32, False),
('exorl', 'xor', 32, True),
('exorb', 'xor', 8, False),
('exorb', 'xor', 8, True),
('exorw', 'xor', 16, False),
('exorw', 'xor', 16, True),
],
RegRegRegNddInstruction: [
('eaddl', 'add', 32, False),
('eaddl', 'add', 32, True),
('eandl', 'and', 32, False),
('eandl', 'and', 32, True),
('eimull', 'imul', 32, False),
('eimull', 'imul', 32, True),
('eorw', 'or', 16, False),
('eorw', 'or', 16, True),
('eorl', 'or', 32, False),
('eorl', 'or', 32, True),
('eshldl', 'shld', 32, False),
('eshldl', 'shld', 32, True),
('eshrdl', 'shrd', 32, False),
('eshrdl', 'shrd', 32, True),
('esubl', 'sub', 32, False),
('esubl', 'sub', 32, True),
('exorl', 'xor', 32, False),
('exorl', 'xor', 32, True),
],
RegRegRegImmNddInstruction: [
('eshldl', 'shld', 32, False),
('eshldl', 'shld', 32, True),
('eshrdl', 'shrd', 32, False),
('eshrdl', 'shrd', 32, True),
],
CondRegRegRegInstruction: [
('ecmovl', 'cmov', 32, key) for key in cond_to_suffix.keys()
],
CondRegRegMemInstruction: [
('ecmovl', 'cmov', 32, key) for key in cond_to_suffix.keys()
],
}
instruction_set64 = {
TwoRegInstruction: [
('adcq', 'adc', 64),
('cmpq', 'cmp', 64),
('imulq', 'imul', 64),
('popcntq', 'popcnt', 64),
('sbbq', 'sbb', 64),
('subq', 'sub', 64),
('tzcntq', 'tzcnt', 64),
('lzcntq', 'lzcnt', 64),
('addq', 'add', 64),
('andq', 'and', 64),
('orq', 'or', 64),
('xorq', 'xor', 64),
('movq', 'mov', 64),
('bsfq', 'bsf', 64),
('bsrq', 'bsr', 64),
('btq', 'bt', 64),
('xchgq', 'xchg', 64),
('testq', 'test', 64),
],
MemRegInstruction: [
('addq', 'add', 64),
('andq', 'and', 64),
('cmpq', 'cmp', 64),
('orq', 'or', 64),
('xorq', 'xor', 64),
('subq', 'sub', 64),
('movq', 'mov', 64),
('xaddq', 'xadd', 64),
],
MemImmInstruction: [
('andq', 'and', 64),
('addq', 'add', 64),
('cmpq', 'cmp', 64),
('sarq', 'sar', 64),
('salq', 'sal', 64),
('sbbq', 'sbb', 64),
('shrq', 'shr', 64),
('subq', 'sub', 64),
('xorq', 'xor', 64),
('orq', 'or', 64),
('movq', 'mov', 64),
('testq', 'test', 64),
],
RegMemInstruction: [
('addq', 'add', 64),
('andq', 'and', 64),
('cmpq', 'cmp', 64),
('lzcntq', 'lzcnt', 64),
('orq', 'or', 64),
('adcq', 'adc', 64),
('imulq', 'imul', 64),
('popcntq', 'popcnt', 64),
('sbbq', 'sbb', 64),
('subq', 'sub', 64),
('tzcntq', 'tzcnt', 64),
('xorq', 'xor', 64),
('movq', 'mov', 64),
('leaq', 'lea', 64),
('cvttsd2siq', 'cvttsd2si', 64),
('xchgq', 'xchg', 64),
('testq', 'test', 64),
],
RegImmInstruction: [
('addq', 'add', 64),
('andq', 'and', 64),
('adcq', 'adc', 64),
('cmpq', 'cmp', 64),
('rclq', 'rcl', 64),
('rcrq', 'rcr', 64),
('rolq', 'rol', 64),
('rorq', 'ror', 64),
('sarq', 'sar', 64),
('salq', 'sal', 64),
('sbbq', 'sbb', 64),
('shlq', 'shl', 64),
('shrq', 'shr', 64),
('subq', 'sub', 64),
('xorq', 'xor', 64),
('movq', 'mov', 64),
('mov64', 'mov', 64),
('btq', 'bt', 64),
('testq', 'test', 64),
('orq_imm32', 'or', 64),
('subq_imm32', 'sub', 64)
],
CondRegMemInstruction: [
('cmovq', 'cmov', 64, key) for key in cond_to_suffix.keys()
],
RegInstruction: [
('call', 'call', 64),
('divq', 'div', 64),
('idivq', 'idiv', 64),
('imulq', 'imul', 64),
('mulq', 'mul', 64),
('negq', 'neg', 64),
('notq', 'not', 64),
('rolq', 'rol', 64),
('rorq', 'ror', 64),
('sarq', 'sar', 64),
('salq', 'sal', 64),
('shlq', 'shl', 64),
('shrq', 'shr', 64),
('incrementq', 'inc', 64),
('decrementq', 'dec', 64),
('pushp', 'pushp', 64),
('popp', 'popp', 64)
],
MemInstruction: [
('call', 'call', 64),
('mulq', 'mul', 64),
('negq', 'neg', 64),
('sarq', 'sar', 64),
('salq', 'sal', 64),
('shrq', 'shr', 64),
('incrementq', 'inc', 64),
('decrementq', 'dec', 64)
],
RegMemImmInstruction: [
('imulq', 'imul', 64)
],
RegRegImmInstruction: [
('imulq', 'imul', 64),
('shldq', 'shld', 64),
('shrdq', 'shrd', 64)
],
Pop2Instruction: [
('pop2', 'pop2', 64),
('pop2p', 'pop2p', 64)
],
Push2Instruction: [
('push2', 'push2', 64),
('push2p', 'push2p', 64)
],
MoveRegMemInstruction: [
('movzbq', 'movzx', 64, 8),
('movzwq', 'movzx', 64, 16),
('movsbq', 'movsx', 64, 8),
('movswq', 'movsx', 64, 16),
],
MoveRegRegInstruction: [
('movzbq', 'movzx', 64, 8),
('movzwq', 'movzx', 64, 16),
('movsbq', 'movsx', 64, 8),
('movswq', 'movsx', 64, 16),
],
CmpxchgInstruction: [
('cmpxchgq', 'cmpxchg', 64),
],
# --- NDD instructions ---
RegNddInstruction: [
('eidivq', 'idiv', 64, False),
('eidivq', 'idiv', 64, True),
('edivq', 'div', 64, False),
('edivq', 'div', 64, True),
('eimulq', 'imul', 64, False),
('eimulq', 'imul', 64, True),
('emulq', 'mul', 64, False),
('emulq', 'mul', 64, True),
],
MemNddInstruction: [
('emulq', 'mul', 64, False),
('emulq', 'mul', 64, True),
],
RegRegNddInstruction: [
('eimulq', 'imul', 64, False),
('eimulq', 'imul', 64, True),
('elzcntq', 'lzcnt', 64, False),
('elzcntq', 'lzcnt', 64, True),
('enegq', 'neg', 64, False),
('enegq', 'neg', 64, True),
('enotq', 'not', 64, None),
('epopcntq', 'popcnt', 64, False),
('epopcntq', 'popcnt', 64, True),
('erolq', 'rol', 64, False),
('erolq', 'rol', 64, True),
('erorq', 'ror', 64, False),
('erorq', 'ror', 64, True),
('esalq', 'sal', 64, False),
('esalq', 'sal', 64, True),
('esarq', 'sar', 64, False),
('esarq', 'sar', 64, True),
('edecq', 'dec', 64, False),
('edecq', 'dec', 64, True),
('eincq', 'inc', 64, False),
('eincq', 'inc', 64, True),
('eshlq', 'shl', 64, False),
('eshlq', 'shl', 64, True),
('eshrq', 'shr', 64, False),
('eshrq', 'shr', 64, True),
('etzcntq', 'tzcnt', 64, False),
('etzcntq', 'tzcnt', 64, True),
],
RegMemNddInstruction: [
('eimulq', 'imul', 64, False),
('eimulq', 'imul', 64, True),
('elzcntq', 'lzcnt', 64, False),
('elzcntq', 'lzcnt', 64, True),
('enegq', 'neg', 64, False),
('enegq', 'neg', 64, True),
('epopcntq', 'popcnt', 64, False),
('epopcntq', 'popcnt', 64, True),
('esalq', 'sal', 64, False),
('esalq', 'sal', 64, True),
('esarq', 'sar', 64, False),
('esarq', 'sar', 64, True),
('edecq', 'dec', 64, False),
('edecq', 'dec', 64, True),
('eincq', 'inc', 64, False),
('eincq', 'inc', 64, True),
('eshrq', 'shr', 64, False),
('eshrq', 'shr', 64, True),
('etzcntq', 'tzcnt', 64, False),
('etzcntq', 'tzcnt', 64, True),
],
RegMemRegNddInstruction: [
('eaddq', 'add', 64, False),
('eaddq', 'add', 64, True),
('eandq', 'and', 64, False),
('eandq', 'and', 64, True),
('eorq', 'or', 64, False),
('eorq', 'or', 64, True),
('esubq', 'sub', 64, False),
('esubq', 'sub', 64, True),
('exorq', 'xor', 64, False),
('exorq', 'xor', 64, True),
],
RegMemImmNddInstruction: [
('eaddq', 'add', 64, False),
('eaddq', 'add', 64, True),
('eandq', 'and', 64, False),
('eandq', 'and', 64, True),
('eimulq', 'imul', 64, False),
('eimulq', 'imul', 64, True),
('eorq', 'or', 64, False),
('eorq', 'or', 64, True),
('esalq', 'sal', 64, False),
('esalq', 'sal', 64, True),
('esarq', 'sar', 64, False),
('esarq', 'sar', 64, True),
('eshrq', 'shr', 64, False),
('eshrq', 'shr', 64, True),
('esubq', 'sub', 64, False),
('esubq', 'sub', 64, True),
('exorq', 'xor', 64, False),
('exorq', 'xor', 64, True),
],
RegRegImmNddInstruction: [
('eaddq', 'add', 64, False),
('eaddq', 'add', 64, True),
('eandq', 'and', 64, False),
('eandq', 'and', 64, True),
('eimulq', 'imul', 64, False),
('eimulq', 'imul', 64, True),
('eorq', 'or', 64, False),
('eorq', 'or', 64, True),
('erclq', 'rcl', 64, None),
('erolq', 'rol', 64, False),
('erolq', 'rol', 64, True),
('erorq', 'ror', 64, False),
('erorq', 'ror', 64, True),
('esalq', 'sal', 64, False),
('esalq', 'sal', 64, True),
('esarq', 'sar', 64, False),
('esarq', 'sar', 64, True),
('eshlq', 'shl', 64, False),
('eshlq', 'shl', 64, True),
('eshrq', 'shr', 64, False),
('eshrq', 'shr', 64, True),
('esubq', 'sub', 64, False),
('esubq', 'sub', 64, True),
('exorq', 'xor', 64, False),
('exorq', 'xor', 64, True),
('eorq_imm32', 'or', 64, False),
('eorq_imm32', 'or', 64, False),
('esubq_imm32', 'sub', 64, False),
('esubq_imm32', 'sub', 64, True),
],
RegRegMemNddInstruction: [
('eaddq', 'add', 64, False),
('eaddq', 'add', 64, True),
('eandq', 'and', 64, False),
('eandq', 'and', 64, True),
('eorq', 'or', 64, False),
('eorq', 'or', 64, True),
('eimulq', 'imul', 64, False),
('eimulq', 'imul', 64, True),
('esubq', 'sub', 64, False),
('esubq', 'sub', 64, True),
('exorq', 'xor', 64, False),
('exorq', 'xor', 64, True),
],
RegRegRegNddInstruction: [
('eaddq', 'add', 64, False),
('eaddq', 'add', 64, True),
('eadcxq', 'adcx', 64, None),
('eadoxq', 'adox', 64, None),
('eandq', 'and', 64, False),
('eandq', 'and', 64, True),
('eimulq', 'imul', 64, False),
('eimulq', 'imul', 64, True),
('eorq', 'or', 64, False),
('eorq', 'or', 64, True),
('esubq', 'sub', 64, False),
('esubq', 'sub', 64, True),
('exorq', 'xor', 64, False),
('exorq', 'xor', 64, True),
],
RegRegRegImmNddInstruction: [
('eshldq', 'shld', 64, False),
('eshldq', 'shld', 64, True),
('eshrdq', 'shrd', 64, False),
('eshrdq', 'shrd', 64, True),
],
CondRegRegRegInstruction: [
('ecmovq', 'cmov', 64, key) for key in cond_to_suffix.keys()
],
CondRegRegMemInstruction: [
('ecmovq', 'cmov', 64, key) for key in cond_to_suffix.keys()
],
}
if __name__ == "__main__":
if platform.system() != "Linux":
print("This script only works on Linux")
exit(1)
full_set = '--full' in sys.argv
ifdef_flags = []
insns_strs = []
print("// BEGIN Generated code -- do not edit")
print("// Generated by x86-asmtest.py")
outfile = open("x86ops.s", "w")
outfile.write(".intel_syntax noprefix\n")
for RegOp, ops in instruction_set.items():
generate(RegOp, ops, True, full_set)
if lp64_flag:
lp64_flag = False
print("#endif // _LP64")
print("#ifdef _LP64")
for RegOp, ops in instruction_set64.items():
generate(RegOp, ops, False, full_set)
print("#endif // _LP64")
outfile.close()
subprocess.check_call([X86_AS, "x86ops.s", "-o", "x86ops.o",])
subprocess.check_call([X86_OBJCOPY, "-O", "binary", "-j", ".text", "x86ops.o", "x86ops.bin"])
infile = open("x86ops.bin", "rb")
bytes = bytearray(infile.read())
infile.close()
disassembly_text = subprocess.check_output([OBJDUMP, "-M", "intel", "-d", "x86ops.o", "--insn-width=16"], text=True)
lines = disassembly_text.split("\n")
instruction_regex = re.compile(r'^\s*([0-9a-f]+):\s*([0-9a-f\s]+?)(?:\s{2,})')
instructions = []
for i, line in enumerate(lines):
match = instruction_regex.match(line)
if match:
offset = int(match.group(1), 16)
insns = match.group(2).split()
binary_code = ", ".join([f"0x{insn}" for insn in insns])
length = len(insns)
instructions.append((length, binary_code))
print()
print(" static const uint8_t insns[] =")
print(" {")
print_with_ifdef(ifdef_flags, instructions, lambda x: f"{x[1]}", 80)
print(" };")
print()
print(" static const unsigned int insns_lens[] =")
print(" {")
print_with_ifdef(ifdef_flags, instructions, lambda x: f"{x[0]}", 5)
print(" };")
print()
print(" static const char* insns_strs[] =")
print(" {")
print_with_ifdef(ifdef_flags, insns_strs, lambda x: f"\"{x}\"", 85)
print(" };")
print("// END Generated code -- do not edit")
for f in ["x86ops.s", "x86ops.o", "x86ops.bin"]:
os.remove(f)