qemu/tests/tcg/alpha/system/boot.S
<<
>>
Prefs
   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