Skip to content

Commit d125509

Browse files
committed
refact: group str related instructs into their module
1 parent 67f463a commit d125509

2 files changed

Lines changed: 140 additions & 139 deletions

File tree

src/arch/z80/backend/__init__.py

Lines changed: 1 addition & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
from .__float import _orf, _andf, _notf, _xorf, _float_oper, _fpush, _fpop
104104

105105
# String arithmetic functions
106-
from .__str import _addstr
106+
from .__str import _addstr, _loadstr, _storestr, _jzerostr, _jnzerostr, _retstr, _paramstr, _fparamstr
107107

108108
# String comparison functions
109109
from .__str import _ltstr, _gtstr, _eqstr, _lestr, _gestr, _nestr, _str_oper, _lenstr
@@ -704,48 +704,6 @@ def _in(ins):
704704
return output
705705

706706

707-
def _loadstr(ins):
708-
"""Loads a string value from a memory address."""
709-
temporal, output = _str_oper(ins.quad[2], no_exaf=True)
710-
711-
if not temporal:
712-
output.append(runtime_call(RuntimeLabel.LOADSTR))
713-
714-
output.append("push hl")
715-
return output
716-
717-
718-
def _storestr(ins):
719-
"""Stores a string value into a memory address.
720-
It copies content of 2nd operand (string), into 1st, reallocating
721-
dynamic memory for the 1st str. These instruction DOES ALLOW
722-
immediate strings for the 2nd parameter, starting with '#'.
723-
724-
Must prepend '#' (immediate sigil) to 1st operand, as we need
725-
the & address of the destination.
726-
"""
727-
op1 = ins.quad[1]
728-
indirect = op1[0] == "*"
729-
if indirect:
730-
op1 = op1[1:]
731-
732-
immediate = op1[0] == "#"
733-
if immediate and not indirect:
734-
raise InvalidIC("storestr does not allow immediate destination", ins.quad)
735-
736-
if not indirect:
737-
op1 = "#" + op1
738-
739-
tmp1, tmp2, output = _str_oper(op1, ins.quad[2], no_exaf=True)
740-
741-
if not tmp2:
742-
output.append(runtime_call(RuntimeLabel.STORE_STR))
743-
else:
744-
output.append(runtime_call(RuntimeLabel.STORE_STR2))
745-
746-
return output
747-
748-
749707
def _cast(ins):
750708
"""Convert data from typeA to typeB (only numeric data types)"""
751709
# Signed and unsigned types are the same in the Z80
@@ -803,79 +761,11 @@ def _jump(ins):
803761
return ["jp %s" % str(ins.quad[1])]
804762

805763

806-
def _jzerostr(ins):
807-
"""Jumps if top of the stack contains a NULL pointer
808-
or its len is Zero
809-
"""
810-
# TODO: Check if this is ever used?
811-
output = []
812-
disposable = False # True if string must be freed from memory
813-
814-
if ins.quad[1][0] == "_": # Variable?
815-
output.append("ld hl, (%s)" % ins.quad[1][0])
816-
else:
817-
output.append("pop hl")
818-
output.append("push hl") # Saves it for later
819-
disposable = True
820-
821-
output.append(runtime_call(RuntimeLabel.STRLEN))
822-
823-
if disposable:
824-
output.append("ex (sp), hl")
825-
output.append(runtime_call(RuntimeLabel.MEM_FREE))
826-
output.append("pop hl")
827-
828-
output.append("ld a, h")
829-
output.append("or l")
830-
output.append("jp z, %s" % str(ins.quad[2]))
831-
return output
832-
833-
834-
def _jnzerostr(ins):
835-
"""Jumps if top of the stack contains a string with
836-
at less 1 char
837-
"""
838-
# TODO: Check if this is ever used?
839-
output = []
840-
disposable = False # True if string must be freed from memory
841-
842-
if ins.quad[1][0] == "_": # Variable?
843-
output.append("ld hl, (%s)" % ins.quad[1][0])
844-
else:
845-
output.append("pop hl")
846-
output.append("push hl") # Saves it for later
847-
disposable = True
848-
849-
output.append(runtime_call(RuntimeLabel.STRLEN))
850-
851-
if disposable:
852-
output.append("ex (sp), hl")
853-
output.append(runtime_call(RuntimeLabel.MEM_FREE))
854-
output.append("pop hl")
855-
856-
output.append("ld a, h")
857-
output.append("or l")
858-
output.append("jp nz, %s" % str(ins.quad[2]))
859-
return output
860-
861-
862764
def _ret(ins):
863765
"""Returns from a procedure / function"""
864766
return ["jp %s" % str(ins.quad[1])]
865767

