master
s 511 lines 8.38 KB
Raw
1 /*
2 * Minimal Alpha system boot code.
3 *
4 * Copyright Linaro Ltd 2019
5 */
6
7 .set noat
8 .set nomacro
9 .arch ev6
10 .text
11
12 .macro load_pci_io reg
13 /* For typhoon, this is
14 * 0xfffffc0000000000 -- kseg identity map
15 * + 0x10000000000 -- typhoon pio base
16 * + 0x1fc000000 -- typhoon pchip0 pci base
17 * = 0xfffffd01fc000000
18 */
19 ldah \reg, -3 /* ff..fd0000 */
20 lda \reg, 0x1fc(\reg) /* ff..fd01fc */
21 sll \reg, 24, \reg
22 .endm
23
24 #define com1Rbr 0x3f8
25 #define com1Thr 0x3f8
26 #define com1Ier 0x3f9
27 #define com1Iir 0x3fa
28 #define com1Lcr 0x3fb
29 #define com1Mcr 0x3fc
30 #define com1Lsr 0x3fd
31 #define com1Msr 0x3fe
32 #define com1Scr 0x3ff
33 #define com1Dll 0x3f8
34 #define com1Dlm 0x3f9
35
36 #define PAL_halt 0
37 #define PAL_wrent 52
38 #define PAL_wrkgp 55
39
40 .text
41 .p2align 4
42 .globl _start
43 .ent _start
44 _start:
45 br $gp, .+4
46 ldah $gp, 0($gp) !gpdisp!1
47 lda $gp, 0($gp) !gpdisp!1
48
49 ldah $sp, $stack_end($gp) !gprelhigh
50 lda $sp, $stack_end($sp) !gprellow
51
52 /* Install kernel gp for exception handlers. */
53 mov $gp, $16
54 call_pal PAL_wrkgp
55
56 /* Install exception handlers. */
57 ldah $16, entInt($gp) !gprelhigh
58 lda $16, entInt($16) !gprellow
59 lda $17, 0
60 call_pal PAL_wrent
61
62 ldah $16, entArith($gp) !gprelhigh
63 lda $16, entArith($16) !gprellow
64 lda $17, 1
65 call_pal PAL_wrent
66
67 ldah $16, entMM($gp) !gprelhigh
68 lda $16, entMM($16) !gprellow
69 lda $17, 2
70 call_pal PAL_wrent
71
72 ldah $16, entIF($gp) !gprelhigh
73 lda $16, entIF($16) !gprellow
74 lda $17, 3
75 call_pal PAL_wrent
76
77 ldah $16, entUna($gp) !gprelhigh
78 lda $16, entUna($16) !gprellow
79 lda $17, 4
80 call_pal PAL_wrent
81
82 ldah $16, entSys($gp) !gprelhigh
83 lda $16, entSys($16) !gprellow
84 lda $17, 5
85 call_pal PAL_wrent
86
87 /*
88 * Initialize COM1.
89 */
90 load_pci_io $1
91 lda $2, 0x87 /* outb(0x87, com1Lcr); */
92 stb $2, com1Lcr($1)
93 stb $31, com1Dlm($1) /* outb(0, com1Dlm); */
94 lda $2, 3 /* baudconst 3 => 56000 */
95 stb $2, com1Dll($1) /* outb(baudconst, com1Dll); */
96 lda $2, 0x07
97 stb $2, com1Lcr($1) /* outb(0x07, com1Lcr) */
98 lda $2, 0x0f
99 stb $2, com1Mcr($1) /* outb(0x0f, com1Mcr) */
100
101 bsr $26, main !samegp
102
103 /* fall through to _exit */
104 .end _start
105
106 .globl _exit
107 .ent _exit
108 _exit:
109 .frame $sp, 0, $26, 0
110 .prologue 0
111
112 /* We cannot return an error code. */
113 call_pal PAL_halt
114 .end _exit
115
116 /*
117 * We have received an exception that we don't handle. Log and exit.
118 */
119 .ent log_exit
120 log_exit:
121 entInt:
122 entArith:
123 entMM:
124 entIF:
125 entUna:
126 entSys:
127 ldah $16, $errormsg($gp) !gprelhigh
128 lda $16, $errormsg($16) !gprellow
129 bsr $26, __sys_outs !samegp
130 bsr $26, _exit !samegp
131 .end log_exit
132
133 .section .rodata
134 $errormsg:
135 .string "Terminated by exception.\n"
136 .previous
137
138 /*
139 * Helper Functions
140 */
141
142 /* Output a single character to serial port */
143 .global __sys_outc
144 .ent __sys_outc
145 __sys_outc:
146 .frame $sp, 0, $26, 0
147 .prologue 0
148
149 load_pci_io $1
150
151 /*
152 * while ((inb(com1Lsr) & 0x20) == 0)
153 * continue;
154 */
155 1: ldbu $0, com1Lsr($1)
156 and $0, 0x20, $0
157 beq $0, 1b
158
159 /* outb(c, com1Thr); */
160 stb $16, com1Thr($1)
161 ret
162 .end __sys_outc
163
164 /* Output a nul-terminated string to serial port */
165 .global __sys_outs
166 .ent __sys_outs
167 __sys_outs:
168 .frame $sp, 0, $26, 0
169 .prologue 0
170
171 load_pci_io $1
172
173 ldbu $2, 0($16)
174 beq $2, 9f
175
176 /*
177 * while ((inb(com1Lsr) & 0x20) == 0)
178 * continue;
179 */
180 1: ldbu $0, com1Lsr($1)
181 and $0, 0x20, $0
182 beq $0, 1b
183
184 /* outb(c, com1Thr); */
185 stb $2, com1Thr($1)
186
187 addq $16, 1, $16
188 ldbu $2, 0($16)
189 bne $2, 1b
190
191 9: ret
192 .end __sys_outs
193
194 /*
195 * Division routines that are normally in libc.
196 *
197 * These do not follow the C calling convention. Arguments are in $24+$25,
198 * the result is in $27. Register $28 may be clobbered; everything else
199 * must be saved.
200 *
201 * We store the remainder in $28, so that we can share code.
202 *
203 * We do not signal divide by zero.
204 */
205
206 /*
207 * Unsigned 64-bit division.
208 */
209
210 .globl __divqu
211 .ent __divqu
212 __divqu:
213 .frame $sp, 48, $23
214 subq $sp, 48, $sp
215 stq $0, 0($sp)
216 stq $1, 8($sp)
217 stq $2, 16($sp)
218 stq $3, 24($sp)
219 stq $4, 32($sp)
220 .prologue 0
221
222 #define mask $0
223 #define divisor $1
224 #define compare $2
225 #define tmp1 $3
226 #define tmp2 $4
227 #define quotient $27
228 #define modulus $28
229
230 mov $24, modulus
231 mov $25, divisor
232 mov $31, quotient
233 mov 1, mask
234 beq $25, 9f
235
236 /* Shift left until divisor >= modulus. */
237 1: cmpult divisor, modulus, compare
238 blt divisor, 2f
239 addq divisor, divisor, divisor
240 addq mask, mask, mask
241 bne compare, 1b
242
243 2: addq quotient, mask, tmp2
244 srl mask, 1, mask
245 cmpule divisor, modulus, compare
246 subq modulus, divisor, tmp1
247 cmovne compare, tmp2, quotient
248 srl divisor, 1, divisor
249 cmovne compare, tmp1, modulus
250 bne mask, 2b
251
252 9: ldq $0, 0($sp)
253 ldq $1, 8($sp)
254 ldq $2, 16($sp)
255 ldq $3, 24($sp)
256 ldq $4, 32($sp)
257 addq $sp, 48, $sp
258 ret $31, ($23), 1
259
260 #undef mask
261 #undef divisor
262 #undef compare
263 #undef tmp1
264 #undef tmp2
265 #undef quotient
266 #undef modulus
267
268 .end __divqu
269
270 /*
271 * Unsigned 64-bit remainder.
272 * Note that __divqu above leaves the result in $28.
273 */
274
275 .globl __remqu
276 .ent __remqu
277 __remqu:
278 .frame $sp, 16, $23
279 subq $sp, 16, $sp
280 stq $23, 0($sp)
281 .prologue 0
282
283 bsr $23, __divqu
284
285 ldq $23, 0($sp)
286 mov $28, $27
287 addq $sp, 16, $sp
288 ret $31, ($23), 1
289 .end __remqu
290
291 /*
292 * Signed 64-bit division.
293 */
294
295 .globl __divqs
296 .ent __divqs
297 __divqs:
298 .prologue 0
299
300 /* Common case: both arguments are positive. */
301 bis $24, $25, $28
302 bge $28, __divqu
303
304 /* At least one argument is negative. */
305 subq $sp, 32, $sp
306 stq $23, 0($sp)
307 stq $24, 8($sp)
308 stq $25, 16($sp)
309
310 /* Compute absolute values. */
311 subq $31, $24, $28
312 cmovlt $24, $28, $24
313 subq $31, $25, $28
314 cmovlt $25, $28, $25
315
316 bsr $23, __divqu
317
318 ldq $24, 8($sp)
319 ldq $25, 16($sp)
320
321 /* -a / b = a / -b = -(a / b) */
322 subq $31, $27, $23
323 xor $24, $25, $28
324 cmovlt $28, $23, $27
325
326 ldq $23, 0($sp)
327 addq $sp, 32, $sp
328 ret $31, ($23), 1
329 .end __divqs
330
331 /*
332 * Signed 64-bit remainder.
333 */
334
335 .globl __remqs
336 .ent __remqs
337 __remqs:
338 .prologue 0
339
340 /* Common case: both arguments are positive. */
341 bis $24, $25, $28
342 bge $28, __remqu
343
344 /* At least one argument is negative. */
345 subq $sp, 32, $sp
346 stq $23, 0($sp)
347 stq $24, 8($sp)
348 stq $25, 16($sp)
349
350 /* Compute absolute values. */
351 subq $31, $24, $28
352 cmovlt $24, $28, $24
353 subq $31, $25, $28
354 cmovlt $25, $28, $25
355
356 bsr $23, __divqu
357
358 ldq $23, 0($sp)
359 ldq $24, 8($sp)
360 ldq $25, 16($sp)
361
362 /* -a % b = -(a % b); a % -b = a % b. */
363 subq $31, $28, $27
364 cmovge $24, $28, $27
365
366 addq $sp, 32, $sp
367 ret $31, ($23), 1
368 .end __remqs
369
370 /*
371 * Unsigned 32-bit division.
372 */
373
374 .globl __divlu
375 .ent __divlu
376 __divlu:
377 .frame $sp, 32, $23
378 subq $sp, 32, $sp
379 stq $23, 0($sp)
380 stq $24, 8($sp)
381 stq $25, 16($sp)
382 .prologue 0
383
384 /* Zero extend and use the 64-bit routine. */
385 zap $24, 0xf0, $24
386 zap $25, 0xf0, $25
387 bsr $23, __divqu
388
389 addl $27, 0, $27
390 ldq $23, 0($sp)
391 ldq $24, 8($sp)
392 ldq $25, 16($sp)
393 addq $sp, 32, $sp
394 ret $31, ($23), 1
395 .end __divlu
396
397 /*
398 * Unsigned 32-bit remainder.
399 */
400
401 .globl __remlu
402 .ent __remlu
403 __remlu:
404 .frame $sp, 32, $23
405 subq $sp, 32, $sp
406 stq $23, 0($sp)
407 stq $24, 8($sp)
408 stq $25, 16($sp)
409 .prologue 0
410
411 /* Zero extend and use the 64-bit routine. */
412 zap $24, 0xf0, $24
413 zap $25, 0xf0, $25
414 bsr $23, __divqu
415
416 /* Recall that the remainder is returned in $28. */
417 addl $28, 0, $27
418 ldq $23, 0($sp)
419 ldq $24, 8($sp)
420 ldq $25, 16($sp)
421 addq $sp, 32, $sp
422 ret $31, ($23), 1
423 .end __remlu
424
425 /*
426 * Signed 32-bit division.
427 */
428
429 .globl __divls
430 .ent __divls
431 __divls:
432 .frame $sp, 32, $23
433 subq $sp, 32, $sp
434 stq $23, 0($sp)
435 stq $24, 8($sp)
436 stq $25, 16($sp)
437 .prologue 0
438
439 /* Sign extend. */
440 addl $24, 0, $24
441 addl $25, 0, $25
442
443 /* Compute absolute values. */
444 subq $31, $24, $28
445 cmovlt $24, $28, $24
446 subq $31, $25, $28
447 cmovlt $25, $28, $25
448
449 bsr $23, __divqu
450
451 ldq $24, 8($sp)
452 ldq $25, 16($sp)
453
454 /* Negate the unsigned result, if necessary. */
455 xor $24, $25, $28
456 subl $31, $27, $23
457 addl $27, 0, $27
458 addl $28, 0, $28
459 cmovlt $28, $23, $27
460
461 ldq $23, 0($sp)
462 addq $sp, 32, $sp
463 ret $31, ($23), 1
464 .end __divls
465
466 /*
467 * Signed 32-bit remainder.
468 */
469
470 .globl __remls
471 .ent __remls
472 __remls:
473 .frame $sp, 32, $23
474 subq $sp, 32, $sp
475 stq $23, 0($sp)
476 stq $24, 8($sp)
477 stq $25, 16($sp)
478 .prologue 0
479
480 /* Sign extend. */
481 addl $24, 0, $24
482 addl $25, 0, $25
483
484 /* Compute absolute values. */
485 subq $31, $24, $28
486 cmovlt $24, $28, $24
487 subq $31, $25, $28
488 cmovlt $25, $28, $25
489
490 bsr $23, __divqu
491
492 ldq $23, 0($sp)
493 ldq $24, 8($sp)
494 ldq $25, 16($sp)
495
496 /* Negate the unsigned result, if necessary. */
497 subl $31, $28, $27
498 addl $28, 0, $28
499 cmovge $24, $28, $27
500
501 addq $sp, 32, $sp
502 ret $31, ($23), 1
503 .end __remls
504
505 .data
506 .p2align 4
507 stack:
508 .skip 65536
509 $stack_end:
510 .type stack,@object
511 .size stack, . - stack