xref: /qemu/tests/tcg/alpha/system/boot.S (revision abff1abf)
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
120log_exit:
121entInt:
122entArith:
123entMM:
124entIF:
125entUna:
126entSys:
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	 */
1551:	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	 */
1801:	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
1919:	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.  */
2371:	cmpult	divisor, modulus, compare
238	blt	divisor, 2f
239	addq	divisor, divisor, divisor
240	addq	mask, mask, mask
241	bne	compare, 1b
242
2432:	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
2529:	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
507stack:
508	.skip	65536
509$stack_end:
510	.type	stack,@object
511	.size	stack, . - stack
512