-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrc-assembler.js
More file actions
131 lines (101 loc) · 3.36 KB
/
Copy pathrc-assembler.js
File metadata and controls
131 lines (101 loc) · 3.36 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
class Assembler {
constructor() {
this.warnings = null
this.errors = null
this.load_address = 0
}
address_mode(value) {
if ('0123456789-'.includes(value[0])) {
this.errors.push(`E007: Implicit address mode is not supported.`)
return addr_direct
}
var name = null
addr_names.forEach((v, k) => {
if (v.display == value) {
name = k
}
})
return name
}
parse_instruction(input) {
var bak = input.replace(/\t/g, ' ')
var items = input.split('\t')
// find correct opcode
var op_string = items[0]
var op = Opcode.from_name(op_string)
if (op == null) {
// this could still be a pseudo-op
switch (op_string) {
case 'END':
if (items.length > 1) {
this.load_address = parseInt(items[1].substr(1))
}
return null
case 'ORG':
if (items.length > 1) {
this.load_address = parseInt(items[1].substr(1))
}
return null
case 'PIN':
if (items.length > 1) {
this.p_space_id = parseInt(items[1].substr(1))
}
return null
}
// it's not. die.
this.errors.push(`E003: Unknown opcode '${op_string}' in '${bak}'`)
return null
}
// check if parameter count is correct/sufficient
const has = items.length - 1
const should = op.num_params
if (has < should) {
this.errors.push(`E004: Too few tokens (${has}/${should}) in '${bak}'`)
return null
}
var values = [null, null]
for (var t = 0; t < has; t++) {
var comp = items[t + 1]
var a = this.address_mode(comp[0])
var v = parseInt(comp.substr(1))
if (a == null) {
this.errors.push(`E005: Unknown address mode ${comp} in '${bak}'`)
return null
}
values[t] = new Value(v, a)
}
var i = null
try {
i = new Instruction(op.opcode, values[0], values[1])
} catch (e) {
this.errors.push(
`E008: Invalid opcode / address mode combination in '${bak}'`)
}
return i
}
assemble(string) {
this.warnings = new Array()
this.errors = new Array()
if (string === undefined) {
string = ''
}
var listing = new Array()
var instructions = new Array()
var components = string.split('\n').filter(x => x != '')
this.labels = new Map()
for (var i = 0; i < components.length; i++) {
var ins = this.parse_instruction(components[i])
if (ins != null) {
instructions.push(ins)
listing.push(ins.to_short_string())
}
}
return {
listing: listing.join('\n'),
load_address: this.load_address,
code: instructions,
errors: this.errors,
warnings: this.warnings
}
}
}