xref: /openbmc/qemu/tests/tcg/alpha/system/boot.S (revision 8c1ecb590497b0349c550607db923972b37f6963)
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
512