mirror of
https://github.com/RRZE-HPC/OSACA.git
synced 2025-12-16 17:10:06 +01:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
457ccdcf77 | ||
|
|
ff61c65d58 | ||
|
|
615c809fe3 | ||
|
|
bce837dec9 | ||
|
|
090c24ade1 | ||
|
|
03a2a1da33 | ||
|
|
d59b100fa8 |
@@ -1,10 +1,10 @@
|
||||
"""Open Source Architecture Code Analyzer"""
|
||||
name = "osaca"
|
||||
__version__ = "0.4.2"
|
||||
__version__ = "0.4.5"
|
||||
|
||||
# To trigger travis deployment to pypi, do the following:
|
||||
# 1. Increment __version___
|
||||
# 2. commit to RRZE-HPC/osaca's master branch
|
||||
# 3. wait for travis to complete successful (unless already tested)
|
||||
# 3. wait for Github Actions to complete successful (unless already tested)
|
||||
# 4. tag commit with 'v{}'.format(__version__) (`git tag vX.Y.Z`)
|
||||
# 5. push tag to github (`git push origin vX.Y.Z` or push all tags with `git push --tags`)
|
||||
|
||||
@@ -520,7 +520,7 @@ instruction_forms:
|
||||
width: '512'
|
||||
throughput: 11.5
|
||||
latency: 49.0 # 11*p0+12*p02
|
||||
port_pressure: [[10, '0'], [12, '02']]
|
||||
port_pressure: [[9, '0'], [14, '02']]
|
||||
- name: fadd
|
||||
operands:
|
||||
- class: register
|
||||
@@ -1095,7 +1095,7 @@ instruction_forms:
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [2, ['5D', '6D']]]
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1d
|
||||
operands:
|
||||
- class: register
|
||||
@@ -1113,7 +1113,7 @@ instruction_forms:
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [2, ['5D', '6D']]]
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1d
|
||||
operands:
|
||||
- class: register
|
||||
@@ -1132,6 +1132,330 @@ instruction_forms:
|
||||
throughput: 2.0
|
||||
latency: 11.0 # 1*p0+1*p3+4*p56+1*p5D6D
|
||||
port_pressure: [[1, '0'],[1, '3'],[4, '56'], [4, ['5D', '6D']]] # not sure if we also have 4 data accesses
|
||||
- name: ld1w
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: ~
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1w
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: x
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1w
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: ~
|
||||
index: z
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 2.0
|
||||
latency: 11.0 # 1*p0+1*p3+4*p56+1*p5D6D
|
||||
port_pressure: [[1, '0'],[1, '3'],[4, '56'], [4, ['5D', '6D']]] # not sure if we also have 4 data accesses
|
||||
- name: ld1h
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: ~
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1h
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: x
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1h
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: ~
|
||||
index: z
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 2.0
|
||||
latency: 11.0 # 1*p0+1*p3+4*p56+1*p5D6D
|
||||
port_pressure: [[1, '0'],[1, '3'],[4, '56'], [4, ['5D', '6D']]] # not sure if we also have 4 data accesses
|
||||
- name: ld1b
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: ~
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1b
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: x
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1b
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: ~
|
||||
index: z
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 2.0
|
||||
latency: 11.0 # 1*p0+1*p3+4*p56+1*p5D6D
|
||||
port_pressure: [[1, '0'],[1, '3'],[4, '56'], [4, ['5D', '6D']]] # not sure if we also have 4 data accesses
|
||||
- name: ld1sw
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: ~
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1sw
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: x
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1sw
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: ~
|
||||
index: z
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 2.0
|
||||
latency: 11.0 # 1*p0+1*p3+4*p56+1*p5D6D
|
||||
port_pressure: [[1, '0'],[1, '3'],[4, '56'], [4, ['5D', '6D']]] # not sure if we also have 4 data accesses
|
||||
- name: ld1sh
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: ~
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1sh
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: x
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1sh
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: ~
|
||||
index: z
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 2.0
|
||||
latency: 11.0 # 1*p0+1*p3+4*p56+1*p5D6D
|
||||
port_pressure: [[1, '0'],[1, '3'],[4, '56'], [4, ['5D', '6D']]] # not sure if we also have 4 data accesses
|
||||
- name: ld1sb
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: ~
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1sb
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: '*'
|
||||
index: x
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 0.5
|
||||
latency: 8.0 # 1*p56+1*p5D6D
|
||||
port_pressure: [[1, '56'], [1, ['5D', '6D']]]
|
||||
- name: ld1sb
|
||||
operands:
|
||||
- class: register
|
||||
prefix: z
|
||||
shape: d
|
||||
- class: register
|
||||
prefix: p
|
||||
predication: '*'
|
||||
- class: memory
|
||||
base: x
|
||||
offset: ~
|
||||
index: z
|
||||
scale: '*'
|
||||
pre-indexed: false
|
||||
post-indexed: false
|
||||
throughput: 2.0
|
||||
latency: 11.0 # 1*p0+1*p3+4*p56+1*p5D6D
|
||||
port_pressure: [[1, '0'],[1, '3'],[4, '56'], [4, ['5D', '6D']]] # not sure if we also have 4 data accesses
|
||||
- name: ld2d
|
||||
operands:
|
||||
- class: register
|
||||
|
||||
@@ -62,6 +62,28 @@ instruction_forms:
|
||||
imd: int
|
||||
source: false
|
||||
destination: false
|
||||
- name: fmla
|
||||
operands:
|
||||
- class: register
|
||||
prefix: "*"
|
||||
shape: "*"
|
||||
source: true
|
||||
destination: true
|
||||
- class: register
|
||||
prefix: "*"
|
||||
shape: "*"
|
||||
source: true
|
||||
destination: false
|
||||
- class: register
|
||||
prefix: "*"
|
||||
shape: "*"
|
||||
source: true
|
||||
destination: false
|
||||
- class: register
|
||||
prefix: "*"
|
||||
shape: "*"
|
||||
source: true
|
||||
destination: false
|
||||
- name: fmla
|
||||
operands:
|
||||
- class: register
|
||||
|
||||
@@ -239,7 +239,7 @@ class ParserAArch64(BaseParser):
|
||||
|
||||
# 1. Parse comment
|
||||
try:
|
||||
result = self.process_operand(self.comment.parseString(line, parseAll=True).asDict())[0]
|
||||
result = self.process_operand(self.comment.parseString(line, parseAll=True).asDict())
|
||||
result = AttrDict.convert_dict(result)
|
||||
instruction_form[self.COMMENT_ID] = " ".join(result[self.COMMENT_ID])
|
||||
except pp.ParseException:
|
||||
@@ -248,7 +248,7 @@ class ParserAArch64(BaseParser):
|
||||
try:
|
||||
result = self.process_operand(
|
||||
self.llvm_markers.parseString(line, parseAll=True).asDict()
|
||||
)[0]
|
||||
)
|
||||
result = AttrDict.convert_dict(result)
|
||||
instruction_form[self.COMMENT_ID] = " ".join(result[self.COMMENT_ID])
|
||||
except pp.ParseException:
|
||||
@@ -256,7 +256,9 @@ class ParserAArch64(BaseParser):
|
||||
# 2. Parse label
|
||||
if result is None:
|
||||
try:
|
||||
result = self.process_operand(self.label.parseString(line, parseAll=True).asDict())[0]
|
||||
result = self.process_operand(
|
||||
self.label.parseString(line, parseAll=True).asDict()
|
||||
)
|
||||
result = AttrDict.convert_dict(result)
|
||||
instruction_form[self.LABEL_ID] = result[self.LABEL_ID].name
|
||||
if self.COMMENT_ID in result[self.LABEL_ID]:
|
||||
@@ -271,7 +273,7 @@ class ParserAArch64(BaseParser):
|
||||
try:
|
||||
result = self.process_operand(
|
||||
self.directive.parseString(line, parseAll=True).asDict()
|
||||
)[0]
|
||||
)
|
||||
result = AttrDict.convert_dict(result)
|
||||
instruction_form[self.DIRECTIVE_ID] = AttrDict(
|
||||
{
|
||||
@@ -311,19 +313,24 @@ class ParserAArch64(BaseParser):
|
||||
# Add operands to list
|
||||
# Check first operand
|
||||
if "operand1" in result:
|
||||
operands += self.process_operand(result["operand1"])
|
||||
operand = self.process_operand(result["operand1"])
|
||||
operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
|
||||
# Check second operand
|
||||
if "operand2" in result:
|
||||
operands += self.process_operand(result["operand2"])
|
||||
operand = self.process_operand(result["operand2"])
|
||||
operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
|
||||
# Check third operand
|
||||
if "operand3" in result:
|
||||
operands += self.process_operand(result["operand3"])
|
||||
operand = self.process_operand(result["operand3"])
|
||||
operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
|
||||
# Check fourth operand
|
||||
if "operand4" in result:
|
||||
operands += self.process_operand(result["operand4"])
|
||||
operand = self.process_operand(result["operand4"])
|
||||
operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
|
||||
# Check fifth operand
|
||||
if "operand5" in result:
|
||||
operands += self.process_operand(result["operand5"])
|
||||
operand = self.process_operand(result["operand5"])
|
||||
operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
|
||||
|
||||
return_dict = AttrDict(
|
||||
{
|
||||
@@ -340,7 +347,7 @@ class ParserAArch64(BaseParser):
|
||||
"""Post-process operand"""
|
||||
# structure memory addresses
|
||||
if self.MEMORY_ID in operand:
|
||||
return [self.process_memory_address(operand[self.MEMORY_ID])]
|
||||
return self.process_memory_address(operand[self.MEMORY_ID])
|
||||
# structure register lists
|
||||
if self.REGISTER_ID in operand and (
|
||||
"list" in operand[self.REGISTER_ID] or "range" in operand[self.REGISTER_ID]
|
||||
@@ -348,15 +355,15 @@ class ParserAArch64(BaseParser):
|
||||
# resolve ranges and lists
|
||||
return self.resolve_range_list(self.process_register_list(operand[self.REGISTER_ID]))
|
||||
if self.REGISTER_ID in operand and operand[self.REGISTER_ID]["name"] == "sp":
|
||||
return [self.process_sp_register(operand[self.REGISTER_ID])]
|
||||
return self.process_sp_register(operand[self.REGISTER_ID])
|
||||
# add value attribute to floating point immediates without exponent
|
||||
if self.IMMEDIATE_ID in operand:
|
||||
return [self.process_immediate(operand[self.IMMEDIATE_ID])]
|
||||
return self.process_immediate(operand[self.IMMEDIATE_ID])
|
||||
if self.LABEL_ID in operand:
|
||||
return [self.process_label(operand[self.LABEL_ID])]
|
||||
return self.process_label(operand[self.LABEL_ID])
|
||||
if self.IDENTIFIER_ID in operand:
|
||||
return [self.process_identifier(operand[self.IDENTIFIER_ID])]
|
||||
return [operand]
|
||||
return self.process_identifier(operand[self.IDENTIFIER_ID])
|
||||
return operand
|
||||
|
||||
def process_memory_address(self, memory_address):
|
||||
"""Post-process memory address operand"""
|
||||
@@ -364,6 +371,8 @@ class ParserAArch64(BaseParser):
|
||||
offset = memory_address.get("offset", None)
|
||||
if isinstance(offset, list) and len(offset) == 1:
|
||||
offset = offset[0]
|
||||
if offset is not None and "value" in offset:
|
||||
offset["value"] = int(offset["value"], 0)
|
||||
base = memory_address.get("base", None)
|
||||
index = memory_address.get("index", None)
|
||||
scale = 1
|
||||
@@ -380,7 +389,12 @@ class ParserAArch64(BaseParser):
|
||||
if "pre_indexed" in memory_address:
|
||||
new_dict["pre_indexed"] = True
|
||||
if "post_indexed" in memory_address:
|
||||
new_dict["post_indexed"] = memory_address["post_indexed"]
|
||||
if "value" in memory_address["post_indexed"]:
|
||||
new_dict["post_indexed"] = {"value": int(
|
||||
memory_address["post_indexed"]["value"], 0
|
||||
)}
|
||||
else:
|
||||
new_dict["post_indexed"] = memory_address["post_indexed"]
|
||||
return AttrDict({self.MEMORY_ID: new_dict})
|
||||
|
||||
def process_sp_register(self, register):
|
||||
@@ -392,32 +406,33 @@ class ParserAArch64(BaseParser):
|
||||
def resolve_range_list(self, operand):
|
||||
"""
|
||||
Resolve range or list register operand to list of registers.
|
||||
|
||||
Returns None if neither list nor range
|
||||
"""
|
||||
if 'register' in operand:
|
||||
if 'list' in operand.register:
|
||||
index = operand.register.get('index')
|
||||
l = []
|
||||
range_list = []
|
||||
for reg in operand.register.list:
|
||||
reg = deepcopy(reg)
|
||||
if index is not None:
|
||||
reg.index = index
|
||||
l.append(AttrDict({self.REGISTER_ID: reg}))
|
||||
return l
|
||||
reg['index'] = int(index, 0)
|
||||
range_list.append(AttrDict({self.REGISTER_ID: reg}))
|
||||
return range_list
|
||||
elif 'range' in operand.register:
|
||||
base_register = operand.register.range[0]
|
||||
index = operand.register.get('index')
|
||||
l = []
|
||||
range_list = []
|
||||
start_name = base_register.name
|
||||
end_name = operand.register.range[1].name
|
||||
for name in range(int(start_name), int(end_name)+1):
|
||||
for name in range(int(start_name), int(end_name) + 1):
|
||||
reg = deepcopy(base_register)
|
||||
if index is not None:
|
||||
reg['index'] = operand.register.range.index
|
||||
reg['index'] = int(index, 0)
|
||||
reg['name'] = str(name)
|
||||
l.append(AttrDict({self.REGISTER_ID: reg}))
|
||||
return l
|
||||
range_list.append(AttrDict({self.REGISTER_ID: reg}))
|
||||
return range_list
|
||||
# neither register list nor range, return unmodified
|
||||
return operand
|
||||
|
||||
def process_register_list(self, register_list):
|
||||
"""Post-process register lists (e.g., {r0,r3,r5}) and register ranges (e.g., {r0-r7})"""
|
||||
@@ -447,11 +462,13 @@ class ParserAArch64(BaseParser):
|
||||
if "value" in immediate:
|
||||
# normal integer value
|
||||
immediate["type"] = "int"
|
||||
# convert hex/bin immediates to dec
|
||||
immediate["value"] = self.normalize_imd(immediate)
|
||||
return AttrDict({self.IMMEDIATE_ID: immediate})
|
||||
if "base_immediate" in immediate:
|
||||
# arithmetic immediate, add calculated value as value
|
||||
immediate["shift"] = immediate["shift"][0]
|
||||
immediate["value"] = int(immediate["base_immediate"]["value"], 0) << int(
|
||||
immediate["value"] = self.normalize_imd(immediate["base_immediate"]) << int(
|
||||
immediate["shift"]["value"]
|
||||
)
|
||||
immediate["type"] = "int"
|
||||
@@ -499,10 +516,11 @@ class ParserAArch64(BaseParser):
|
||||
def normalize_imd(self, imd):
|
||||
"""Normalize immediate to decimal based representation"""
|
||||
if "value" in imd:
|
||||
if imd["value"].lower().startswith("0x"):
|
||||
# hex, return decimal
|
||||
return int(imd["value"], 16)
|
||||
return int(imd["value"], 10)
|
||||
if isinstance(imd["value"], str):
|
||||
# hex or bin, return decimal
|
||||
return int(imd["value"], 0)
|
||||
else:
|
||||
return imd["value"]
|
||||
elif "float" in imd:
|
||||
return self.ieee_to_float(imd["float"])
|
||||
elif "double" in imd:
|
||||
|
||||
@@ -327,9 +327,14 @@ class ParserX86ATT(BaseParser):
|
||||
offset = memory_address.get("offset", None)
|
||||
base = memory_address.get("base", None)
|
||||
index = memory_address.get("index", None)
|
||||
scale = 1 if "scale" not in memory_address else int(memory_address["scale"])
|
||||
scale = 1 if "scale" not in memory_address else int(memory_address["scale"], 0)
|
||||
if isinstance(offset, str) and base is None and index is None:
|
||||
offset = {"value": offset}
|
||||
try:
|
||||
offset = {"value": int(offset, 0)}
|
||||
except ValueError:
|
||||
offset = {"value": offset}
|
||||
elif offset is not None and "value" in offset:
|
||||
offset["value"] = int(offset["value"], 0)
|
||||
new_dict = AttrDict({"offset": offset, "base": base, "index": index, "scale": scale})
|
||||
# Add segmentation extension if existing
|
||||
if self.SEGMENT_EXT_ID in memory_address:
|
||||
@@ -347,7 +352,8 @@ class ParserX86ATT(BaseParser):
|
||||
if "identifier" in immediate:
|
||||
# actually an identifier, change declaration
|
||||
return immediate
|
||||
# otherwise nothing to do
|
||||
# otherwise just make sure the immediate is a decimal
|
||||
immediate["value"] = int(immediate["value"], 0)
|
||||
return AttrDict({self.IMMEDIATE_ID: immediate})
|
||||
|
||||
def get_full_reg_name(self, register):
|
||||
@@ -358,10 +364,11 @@ class ParserX86ATT(BaseParser):
|
||||
def normalize_imd(self, imd):
|
||||
"""Normalize immediate to decimal based representation"""
|
||||
if "value" in imd:
|
||||
if imd["value"].lower().startswith("0x"):
|
||||
# hex, return decimal
|
||||
return int(imd["value"], 16)
|
||||
return int(imd["value"], 10)
|
||||
if isinstance(imd["value"], str):
|
||||
# return decimal
|
||||
return int(imd["value"], 0)
|
||||
else:
|
||||
return imd["value"]
|
||||
# identifier
|
||||
return imd
|
||||
|
||||
|
||||
@@ -163,10 +163,10 @@ class ISASemantics(object):
|
||||
if only_postindexed:
|
||||
for o in instruction_form.operands:
|
||||
if 'post_indexed' in o.get('memory', {}):
|
||||
base_name = o.memory.base.get('prefix', '')+o.memory.base.name
|
||||
base_name = o.memory.base.get('prefix', '') + o.memory.base.name
|
||||
return {base_name: {
|
||||
'name': o.memory.base.get('prefix', '')+o.memory.base.name,
|
||||
'value': int(o.memory.post_indexed.value)
|
||||
'name': o.memory.base.get('prefix', '') + o.memory.base.name,
|
||||
'value': o.memory.post_indexed.value
|
||||
}}
|
||||
return {}
|
||||
|
||||
@@ -180,24 +180,24 @@ class ISASemantics(object):
|
||||
raise ValueError(
|
||||
"ISA information for pre-indexed instruction {!r} has operation set."
|
||||
"This is currently not supprted.".format(instruction_form.line))
|
||||
base_name = o.memory.base.get('prefix', '')+o.memory.base.name
|
||||
base_name = o.memory.base.get('prefix', '') + o.memory.base.name
|
||||
reg_operand_names = {base_name: 'op1'}
|
||||
operand_state = {'op1': {
|
||||
'name': base_name,
|
||||
'value': int(o.memory.offset.value)
|
||||
'value': o.memory.offset.value
|
||||
}}
|
||||
|
||||
if isa_data is not None and 'operation' in isa_data:
|
||||
for i, o in enumerate(instruction_form.operands):
|
||||
operand_name = "op{}".format(i+1)
|
||||
operand_name = "op{}".format(i + 1)
|
||||
if "register" in o:
|
||||
o_reg_name = o["register"].get('prefix', '')+o["register"]["name"]
|
||||
o_reg_name = o["register"].get('prefix', '') + o["register"]["name"]
|
||||
reg_operand_names[o_reg_name] = operand_name
|
||||
operand_state[operand_name] = {
|
||||
'name': o_reg_name,
|
||||
'value': 0}
|
||||
elif "immediate" in o:
|
||||
operand_state[operand_name] = {'value': int(o["immediate"]["value"])}
|
||||
operand_state[operand_name] = {'value': o["immediate"]["value"]}
|
||||
elif "memory" in o:
|
||||
# TODO lea needs some thinking about
|
||||
pass
|
||||
|
||||
@@ -382,9 +382,9 @@ class KernelDG(nx.DiGraph):
|
||||
# determine absolute address change
|
||||
addr_change = 0
|
||||
if src.offset and "value" in src.offset:
|
||||
addr_change += int(src.offset.value, 0)
|
||||
addr_change += src.offset.value
|
||||
if mem.offset:
|
||||
addr_change -= int(mem.offset.value, 0)
|
||||
addr_change -= mem.offset.value
|
||||
if mem.base and src.base:
|
||||
base_change = register_changes.get(
|
||||
src.base.get('prefix', '') + src.base.name,
|
||||
|
||||
@@ -102,7 +102,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
self.assertEqual(parsed_3.instruction, "mov")
|
||||
self.assertEqual(parsed_3.operands[0].register.name, "2")
|
||||
self.assertEqual(parsed_3.operands[0].register.prefix, "x")
|
||||
self.assertEqual(parsed_3.operands[1].immediate.value, "0x222")
|
||||
self.assertEqual(parsed_3.operands[1].immediate.value, int("0x222", 0))
|
||||
self.assertEqual(parsed_3.comment, "NOT IACA END")
|
||||
|
||||
self.assertEqual(parsed_4.instruction, "str")
|
||||
@@ -208,7 +208,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
{"prfop": {"type": ["PLD"], "target": ["L1"], "policy": ["KEEP"]}},
|
||||
{
|
||||
"memory": {
|
||||
"offset": {"value": "2048"},
|
||||
"offset": {"value": 2048},
|
||||
"base": {"prefix": "x", "name": "26"},
|
||||
"index": None,
|
||||
"scale": 1,
|
||||
@@ -228,7 +228,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
{"register": {"prefix": "x", "name": "30"}},
|
||||
{
|
||||
"memory": {
|
||||
"offset": {"value": "-16"},
|
||||
"offset": {"value": -16},
|
||||
"base": {"name": "sp", "prefix": "x"},
|
||||
"index": None,
|
||||
"scale": 1,
|
||||
@@ -253,7 +253,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
"base": {"prefix": "x", "name": "11"},
|
||||
"index": None,
|
||||
"scale": 1,
|
||||
"post_indexed": {"value": "64"},
|
||||
"post_indexed": {"value": 64},
|
||||
}
|
||||
},
|
||||
],
|
||||
@@ -270,7 +270,7 @@ class TestParserAArch64(unittest.TestCase):
|
||||
{"register": {"prefix": "p", "name": "0", "predication": "m"}},
|
||||
{"register": {"prefix": "z", "name": "29", "shape": "d"}},
|
||||
{"register": {"prefix": "z", "name": "21", "shape": "d"}},
|
||||
{"immediate": {"value": "90", "type": "int"}},
|
||||
{"immediate": {"value": 90, "type": "int"}},
|
||||
],
|
||||
"directive": None,
|
||||
"comment": None,
|
||||
@@ -327,16 +327,33 @@ class TestParserAArch64(unittest.TestCase):
|
||||
def test_multiple_regs(self):
|
||||
instr_range = "PUSH {x5-x7}"
|
||||
instr_list = "POP {x5, x6, x7}"
|
||||
instr_range_with_index = "ld4 {v0.S - v3.S}[2]"
|
||||
instr_list_with_index = "ld4 {v0.S, v1.S, v2.S, v3.S}[2]"
|
||||
instr_range_single = "dummy { z1.d }"
|
||||
reg_list = [
|
||||
AttrDict({"register": {"prefix": "x", "name": "5"}}),
|
||||
AttrDict({"register": {"prefix": "x", "name": "6"}}),
|
||||
AttrDict({"register": {"prefix": "x", "name": "7"}}),
|
||||
]
|
||||
reg_list_idx = [
|
||||
AttrDict({"register": {"prefix": "v", "name": "0", "shape": "S", "index": 2}}),
|
||||
AttrDict({"register": {"prefix": "v", "name": "1", "shape": "S", "index": 2}}),
|
||||
AttrDict({"register": {"prefix": "v", "name": "2", "shape": "S", "index": 2}}),
|
||||
AttrDict({"register": {"prefix": "v", "name": "3", "shape": "S", "index": 2}}),
|
||||
]
|
||||
reg_list_single = [AttrDict({"register": {"prefix": "z", "name": "1", "shape": "d"}})]
|
||||
|
||||
prange = self.parser.parse_line(instr_range)
|
||||
plist = self.parser.parse_line(instr_list)
|
||||
p_idx_range = self.parser.parse_line(instr_range_with_index)
|
||||
p_idx_list = self.parser.parse_line(instr_list_with_index)
|
||||
p_single = self.parser.parse_line(instr_range_single)
|
||||
|
||||
self.assertEqual(prange.operands, reg_list)
|
||||
self.assertEqual(plist.operands, reg_list)
|
||||
self.assertEqual(p_idx_range.operands, reg_list_idx)
|
||||
self.assertEqual(p_idx_list.operands, reg_list_idx)
|
||||
self.assertEqual(p_single.operands, reg_list_single)
|
||||
|
||||
def test_reg_dependency(self):
|
||||
reg_1_1 = AttrDict({"prefix": "b", "name": "1"})
|
||||
@@ -390,18 +407,18 @@ class TestParserAArch64(unittest.TestCase):
|
||||
def _get_comment(self, parser, comment):
|
||||
return " ".join(
|
||||
AttrDict.convert_dict(
|
||||
parser.process_operand(parser.comment.parseString(comment, parseAll=True).asDict())[0]
|
||||
parser.process_operand(parser.comment.parseString(comment, parseAll=True).asDict())
|
||||
).comment
|
||||
)
|
||||
|
||||
def _get_label(self, parser, label):
|
||||
return AttrDict.convert_dict(
|
||||
parser.process_operand(parser.label.parseString(label, parseAll=True).asDict())[0]
|
||||
parser.process_operand(parser.label.parseString(label, parseAll=True).asDict())
|
||||
).label
|
||||
|
||||
def _get_directive(self, parser, directive):
|
||||
return AttrDict.convert_dict(
|
||||
parser.process_operand(parser.directive.parseString(directive, parseAll=True).asDict())[0]
|
||||
parser.process_operand(parser.directive.parseString(directive, parseAll=True).asDict())
|
||||
).directive
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -120,12 +120,12 @@ class TestParserX86ATT(unittest.TestCase):
|
||||
self.assertIsNone(parsed_2.comment)
|
||||
|
||||
self.assertEqual(parsed_3.instruction, "movl")
|
||||
self.assertEqual(parsed_3.operands[0].immediate.value, "222")
|
||||
self.assertEqual(parsed_3.operands[0].immediate.value, 222)
|
||||
self.assertEqual(parsed_3.operands[1].register.name, "ebx")
|
||||
self.assertEqual(parsed_3.comment, "IACA END")
|
||||
|
||||
self.assertEqual(parsed_4.instruction, "vmovss")
|
||||
self.assertEqual(parsed_4.operands[1].memory.offset.value, "-4")
|
||||
self.assertEqual(parsed_4.operands[1].memory.offset.value, -4)
|
||||
self.assertEqual(parsed_4.operands[1].memory.base.name, "rsp")
|
||||
self.assertEqual(parsed_4.operands[1].memory.index.name, "rax")
|
||||
self.assertEqual(parsed_4.operands[1].memory.scale, 8)
|
||||
@@ -146,7 +146,7 @@ class TestParserX86ATT(unittest.TestCase):
|
||||
self.assertEqual(parsed_6.operands[0].memory.scale, 8)
|
||||
self.assertEqual(parsed_6.operands[1].register.name, "rbx")
|
||||
|
||||
self.assertEqual(parsed_7.operands[0].immediate.value, "0x1")
|
||||
self.assertEqual(parsed_7.operands[0].immediate.value, 0x1)
|
||||
self.assertEqual(parsed_7.operands[1].register.name, "xmm0")
|
||||
self.assertEqual(parsed_7.operands[2].register.name, "ymm1")
|
||||
self.assertEqual(parsed_7.operands[3].register.name, "ymm1")
|
||||
@@ -189,7 +189,7 @@ class TestParserX86ATT(unittest.TestCase):
|
||||
"operands": [
|
||||
{
|
||||
"memory": {
|
||||
"offset": {"value": "2"},
|
||||
"offset": {"value": 2},
|
||||
"base": {"name": "rax"},
|
||||
"index": {"name": "rax"},
|
||||
"scale": 1,
|
||||
@@ -240,7 +240,7 @@ class TestParserX86ATT(unittest.TestCase):
|
||||
imd_decimal_1 = {"value": "79"}
|
||||
imd_hex_1 = {"value": "0x4f"}
|
||||
imd_decimal_2 = {"value": "8"}
|
||||
imd_hex_2 = {"value": "0x8"}
|
||||
imd_hex_2 = {"value": "8"}
|
||||
self.assertEqual(
|
||||
self.parser.normalize_imd(imd_decimal_1), self.parser.normalize_imd(imd_hex_1)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user