mirror of
https://github.com/ModOrganizer2/udis86.git
synced 2026-07-27 14:05:57 -07:00
Use standard notation for sse opcode extension (/sse=66,f3,f2)
This commit is contained in:
+66
-60
@@ -37,6 +37,8 @@ class UdOpcodeTables:
|
||||
'/o' : { 'name' : 'UD_TAB__OPC_OSIZE', 'size' : 3 },
|
||||
'/3dnow' : { 'name' : 'UD_TAB__OPC_3DNOW', 'size' : 256 },
|
||||
'vendor' : { 'name' : 'UD_TAB__OPC_VENDOR', 'size' : 3 },
|
||||
'/vex.p' : { 'name' : 'UD_TAB__OPC_VEX_P', 'size' : 4 },
|
||||
'/vex.m' : { 'name' : 'UD_TAB__OPC_VEX_M', 'size' : 3 },
|
||||
}
|
||||
|
||||
OpcodeTable0 = {
|
||||
@@ -72,14 +74,27 @@ class UdOpcodeTables:
|
||||
'amd' : '00',
|
||||
'intel' : '01',
|
||||
'any' : '02'
|
||||
}
|
||||
},
|
||||
|
||||
'vex.p': {
|
||||
'none' : '00',
|
||||
'f2' : '01',
|
||||
'f3' : '02',
|
||||
'66' : '03'
|
||||
},
|
||||
|
||||
'vex.m': {
|
||||
'none' : '00',
|
||||
'38' : '01',
|
||||
'3a' : '02',
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
|
||||
InsnTable = []
|
||||
MnemonicsTable = []
|
||||
|
||||
ThreeDNowTable = {}
|
||||
|
||||
def sizeOfTable( self, t ):
|
||||
return self.TableInfo[ t ][ 'size' ]
|
||||
|
||||
@@ -96,7 +111,7 @@ class UdOpcodeTables:
|
||||
table[ 'entries' ][ index ] = { 'type' : type, 'entries' : {}, 'meta' : meta }
|
||||
if table[ 'entries' ][ index ][ 'type' ] != type:
|
||||
raise NameError( "error: violation in opcode mapping (overwrite) %s with %s." %
|
||||
( table[ 'entries' ][ index ][ 'type' ], type) )
|
||||
( table[ 'entries' ][ index ], type) )
|
||||
return table[ 'entries' ][ index ]
|
||||
|
||||
class Insn:
|
||||
@@ -118,73 +133,59 @@ class UdOpcodeTables:
|
||||
'/o' : lambda v: "%02x" % (int(v) / 32),
|
||||
'/a' : lambda v: "%02x" % (int(v) / 32),
|
||||
'/m' : lambda v: '00' if v == '!64' else '01',
|
||||
'/sse' : lambda v: UdOpcodeTables.OpcExtIndex['sse'][v]
|
||||
# SSE
|
||||
'/sse' : lambda v: UdOpcodeTables.OpcExtIndex['sse'][v],
|
||||
# AVX
|
||||
'/vex.p' : lambda v: UdOpcodeTables.OpcExtIndex['vex.p'][v],
|
||||
'/vex.m' : lambda v: UdOpcodeTables.OpcExtIndex['vex.m'][v]
|
||||
}
|
||||
|
||||
def __init__(self, prefixes, mnemonic, opcodes, operands, vendor):
|
||||
self.opcodes = opcodes
|
||||
self.opcodes = []
|
||||
self.prefixes = prefixes
|
||||
self.mnemonic = mnemonic
|
||||
self.operands = operands
|
||||
self.vendor = vendor
|
||||
self.opcext = {}
|
||||
|
||||
ssePrefix = None
|
||||
if self.opcodes[0] in ('ssef2', 'ssef3', 'sse66'):
|
||||
ssePrefix = self.opcodes[0][3:]
|
||||
self.opcodes.pop(0)
|
||||
# artificially add a /sse=none for 2 byte opcodes
|
||||
if opcodes[0] == '0f' and opcodes[1] != '0f':
|
||||
opcodes.append('/sse=none')
|
||||
|
||||
# do some preliminary decoding of the instruction type
|
||||
# 1byte, 2byte or 3byte instruction?
|
||||
self.nByteInsn = 1
|
||||
if self.opcodes[0] == '0f': # 2byte
|
||||
# 2+ byte opcodes are always disambiguated by an
|
||||
# sse prefix, unless it is a 3d now instruction
|
||||
# which is 0f 0f ...
|
||||
if self.opcodes[1] != '0f' and ssePrefix is None:
|
||||
ssePrefix = 'none'
|
||||
if self.opcodes[1] in ('38', '3a'): # 3byte
|
||||
self.nByteInsn = 3
|
||||
else:
|
||||
self.nByteInsn = 2
|
||||
|
||||
# The opcode that indexes into the opcode table.
|
||||
self.opcode = self.opcodes[self.nByteInsn - 1]
|
||||
|
||||
# Record opcode extensions
|
||||
for opcode in self.opcodes[self.nByteInsn:]:
|
||||
arg, val = opcode.split('=')
|
||||
self.opcext[arg] = self.OpcExtMap[arg](val)
|
||||
# begin the list with all plain opcodes
|
||||
for opc in opcodes:
|
||||
if not opc.startswith('/'):
|
||||
self.opcodes.append(opc)
|
||||
|
||||
# Record sse extension: the reason sse extension is handled
|
||||
# separately is that historically sse was handled as a first
|
||||
# class opcode, not as an extension. Now that sse is handled
|
||||
# as an extension, we do the manual conversion here, as opposed
|
||||
# to modifying the opcode xml file.
|
||||
if ssePrefix is not None:
|
||||
self.opcext['/sse'] = self.OpcExtMap['/sse'](ssePrefix)
|
||||
# re-order vex/xop prefixes to follow vex opcode
|
||||
if self.opcodes[0] == 'c4' or self.opcodes[0] == 'c5':
|
||||
for opc in opcodes:
|
||||
if opc.startswith('/vex'):
|
||||
self.opcodes.insert(1, opc)
|
||||
|
||||
# Add extensions. The order is important, and determines how
|
||||
# well the opcode table is packed. Also note, /sse must be
|
||||
# before /o, because /sse may consume operand size prefix
|
||||
# affect the outcome of /o.
|
||||
for ext in ('/mod', '/x87', '/reg', '/rm', '/sse',
|
||||
'/o', '/a', '/m', '/3dnow'):
|
||||
for opc in opcodes:
|
||||
if opc.startswith(ext):
|
||||
self.opcodes.append(opc)
|
||||
|
||||
def parse(self, table, insn):
|
||||
# Walk down the tree, create levels as needed
|
||||
assert not insn.opcodes[0].startswith("/")
|
||||
index = insn.opcodes[0];
|
||||
if insn.nByteInsn > 1:
|
||||
assert index == '0f'
|
||||
table = self.updateTable(table, index, 'opctbl', '0f')
|
||||
index = insn.opcodes[1]
|
||||
|
||||
if insn.nByteInsn == 3:
|
||||
table = self.updateTable(table, index, 'opctbl', index)
|
||||
index = insn.opcodes[2]
|
||||
|
||||
# Walk down the tree, create levels as needed, for opcode
|
||||
# extensions. The order is important, and determines how
|
||||
# well the opcode table is packed. Also note, /sse must be
|
||||
# before /o, because /sse may consume operand size prefix
|
||||
# affect the outcome of /o.
|
||||
for ext in ('/mod', '/x87', '/reg', '/rm', '/sse',
|
||||
'/o', '/a', '/m', '/3dnow'):
|
||||
if ext in insn.opcext:
|
||||
for opc in insn.opcodes[1:]:
|
||||
if opc.startswith('/'):
|
||||
ext, v= opc.split('=')
|
||||
table = self.updateTable(table, index, ext, ext)
|
||||
index = insn.opcext[ext]
|
||||
index = insn.OpcExtMap[ext](v)
|
||||
insn.opcext[ext] = index
|
||||
else:
|
||||
table = self.updateTable(table, index, 'opctbl', index)
|
||||
index = opc
|
||||
|
||||
# additional table for disambiguating vendor
|
||||
if len(insn.vendor):
|
||||
@@ -200,10 +201,11 @@ class UdOpcodeTables:
|
||||
|
||||
# add instruction to linear table of instruction forms
|
||||
self.InsnTable.append({ 'prefixes' : insn.prefixes,
|
||||
'opcext' : insn.opcext,
|
||||
'mnemonic' : insn.mnemonic,
|
||||
'operands' : insn.operands,
|
||||
'vendor' : insn.vendor })
|
||||
'vendor' : insn.vendor,
|
||||
'opcext' : insn.opcext,
|
||||
'opcodes' : insn.opcodes })
|
||||
|
||||
# add mnemonic to mnemonic table
|
||||
if not insn.mnemonic in self.MnemonicsTable:
|
||||
@@ -217,7 +219,11 @@ class UdOpcodeTables:
|
||||
opcodes=opcodes,
|
||||
operands=operands,
|
||||
vendor=vendor)
|
||||
self.parse(self.OpcodeTable0, insn)
|
||||
try:
|
||||
self.parse(self.OpcodeTable0, insn)
|
||||
except:
|
||||
self.print_tree()
|
||||
raise
|
||||
|
||||
def print_table( self, table, pfxs ):
|
||||
print("%s |" % pfxs)
|
||||
@@ -227,7 +233,7 @@ class UdOpcodeTables:
|
||||
for idx in keys:
|
||||
e = table[ 'entries' ][ idx ]
|
||||
if e[ 'type' ] == 'insn':
|
||||
print("%s |-<%s>" % ( pfxs, idx ),)
|
||||
print("%s |-<%s>" % ( pfxs, idx )),
|
||||
print("%s %s" % ( e[ 'mnemonic' ], ' '.join( e[ 'operands'] ) ))
|
||||
else:
|
||||
print("%s |-<%s> %s" % ( pfxs, idx, e['type'] ))
|
||||
|
||||
Reference in New Issue
Block a user