-
Notifications
You must be signed in to change notification settings - Fork 0
/
translator.py
114 lines (88 loc) · 3.12 KB
/
translator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from syntax import is_label_decl, is_r_type, is_mem, is_beq
def translate(args, lines, labels_map):
"""For each of the instructions in lines, generates the equivalent machine
code and returns the result as a list. The input lines should contain only
syntactically valid instructions or label declarations. No code is generated
for labels. The labels_map should map labels to byte offsets in the machine
code (assuming 4 bytes per instruction)."""
offset = 0
result = []
for line in lines:
if is_label_decl(line):
continue
if is_r_type(line):
result.append(translate_r_type(line))
if is_mem(line):
result.append(translate_mem(line))
if is_beq(line):
beq = translate_beq(args, line, offset, labels_map)
if beq is None:
if args.skip_errors:
continue
else:
return None
result.append(beq)
offset += 4
return result
def translate_reg(arg):
return int(arg[1:])
def translate_imm_reg(arg):
[imm, reg] = arg[:-1].split("(", 1)
return (int(imm), translate_reg(reg))
def translate_r_type(line):
[op, args] = line.split(" ", 1)
args = args.split(",")
args = [arg.strip() for arg in args]
regs = [translate_reg(arg) for arg in args]
opcode = 0b0110011
(f3, f7) = {
"add": (0b000, 0b0000000),
"sub": (0b000, 0b0100000),
"and": (0b111, 0b0000000),
"or": (0b110, 0b0000000),
}[op]
result = f7 << 25 | regs[2] << 20 | regs[1] << 15 | f3 << 12 | regs[0] << 7 | opcode
return "%0.8X" % result
def translate_mem(line):
[op, args] = line.split(" ", 1)
args = args.split(",")
args = [arg.strip() for arg in args]
r0 = translate_reg(args[0])
(imm, rs1) = translate_imm_reg(args[1])
opcode = {
"lw": 0b0000011,
"sw": 0b0100011,
}[op]
f3 = 0b010
result = 0
if op == "lw":
result = imm << 20 | rs1 << 15 | f3 << 12 | r0 << 7 | opcode
else:
imm_h = imm >> 5
imm_l = imm & 0b11111
result = imm_h << 25 | r0 << 20 | rs1 << 15 | f3 << 12 | imm_l << 7 | opcode
return "%0.8X" % result
def translate_beq(program_args, line, offset, labels_map):
[op, args] = line.split(" ", 1)
args = args.split(",")
args = [arg.strip() for arg in args]
rs1 = translate_reg(args[0])
rs2 = translate_reg(args[1])
label = args[2]
if not label in labels_map:
prefix = "error:"
if args.skip_errors:
prefix = "warning:"
print(prefix, "no declaration for label %s" % label)
return None
imm = labels_map[label] - offset
if program_args.debug:
print("label in instruction [%s] computes to offset diff %d" % (line, imm))
opcode = 0b1100011
f3 = 0b000
# imm_h = imm[12 | 10:5]
imm_h = ((imm >> 12 & 0b1) << 6) | (imm >> 5 & 0b111111)
# imm_l = imm[4:1|11]
imm_l = ((imm >> 1 & 0b1111) << 1) | (imm >> 11 & 0b1)
result = imm_h << 25 | rs2 << 20 | rs1 << 15 | f3 << 12 | imm_l << 7 | opcode
return "%0.8X" % result