qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

boot.S (8576B)


      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