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