-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathstart.b
210 lines (186 loc) · 5.58 KB
/
start.b
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import "io"
static { next_free_page, last_page, num_pages }
let set_first_and_last_page() be
{
let first_word = (! 0x101);
let last_word = (! 0x100) - 1;
next_free_page := (first_word + 2047) >> 11;
last_page := last_word >> 11;
out("%d\n", last_page)
}
let get_page_address() be
{
let p = next_free_page << 11;
if next_free_page > last_page then
{
outs("OUT OF MEMORY BEFORE VM STARTED\n");
finish
}
next_free_page +:= 1;
assembly
{
clrpp [<p>]
}
resultis p
}
let tape_load(tape_number, file_name, read_or_write) be
{
let load = devctl(DC_TAPE_LOAD, tape_number, file_name, read_or_write);
if load <= 0 then
{
out("tape load failed for tape %d\n", tape_number)
}
resultis load
}
let tape_check(tape_number) be
{
let read_or_write = devctl(DC_TAPE_CHECK, tape_number);
if read_or_write = 0 then
{
out("tape check failed for tape %d\n", tape_number);
}
resultis read_or_write
}
manifest
{
tape_one = 1,
words_per_block = 128,
bytes_per_block = 512
}
let load_os(exe_name) be
{
let call_gates = get_page_address();
let interrupt_vec = get_page_address();
let pgdir = get_page_address();
let freelist = get_page_address();
let pt_code = get_page_address();
let pt_heap = get_page_address();
let pt_stack = get_page_address();
let pt_special = get_page_address();
let infopage = get_page_address();
let pt_user_heap = get_page_address();
let pt_user_code = get_page_address();
let pt_user_stack = get_page_address();
let system_code = get_page_address();
let system_heap = get_page_address();
let system_stack = get_page_address();
let available_blocks = 16, pt_code_index = 1;
let r = bytes_per_block, bytes_read = 0;
assembly
{
load r1, [<call_gates>]
setsr r1, $cgbr
load r1, [<interrupt_vec>]
setsr r1, $intvec
}
pt_code ! 0 := system_code bitor 1;
pt_heap ! 1 := system_heap bitor 1;
pt_stack ! 2047 := system_stack bitor 1;
//read in system code
tape_load(tape_one, exe_name, 'R');
tape_check(tape_one);
while r = bytes_per_block do
{
r := devctl(DC_TAPE_READ, 1, system_code);
if r < 0 then
{
out("error %d while reading tape '%s'\n", r, exe_name);
finish
}
bytes_read +:= r;
available_blocks -:= 1;
system_code +:= words_per_block;
if available_blocks = 0 then
{
system_code := get_page_address();
pt_code ! pt_code_index := system_code bitor 1;
pt_code_index +:= 1;
available_blocks := 16
}
}
out("Loaded %d bytes, %d pages of '%s'\n", bytes_read, pt_code_index, exe_name);
freelist ! 0 := freelist bitor 1;
infopage ! 0 := infopage bitor 1;
pt_heap ! 0 := pt_heap bitor 1;
pt_user_heap ! 0 := pt_user_heap bitor 1;
pt_user_code ! 0 := pt_user_code bitor 1;
pt_user_stack ! 0 := pt_user_stack bitor 1;
pgdir ! 0x010 := freelist bitor 1;
pgdir ! 0x020 := infopage bitor 1;
pgdir ! 0x030 := pt_heap bitor 1;
pgdir ! 0x040 := pt_user_heap bitor 1;
pgdir ! 0x100 := pt_user_code bitor 1;
pgdir ! 0x1FF := pt_user_stack bitor 1;
pgdir ! 0x200 := pt_code bitor 1;
pgdir ! 0x2FF := pt_stack bitor 1;
pgdir ! 0x300 := pt_special bitor 1;
//system stuff
pt_special ! 0 := pt_special bitor 1;
pt_special ! 1 := pgdir bitor 1;
pt_special ! 2 := 1; //system heap index
pt_special ! 3 := call_gates bitor 1; //syscalls
pt_special ! 4 := interrupt_vec bitor 1;
//create freelist
num_pages := last_page - next_free_page + 1;
for ii = 1 to num_pages do
{
freelist ! ii := get_page_address() bitor 1;
}
out("num pages = %d\n", num_pages);
resultis pgdir;
}
//debugging
let print_memory_map(pgdir_address) be
{
out("\npgdir address = 0x%x\n\n", pgdir_address);
for ptn = 0 to 1023 do
{
if pgdir_address ! ptn <> 0 then
{
let pt_address = (pgdir_address ! ptn) bitand 0xFFFFF800; //clear last 11 bits from page table address
let pt_va = ptn << 22;
out("0x%x ! 0x%x = 0x%x\n", pgdir_address, ptn, pt_address);
out("for VAs: 0x%x to 0x%x ", pt_va, ((ptn + 1) << 22) - 1);
for pn = 0 to 2047 do
{
if pt_address ! pn bitand 1 then
{
let page_address = (pt_address ! pn) bitand 0xFFFF800;
let page_va = (ptn << 22) + (pn << 11);
out(" 0x%x ! 0x%x = 0x%x", pt_address, pn, page_address);
out(" for VAs: 0x%x to 0x%x", page_va, page_va+2047);
}
out("\n");
}
}
}
}
let start() be
{
let pgdir_address;
set_first_and_last_page();
pgdir_address := load_os("os.exe");
// debugging
//out("\n\n");
//for i = 0 to 1023 do
//{
// if i rem 16 = 0 then out("\n");
// test pgdir_address ! i = 0 then out("0x__")
// else out("0x%10x ", i << 22)
//}
//print_memory_map(pgdir_address);
assembly
{
load r1, [<pgdir_address>]
load sp, 0x0000
loadh sp, 0xC000
load fp, sp
setsr r1, $pdbr
getsr r1, $flags
sbit r1, $vm
load r2, 0x0000
loadh r2, 0x8000
flagsj r1, r2
}
outs("Don't get here!\n");
}