1/* 2 * mips 24k machine assist for routerboard rb450g 3 */ 4#include "mem.h" 5#include "mips.s" 6 7#define SANITY 0x12345678 8 9 NOSCHED 10 11/* 12 * Boot only processor 13 */ 14TEXT start(SB), $-4 15 MOVW $setR30(SB), R30 16 17PUTC('9', R1, R2) 18 DI(0) 19 20 MOVW sanity(SB), R1 21 CONST(SANITY, R2) 22 SUBU R1, R2, R2 23 BNE R2, insane 24 NOP 25 26 MOVW R0, M(COMPARE) 27 EHB 28 29 /* don't enable any interrupts nor FP, but leave BEV on. */ 30 MOVW $BEV,R1 31 MOVW R1, M(STATUS) 32 UBARRIERS(7, R7, stshb) /* returns to kseg1 space */ 33 MOVW R0, M(CAUSE) 34 EHB 35 36 /* silence the atheros watchdog */ 37 MOVW $(KSEG1|0x18060008), R1 38 MOVW R0, (R1) /* set no action */ 39 SYNC 40 41 MOVW $PE, R1 42 MOVW R1, M(CACHEECC) /* aka ErrCtl */ 43 EHB 44 JAL cleancache(SB) 45 NOP 46 47 MOVW $TLBROFF, R1 48 MOVW R1, M(WIRED) 49 50 MOVW R0, M(CONTEXT) 51 EHB 52 53 /* set KSEG0 cachability before trying LL/SC in lock code */ 54 MOVW M(CONFIG), R1 55 AND $~CFG_K0, R1 56 /* make kseg0 cachable, enable write-through merging */ 57 OR $((PTECACHABILITY>>3)|CFG_MM), R1 58 MOVW R1, M(CONFIG) 59 BARRIERS(7, R7, cfghb) /* back to kseg0 space */ 60 61 MOVW $setR30(SB), R30 /* again */ 62 63 /* initialize Mach, including stack */ 64 MOVW $MACHADDR, R(MACH) 65 ADDU $(MACHSIZE-BY2V), R(MACH), SP 66 MOVW R(MACH), R1 67clrmach: 68 MOVW R0, (R1) 69 ADDU $BY2WD, R1 70 BNE R1, SP, clrmach 71 NOP 72 MOVW R0, 0(R(MACH)) /* m->machno = 0 */ 73 MOVW R0, R(USER) /* up = nil */ 74 75 /* zero bss, byte-by-byte */ 76 MOVW $edata(SB), R1 77 MOVW $end(SB), R2 78clrbss: 79 MOVB R0, (R1) 80 ADDU $1, R1 81 BNE R1, R2, clrbss 82 NOP 83 84 MOVW $0x16, R16 85 MOVW $0x17, R17 86 MOVW $0x18, R18 87 MOVW $0x19, R19 88 MOVW $0x20, R20 89 MOVW $0x21, R21 90 MOVW $0x22, R22 91 MOVW $0x23, R23 92 93 MOVW R0, HI 94 MOVW R0, LO 95 96PUTC('\r', R1, R2) 97PUTC('\n', R1, R2) 98 JAL main(SB) 99 NOP 100 CONST(ROM, R1) 101 JMP (R1) /* back to the rom */ 102 103#define PUT(c) PUTC(c, R1, R2) 104#define DELAY(lab) \ 105 CONST(34000000, R3); \ 106lab: SUBU $1, R3; \ 107 BNE R3, lab; \ 108 NOP 109 110insane: 111 /* 112 * data segment is misaligned; kernel needs vl -R4096 or -R16384, 113 * as appropriate, for reboot. 114 */ 115 PUT('?'); PUT('d'); PUT('a'); PUT('t'); PUT('a'); PUT(' '); DELAY(dl1) 116 PUT('s'); PUT('e'); PUT('g'); PUT('m'); PUT('e'); PUT('n'); DELAY(dl2) 117 PUT('t'); PUT(' '); PUT('m'); PUT('i'); PUT('s'); PUT('a'); DELAY(dl3) 118 PUT('l'); PUT('i'); PUT('g'); PUT('n'); PUT('e'); PUT('d'); DELAY(dl4) 119 PUT('\r'); PUT('\n'); DELAY(dl5) 120 CONST(ROM, R1) 121 JMP (R1) /* back to the rom */ 122 NOP 123 124/* target for JALRHB in BARRIERS */ 125TEXT ret(SB), $-4 126 JMP (R22) 127 NOP 128 129/* print R1 in hex; clobbers R3—8 */ 130TEXT printhex(SB), $-4 131 MOVW $32, R5 132 MOVW $9, R7 133prtop: 134 SUB $4, R5 135 MOVW R1, R6 136 SRL R5, R6 137 AND $0xf, R6 138 SGTU R6, R7, R8 139 BEQ R8, prdec /* branch if R6 <= 9 */ 140 NOP 141 ADD $('a'-10), R6 142 JMP prchar 143 NOP 144prdec: 145 ADD $'0', R6 146prchar: 147 PUTC(R6, R3, R4) 148 BNE R5, prtop 149 NOP 150 RETURN 151 152/* 153 * Take first processor into user mode 154 * - argument is stack pointer to user 155 */ 156TEXT touser(SB), $-4 157 MOVW R1, SP 158 MOVW $(UTZERO+32), R2 /* header appears in text */ 159 MOVW R2, M(EPC) 160 EHB 161 MOVW M(STATUS), R4 162 AND $(~KMODEMASK), R4 163 OR $(KUSER|IE|EXL), R4 /* switch to user mode, intrs on, exc */ 164 MOVW R4, M(STATUS) /* " */ 165 ERET /* clears EXL */ 166 167/* 168 * manipulate interrupts 169 */ 170 171/* enable an interrupt; bit is in R1 */ 172TEXT intron(SB), $0 173 MOVW M(STATUS), R2 174 OR R1, R2 175 MOVW R2, M(STATUS) 176 EHB 177 RETURN 178 179/* disable an interrupt; bit is in R1 */ 180TEXT introff(SB), $0 181 MOVW M(STATUS), R2 182 XOR $-1, R1 183 AND R1, R2 184 MOVW R2, M(STATUS) 185 EHB 186 RETURN 187 188/* on our 24k, wait instructions are not interruptible, alas. */ 189TEXT idle(SB), $-4 190 EI(1) /* old M(STATUS) into R1 */ 191 EHB 192 /* fall through */ 193 194TEXT wait(SB), $-4 195 WAIT 196 NOP 197 198 MOVW R1, M(STATUS) /* interrupts restored */ 199 EHB 200 RETURN 201 202TEXT splhi(SB), $0 203 EHB 204 MOVW R31, 12(R(MACH)) /* save PC in m->splpc */ 205 DI(1) /* old M(STATUS) into R1 */ 206 EHB 207 RETURN 208 209TEXT splx(SB), $0 210 EHB 211 MOVW R31, 12(R(MACH)) /* save PC in m->splpc */ 212 MOVW M(STATUS), R2 213 AND $IE, R1 214 AND $~IE, R2 215 OR R2, R1 216 MOVW R1, M(STATUS) 217 EHB 218 RETURN 219 220TEXT spllo(SB), $0 221 EHB 222 EI(1) /* old M(STATUS) into R1 */ 223 EHB 224 RETURN 225 226TEXT spldone(SB), $0 227 RETURN 228 229TEXT islo(SB), $0 230 MOVW M(STATUS), R1 231 AND $IE, R1 232 RETURN 233 234TEXT coherence(SB), $-4 235 BARRIERS(7, R7, cohhb) 236 SYNC 237 EHB 238 RETURN 239 240/* 241 * process switching 242 */ 243 244TEXT setlabel(SB), $-4 245 MOVW R29, 0(R1) 246 MOVW R31, 4(R1) 247 MOVW R0, R1 248 RETURN 249 250TEXT gotolabel(SB), $-4 251 MOVW 0(R1), R29 252 MOVW 4(R1), R31 253 MOVW $1, R1 254 RETURN 255 256/* 257 * the tlb routines need to be called at splhi. 258 */ 259 260TEXT puttlb(SB), $0 /* puttlb(virt, phys0, phys1) */ 261 EHB 262 MOVW R1, M(TLBVIRT) 263 EHB 264 MOVW 4(FP), R2 /* phys0 */ 265 MOVW 8(FP), R3 /* phys1 */ 266 MOVW R2, M(TLBPHYS0) 267 EHB 268 MOVW $PGSZ, R1 269 MOVW R3, M(TLBPHYS1) 270 EHB 271 MOVW R1, M(PAGEMASK) 272 OR R2, R3, R4 /* MTC0 delay slot */ 273 AND $PTEVALID, R4 /* MTC0 delay slot */ 274 EHB 275 TLBP /* tlb probe */ 276 EHB 277 MOVW M(INDEX), R1 278 BGEZ R1, index /* if tlb entry found, use it */ 279 NOP 280 BEQ R4, dont /* not valid? cf. kunmap */ 281 NOP 282 MOVW M(RANDOM), R1 /* write random tlb entry */ 283 MOVW R1, M(INDEX) 284index: 285 EHB 286 TLBWI /* write indexed tlb entry */ 287 JRHB(31) /* return and clear all hazards */ 288dont: 289 RETURN 290 291TEXT getwired(SB),$0 292 MOVW M(WIRED), R1 293 RETURN 294 295TEXT setwired(SB),$0 296 MOVW R1, M(WIRED) 297 EHB 298 RETURN 299 300TEXT getrandom(SB),$0 301 MOVW M(RANDOM), R1 302 RETURN 303 304TEXT getpagemask(SB),$0 305 MOVW M(PAGEMASK), R1 306 RETURN 307 308TEXT setpagemask(SB),$0 309 EHB 310 MOVW R1, M(PAGEMASK) 311 EHB 312 MOVW R0, R1 /* prevent accidents */ 313 RETURN 314 315TEXT puttlbx(SB), $0 /* puttlbx(index, virt, phys0, phys1, pagemask) */ 316 MOVW 4(FP), R2 317 MOVW 8(FP), R3 318 MOVW 12(FP), R4 319 MOVW 16(FP), R5 320 EHB 321 MOVW R2, M(TLBVIRT) 322 EHB 323 MOVW R3, M(TLBPHYS0) 324 MOVW R4, M(TLBPHYS1) 325 MOVW R5, M(PAGEMASK) 326 EHB 327 MOVW R1, M(INDEX) 328 EHB 329 TLBWI /* write indexed tlb entry */ 330 JRHB(31) /* return and clear all hazards */ 331 332TEXT tlbvirt(SB), $0 333 EHB 334 MOVW M(TLBVIRT), R1 335 EHB 336 RETURN 337 338TEXT gettlbx(SB), $0 /* gettlbx(index, &entry) */ 339 MOVW 4(FP), R5 340 MOVW M(TLBVIRT), R10 /* save our asid */ 341 EHB 342 MOVW R1, M(INDEX) 343 EHB 344 TLBR /* read indexed tlb entry */ 345 EHB 346 MOVW M(TLBVIRT), R2 347 MOVW M(TLBPHYS0), R3 348 MOVW M(TLBPHYS1), R4 349 MOVW R2, 0(R5) 350 MOVW R3, 4(R5) 351 MIPS24KNOP 352 MOVW R4, 8(R5) 353 EHB 354 MOVW R10, M(TLBVIRT) /* restore our asid */ 355 EHB 356 RETURN 357 358TEXT gettlbp(SB), $0 /* gettlbp(tlbvirt, &entry) */ 359 MOVW 4(FP), R5 360 MOVW M(TLBVIRT), R10 /* save our asid */ 361 EHB 362 MOVW R1, M(TLBVIRT) 363 EHB 364 TLBP /* probe tlb */ 365 EHB 366 MOVW M(INDEX), R1 367 BLTZ R1, gettlbp1 /* if no tlb entry found, return */ 368 NOP 369 EHB 370 TLBR /* read indexed tlb entry */ 371 EHB 372 MOVW M(TLBVIRT), R2 373 MOVW M(TLBPHYS0), R3 374 MOVW M(TLBPHYS1), R4 375 MOVW M(PAGEMASK), R6 376 MOVW R2, 0(R5) 377 MOVW R3, 4(R5) 378 MIPS24KNOP 379 MOVW R4, 8(R5) 380 MOVW R6, 12(R5) 381gettlbp1: 382 EHB 383 MOVW R10, M(TLBVIRT) /* restore our asid */ 384 EHB 385 RETURN 386 387TEXT gettlbvirt(SB), $0 /* gettlbvirt(index) */ 388 MOVW M(TLBVIRT), R10 /* save our asid */ 389 EHB 390 MOVW R1, M(INDEX) 391 EHB 392 TLBR /* read indexed tlb entry */ 393 EHB 394 MOVW M(TLBVIRT), R1 395 EHB 396 MOVW R10, M(TLBVIRT) /* restore our asid */ 397 EHB 398 RETURN 399 400/* 401 * exceptions. 402 * mips promises that there will be no current hazards upon entry 403 * to exception handlers. 404 */ 405 406TEXT vector0(SB), $-4 407 MOVW $utlbmiss(SB), R26 408 JMP (R26) 409 NOP 410 411/* 412 * compute stlb hash index. 413 * must match index calculation in mmu.c/putstlb() 414 * 415 * M(TLBVIRT) [page & asid] in arg, result in arg. 416 * stir in swizzled asid; we get best results with asid in both high & low bits. 417 * 418 * page = tlbvirt >> (PGSHIFT+1); // ignoring even/odd bit 419 * R27 = ((tlbvirt<<(STLBLOG-8) ^ (uchar)tlbvirt ^ page ^ 420 * ((page & (MASK(HIPFNBITS) << STLBLOG)) >> HIPFNBITS)) & 421 * (STLBSIZE-1)) * 12; 422 */ 423#define STLBHASH(arg, tmp, tmp2) \ 424 MOVW arg, tmp2; \ 425 SRL $(PGSHIFT+1), arg; /* move low page # bits to low bits */ \ 426 CONST ((MASK(HIPFNBITS) << STLBLOG), tmp); \ 427 AND arg, tmp; /* extract high page # bits */ \ 428 SRL $HIPFNBITS, tmp; /* position them */ \ 429 XOR tmp, arg; /* include them */ \ 430 MOVW tmp2, tmp; /* asid in low byte */ \ 431 SLL $(STLBLOG-8), tmp; /* move asid to high bits */ \ 432 XOR tmp, arg; /* include asid in high bits too */ \ 433 AND $0xff, tmp2, tmp; /* asid in low byte */ \ 434 XOR tmp, arg; /* include asid in low bits */ \ 435 CONST (STLBSIZE-1, tmp); \ 436 AND tmp, arg /* chop to fit */ 437 438TEXT utlbmiss(SB), $-4 439 /* 440 * don't use R28 by using constants that span both word halves, 441 * it's unsaved so far. avoid R24 (up in kernel) and R25 (m in kernel). 442 */ 443 /* update statistics */ 444 CONST (MACHADDR, R26) /* R26 = m-> */ 445 MOVW 16(R26), R27 446 ADDU $1, R27 447 MOVW R27, 16(R26) /* m->tlbfault++ */ 448 449 MOVW R23, M(DESAVE) /* save R23 */ 450 451#ifdef KUTLBSTATS 452 MOVW M(STATUS), R23 453 AND $KUSER, R23 454 BEQ R23, kmiss 455 456 MOVW 24(R26), R27 457 ADDU $1, R27 458 MOVW R27, 24(R26) /* m->utlbfault++ */ 459 JMP either 460kmiss: 461 MOVW 20(R26), R27 462 ADDU $1, R27 463 MOVW R27, 20(R26) /* m->ktlbfault++ */ 464either: 465#endif 466 467 /* compute stlb index */ 468 EHB 469 MOVW M(TLBVIRT), R27 /* asid in low byte */ 470 STLBHASH(R27, R26, R23) 471 MOVW M(DESAVE), R23 /* restore R23 */ 472 473 /* scale to a byte index (multiply by 12) */ 474 SLL $1, R27, R26 /* × 2 */ 475 ADDU R26, R27 /* × 3 */ 476 SLL $2, R27 /* × 12 */ 477 478 CONST (MACHADDR, R26) /* R26 = m-> */ 479 MOVW 4(R26), R26 /* R26 = m->stb */ 480 ADDU R26, R27 /* R27 = &m->stb[hash] */ 481 482 MOVW M(BADVADDR), R26 483 AND $BY2PG, R26 484 BNE R26, utlbodd /* odd page? */ 485 NOP 486 487utlbeven: 488 MOVW 4(R27), R26 /* R26 = m->stb[hash].phys0 */ 489 BEQ R26, stlbm /* nothing cached? do it the hard way */ 490 NOP 491 MOVW R26, M(TLBPHYS0) 492 EHB 493 MOVW 8(R27), R26 /* R26 = m->stb[hash].phys1 */ 494 JMP utlbcom 495 MOVW R26, M(TLBPHYS1) /* branch delay slot */ 496 497utlbodd: 498 MOVW 8(R27), R26 /* R26 = m->stb[hash].phys1 */ 499 BEQ R26, stlbm /* nothing cached? do it the hard way */ 500 NOP 501 MOVW R26, M(TLBPHYS1) 502 EHB 503 MOVW 4(R27), R26 /* R26 = m->stb[hash].phys0 */ 504 MOVW R26, M(TLBPHYS0) 505 506utlbcom: 507 EHB /* MTC0/MFC0 hazard */ 508 MOVW M(TLBVIRT), R26 509 MOVW (R27), R27 /* R27 = m->stb[hash].virt */ 510 BEQ R27, stlbm /* nothing cached? do it the hard way */ 511 NOP 512 /* is the stlb entry for the right virtual address? */ 513 BNE R26, R27, stlbm /* M(TLBVIRT) != m->stb[hash].virt? */ 514 NOP 515 516 /* if an entry exists, overwrite it, else write a random one */ 517 CONST (PGSZ, R27) 518 MOVW R27, M(PAGEMASK) /* select page size */ 519 EHB 520 TLBP /* probe tlb */ 521 EHB 522 MOVW M(INDEX), R26 523 BGEZ R26, utlindex /* if tlb entry found, rewrite it */ 524 EHB /* delay slot */ 525 TLBWR /* else write random tlb entry */ 526 ERET 527utlindex: 528 TLBWI /* write indexed tlb entry */ 529 ERET 530 531/* not in the stlb either; make trap.c figure it out */ 532stlbm: 533 MOVW $exception(SB), R26 534 JMP (R26) 535 NOP 536 537TEXT stlbhash(SB), $-4 538 STLBHASH(R1, R2, R3) 539 RETURN 540 541TEXT vector100(SB), $-4 542 MOVW $exception(SB), R26 543 JMP (R26) 544 NOP 545 546TEXT vector180(SB), $-4 547 MOVW $exception(SB), R26 548 JMP (R26) 549 NOP 550 551TEXT exception(SB), $-4 552 MOVW M(STATUS), R26 553 AND $KUSER, R26, R27 554 BEQ R27, waskernel 555 MOVW SP, R27 /* delay slot */ 556 557wasuser: 558 CONST (MACHADDR, SP) /* m-> */ 559 MOVW 8(SP), SP /* m->proc */ 560 MOVW 8(SP), SP /* m->proc->kstack */ 561 MOVW M(STATUS), R26 /* redundant load */ 562 ADDU $(KSTACK-UREGSIZE), SP 563 MOVW R31, Ureg_r31(SP) 564 565 JAL savereg1(SB) 566 NOP 567 568 MOVW R30, Ureg_r30(SP) 569 MOVW R(MACH), Ureg_r25(SP) 570 MIPS24KNOP 571 MOVW R(USER), Ureg_r24(SP) 572 573 MOVW $setR30(SB), R30 574 CONST (MACHADDR, R(MACH)) /* R(MACH) = m-> */ 575 MOVW 8(R(MACH)), R(USER) /* up = m->proc */ 576 577 AND $(EXCMASK<<2), R26, R1 578 SUBU $(CSYS<<2), R1 579 BNE R1, notsys 580 NOP 581 582 /* the carrera does this: */ 583// ADDU $8, SP, R1 /* first arg for syscall */ 584 585 MOVW SP, R1 /* first arg for syscall */ 586 JAL syscall(SB) 587 SUBU $Notuoffset, SP /* delay slot */ 588sysrestore: 589 JAL restreg1(SB) 590 ADDU $Notuoffset, SP /* delay slot */ 591 592 MOVW Ureg_r31(SP), R31 593 MOVW Ureg_status(SP), R26 594 MOVW Ureg_r30(SP), R30 595 MOVW R26, M(STATUS) 596 EHB 597 MOVW Ureg_pc(SP), R26 /* old pc */ 598 MOVW Ureg_sp(SP), SP 599 MOVW R26, M(EPC) 600 ERET 601 602notsys: 603 JAL savereg2(SB) 604 NOP 605 606 /* the carrera does this: */ 607// ADDU $8, SP, R1 /* first arg for trap */ 608 609 MOVW SP, R1 /* first arg for trap */ 610 JAL trap(SB) 611 SUBU $Notuoffset, SP /* delay slot */ 612 613 ADDU $Notuoffset, SP 614 615restore: 616 JAL restreg1(SB) 617 NOP 618 JAL restreg2(SB) /* restores R28, among others */ 619 NOP 620 621 MOVW Ureg_r30(SP), R30 622 MOVW Ureg_r31(SP), R31 623 MOVW Ureg_r25(SP), R(MACH) 624 MOVW Ureg_r24(SP), R(USER) 625 MOVW Ureg_sp(SP), SP 626 MOVW R26, M(EPC) 627 ERET 628 629waskernel: 630 SUBU $UREGSIZE, SP 631 OR $7, SP /* conservative rounding */ 632 XOR $7, SP 633 MOVW R31, Ureg_r31(SP) 634 635 JAL savereg1(SB) 636 NOP 637 JAL savereg2(SB) 638 NOP 639 640 /* the carrera does this: */ 641// ADDU $8, SP, R1 /* first arg for trap */ 642 643 MOVW SP, R1 /* first arg for trap */ 644 JAL trap(SB) 645 SUBU $Notuoffset, SP /* delay slot */ 646 647 ADDU $Notuoffset, SP 648 649 JAL restreg1(SB) 650 NOP 651 652 /* 653 * if about to return to `wait', interrupt arrived just before 654 * executing wait, so move saved pc past it. 655 */ 656 MOVW Ureg_pc(SP), R26 657 MOVW R26, R31 658 MOVW $wait(SB), R1 659 SUBU R1, R31 660 BNE R31, notwait 661 NOP 662 ADD $BY2WD, R26 /* advance saved pc */ 663 MOVW R26, Ureg_pc(SP) 664notwait: 665 JAL restreg2(SB) /* restores R28, among others */ 666 NOP 667 668 MOVW Ureg_r31(SP), R31 669 MOVW Ureg_sp(SP), SP 670 MOVW R26, M(EPC) 671 ERET 672 673TEXT forkret(SB), $0 674 JMP sysrestore 675 MOVW R0, R1 /* delay slot; child returns 0 */ 676 677/* 678 * save mandatory registers. 679 * called with old M(STATUS) in R26. 680 * called with old SP in R27 681 * returns with M(CAUSE) in R26 682 */ 683TEXT savereg1(SB), $-4 684 MOVW R1, Ureg_r1(SP) 685 686 MOVW $(~KMODEMASK),R1 /* don't use R28, it's unsaved so far */ 687 AND R26, R1 688 MOVW R1, M(STATUS) 689 EHB 690 691 MOVW R26, Ureg_status(SP) /* status */ 692 MOVW R27, Ureg_sp(SP) /* user SP */ 693 694 MOVW M(EPC), R1 695 MOVW M(CAUSE), R26 696 697 MOVW R23, Ureg_r23(SP) 698 MOVW R22, Ureg_r22(SP) 699 MIPS24KNOP 700 MOVW R21, Ureg_r21(SP) 701 MOVW R20, Ureg_r20(SP) 702 MIPS24KNOP 703 MOVW R19, Ureg_r19(SP) 704 MOVW R1, Ureg_pc(SP) 705 RETURN 706 707/* 708 * all other registers. 709 * called with M(CAUSE) in R26 710 */ 711TEXT savereg2(SB), $-4 712 MOVW R2, Ureg_r2(SP) 713 714 MOVW M(BADVADDR), R2 715 MOVW R26, Ureg_cause(SP) 716 MOVW M(TLBVIRT), R1 717 MOVW R2, Ureg_badvaddr(SP) 718 MOVW R1, Ureg_tlbvirt(SP) 719 MOVW HI, R1 720 MOVW LO, R2 721 MOVW R1, Ureg_hi(SP) 722 MOVW R2, Ureg_lo(SP) 723 MIPS24KNOP 724 /* LINK,SB,SP missing */ 725 MOVW R28, Ureg_r28(SP) 726 /* R27, R26 not saved */ 727 /* R25, R24 missing */ 728 /* R23- R19 saved in save1 */ 729 MOVW R18, Ureg_r18(SP) 730 MIPS24KNOP 731 MOVW R17, Ureg_r17(SP) 732 MOVW R16, Ureg_r16(SP) 733 MIPS24KNOP 734 MOVW R15, Ureg_r15(SP) 735 MOVW R14, Ureg_r14(SP) 736 MIPS24KNOP 737 MOVW R13, Ureg_r13(SP) 738 MOVW R12, Ureg_r12(SP) 739 MIPS24KNOP 740 MOVW R11, Ureg_r11(SP) 741 MOVW R10, Ureg_r10(SP) 742 MIPS24KNOP 743 MOVW R9, Ureg_r9(SP) 744 MOVW R8, Ureg_r8(SP) 745 MIPS24KNOP 746 MOVW R7, Ureg_r7(SP) 747 MOVW R6, Ureg_r6(SP) 748 MIPS24KNOP 749 MOVW R5, Ureg_r5(SP) 750 MOVW R4, Ureg_r4(SP) 751 MIPS24KNOP 752 MOVW R3, Ureg_r3(SP) 753 RETURN 754 755TEXT restreg1(SB), $-4 756 MOVW Ureg_r23(SP), R23 757 MOVW Ureg_r22(SP), R22 758 MOVW Ureg_r21(SP), R21 759 MOVW Ureg_r20(SP), R20 760 MOVW Ureg_r19(SP), R19 761 RETURN 762 763TEXT restreg2(SB), $-4 764 /* LINK,SB,SP missing */ 765 MOVW Ureg_r28(SP), R28 766 /* R27, R26 not saved */ 767 /* R25, R24 missing */ 768 /* R19- R23 restored in rest1 */ 769 MOVW Ureg_r18(SP), R18 770 MOVW Ureg_r17(SP), R17 771 MOVW Ureg_r16(SP), R16 772 MOVW Ureg_r15(SP), R15 773 MOVW Ureg_r14(SP), R14 774 MOVW Ureg_r13(SP), R13 775 MOVW Ureg_r12(SP), R12 776 MOVW Ureg_r11(SP), R11 777 MOVW Ureg_r10(SP), R10 778 MOVW Ureg_r9(SP), R9 779 MOVW Ureg_r8(SP), R8 780 MOVW Ureg_r7(SP), R7 781 MOVW Ureg_r6(SP), R6 782 MOVW Ureg_r5(SP), R5 783 MOVW Ureg_r4(SP), R4 784 MOVW Ureg_r3(SP), R3 785 MOVW Ureg_lo(SP), R2 786 MOVW Ureg_hi(SP), R1 787 MOVW R2, LO 788 MOVW R1, HI 789 790 MOVW Ureg_status(SP), R1 791 MOVW Ureg_r2(SP), R2 792 MOVW R1, M(STATUS) /* could change interruptibility */ 793 EHB 794 MOVW Ureg_r1(SP), R1 /* BOTCH */ 795 MOVW Ureg_pc(SP), R26 796 RETURN 797 798#ifdef OLD_MIPS_EXAMPLE 799/* this appears to be a dreg from the distant past */ 800TEXT rfnote(SB), $0 801 MOVW R1, R26 /* 1st arg is &uregpointer */ 802 JMP restore 803 SUBU $(BY2WD), R26, SP /* delay slot: pc hole */ 804#endif 805 806/* 807 * degenerate floating-point stuff 808 */ 809 810TEXT clrfpintr(SB), $0 811 RETURN 812 813TEXT savefpregs(SB), $0 814 RETURN 815 816TEXT restfpregs(SB), $0 817 RETURN 818 819TEXT fcr31(SB), $0 /* fp csr */ 820 MOVW R0, R1 821 RETURN 822 823/* 824 * Emulate 68020 test and set: load linked / store conditional 825 */ 826 827TEXT tas(SB), $0 828 MOVW R1, R2 /* address of key */ 829tas1: 830 MOVW $1, R3 831 LL(2, 1) 832 NOP 833 SC(2, 3) 834 NOP 835 BEQ R3, tas1 836 NOP 837 RETURN 838 839TEXT _xinc(SB), $0 840 MOVW R1, R2 /* address of counter */ 841loop: 842 MOVW $1, R3 843 LL(2, 1) 844 NOP 845 ADDU R1, R3, R3 846 SC(2, 3) 847 NOP 848 BEQ R3, loop 849 NOP 850 RETURN 851 852TEXT _xdec(SB), $0 853 SYNC 854 MOVW R1, R2 /* address of counter */ 855loop1: 856 MOVW $-1, R3 857 LL(2, 1) 858 NOP 859 ADDU R1, R3, R3 860 MOVW R3, R1 861 SC(2, 3) 862 NOP 863 BEQ R3, loop1 864 NOP 865 RETURN 866 867TEXT cmpswap(SB), $0 868 MOVW R1, R2 /* address of key */ 869 MOVW old+4(FP), R3 /* old value */ 870 MOVW new+8(FP), R4 /* new value */ 871 LL(2, 1) /* R1 = (R2) */ 872 NOP 873 BNE R1, R3, fail 874 NOP 875 MOVW R4, R1 876 SC(2, 1) /* (R2) = R1 if (R2) hasn't changed; R1 = success */ 877 NOP 878 RETURN 879fail: 880 MOVW R0, R1 881 RETURN 882 883/* 884 * cache manipulation 885 */ 886 887/* 888 * we avoided using R4, R5, R6, and R7 so gotopc can call us without saving 889 * them, but gotopc is now gone. 890 */ 891TEXT icflush(SB), $-4 /* icflush(virtaddr, count) */ 892 MOVW 4(FP), R9 893 DI(10) /* intrs off, old status -> R10 */ 894 UBARRIERS(7, R7, ichb); /* return to kseg1 (uncached) */ 895 ADDU R1, R9 /* R9 = last address */ 896 MOVW $(~(CACHELINESZ-1)), R8 897 AND R1, R8 /* R8 = first address, rounded down */ 898 ADDU $(CACHELINESZ-1), R9 899 AND $(~(CACHELINESZ-1)), R9 /* round last address up */ 900 SUBU R8, R9 /* R9 = revised count */ 901icflush1: 902// CACHE PD+HWB, (R8) /* flush D to ram */ 903 CACHE PI+HINV, (R8) /* invalidate in I */ 904 SUBU $CACHELINESZ, R9 905 BGTZ R9, icflush1 906 ADDU $CACHELINESZ, R8 /* delay slot */ 907 908 BARRIERS(7, R7, ic2hb); /* return to kseg0 (cached) */ 909 MOVW R10, M(STATUS) 910 JRHB(31) /* return and clear all hazards */ 911 912TEXT dcflush(SB), $-4 /* dcflush(virtaddr, count) */ 913 MOVW 4(FP), R9 914 DI(10) /* intrs off, old status -> R10 */ 915 SYNC 916 EHB 917 ADDU R1, R9 /* R9 = last address */ 918 MOVW $(~(CACHELINESZ-1)), R8 919 AND R1, R8 /* R8 = first address, rounded down */ 920 ADDU $(CACHELINESZ-1), R9 921 AND $(~(CACHELINESZ-1)), R9 /* round last address up */ 922 SUBU R8, R9 /* R9 = revised count */ 923dcflush1: 924// CACHE PI+HINV, (R8) /* invalidate in I */ 925 CACHE PD+HWBI, (R8) /* flush & invalidate in D */ 926 SUBU $CACHELINESZ, R9 927 BGTZ R9, dcflush1 928 ADDU $CACHELINESZ, R8 /* delay slot */ 929 SYNC 930 EHB 931 MOVW R10, M(STATUS) 932 JRHB(31) /* return and clear all hazards */ 933 934/* the i and d caches may be different sizes, so clean them separately */ 935TEXT cleancache(SB), $-4 936 DI(10) /* intrs off, old status -> R10 */ 937 938 UBARRIERS(7, R7, cchb); /* return to kseg1 (uncached) */ 939 MOVW R0, R1 /* index, not address */ 940 MOVW $ICACHESIZE, R9 941iccache: 942 CACHE PI+IWBI, (R1) /* flush & invalidate I by index */ 943 SUBU $CACHELINESZ, R9 944 BGTZ R9, iccache 945 ADDU $CACHELINESZ, R1 /* delay slot */ 946 947 BARRIERS(7, R7, cc2hb); /* return to kseg0 (cached) */ 948 949 MOVW R0, R1 /* index, not address */ 950 MOVW $DCACHESIZE, R9 951dccache: 952 CACHE PD+IWBI, (R1) /* flush & invalidate D by index */ 953 SUBU $CACHELINESZ, R9 954 BGTZ R9, dccache 955 ADDU $CACHELINESZ, R1 /* delay slot */ 956 957 SYNC 958 MOVW R10, M(STATUS) 959 JRHB(31) /* return and clear all hazards */ 960 961/* 962 * access to CP0 registers 963 */ 964 965TEXT prid(SB), $0 966 MOVW M(PRID), R1 967 RETURN 968 969TEXT rdcount(SB), $0 970 MOVW M(COUNT), R1 971 RETURN 972 973TEXT wrcount(SB), $0 974 MOVW R1, M(COUNT) 975 EHB 976 RETURN 977 978TEXT wrcompare(SB), $0 979 MOVW R1, M(COMPARE) 980 EHB 981 RETURN 982 983TEXT rdcompare(SB), $0 984 MOVW M(COMPARE), R1 985 RETURN 986 987TEXT getconfig(SB), $-4 988 MOVW M(CONFIG), R1 989 RETURN 990 991TEXT getconfig1(SB), $-4 992 MFC0(CONFIG, 1, 1) 993 RETURN 994 995TEXT getconfig2(SB), $-4 996 MFC0(CONFIG, 2, 1) 997 RETURN 998 999TEXT getconfig3(SB), $-4 1000 MFC0(CONFIG, 3, 1) 1001 RETURN 1002 1003TEXT getconfig4(SB), $-4 1004 MFC0(CONFIG, 4, 1) 1005 RETURN 1006 1007TEXT getconfig7(SB), $-4 1008 MFC0(CONFIG, 7, 1) 1009 RETURN 1010 1011TEXT gethwreg3(SB), $-4 1012 RDHWR(3, 1) 1013 RETURN 1014 1015TEXT getcause(SB), $-4 1016 MOVW M(CAUSE), R1 1017 RETURN 1018 1019TEXT C_fcr0(SB), $-4 /* fp implementation */ 1020 MOVW $0x500, R1 /* claim to be an r4k, thus have ll/sc */ 1021 RETURN 1022 1023TEXT getstatus(SB), $0 1024 MOVW M(STATUS), R1 1025 RETURN 1026 1027TEXT setstatus(SB), $0 1028 MOVW R1, M(STATUS) 1029 EHB 1030 RETURN 1031 1032TEXT setwatchhi0(SB), $0 1033 MOVW R1, M(WATCHHI) 1034 EHB 1035 RETURN 1036 1037/* 1038 * beware that the register takes a double-word address, so it's not 1039 * precise to the individual instruction. 1040 */ 1041TEXT setwatchlo0(SB), $0 1042 MOVW R1, M(WATCHLO) 1043 EHB 1044 RETURN 1045 1046TEXT setsp(SB), $-4 1047 MOVW R1, SP 1048 RETURN 1049 1050TEXT getintctl(SB), $-4 1051 MFC0(STATUS, 1, 1) 1052 RETURN 1053 1054TEXT getsrsctl(SB), $-4 1055 MFC0(STATUS, 2, 1) 1056 RETURN 1057 1058TEXT getsrsmap(SB), $-4 1059 MFC0(STATUS, 3, 1) 1060 RETURN 1061 1062TEXT getperfctl0(SB), $-4 1063 MFC0(PERFCOUNT, 0, 1) 1064 RETURN 1065 1066TEXT getperfctl1(SB), $-4 1067 MFC0(PERFCOUNT, 2, 1) 1068 RETURN 1069 1070 GLOBL sanity(SB), $4 1071 DATA sanity(SB)/4, $SANITY 1072 1073 SCHED 1074