866768

867-
def _retstr(ins):
868-
"""Returns from a procedure / function a string pointer (16bits) value"""
869-
tmp, output = _str_oper(ins.quad[1], no_exaf=True)
870-
871-
if not tmp:
872-
output.append(runtime_call(RuntimeLabel.LOADSTR))
873-
874-
output.append("#pragma opt require hl")
875-
output.append("jp %s" % str(ins.quad[2]))
876-
return output
877-
878-
879769
def _call(ins):
880770
"""Calls a function XXXX (or address XXXX)
881771
2nd parameter contains size of the returning result if any, and will be
@@ -1009,33 +899,6 @@ def _enter(ins):
1009899
return output
1010900

1011901

1012-
def _paramstr(ins):
1013-
"""Pushes an 16 bit unsigned value, which points
1014-
to a string. For indirect values, it will push
1015-
the pointer to the pointer :-)
1016-
"""
1017-
(tmp, output) = _str_oper(ins.quad[1])
1018-
output.pop() # Remove a register flag (useless here)
1019-
tmp = ins.quad[1][0] in ("#", "_") # Determine if the string must be duplicated
1020-
1021-
if tmp:
1022-
output.append(runtime_call(RuntimeLabel.LOADSTR)) # Must be duplicated
1023-
1024-
output.append("push hl")
1025-
return output
1026-
1027-
1028-
def _fparamstr(ins):
1029-
"""Passes a string ptr as a __FASTCALL__ parameter.
1030-
This is done by popping out of the stack for a
1031-
value, or by loading it from memory (indirect)
1032-
or directly (immediate) --prefixed with '#'--
1033-
"""
1034-
(tmp1, output) = _str_oper(ins.quad[1])
1035-
1036-
return output
1037-
1038-
1039902
def _memcopy(ins):
1040903
"""Copies a block of memory from param 2 addr
1041904
to param 1 addr.

src/arch/z80/backend/__str.py

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
from .__common import runtime_call
1414

15-
from src.arch.z80.backend.runtime import Labels as RuntimeLabels
15+
from src.arch.z80.backend.runtime import Labels as RuntimeLabels, Labels as RuntimeLabel
16+
from .errors import InvalidICError as InvalidIC
1617

1718

