Skip to content

Commit 00e321c

Browse files
committed
add literals support
1 parent f3bb05b commit 00e321c

File tree

2 files changed

+115
-8
lines changed

2 files changed

+115
-8
lines changed

sicas.py

+115-7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(self, assembly, lineno):
1818
self.fmt = 0
1919
self.loc = None
2020
self.base = -1
21+
self.litpool = []
2122

2223
def __str__(self):
2324
return self.assembly
@@ -38,6 +39,8 @@ def listing_tuple(self):
3839
if self.code != "":
3940
codefmt = "%%0%dX" % (self.fmt * 2)
4041
codefmt = codefmt % self.code
42+
if any(self.litpool):
43+
locfmt = ""
4144
return (self.lineno, locfmt, self.src.expandtabs(8), codefmt)
4245

4346
# class to store each program info
@@ -52,6 +55,8 @@ def __init__(self, source):
5255
self.lineno = 0
5356
self.content = list(Line(line.strip('\n'), lineno) for lineno, line in enumerate(open(source, "r").readlines(), 1))
5457
self.symtab = PRELOAD_SYMTAB.copy()
58+
self.littab = {}
59+
self.endlitpool = []
5560
self.base = -1
5661

5762
# print error message indicating the line number and throw the error
@@ -81,6 +86,10 @@ def assemble(self):
8186
continue
8287
else:
8388
program.error("Except a directive, opcde or label.")
89+
end_LITPOOL(self)
90+
for k, v in self.symtab.items():
91+
if type(v) == list:
92+
program.error("Undefined symbol %s." % v)
8493

8594
# write assembly listing to file
8695
def listing(self, filename):
@@ -90,6 +99,23 @@ def listing(self, filename):
9099
f.write(fmt % ("Lineno", "LOCCTR", "Source Statements", "Object Code"))
91100
for line in self.content:
92101
f.write(fmt % line.listing_tuple())
102+
if any(line.litpool):
103+
for lit in line.litpool:
104+
code = lit[2]
105+
if lit[1][0] == 'C':
106+
code = "%%0%dX" % (len(lit[1]) - 3)
107+
code = code % lit[2]
108+
elif lit[1][0] == 'X':
109+
code = "%02X" % lit[2]
110+
f.write(fmt % ("", "%04X" % lit[0], "*\t".expandtabs(8) + lit[1], code))
111+
for lit in self.endlitpool:
112+
code = lit[2]
113+
if lit[1][0] == 'C':
114+
code = "%%0%dX" % (len(lit[1]) - 3)
115+
code = code % lit[2]
116+
elif lit[1][0] == 'X':
117+
code = "%02X" % lit[2]
118+
f.write(fmt % ("", "%04X" % lit[0], "*\t".expandtabs(8) + lit[1], code))
93119

94120
# get current line
95121
def current_line(self):
@@ -178,7 +204,7 @@ def handler_START(program, tokens):
178204
program.current_line().loc = None
179205

180206
def handler_END(program, tokens):
181-
program.current_line().loc = Nones
207+
program.current_line().loc = None
182208

183209
def handler_BYTE(program, tokens):
184210
if tokens[0] == "BYTE":
@@ -252,6 +278,50 @@ def handler_NOBASE(program, tokens):
252278
program.base = -1
253279
program.current_line().loc = None
254280

281+
def handler_LTORG(program, tokens):
282+
for key, lit_lst in program.littab.items():
283+
if key[0] == 'C':
284+
hexstr = ''.join(["%2X" % c for c in key[2:-1].encode()])
285+
code = int(hexstr, 16)
286+
287+
fill_lit(lit_lst, program.LOCCTR, program)
288+
program.littab[key] = program.LOCCTR
289+
program.current_line().litpool.append((program.LOCCTR, key, code))
290+
program.LOCCTR += len(key[2:-1])
291+
elif key[0] == 'X':
292+
try:
293+
code = int(key[2:-1], 16)
294+
fill_lit(lit_lst, program.LOCCTR, program)
295+
program.littab[key] = program.LOCCTR
296+
program.current_line().litpool.append((program.LOCCTR, key, code))
297+
program.LOCCTR += 1
298+
except ValueError:
299+
program.error("The \"X\" requires a hex value, but %s is not." % value[2:-1])
300+
301+
def end_LITPOOL(program):
302+
for key, lit_lst in program.littab.items():
303+
if type(lit_lst) != list:
304+
continue
305+
if key[0] == 'C':
306+
hexstr = ''.join(["%2X" % c for c in key[2:-1].encode()])
307+
308+
fill_lit(lit_lst, program.LOCCTR, program)
309+
program.littab[key] = program.LOCCTR
310+
program.endlitpool.append((program.LOCCTR, key, hexstr))
311+
program.LOCCTR += len(key[2:-1])
312+
elif key[0] == 'X':
313+
try:
314+
code = int(key[2:-1], 16)
315+
fill_lit(lit_lst, program.LOCCTR, program)
316+
program.littab[key] = program.LOCCTR
317+
program.endlitpool.append((program.LOCCTR, key, code))
318+
program.LOCCTR += 1
319+
except ValueError:
320+
program.error("The \"X\" requires a hex value, but %s is not." % value[2:-1])
321+
322+
def handler_EQU(program, tokens):
323+
print("EQU")
324+
255325
DIRTAB = {
256326
"START" : handler_START,
257327
"END" : handler_END,
@@ -261,6 +331,8 @@ def handler_NOBASE(program, tokens):
261331
"RESW" : handler_RESW,
262332
"BASE" : handler_BASE,
263333
"NOBASE" : handler_NOBASE,
334+
"LTORG" : handler_LTORG,
335+
"EQU" : handler_EQU,
264336
}
265337

