1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// +build mips mipsle 6 7#include "go_asm.h" 8#include "go_tls.h" 9#include "funcdata.h" 10#include "textflag.h" 11 12#define REGCTXT R22 13 14TEXT runtime·rt0_go(SB),NOSPLIT,$0 15 // R29 = stack; R4 = argc; R5 = argv 16 17 ADDU $-12, R29 18 MOVW R4, 4(R29) // argc 19 MOVW R5, 8(R29) // argv 20 21 // create istack out of the given (operating system) stack. 22 // _cgo_init may update stackguard. 23 MOVW $runtime·g0(SB), g 24 MOVW $(-64*1024), R23 25 ADD R23, R29, R1 26 MOVW R1, g_stackguard0(g) 27 MOVW R1, g_stackguard1(g) 28 MOVW R1, (g_stack+stack_lo)(g) 29 MOVW R29, (g_stack+stack_hi)(g) 30 31 // if there is a _cgo_init, call it using the gcc ABI. 32 MOVW _cgo_init(SB), R25 33 BEQ R25, nocgo 34 ADDU $-16, R29 35 MOVW R0, R7 // arg 3: not used 36 MOVW R0, R6 // arg 2: not used 37 MOVW $setg_gcc<>(SB), R5 // arg 1: setg 38 MOVW g, R4 // arg 0: G 39 JAL (R25) 40 ADDU $16, R29 41 42nocgo: 43 // update stackguard after _cgo_init 44 MOVW (g_stack+stack_lo)(g), R1 45 ADD $const__StackGuard, R1 46 MOVW R1, g_stackguard0(g) 47 MOVW R1, g_stackguard1(g) 48 49 // set the per-goroutine and per-mach "registers" 50 MOVW $runtime·m0(SB), R1 51 52 // save m->g0 = g0 53 MOVW g, m_g0(R1) 54 // save m0 to g0->m 55 MOVW R1, g_m(g) 56 57 JAL runtime·check(SB) 58 59 // args are already prepared 60 JAL runtime·args(SB) 61 JAL runtime·osinit(SB) 62 JAL runtime·schedinit(SB) 63 64 // create a new goroutine to start program 65 MOVW $runtime·mainPC(SB), R1 // entry 66 ADDU $-12, R29 67 MOVW R1, 8(R29) 68 MOVW R0, 4(R29) 69 MOVW R0, 0(R29) 70 JAL runtime·newproc(SB) 71 ADDU $12, R29 72 73 // start this M 74 JAL runtime·mstart(SB) 75 76 UNDEF 77 RET 78 79DATA runtime·mainPC+0(SB)/4,$runtime·main(SB) 80GLOBL runtime·mainPC(SB),RODATA,$4 81 82TEXT runtime·breakpoint(SB),NOSPLIT,$0-0 83 BREAK 84 RET 85 86TEXT runtime·asminit(SB),NOSPLIT,$0-0 87 RET 88 89/* 90 * go-routine 91 */ 92 93// void gosave(Gobuf*) 94// save state in Gobuf; setjmp 95TEXT runtime·gosave(SB),NOSPLIT|NOFRAME,$0-4 96 MOVW buf+0(FP), R1 97 MOVW R29, gobuf_sp(R1) 98 MOVW R31, gobuf_pc(R1) 99 MOVW g, gobuf_g(R1) 100 MOVW R0, gobuf_lr(R1) 101 MOVW R0, gobuf_ret(R1) 102 // Assert ctxt is zero. See func save. 103 MOVW gobuf_ctxt(R1), R1 104 BEQ R1, 2(PC) 105 JAL runtime·badctxt(SB) 106 RET 107 108// void gogo(Gobuf*) 109// restore state from Gobuf; longjmp 110TEXT runtime·gogo(SB),NOSPLIT,$8-4 111 MOVW buf+0(FP), R3 112 MOVW gobuf_g(R3), g // make sure g is not nil 113 JAL runtime·save_g(SB) 114 115 MOVW 0(g), R2 116 MOVW gobuf_sp(R3), R29 117 MOVW gobuf_lr(R3), R31 118 MOVW gobuf_ret(R3), R1 119 MOVW gobuf_ctxt(R3), REGCTXT 120 MOVW R0, gobuf_sp(R3) 121 MOVW R0, gobuf_ret(R3) 122 MOVW R0, gobuf_lr(R3) 123 MOVW R0, gobuf_ctxt(R3) 124 MOVW gobuf_pc(R3), R4 125 JMP (R4) 126 127// void mcall(fn func(*g)) 128// Switch to m->g0's stack, call fn(g). 129// Fn must never return. It should gogo(&g->sched) 130// to keep running g. 131TEXT runtime·mcall(SB),NOSPLIT|NOFRAME,$0-4 132 // Save caller state in g->sched 133 MOVW R29, (g_sched+gobuf_sp)(g) 134 MOVW R31, (g_sched+gobuf_pc)(g) 135 MOVW R0, (g_sched+gobuf_lr)(g) 136 MOVW g, (g_sched+gobuf_g)(g) 137 138 // Switch to m->g0 & its stack, call fn. 139 MOVW g, R1 140 MOVW g_m(g), R3 141 MOVW m_g0(R3), g 142 JAL runtime·save_g(SB) 143 BNE g, R1, 2(PC) 144 JMP runtime·badmcall(SB) 145 MOVW fn+0(FP), REGCTXT // context 146 MOVW 0(REGCTXT), R4 // code pointer 147 MOVW (g_sched+gobuf_sp)(g), R29 // sp = m->g0->sched.sp 148 ADDU $-8, R29 // make room for 1 arg and fake LR 149 MOVW R1, 4(R29) 150 MOVW R0, 0(R29) 151 JAL (R4) 152 JMP runtime·badmcall2(SB) 153 154// systemstack_switch is a dummy routine that systemstack leaves at the bottom 155// of the G stack. We need to distinguish the routine that 156// lives at the bottom of the G stack from the one that lives 157// at the top of the system stack because the one at the top of 158// the system stack terminates the stack walk (see topofstack()). 159TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0 160 UNDEF 161 JAL (R31) // make sure this function is not leaf 162 RET 163 164// func systemstack(fn func()) 165TEXT runtime·systemstack(SB),NOSPLIT,$0-4 166 MOVW fn+0(FP), R1 // R1 = fn 167 MOVW R1, REGCTXT // context 168 MOVW g_m(g), R2 // R2 = m 169 170 MOVW m_gsignal(R2), R3 // R3 = gsignal 171 BEQ g, R3, noswitch 172 173 MOVW m_g0(R2), R3 // R3 = g0 174 BEQ g, R3, noswitch 175 176 MOVW m_curg(R2), R4 177 BEQ g, R4, switch 178 179 // Bad: g is not gsignal, not g0, not curg. What is it? 180 // Hide call from linker nosplit analysis. 181 MOVW $runtime·badsystemstack(SB), R4 182 JAL (R4) 183 JAL runtime·abort(SB) 184 185switch: 186 // save our state in g->sched. Pretend to 187 // be systemstack_switch if the G stack is scanned. 188 MOVW $runtime·systemstack_switch(SB), R4 189 ADDU $8, R4 // get past prologue 190 MOVW R4, (g_sched+gobuf_pc)(g) 191 MOVW R29, (g_sched+gobuf_sp)(g) 192 MOVW R0, (g_sched+gobuf_lr)(g) 193 MOVW g, (g_sched+gobuf_g)(g) 194 195 // switch to g0 196 MOVW R3, g 197 JAL runtime·save_g(SB) 198 MOVW (g_sched+gobuf_sp)(g), R1 199 // make it look like mstart called systemstack on g0, to stop traceback 200 ADDU $-4, R1 201 MOVW $runtime·mstart(SB), R2 202 MOVW R2, 0(R1) 203 MOVW R1, R29 204 205 // call target function 206 MOVW 0(REGCTXT), R4 // code pointer 207 JAL (R4) 208 209 // switch back to g 210 MOVW g_m(g), R1 211 MOVW m_curg(R1), g 212 JAL runtime·save_g(SB) 213 MOVW (g_sched+gobuf_sp)(g), R29 214 MOVW R0, (g_sched+gobuf_sp)(g) 215 RET 216 217noswitch: 218 // already on m stack, just call directly 219 // Using a tail call here cleans up tracebacks since we won't stop 220 // at an intermediate systemstack. 221 MOVW 0(REGCTXT), R4 // code pointer 222 MOVW 0(R29), R31 // restore LR 223 ADD $4, R29 224 JMP (R4) 225 226/* 227 * support for morestack 228 */ 229 230// Called during function prolog when more stack is needed. 231// Caller has already loaded: 232// R1: framesize, R2: argsize, R3: LR 233// 234// The traceback routines see morestack on a g0 as being 235// the top of a stack (for example, morestack calling newstack 236// calling the scheduler calling newm calling gc), so we must 237// record an argument size. For that purpose, it has no arguments. 238TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 239 // Cannot grow scheduler stack (m->g0). 240 MOVW g_m(g), R7 241 MOVW m_g0(R7), R8 242 BNE g, R8, 3(PC) 243 JAL runtime·badmorestackg0(SB) 244 JAL runtime·abort(SB) 245 246 // Cannot grow signal stack (m->gsignal). 247 MOVW m_gsignal(R7), R8 248 BNE g, R8, 3(PC) 249 JAL runtime·badmorestackgsignal(SB) 250 JAL runtime·abort(SB) 251 252 // Called from f. 253 // Set g->sched to context in f. 254 MOVW R29, (g_sched+gobuf_sp)(g) 255 MOVW R31, (g_sched+gobuf_pc)(g) 256 MOVW R3, (g_sched+gobuf_lr)(g) 257 MOVW REGCTXT, (g_sched+gobuf_ctxt)(g) 258 259 // Called from f. 260 // Set m->morebuf to f's caller. 261 MOVW R3, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 262 MOVW R29, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 263 MOVW g, (m_morebuf+gobuf_g)(R7) 264 265 // Call newstack on m->g0's stack. 266 MOVW m_g0(R7), g 267 JAL runtime·save_g(SB) 268 MOVW (g_sched+gobuf_sp)(g), R29 269 // Create a stack frame on g0 to call newstack. 270 MOVW R0, -4(R29) // Zero saved LR in frame 271 ADDU $-4, R29 272 JAL runtime·newstack(SB) 273 274 // Not reached, but make sure the return PC from the call to newstack 275 // is still in this function, and not the beginning of the next. 276 UNDEF 277 278TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0 279 MOVW R0, REGCTXT 280 JMP runtime·morestack(SB) 281 282// reflectcall: call a function with the given argument list 283// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 284// we don't have variable-sized frames, so we use a small number 285// of constant-sized-frame functions to encode a few bits of size in the pc. 286 287#define DISPATCH(NAME,MAXSIZE) \ 288 MOVW $MAXSIZE, R23; \ 289 SGTU R1, R23, R23; \ 290 BNE R23, 3(PC); \ 291 MOVW $NAME(SB), R4; \ 292 JMP (R4) 293 294TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-20 295 MOVW argsize+12(FP), R1 296 297 DISPATCH(runtime·call16, 16) 298 DISPATCH(runtime·call32, 32) 299 DISPATCH(runtime·call64, 64) 300 DISPATCH(runtime·call128, 128) 301 DISPATCH(runtime·call256, 256) 302 DISPATCH(runtime·call512, 512) 303 DISPATCH(runtime·call1024, 1024) 304 DISPATCH(runtime·call2048, 2048) 305 DISPATCH(runtime·call4096, 4096) 306 DISPATCH(runtime·call8192, 8192) 307 DISPATCH(runtime·call16384, 16384) 308 DISPATCH(runtime·call32768, 32768) 309 DISPATCH(runtime·call65536, 65536) 310 DISPATCH(runtime·call131072, 131072) 311 DISPATCH(runtime·call262144, 262144) 312 DISPATCH(runtime·call524288, 524288) 313 DISPATCH(runtime·call1048576, 1048576) 314 DISPATCH(runtime·call2097152, 2097152) 315 DISPATCH(runtime·call4194304, 4194304) 316 DISPATCH(runtime·call8388608, 8388608) 317 DISPATCH(runtime·call16777216, 16777216) 318 DISPATCH(runtime·call33554432, 33554432) 319 DISPATCH(runtime·call67108864, 67108864) 320 DISPATCH(runtime·call134217728, 134217728) 321 DISPATCH(runtime·call268435456, 268435456) 322 DISPATCH(runtime·call536870912, 536870912) 323 DISPATCH(runtime·call1073741824, 1073741824) 324 MOVW $runtime·badreflectcall(SB), R4 325 JMP (R4) 326 327#define CALLFN(NAME,MAXSIZE) \ 328TEXT NAME(SB),WRAPPER,$MAXSIZE-20; \ 329 NO_LOCAL_POINTERS; \ 330 /* copy arguments to stack */ \ 331 MOVW arg+8(FP), R1; \ 332 MOVW argsize+12(FP), R2; \ 333 MOVW R29, R3; \ 334 ADDU $4, R3; \ 335 ADDU R3, R2; \ 336 BEQ R3, R2, 6(PC); \ 337 MOVBU (R1), R4; \ 338 ADDU $1, R1; \ 339 MOVBU R4, (R3); \ 340 ADDU $1, R3; \ 341 JMP -5(PC); \ 342 /* call function */ \ 343 MOVW f+4(FP), REGCTXT; \ 344 MOVW (REGCTXT), R4; \ 345 PCDATA $PCDATA_StackMapIndex, $0; \ 346 JAL (R4); \ 347 /* copy return values back */ \ 348 MOVW argtype+0(FP), R5; \ 349 MOVW arg+8(FP), R1; \ 350 MOVW n+12(FP), R2; \ 351 MOVW retoffset+16(FP), R4; \ 352 ADDU $4, R29, R3; \ 353 ADDU R4, R3; \ 354 ADDU R4, R1; \ 355 SUBU R4, R2; \ 356 JAL callRet<>(SB); \ 357 RET 358 359// callRet copies return values back at the end of call*. This is a 360// separate function so it can allocate stack space for the arguments 361// to reflectcallmove. It does not follow the Go ABI; it expects its 362// arguments in registers. 363TEXT callRet<>(SB), NOSPLIT, $16-0 364 MOVW R5, 4(R29) 365 MOVW R1, 8(R29) 366 MOVW R3, 12(R29) 367 MOVW R2, 16(R29) 368 JAL runtime·reflectcallmove(SB) 369 RET 370 371CALLFN(·call16, 16) 372CALLFN(·call32, 32) 373CALLFN(·call64, 64) 374CALLFN(·call128, 128) 375CALLFN(·call256, 256) 376CALLFN(·call512, 512) 377CALLFN(·call1024, 1024) 378CALLFN(·call2048, 2048) 379CALLFN(·call4096, 4096) 380CALLFN(·call8192, 8192) 381CALLFN(·call16384, 16384) 382CALLFN(·call32768, 32768) 383CALLFN(·call65536, 65536) 384CALLFN(·call131072, 131072) 385CALLFN(·call262144, 262144) 386CALLFN(·call524288, 524288) 387CALLFN(·call1048576, 1048576) 388CALLFN(·call2097152, 2097152) 389CALLFN(·call4194304, 4194304) 390CALLFN(·call8388608, 8388608) 391CALLFN(·call16777216, 16777216) 392CALLFN(·call33554432, 33554432) 393CALLFN(·call67108864, 67108864) 394CALLFN(·call134217728, 134217728) 395CALLFN(·call268435456, 268435456) 396CALLFN(·call536870912, 536870912) 397CALLFN(·call1073741824, 1073741824) 398 399TEXT runtime·procyield(SB),NOSPLIT,$0-4 400 RET 401 402// void jmpdefer(fv, sp); 403// called from deferreturn. 404// 1. grab stored LR for caller 405// 2. sub 8 bytes to get back to JAL deferreturn 406// 3. JMP to fn 407TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 408 MOVW 0(R29), R31 409 ADDU $-8, R31 410 411 MOVW fv+0(FP), REGCTXT 412 MOVW argp+4(FP), R29 413 ADDU $-4, R29 414 NOR R0, R0 // prevent scheduling 415 MOVW 0(REGCTXT), R4 416 JMP (R4) 417 418// Save state of caller into g->sched. Smashes R1. 419TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0 420 MOVW R31, (g_sched+gobuf_pc)(g) 421 MOVW R29, (g_sched+gobuf_sp)(g) 422 MOVW R0, (g_sched+gobuf_lr)(g) 423 MOVW R0, (g_sched+gobuf_ret)(g) 424 // Assert ctxt is zero. See func save. 425 MOVW (g_sched+gobuf_ctxt)(g), R1 426 BEQ R1, 2(PC) 427 JAL runtime·badctxt(SB) 428 RET 429 430// func asmcgocall(fn, arg unsafe.Pointer) int32 431// Call fn(arg) on the scheduler stack, 432// aligned appropriately for the gcc ABI. 433// See cgocall.go for more details. 434TEXT ·asmcgocall(SB),NOSPLIT,$0-12 435 MOVW fn+0(FP), R25 436 MOVW arg+4(FP), R4 437 438 MOVW R29, R3 // save original stack pointer 439 MOVW g, R2 440 441 // Figure out if we need to switch to m->g0 stack. 442 // We get called to create new OS threads too, and those 443 // come in on the m->g0 stack already. 444 MOVW g_m(g), R5 445 MOVW m_g0(R5), R6 446 BEQ R6, g, g0 447 448 JAL gosave<>(SB) 449 MOVW R6, g 450 JAL runtime·save_g(SB) 451 MOVW (g_sched+gobuf_sp)(g), R29 452 453 // Now on a scheduling stack (a pthread-created stack). 454g0: 455 // Save room for two of our pointers and O32 frame. 456 ADDU $-24, R29 457 AND $~7, R29 // O32 ABI expects 8-byte aligned stack on function entry 458 MOVW R2, 16(R29) // save old g on stack 459 MOVW (g_stack+stack_hi)(R2), R2 460 SUBU R3, R2 461 MOVW R2, 20(R29) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 462 JAL (R25) 463 464 // Restore g, stack pointer. R2 is return value. 465 MOVW 16(R29), g 466 JAL runtime·save_g(SB) 467 MOVW (g_stack+stack_hi)(g), R5 468 MOVW 20(R29), R6 469 SUBU R6, R5 470 MOVW R5, R29 471 472 MOVW R2, ret+8(FP) 473 RET 474 475// cgocallback(void (*fn)(void*), void *frame, uintptr framesize) 476// Turn the fn into a Go func (by taking its address) and call 477// cgocallback_gofunc. 478TEXT runtime·cgocallback(SB),NOSPLIT,$16-16 479 MOVW $fn+0(FP), R1 480 MOVW R1, 4(R29) 481 MOVW frame+4(FP), R1 482 MOVW R1, 8(R29) 483 MOVW framesize+8(FP), R1 484 MOVW R1, 12(R29) 485 MOVW ctxt+12(FP), R1 486 MOVW R1, 16(R29) 487 MOVW $runtime·cgocallback_gofunc(SB), R1 488 JAL (R1) 489 RET 490 491// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) 492// See cgocall.go for more details. 493TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16 494 NO_LOCAL_POINTERS 495 496 // Load m and g from thread-local storage. 497 MOVB runtime·iscgo(SB), R1 498 BEQ R1, nocgo 499 JAL runtime·load_g(SB) 500nocgo: 501 502 // If g is nil, Go did not create the current thread. 503 // Call needm to obtain one for temporary use. 504 // In this case, we're running on the thread stack, so there's 505 // lots of space, but the linker doesn't know. Hide the call from 506 // the linker analysis by using an indirect call. 507 BEQ g, needm 508 509 MOVW g_m(g), R3 510 MOVW R3, savedm-4(SP) 511 JMP havem 512 513needm: 514 MOVW g, savedm-4(SP) // g is zero, so is m. 515 MOVW $runtime·needm(SB), R4 516 JAL (R4) 517 518 // Set m->sched.sp = SP, so that if a panic happens 519 // during the function we are about to execute, it will 520 // have a valid SP to run on the g0 stack. 521 // The next few lines (after the havem label) 522 // will save this SP onto the stack and then write 523 // the same SP back to m->sched.sp. That seems redundant, 524 // but if an unrecovered panic happens, unwindm will 525 // restore the g->sched.sp from the stack location 526 // and then systemstack will try to use it. If we don't set it here, 527 // that restored SP will be uninitialized (typically 0) and 528 // will not be usable. 529 MOVW g_m(g), R3 530 MOVW m_g0(R3), R1 531 MOVW R29, (g_sched+gobuf_sp)(R1) 532 533havem: 534 // Now there's a valid m, and we're running on its m->g0. 535 // Save current m->g0->sched.sp on stack and then set it to SP. 536 // Save current sp in m->g0->sched.sp in preparation for 537 // switch back to m->curg stack. 538 // NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP). 539 MOVW m_g0(R3), R1 540 MOVW (g_sched+gobuf_sp)(R1), R2 541 MOVW R2, savedsp-8(SP) 542 MOVW R29, (g_sched+gobuf_sp)(R1) 543 544 // Switch to m->curg stack and call runtime.cgocallbackg. 545 // Because we are taking over the execution of m->curg 546 // but *not* resuming what had been running, we need to 547 // save that information (m->curg->sched) so we can restore it. 548 // We can restore m->curg->sched.sp easily, because calling 549 // runtime.cgocallbackg leaves SP unchanged upon return. 550 // To save m->curg->sched.pc, we push it onto the stack. 551 // This has the added benefit that it looks to the traceback 552 // routine like cgocallbackg is going to return to that 553 // PC (because the frame we allocate below has the same 554 // size as cgocallback_gofunc's frame declared above) 555 // so that the traceback will seamlessly trace back into 556 // the earlier calls. 557 // 558 // In the new goroutine, -4(SP) is unused (where SP refers to 559 // m->curg's SP while we're setting it up, before we've adjusted it). 560 MOVW m_curg(R3), g 561 JAL runtime·save_g(SB) 562 MOVW (g_sched+gobuf_sp)(g), R2 // prepare stack as R2 563 MOVW (g_sched+gobuf_pc)(g), R4 564 MOVW R4, -12(R2) 565 MOVW ctxt+12(FP), R1 566 MOVW R1, -8(R2) 567 MOVW $-12(R2), R29 568 JAL runtime·cgocallbackg(SB) 569 570 // Restore g->sched (== m->curg->sched) from saved values. 571 MOVW 0(R29), R4 572 MOVW R4, (g_sched+gobuf_pc)(g) 573 MOVW $12(R29), R2 574 MOVW R2, (g_sched+gobuf_sp)(g) 575 576 // Switch back to m->g0's stack and restore m->g0->sched.sp. 577 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 578 // so we do not have to restore it.) 579 MOVW g_m(g), R3 580 MOVW m_g0(R3), g 581 JAL runtime·save_g(SB) 582 MOVW (g_sched+gobuf_sp)(g), R29 583 MOVW savedsp-8(SP), R2 584 MOVW R2, (g_sched+gobuf_sp)(g) 585 586 // If the m on entry was nil, we called needm above to borrow an m 587 // for the duration of the call. Since the call is over, return it with dropm. 588 MOVW savedm-4(SP), R3 589 BNE R3, droppedm 590 MOVW $runtime·dropm(SB), R4 591 JAL (R4) 592droppedm: 593 594 // Done! 595 RET 596 597// void setg(G*); set g. for use by needm. 598// This only happens if iscgo, so jump straight to save_g 599TEXT runtime·setg(SB),NOSPLIT,$0-4 600 MOVW gg+0(FP), g 601 JAL runtime·save_g(SB) 602 RET 603 604// void setg_gcc(G*); set g in C TLS. 605// Must obey the gcc calling convention. 606TEXT setg_gcc<>(SB),NOSPLIT,$0 607 MOVW R4, g 608 JAL runtime·save_g(SB) 609 RET 610 611TEXT runtime·abort(SB),NOSPLIT,$0-0 612 UNDEF 613 614// AES hashing not implemented for mips 615TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-16 616 JMP runtime·memhashFallback(SB) 617TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-12 618 JMP runtime·strhashFallback(SB) 619TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-12 620 JMP runtime·memhash32Fallback(SB) 621TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-12 622 JMP runtime·memhash64Fallback(SB) 623 624TEXT runtime·return0(SB),NOSPLIT,$0 625 MOVW $0, R1 626 RET 627 628// Called from cgo wrappers, this function returns g->m->curg.stack.hi. 629// Must obey the gcc calling convention. 630TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 631 // g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23 632 // are callee-save in the gcc calling convention, so save them. 633 MOVW R23, R8 634 MOVW g, R9 635 MOVW R31, R10 // this call frame does not save LR 636 637 JAL runtime·load_g(SB) 638 MOVW g_m(g), R1 639 MOVW m_curg(R1), R1 640 MOVW (g_stack+stack_hi)(R1), R2 // return value in R2 641 642 MOVW R8, R23 643 MOVW R9, g 644 MOVW R10, R31 645 646 RET 647 648// The top-most function running on a goroutine 649// returns to goexit+PCQuantum. 650TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 651 NOR R0, R0 // NOP 652 JAL runtime·goexit1(SB) // does not return 653 // traceback from goexit1 must hit code range of goexit 654 NOR R0, R0 // NOP 655 656TEXT ·checkASM(SB),NOSPLIT,$0-1 657 MOVW $1, R1 658 MOVB R1, ret+0(FP) 659 RET 660 661// gcWriteBarrier performs a heap pointer write and informs the GC. 662// 663// gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: 664// - R20 is the destination of the write 665// - R21 is the value being written at R20. 666// It clobbers R23 (the linker temp register). 667// The act of CALLing gcWriteBarrier will clobber R31 (LR). 668// It does not clobber any other general-purpose registers, 669// but may clobber others (e.g., floating point registers). 670TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104 671 // Save the registers clobbered by the fast path. 672 MOVW R1, 100(R29) 673 MOVW R2, 104(R29) 674 MOVW g_m(g), R1 675 MOVW m_p(R1), R1 676 MOVW (p_wbBuf+wbBuf_next)(R1), R2 677 // Increment wbBuf.next position. 678 ADD $8, R2 679 MOVW R2, (p_wbBuf+wbBuf_next)(R1) 680 MOVW (p_wbBuf+wbBuf_end)(R1), R1 681 MOVW R1, R23 // R23 is linker temp register 682 // Record the write. 683 MOVW R21, -8(R2) // Record value 684 MOVW (R20), R1 // TODO: This turns bad writes into bad reads. 685 MOVW R1, -4(R2) // Record *slot 686 // Is the buffer full? 687 BEQ R2, R23, flush 688ret: 689 MOVW 100(R29), R1 690 MOVW 104(R29), R2 691 // Do the write. 692 MOVW R21, (R20) 693 RET 694 695flush: 696 // Save all general purpose registers since these could be 697 // clobbered by wbBufFlush and were not saved by the caller. 698 MOVW R20, 4(R29) // Also first argument to wbBufFlush 699 MOVW R21, 8(R29) // Also second argument to wbBufFlush 700 // R1 already saved 701 // R2 already saved 702 MOVW R3, 12(R29) 703 MOVW R4, 16(R29) 704 MOVW R5, 20(R29) 705 MOVW R6, 24(R29) 706 MOVW R7, 28(R29) 707 MOVW R8, 32(R29) 708 MOVW R9, 36(R29) 709 MOVW R10, 40(R29) 710 MOVW R11, 44(R29) 711 MOVW R12, 48(R29) 712 MOVW R13, 52(R29) 713 MOVW R14, 56(R29) 714 MOVW R15, 60(R29) 715 MOVW R16, 64(R29) 716 MOVW R17, 68(R29) 717 MOVW R18, 72(R29) 718 MOVW R19, 76(R29) 719 MOVW R20, 80(R29) 720 // R21 already saved 721 // R22 already saved. 722 MOVW R22, 84(R29) 723 // R23 is tmp register. 724 MOVW R24, 88(R29) 725 MOVW R25, 92(R29) 726 // R26 is reserved by kernel. 727 // R27 is reserved by kernel. 728 MOVW R28, 96(R29) 729 // R29 is SP. 730 // R30 is g. 731 // R31 is LR, which was saved by the prologue. 732 733 // This takes arguments R20 and R21. 734 CALL runtime·wbBufFlush(SB) 735 736 MOVW 4(R29), R20 737 MOVW 8(R29), R21 738 MOVW 12(R29), R3 739 MOVW 16(R29), R4 740 MOVW 20(R29), R5 741 MOVW 24(R29), R6 742 MOVW 28(R29), R7 743 MOVW 32(R29), R8 744 MOVW 36(R29), R9 745 MOVW 40(R29), R10 746 MOVW 44(R29), R11 747 MOVW 48(R29), R12 748 MOVW 52(R29), R13 749 MOVW 56(R29), R14 750 MOVW 60(R29), R15 751 MOVW 64(R29), R16 752 MOVW 68(R29), R17 753 MOVW 72(R29), R18 754 MOVW 76(R29), R19 755 MOVW 80(R29), R20 756 MOVW 84(R29), R22 757 MOVW 88(R29), R24 758 MOVW 92(R29), R25 759 MOVW 96(R29), R28 760 JMP ret 761 762// Note: these functions use a special calling convention to save generated code space. 763// Arguments are passed in registers, but the space for those arguments are allocated 764// in the caller's stack frame. These stubs write the args into that stack space and 765// then tail call to the corresponding runtime handler. 766// The tail call makes these stubs disappear in backtraces. 767TEXT runtime·panicIndex(SB),NOSPLIT,$0-8 768 MOVW R1, x+0(FP) 769 MOVW R2, y+4(FP) 770 JMP runtime·goPanicIndex(SB) 771TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8 772 MOVW R1, x+0(FP) 773 MOVW R2, y+4(FP) 774 JMP runtime·goPanicIndexU(SB) 775TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8 776 MOVW R2, x+0(FP) 777 MOVW R3, y+4(FP) 778 JMP runtime·goPanicSliceAlen(SB) 779TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8 780 MOVW R2, x+0(FP) 781 MOVW R3, y+4(FP) 782 JMP runtime·goPanicSliceAlenU(SB) 783TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8 784 MOVW R2, x+0(FP) 785 MOVW R3, y+4(FP) 786 JMP runtime·goPanicSliceAcap(SB) 787TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8 788 MOVW R2, x+0(FP) 789 MOVW R3, y+4(FP) 790 JMP runtime·goPanicSliceAcapU(SB) 791TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8 792 MOVW R1, x+0(FP) 793 MOVW R2, y+4(FP) 794 JMP runtime·goPanicSliceB(SB) 795TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8 796 MOVW R1, x+0(FP) 797 MOVW R2, y+4(FP) 798 JMP runtime·goPanicSliceBU(SB) 799TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8 800 MOVW R3, x+0(FP) 801 MOVW R4, y+4(FP) 802 JMP runtime·goPanicSlice3Alen(SB) 803TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8 804 MOVW R3, x+0(FP) 805 MOVW R4, y+4(FP) 806 JMP runtime·goPanicSlice3AlenU(SB) 807TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8 808 MOVW R3, x+0(FP) 809 MOVW R4, y+4(FP) 810 JMP runtime·goPanicSlice3Acap(SB) 811TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8 812 MOVW R3, x+0(FP) 813 MOVW R4, y+4(FP) 814 JMP runtime·goPanicSlice3AcapU(SB) 815TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8 816 MOVW R2, x+0(FP) 817 MOVW R3, y+4(FP) 818 JMP runtime·goPanicSlice3B(SB) 819TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8 820 MOVW R2, x+0(FP) 821 MOVW R3, y+4(FP) 822 JMP runtime·goPanicSlice3BU(SB) 823TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8 824 MOVW R1, x+0(FP) 825 MOVW R2, y+4(FP) 826 JMP runtime·goPanicSlice3C(SB) 827TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8 828 MOVW R1, x+0(FP) 829 MOVW R2, y+4(FP) 830 JMP runtime·goPanicSlice3CU(SB) 831 832// Extended versions for 64-bit indexes. 833TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 834 MOVW R5, hi+0(FP) 835 MOVW R1, lo+4(FP) 836 MOVW R2, y+8(FP) 837 JMP runtime·goPanicExtendIndex(SB) 838TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12 839 MOVW R5, hi+0(FP) 840 MOVW R1, lo+4(FP) 841 MOVW R2, y+8(FP) 842 JMP runtime·goPanicExtendIndexU(SB) 843TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12 844 MOVW R5, hi+0(FP) 845 MOVW R2, lo+4(FP) 846 MOVW R3, y+8(FP) 847 JMP runtime·goPanicExtendSliceAlen(SB) 848TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12 849 MOVW R5, hi+0(FP) 850 MOVW R2, lo+4(FP) 851 MOVW R3, y+8(FP) 852 JMP runtime·goPanicExtendSliceAlenU(SB) 853TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12 854 MOVW R5, hi+0(FP) 855 MOVW R2, lo+4(FP) 856 MOVW R3, y+8(FP) 857 JMP runtime·goPanicExtendSliceAcap(SB) 858TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12 859 MOVW R5, hi+0(FP) 860 MOVW R2, lo+4(FP) 861 MOVW R3, y+8(FP) 862 JMP runtime·goPanicExtendSliceAcapU(SB) 863TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12 864 MOVW R5, hi+0(FP) 865 MOVW R1, lo+4(FP) 866 MOVW R2, y+8(FP) 867 JMP runtime·goPanicExtendSliceB(SB) 868TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12 869 MOVW R5, hi+0(FP) 870 MOVW R1, lo+4(FP) 871 MOVW R2, y+8(FP) 872 JMP runtime·goPanicExtendSliceBU(SB) 873TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12 874 MOVW R5, hi+0(FP) 875 MOVW R3, lo+4(FP) 876 MOVW R4, y+8(FP) 877 JMP runtime·goPanicExtendSlice3Alen(SB) 878TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12 879 MOVW R5, hi+0(FP) 880 MOVW R3, lo+4(FP) 881 MOVW R4, y+8(FP) 882 JMP runtime·goPanicExtendSlice3AlenU(SB) 883TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12 884 MOVW R5, hi+0(FP) 885 MOVW R3, lo+4(FP) 886 MOVW R4, y+8(FP) 887 JMP runtime·goPanicExtendSlice3Acap(SB) 888TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12 889 MOVW R5, hi+0(FP) 890 MOVW R3, lo+4(FP) 891 MOVW R4, y+8(FP) 892 JMP runtime·goPanicExtendSlice3AcapU(SB) 893TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12 894 MOVW R5, hi+0(FP) 895 MOVW R2, lo+4(FP) 896 MOVW R3, y+8(FP) 897 JMP runtime·goPanicExtendSlice3B(SB) 898TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12 899 MOVW R5, hi+0(FP) 900 MOVW R2, lo+4(FP) 901 MOVW R3, y+8(FP) 902 JMP runtime·goPanicExtendSlice3BU(SB) 903TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12 904 MOVW R5, hi+0(FP) 905 MOVW R1, lo+4(FP) 906 MOVW R2, y+8(FP) 907 JMP runtime·goPanicExtendSlice3C(SB) 908TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12 909 MOVW R5, hi+0(FP) 910 MOVW R1, lo+4(FP) 911 MOVW R2, y+8(FP) 912 JMP runtime·goPanicExtendSlice3CU(SB) 913