1819
def _str_oper(op1, op2=None, reversed=False, no_exaf=False):
@@ -208,3 +209,140 @@ def _lenstr(ins):
208209
output.extend(_free_sequence(tmp1))
209210
output.append("push hl")
210211
return output
212+
213+
214+
def _loadstr(ins):
215+
"""Loads a string value from a memory address."""
216+
temporal, output = _str_oper(ins.quad[2], no_exaf=True)
217+
218+
if not temporal:
219+
output.append(runtime_call(RuntimeLabel.LOADSTR))
220+
221+
output.append("push hl")
222+
return output
223+
224+
225+
def _storestr(ins):
226+
"""Stores a string value into a memory address.
227+
It copies content of 2nd operand (string), into 1st, reallocating
228+
dynamic memory for the 1st str. These instruction DOES ALLOW
229+
immediate strings for the 2nd parameter, starting with '#'.
230+
231+
Must prepend '#' (immediate sigil) to 1st operand, as we need
232+
the & address of the destination.
233+
"""
234+
op1 = ins.quad[1]
235+
indirect = op1[0] == "*"
236+
if indirect:
237+
op1 = op1[1:]
238+
239+
immediate = op1[0] == "#"
240+
if immediate and not indirect:
241+
raise InvalidIC("storestr does not allow immediate destination", ins.quad)
242+
243+
if not indirect:
244+
op1 = "#" + op1
245+
246+
tmp1, tmp2, output = _str_oper(op1, ins.quad[2], no_exaf=True)
247+
248+
if not tmp2:
249+
output.append(runtime_call(RuntimeLabel.STORE_STR))
250+
else:
251+
output.append(runtime_call(RuntimeLabel.STORE_STR2))
252+
253+
return output
254+
255+
256+
def _jzerostr(ins):
257+
"""Jumps if top of the stack contains a NULL pointer
258+
or its len is Zero
259+
"""
260+
# TODO: Check if this is ever used?
261+
output = []
262+
disposable = False # True if string must be freed from memory
263+
264+
if ins.quad[1][0] == "_": # Variable?
265+
output.append("ld hl, (%s)" % ins.quad[1][0])
266+
else:
267+
output.append("pop hl")
268+
output.append("push hl") # Saves it for later
269+
disposable = True
270+
271+
output.append(runtime_call(RuntimeLabel.STRLEN))
272+
273+
if disposable:
274+
output.append("ex (sp), hl")
275+
output.append(runtime_call(RuntimeLabel.MEM_FREE))
276+
output.append("pop hl")
277+
278+
output.append("ld a, h")
279+
output.append("or l")
280+
output.append("jp z, %s" % str(ins.quad[2]))
281+
return output
282+
283+
284+
def _jnzerostr(ins):
285+
"""Jumps if top of the stack contains a string with
286+
at less 1 char
287+
"""
288+
# TODO: Check if this is ever used?
289+
output = []
290+
disposable = False # True if string must be freed from memory
291+
292+
if ins.quad[1][0] == "_": # Variable?
293+
output.append("ld hl, (%s)" % ins.quad[1][0])
294+
else:
295+
output.append("pop hl")
296+
output.append("push hl") # Saves it for later
297+
disposable = True
298+
299+
output.append(runtime_call(RuntimeLabel.STRLEN))
300+
301+
if disposable:
302+
output.append("ex (sp), hl")
303+
output.append(runtime_call(RuntimeLabel.MEM_FREE))
304+
output.append("pop hl")
305+
306+
output.append("ld a, h")
307+
output.append("or l")
308+
output.append("jp nz, %s" % str(ins.quad[2]))
309+
return output
310+
311+
312+
def _retstr(ins):
313+
"""Returns from a procedure / function a string pointer (16bits) value"""
314+
tmp, output = _str_oper(ins.quad[1], no_exaf=True)
315+
316+
if not tmp:
317+
output.append(runtime_call(RuntimeLabel.LOADSTR))
318+
319+
output.append("#pragma opt require hl")
320+
output.append("jp %s" % str(ins.quad[2]))
321+
return output
322+
323+
324+
def _paramstr(ins):
325+
"""Pushes an 16 bit unsigned value, which points
326+
to a string. For indirect values, it will push
327+
the pointer to the pointer :-)
328+
"""
329+
(tmp, output) = _str_oper(ins.quad[1])
330+
output.pop() # Remove a register flag (useless here)
331+
tmp = ins.quad[1][0] in ("#", "_") # Determine if the string must be duplicated
332+
333+
if tmp:
334+
output.append(runtime_call(RuntimeLabel.LOADSTR)) # Must be duplicated
335+
336+
output.append("push hl")
337+
return output
338+
339+
340+
def _fparamstr(ins):
341+
"""Passes a string ptr as a __FASTCALL__ parameter.
342+
This is done by popping out of the stack for a
343+
value, or by loading it from memory (indirect)
344+
or directly (immediate) --prefixed with '#'--
345+
"""
346+
(tmp1, output) = _str_oper(ins.quad[1])
347+
348+
return output

0 commit comments

Comments
 (0)