266338
# fill the instructions which referencing foward symbols
@@ -274,7 +346,7 @@ def fill_forward(fwd_lst, addr, program):
274346
elif line.base != -1:
275347
# if base is defined
276348
if line.base in program.symtab and type(program.symtab[line.base]) != list:
277-
disp = (program.symtab[operand] - program.symtab[line.base])
349+
disp = (addr - program.symtab[line.base])
278350
if 0 <= disp < 4096:
279351
code |= (disp & 0xFFF) | BASE_RELATIVE
280352
else:
@@ -295,6 +367,30 @@ def fill_forward(fwd_lst, addr, program):
295367
else:
296368
program.error("no enough length to hold the displacement, try format 4.", line)
297369

370+
def fill_lit(lit_lst, addr, program):
371+
for line in lit_lst:
372+
if line.fmt == 3:
373+
disp = (addr - (line.loc + line.fmt))
374+
if -2048 <= disp < 2048:
375+
line.code |= (disp & 0xFFF) | PC_RELATIVE
376+
elif line.base != -1:
377+
# if base is defined
378+
if line.base in program.symtab and type(program.symtab[line.base]) != list:
379+
disp = (addr - program.symtab[line.base])
380+
if 0 <= disp < 4096:
381+
code |= (disp & 0xFFF) | BASE_RELATIVE
382+
else:
383+
program.error("no enough length to hold the displacement, try format 4.", line)
384+
# forward base reference
385+
elif line.base in program.symtab:
386+
program.symtab[line.base].append((program.current_line(), REF_BASE))
387+
else:
388+
program.symtab[line.base] = [(program.current_line(), REF_BASE)]
389+
else:
390+
program.error("no enough length to hold the displacement, try format 4.", line)
391+
elif line.fmt == 4:
392+
line.code |= addr
393+
298394
def has_directives(program, tokens):
299395
for token in tokens:
300396
if token in DIRTAB:
@@ -342,7 +438,7 @@ def has_instructions(program, tokens):
342438
else:
343439
if token.find(',') != -1:
344440
operand, operand2, *dummy = token.split(',')
345-
if len(dummy) > 1:
441+
if any(dummy):
346442
program.error("too many operands")
347443
else:
348444
operand = token
@@ -358,11 +454,12 @@ def has_instructions(program, tokens):
358454
# validate the foramt
359455
if (operand2 != "" and fmt != 2) and operand2 != 'X':
360456
program.error("Only format 2 insturctions allow two operands.")
361-
if fmt < 3 and operand2 == 'X':
362-
program.error("Only format 3 and 4 allow indexed addresing")
457+
if fmt == 1 and operand != "":
458+
program.error("Format 1 instructions should not have any operands.")
363459

364460
# generate opcode
365461
code = OPTAB[inst].opcode
462+
isLiteral = False
366463
# parse the prefix for format 3 & 4 instructions
367464
if (fmt == 3 or fmt == 4) and inst != "RSUB":
368465
prefix = ""
@@ -377,6 +474,17 @@ def has_instructions(program, tokens):
377474
mask = IMM_ADDR
378475
elif prefix == '@':
379476
mask = INDR_ADDR
477+
elif prefix == '=':
478+
isLiteral = True
479+
if operand not in program.littab:
480+
program.littab[operand] = [program.current_line()]
481+
# already defined or is not yet
482+
elif operand in program.littab:
483+
# try to use
484+
# but if is too far, wait next
485+
pass
486+
else:
487+
program.littab[operand].append(program.current_line())
380488
elif prefix != "":
381489
program.error("Unrecognized addressing prefix \"%s\"." % prefix)
382490

@@ -393,9 +501,9 @@ def has_instructions(program, tokens):
393501
# shift format 4 instructions
394502
if fmt == 4:
395503
code <<= BYTESIZE
396-
504+
397505
# generate operand
398-
if inst != "RSUB":
506+
if inst != "RSUB" and not isLiteral:
399507
if operand.isnumeric():
400508
operand = int(operand)
401509
if (fmt == 3 and operand > 2**12 - 1) or (fmt == 4 and operand > 2**20 - 1):

sicxe.py

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
FORMAT2 = 0x40
1414
FORMAT1 = 0x80
1515

16-
1716
PC_RELATIVE = 0b000010 << 12
1817
BASE_RELATIVE = 0b000100 << 12
1918

0 commit comments

Comments
 (0)