1/* $NetBSD: start.S,v 1.1 2011/01/26 01:18:54 pooka Exp $ */ 2 3/*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code was written by Alessandro Forin and Neil Pittman 8 * at Microsoft Research and contributed to The NetBSD Foundation 9 * by Microsoft Corporation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* Trivial support for printing stuff on the serial line from C pgms. 34 */ 35#include <mips/asm.h> 36#include <mips/cpuregs.h> 37#define __ASSEMBLER__ 1 38#include <machine/emipsreg.h> 39 40/* Offsets in the CXTINFO structure 41 */ 42#define TS_AT (1 * 4) 43#define TS_V0 (2 * 4) 44#define TS_V1 (3 * 4) 45#define TS_A0 (4 * 4) 46#define TS_A1 (5 * 4) 47#define TS_A2 (6 * 4) 48#define TS_A3 (7 * 4) 49#define TS_T0 (8 * 4) 50#define TS_T1 (9 * 4) 51#define TS_T2 (10 * 4) 52#define TS_T3 (11 * 4) 53#define TS_T4 (12 * 4) 54#define TS_T5 (13 * 4) 55#define TS_T6 (14 * 4) 56#define TS_T7 (15 * 4) 57#define TS_S0 (16 * 4) 58#define TS_S1 (17 * 4) 59#define TS_S2 (18 * 4) 60#define TS_S3 (19 * 4) 61#define TS_S4 (20 * 4) 62#define TS_S5 (21 * 4) 63#define TS_S6 (22 * 4) 64#define TS_S7 (23 * 4) 65#define TS_T8 (24 * 4) 66#define TS_T9 (25 * 4) 67#define TS_K0 (26 * 4) 68#define TS_K1 (27 * 4) 69#define TS_GP (28 * 4) 70#define TS_SP (29 * 4) 71#define TS_FP (30 * 4) 72#define fp s8 73#define TS_RA (31 * 4) 74 75#define TS_PC (32 * 4) 76#define TS_SR (33 * 4) 77#define TS_HI (34 * 4) 78#define TS_LO (35 * 4) 79#define TS_EC (36 * 4) 80#define SIZEOF_CXTINFO (37*4) 81 82/* PROM_MODE means the user plans to keep this code around while running an OS. 83 * So we act kind of like PROM code (BIOS?), but we live in RAM. 84 * So we need to safeguard ourselves against corruptions, some unavoidable. 85 * Like the overriding of the exception vectors, rigth where our "start" code is. 86 */ 87 88 IMPORT(main,4) 89 IMPORT(_end,4) 90 91 .set noreorder 92 93EXPORT(start) 94 bgezal zero,_C_LABEL(real_start) 95 nop 96 97 98/* Does not handle the exception, really. 99 * But to test interrupts should be enough 100 */ 101 .org 0x00000080 102VECTOR(ExceptionHandler,0) 103 .frame sp,SIZEOF_CXTINFO,$31 104 la k1, UserInterruptHandler 105 lw k1,0(k1) 106 bne k1,zero,Dispatch 107 mfc0 k0, MIPS_COP_0_EXC_PC 108 j k0 109 nop /* do not! pop status */ 110 111EXPORT(UserInterruptHandler) 112 .word 0 113 114EXPORT(Dispatch) 115 /* Save state on stack */ 116 addiu sp, sp, -SIZEOF_CXTINFO 117 /* save registers */ 118 .set noat 119 sw AT, TS_AT(sp) 120 .set at 121 sw v0, TS_V0(sp) 122 sw v1, TS_V1(sp) 123 sw a0, TS_A0(sp) 124 sw a1, TS_A1(sp) 125 sw a2, TS_A2(sp) 126 sw a3, TS_A3(sp) 127 sw t0, TS_T0(sp) 128 sw t1, TS_T1(sp) 129 sw t2, TS_T2(sp) 130 sw t3, TS_T3(sp) 131 sw t4, TS_T4(sp) 132 sw t5, TS_T5(sp) 133 sw t6, TS_T6(sp) 134 sw t7, TS_T7(sp) 135 sw s0, TS_S0(sp) 136 sw s1, TS_S1(sp) 137 sw s2, TS_S2(sp) 138 sw s3, TS_S3(sp) 139 sw s4, TS_S4(sp) 140 sw s5, TS_S5(sp) 141 sw s6, TS_S6(sp) 142 sw s7, TS_S7(sp) 143 sw t8, TS_T8(sp) 144 sw t9, TS_T9(sp) 145 sw k0, TS_K0(sp) 146 sw k1, TS_K1(sp) 147 sw gp, TS_GP(sp) 148 /* sp: later */ 149 sw fp, TS_FP(sp) 150 sw ra, TS_RA(sp) 151 152 mfc0 a0, MIPS_COP_0_STATUS 153 mflo t0 154 mfhi t1 155 sw a0, TS_SR(sp) 156 sw t0, TS_LO(sp) 157 sw t1, TS_HI(sp) 158 sw k0, TS_PC(sp) 159 160 /* Save original stack */ 161 move a0,sp 162 addiu t0, sp, SIZEOF_CXTINFO 163 jalr k1 164 sw t0, TS_SP(sp) 165 166 /* Returned value is new PCXINFO */ 167 move a0,v0 168 169 /* First load most registers */ 170 .set noat 171 lw AT, TS_AT(a0) 172 lw v0, TS_V0(a0) 173 lw v1, TS_V1(a0) 174 /* a0 later */ 175 lw a1, TS_A1(a0) 176 lw a2, TS_A2(a0) 177 lw a3, TS_A3(a0) 178 lw t0, TS_T0(a0) 179 lw t1, TS_T1(a0) 180 lw t2, TS_T2(a0) 181 lw t3, TS_T3(a0) 182 lw t4, TS_T4(a0) 183 lw t5, TS_T5(a0) 184 lw t6, TS_T6(a0) 185 lw t7, TS_T7(a0) 186 lw s0, TS_S0(a0) 187 lw s1, TS_S1(a0) 188 lw s2, TS_S2(a0) 189 lw s3, TS_S3(a0) 190 lw s4, TS_S4(a0) 191 lw s5, TS_S5(a0) 192 lw s6, TS_S6(a0) 193 lw s7, TS_S7(a0) 194 lw t8, TS_T8(a0) 195 lw t9, TS_T9(a0) 196 /* k0,k1 not restored */ 197 lw gp, TS_GP(a0) 198 /* sp later */ 199 lw fp, TS_FP(a0) 200 lw ra, TS_RA(a0) 201 202 lw k1, TS_HI(a0) 203 lw k0, TS_LO(a0) 204 mthi k1 205 mtlo k0 206 lw k1, TS_SR(a0) 207 mtc0 k1, MIPS_COP_0_STATUS 208 /* NB: After this instruction we cannot take any interrupts or traps 209 */ 210 lw sp, TS_SP(a0) 211 212 /* Put pc into k0 */ 213 lw k0, TS_PC(a0) 214 lw a0, TS_A0(a0) 215 j k0 216 rfe 217 .set at 218 219VECTOR_END(ExceptionHandler) 220 221 .org 0x00000200 222EXPORT(real_start) 223 .ent _C_LABEL(real_start) 224 225#ifdef SECONDARY_BOOTBLOCK 226 /* 227 * If this is the program that goes into FLASH we must copy ourselves down to RAM. 228 * FLASH default on the MLx is at 0xf0000000, DRAM at 0. 229 */ 230 addi a0,ra,-8 /* Compensate for the first two instructions */ 231 232 /* Get the address(relative) of TextStart 233 */ 234 bgezal zero, _C_LABEL(MipsStart2) /* Always jumps */ 235 nop 236 237 /* All of the static data, since we are at it. 238 */ 239TextStart: /* + 0 */ 240 /* Text start at final link address */ 241 .int start 242 243DataEnd: /* + 4 */ 244 /* Data end == bss start */ 245 .int _edata 246 247BssEnd: /* + 8 */ 248 /* Bss end */ 249 .int _end 250 251RelocToRAM: /* *+12 */ 252 .int InRAM 253 254MipsStart2: 255 256 /* Source = a0, Dst = t2 */ 257 lw t2, 0(ra) /* _C_LABEL(TextStart) */ 258 259 /* EndPtr = t3 */ 260 /* in bdelay slot */ 261 262 /* If a0 != t2 then we are running in Flash but should run in RAM 263 * In that case copy .text. Otherwise skip to .bss. 264 */ 265 beq a0,t2,ZroLoop-4 266 lw t3, 4(ra) /* _C_LABEL(DataEnd) */ 267 268CpyLoop: 269 /* loop copying 2 words at a time */ 270 lw t4,0(a0) 271 lw t5,4(a0) 272 addiu a0,a0,8 273 sw t4,0(t2) 274 addiu t2,t2,8 275 sltu t1,t2,t3 276 bne t1,zero,CpyLoop 277 sw t5,-4(t2) 278 279 /* zero the bss 280 */ 281 lw t4, 8(ra) /* _C_LABEL(BssEnd) */ 282ZroLoop: 283 sltu t1,t3,t4 284 sw zero,0(t3) 285 bne t1,zero,ZroLoop 286 addiu t3,t3,4 287 288 /* Jump to RAM copy (below) 289 */ 290 lw t1, 12(ra) /* _C_LABEL(RelocToRAM) */ 291 jr t1 292 nop 293 294 /* 295 * Execute from here after copying out of FLASH into RAM 296 */ 297InRAM: 298 299#endif /* SECONDARY_BOOTBLOCK */ 300 301 /* Get a stack 302 */ 303#ifdef __GP_SUPPORT__ 304 la gp, _C_LABEL (_gp) 305#endif 306 la sp,_end 307 addiu sp,sp,(8*1024) /* BUGBUG arbitrary */ 308 309 /* Jump to main 310 */ 311 jal main 312 add a0,sp,zero 313 314 /* Load failed, reset the processor and jump back to the origins. 315 */ 316EXPORT(_rtt) /* ahem */ 317 li t0,0x1260ff80 /* NB: On new builds this is a SYS-RESET as well */ 318 mtc0 t0,MIPS_COP_0_STATUS 319 320 lui t0,(BRAM_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */ 321 jr t0 322 nop 323 324EXPORT(Stop) 325 b Stop 326 nop 327 328END(real_start) 329 330 .set noreorder 331 .set noat 332 .set nomacro 333 334/* void Delay(UINT32 count) 335 */ 336LEAF(Delay) 337 bne a0,zero,_C_LABEL(Delay) 338 subu a0,1 339 j ra 340 nop 341END(Delay) 342 343/* UINT32 GetPsr(void) 344 * Returns the PSR (coprocessor 0 status) 345 */ 346LEAF(GetPsr) 347 mfc0 v0, MIPS_COP_0_STATUS 348 j ra 349 nop 350END(GetPsr) 351 352/* void SetPsr(UINT32 Psr) 353 * Sets the PSR (coprocessor 0 status) 354 */ 355LEAF(SetPsr) 356 mtc0 a0,MIPS_COP_0_STATUS 357 j ra 358 nop 359END(SetPsr) 360 361/* UINT32 GetCause(void) 362 * Returns the Cause register (coprocessor 0) 363 */ 364LEAF(GetCause) 365 mfc0 v0,MIPS_COP_0_CAUSE 366 j ra 367 nop 368END(GetCause) 369 370/* UINT32 GetEpc(void) 371 * Returns the Epc register (coprocessor 0) 372 */ 373LEAF(GetEpc) 374 mfc0 v0,MIPS_COP_0_EXC_PC 375 j ra 376 nop 377END(GetEpc) 378 379 380/* int PutWord(UINT32 Word); 381 * Returns: 0 if ok, -1 otherwise 382 */ 383NESTED(PutWord,12,$31) 384 subu sp,sp,12 385 sw s0,8(sp) 386 sw s1,4(sp) 387 sw ra,0(sp) 388 389 or s1,a0,zero 390 /* Spit all nibbles 391 */ 392 li s0,8 393PutWordLoop: 394 srl a0,s1,32-4 395 li t0,10 396 sltu t1,a0,t0 397 bnez t1,$Digit 398 li a1,'0' 399 subu a0,a0,t0 400 li a1,'a' 401$Digit: 402 sll s1,s1,4 403 jal PutChar 404 add a0,a0,a1 405 406 subu s0,s0,1 407 bne v0,zero,PutWordDone /* printed ok? */ 408 li v0,-1 409 410 /* done yet? */ 411 bne s0,zero,PutWordLoop 412 nop 413 414 /* done 415 */ 416 li v0,0 417PutWordDone: 418 lw ra,0(sp) 419 lw s1,4(sp) 420 lw s0,8(sp) 421 jr ra 422 addiu sp,sp,12 423 424END(PutWord) 425 426/* int Puts(char *String); 427 * Returns: 0 if ok, -1 otherwise 428 */ 429NESTED(Puts,8,$31) 430 subu sp,sp,8 431 sw s0,4(sp) 432 sw ra,0(sp) 433 434 or s0,a0,zero 435 /* Spit all chars until zero 436 */ 437PutsLoop: 438 lbu a0,0(s0) 439 addiu s0,s0,1 440 beq a0,zero,PutsDoneOk 441 nop 442 jal PutChar 443 nop 444 beq v0,zero,PutsLoop 445 nop 446 447 /* Timed out 448 */ 449 b PutsDone 450 li v0,-1 451 452 /* done 453 */ 454PutsDoneOk: 455 li v0,0 456PutsDone: 457 lw ra,0(sp) 458 lw s0,4(sp) 459 jr ra 460 addiu sp,sp,8 461 462END(Puts) 463 464 465/* int GetChar(void); 466 * Returns: a non-negative value if ok, -1 otherwise 467 */ 468LEAF(GetChar) 469 lui t0,(USART_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */ 470 lui t1,1000 /* n*65k spins max */ 471RxNotReady: 472 lw t4,USARTST(t0) /* ChannelStatus */ 473 andi t4,t4,USI_RXRDY 474 bgtz t4,$GotByte 475 subu t1,t1,1 476 /* still ok to spin? */ 477 bgtz t1,RxNotReady 478 nop 479 /* Timed out 480 */ 481 jr ra 482 li v0,-1 483 484 /* Gottabyte 485 */ 486$GotByte: 487 lw v0,USARTRX(t0) /* RxData */ 488 jr ra 489 andi v0,0xff 490END(GetChar) 491 492/* int PutChar(UINT8 v); 493 * Returns: 0 if ok, -1 otherwise 494 */ 495LEAF(PutChar) 496 lui t0,(USART_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */ 497 lui t1,1000 /* n*65k spins max */ 498 li v0,0 499TxNotReady: 500 lw t4,USARTST(t0) /* ChannelStatus */ 501 andi t4,t4,USI_TXRDY 502 bgtz t4,TxReady 503 subu t1,t1,1 504 /* still ok to spin? */ 505 bgtz t1,TxNotReady 506 nop 507 /* Timed out 508 */ 509 jr ra 510 li v0,-1 511 512 /* Send it 513 */ 514TxReady: 515 jr ra 516 sw a0,USARTTX(t0) 517 518END(PutChar) 519 520/* Second arg is a function to call with the first arg: 521 * void switch_stack_and_call(void *arg, void (*function)(void *)); 522 */ 523LEAF(switch_stack_and_call) 524 /* Get a stack and jump. It would be a very bad idea to return but.. 525 */ 526#ifdef __GP_SUPPORT__ 527 la gp, _C_LABEL (_gp) 528#endif 529 la sp,_end 530 jr a1 531 addiu sp,sp,(2*1024) /* BUGBUG arbitrary */ 532 533END(switch_stack_and_call) 534 535