-
Notifications
You must be signed in to change notification settings - Fork 0
/
link.js
92 lines (81 loc) · 2.65 KB
/
link.js
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
'use strict';
const err = require('./err');
const err_unknown_value = (value, lineno) => {
err.log(`Unknown value or label: ${value}`, lineno);
}
const link = {
object: (program) => {
const labels = {};
const size = link.count(program, labels);
return link.make_binary(program, labels, size);
},
make_binary: (program, labels, size) => {
const out = new Uint8Array(size);
for (const line of program) {
if (line.code) {
out[line.pc] = line.code;
link.write_arg(line, labels, out, line.value);
} else if (line.codename == 'DW') {
let pc = line.pc;
for (const in_value of line.value) {
const value = typeof in_value == 'number' ?
in_value : labels[in_value];
if (value === undefined) {
err_unknown_value(in_value, line.lineno);
}
out[pc++] = value;
out[pc++] = value >> 8;
}
} else if (line.codename == 'DB') {
let pc = line.pc;
for (const value of line.value) {
if (typeof value !== 'number') {
err_unknown_value(value, line.lineno);
}
out[pc++] = value;
}
}
}
return out;
},
write_arg: (line, labels, out, arg) => {
const label = labels[arg];
const [value, relative] =
typeof arg === 'number' ? [arg] :
line.width === 3 ? [label] :
line.width === 2 ? [label - line.pc - line.width, true] : [];
if (line.width >= 2 && value === undefined) {
err_unknown_value(arg, line.lineno);
}
switch (line.width) {
case 2:
if (relative
? (value < -0x80 || value > 0x7f)
: (value < 0 || value > 0xff)) {
err.log(`Overflow on value: ${value}`, line.lineno);
}
out[line.pc+1] = value;
break;
case 3:
out[line.pc+1] = value;
out[line.pc+2] = value >> 8;
break;
default:
break;
}
},
count: (program, labels, pc = 0) => {
for (const line of program) {
if (line.codename == 'ORG') {
pc = line.value;
}
if (line.label) {
labels[line.label] = pc;
}
line.pc = pc;
pc += line.width;
}
return pc;
},
};
module.exports = link;