2024-10-21 16:46:41 +00:00
|
|
|
# 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
|
2024-10-24 16:02:30 +00:00
|
|
|
import sys
|
2024-10-21 16:46:41 +00:00
|
|
|
import platform
|
|
|
|
import random
|
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
OBJDUMP = "objdump"
|
|
|
|
X86_AS = "as"
|
|
|
|
X86_OBJCOPY = "objcopy"
|
2024-11-13 16:19:33 +00:00
|
|
|
SEED = 1327
|
|
|
|
|
|
|
|
random.seed(SEED)
|
2024-10-21 16:46:41 +00:00
|
|
|
|
|
|
|
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',
|
|
|
|
}
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
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'}
|
2024-10-21 16:46:41 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
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
|
|
|
|
|
2024-10-21 16:46:41 +00:00
|
|
|
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()
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
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])
|
|
|
|
|
2024-10-21 16:46:41 +00:00
|
|
|
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)
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
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)
|
|
|
|
|
2024-10-21 16:46:41 +00:00
|
|
|
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):
|
2024-10-24 16:02:30 +00:00
|
|
|
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'}
|
2024-10-21 16:46:41 +00:00
|
|
|
|
|
|
|
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")
|
|
|
|
|
2024-10-24 16:02:30 +00:00
|
|
|
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
|
2024-10-21 16:46:41 +00:00
|
|
|
return lp64_flag
|
|
|
|
|
|
|
|
def get_immediate_list(op_name, width):
|
|
|
|
# special cases
|
|
|
|
word_imm_ops = {'addw', 'cmpw'}
|
2024-11-13 16:19:33 +00:00
|
|
|
dword_imm_ops = {'subl_imm32', 'subq_imm32', 'orq_imm32', 'cmpl_imm32', 'esubl_imm32', 'esubq_imm32', 'eorq_imm32', 'testl'}
|
2024-10-21 16:46:41 +00:00
|
|
|
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]
|
|
|
|
|
2024-10-24 16:02:30 +00:00
|
|
|
lp64_flag = False
|
|
|
|
def generate(RegOp, ops, print_lp64_flag=True, full_set=False):
|
|
|
|
global lp64_flag
|
2024-10-21 16:46:41 +00:00
|
|
|
for op in ops:
|
|
|
|
op_name = op[0]
|
|
|
|
width = op[2]
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
if RegOp in [RegInstruction, CondRegInstruction, RegNddInstruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
print_instruction(instr, lp64_flag, print_lp64_flag)
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
elif RegOp in [TwoRegInstruction, MoveRegRegInstruction, RegRegNddInstruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
print_instruction(instr, lp64_flag, print_lp64_flag)
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
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]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
print_instruction(instr, lp64_flag, print_lp64_flag)
|
|
|
|
|
|
|
|
elif RegOp in [RegImmInstruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
|
|
|
|
elif RegOp in [MemImmInstruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
elif RegOp in [MemInstruction, MemNddInstruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
if full_set:
|
2024-10-21 16:46:41 +00:00
|
|
|
for i in range(len(test_regs)):
|
2024-10-24 16:02:30 +00:00
|
|
|
test_mem_base = test_regs[i]
|
|
|
|
test_mem_idx = test_regs[(i + 1) % len(test_regs)]
|
|
|
|
if test_mem_idx == 'rsp':
|
2024-10-21 16:46:41 +00:00
|
|
|
continue
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
print_instruction(instr, lp64_flag, print_lp64_flag)
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
print_instruction(instr, lp64_flag, print_lp64_flag)
|
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
elif RegOp in [RegRegImmInstruction, RegRegImmNddInstruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
elif RegOp in [RegMemImmInstruction, RegMemImmNddInstruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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':
|
2024-10-21 16:46:41 +00:00
|
|
|
continue
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
|
2024-11-13 16:19:33 +00:00
|
|
|
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)
|
|
|
|
|
2024-10-21 16:46:41 +00:00
|
|
|
elif RegOp in [Push2Instruction, Pop2Instruction]:
|
2024-10-24 16:02:30 +00:00
|
|
|
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)
|
2024-10-21 16:46:41 +00:00
|
|
|
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),
|
|
|
|
],
|
2024-11-13 16:19:33 +00:00
|
|
|
# --- 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()
|
|
|
|
],
|
2024-10-21 16:46:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
|
|
|
],
|
2024-11-13 16:19:33 +00:00
|
|
|
# --- 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()
|
|
|
|
],
|
2024-10-21 16:46:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
if platform.system() != "Linux":
|
|
|
|
print("This script only works on Linux")
|
|
|
|
exit(1)
|
|
|
|
|
2024-10-24 16:02:30 +00:00
|
|
|
full_set = '--full' in sys.argv
|
|
|
|
|
2024-10-21 16:46:41 +00:00
|
|
|
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():
|
2024-10-24 16:02:30 +00:00
|
|
|
generate(RegOp, ops, True, full_set)
|
|
|
|
|
|
|
|
if lp64_flag:
|
|
|
|
lp64_flag = False
|
|
|
|
print("#endif // _LP64")
|
2024-10-21 16:46:41 +00:00
|
|
|
|
|
|
|
print("#ifdef _LP64")
|
|
|
|
for RegOp, ops in instruction_set64.items():
|
2024-10-24 16:02:30 +00:00
|
|
|
generate(RegOp, ops, False, full_set)
|
2024-10-21 16:46:41 +00:00
|
|
|
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)
|