aboutsummaryrefslogtreecommitdiffstats
path: root/src/asm_pass4.py
blob: 96d9e6589d06d4f6b4ec732ba7ed0ba3239e14a0 (plain)
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
from dataclasses import dataclass
from assembler_ops import *
from assembler_eval import *
from asm_pass3 import *

@dataclass
class Result4Line:
  line_num: int
  address: int
  word: int
  text: str

@dataclass
class Result4:
  lines: list[Result4Line]
  options: Options
  operations: OpExpansionDict
  labels: dict[str, int]

def translate_opt(arg: str, options: Options) -> str:
  match arg:
    case "__STACK_POINTER": return options.stack_pointer
    case "__CSR_SCRATCH": return options.csr_scratch
    case _: return arg

def pass_4(result3: Result3) -> Result4:
  result_lines: list[Result4Line] = []
  address = 0

  for line in result3.lines:
    keyword, *args = line.parts
    meta = Meta(
      address=address,
    )

    args = list(map(lambda a: translate_opt(a, result3.options), args))
    text = " ".join([keyword, *args])

    if keyword in operations:
      fn = operations[keyword]
      word = fn(meta, result3.labels, *args)
      result_lines.append(Result4Line(
        line_num=line.line_num,
        address=line.address,
        word=word,
        text=text,
      ))
    else:
      try:
        result_lines.append(Result4Line(
          line_num=line.line_num,
          address=line.address,
          word=eval_expr(result3.labels, keyword),
          text=text,
        ))
      except:
        raise Exception(f"Invalid assembly at {line.line_num + 1}\n\n{line}")

  return Result4(
    operations=result3.operations,
    labels=result3.labels,
    options=result3.options,
    lines=result_lines,
  )