Skip to content

Commit fe1463b

Browse files
committed
Add function simplify_asm_arg
Simplifies asm instructions like: ld a, (1235 + 4) becomes: ld a, (1239) Also refacts is_number to use is_mem_access().
1 parent e068585 commit fe1463b

2 files changed

Lines changed: 71 additions & 2 deletions

File tree

arch/zx48k/optimizer/helpers.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ def get_H_from_unknown_value(tmp_val):
9797
return tmp_val.split(HL_SEP)[0]
9898

9999

100+
def is_mem_access(arg):
101+
""" Returns if a given string is a memory access, that is
102+
if it matches the form (...)
103+
"""
104+
arg = arg.strip()
105+
return (arg[0], arg[-1]) == ('(', ')')
106+
107+
100108
# TODO: to be rewritten
101109
def is_number(x):
102110
""" Returns whether X """
@@ -109,7 +117,7 @@ def is_number(x):
109117
if isinstance(x, str):
110118
x = x.strip()
111119

112-
if isinstance(x, str) and x[0] == '(' and x[-1] == ')':
120+
if isinstance(x, str) and is_mem_access(x):
113121
return False
114122

115123
try:
@@ -151,6 +159,54 @@ def valnum(x):
151159
return int(eval(x, {}, {}))
152160

153161

162+
def simplify_arg(arg):
163+
""" Given an asm operand (str), if it can be evaluated to a single 16 bit integer number it will be done so.
164+
Memory addresses will preserve their parenthesis. If the string can not be simplified, it will be
165+
returned as is.
166+
167+
eg.:
168+
0 -> 0
169+
(0) -> (0)
170+
0 + 3 -> 3
171+
(3 + 1) -> (4)
172+
(a - 1) -> (a - 1)
173+
b - 5 -> b - 5
174+
175+
This is very simple "parsing" (for speed) and it won't understand (5) + (6) and will be returned as (11)
176+
"""
177+
result = None
178+
arg = arg.strip()
179+
try:
180+
tmp = eval(arg, {}, {})
181+
if isinstance(tmp, (int, float)):
182+
result = str(tmp)
183+
except NameError:
184+
pass
185+
except SyntaxError:
186+
pass
187+
except ValueError:
188+
pass
189+
190+
if result is None:
191+
return arg
192+
193+
if not is_mem_access(arg):
194+
return result
195+
196+
return '({})'.format(result)
197+
198+
199+
def simplify_asm_args(asm):
200+
""" Given an asm instruction try to simplify its args.
201+
"""
202+
chunks = [x for x in asm.split(' ', 1)]
203+
if len(chunks) != 2:
204+
return asm
205+
206+
args = [simplify_arg(x) for x in chunks[1].split(',', 1)]
207+
return '{} {}'.format(chunks[0], ', '.join(args))
208+
209+
154210
def is_register(x):
155211
""" True if x is a register.
156212
"""

tests/arch/zx48k/optimizer/test_optimizer_asm.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
import unittest
4-
from arch.zx48k.optimizer import asm
4+
from arch.zx48k.optimizer import asm, helpers
55

66

77
class TestASM(unittest.TestCase):
@@ -17,3 +17,16 @@ def test_raises_error_on_empty_instruction(self):
1717
def test_unknown_instruction(self):
1818
a = asm.Asm(' unknown instr ')
1919
self.assertEqual(a.bytes, ())
20+
21+
def test_simplify_arg(self):
22+
a = helpers.simplify_asm_args('ld a, (126 - 1)')
23+
self.assertEqual('ld a, (125)', a)
24+
25+
a = helpers.simplify_asm_args('ld hl, (30 + 40)')
26+
self.assertEqual('ld hl, (70)', a)
27+
28+
a = helpers.simplify_asm_args('ld hl, ((30) + (40))')
29+
self.assertEqual('ld hl, (70)', a)
30+
31+
a = helpers.simplify_asm_args('ld de, (30) + (40)')
32+
self.assertEqual('ld de, (70)', a)

0 commit comments

Comments
 (0)