#include "label.h" #include typedef unsigned long ulong; /* * return stack location guaranteed to have args for f in it */ unsigned long * argbase(Label f) { f = upframe(upframe(f)); return (ulong *)f.sp; } /* * adjust label to reflect a moved stack location */ Label movelabel(Label f, ulong sp) { f.sp = sp; return f; } /* * return the top of main's stack * main => _main => __task__init => setlabel(m) */ ulong * stackbase(Label m) { return (ulong *)upframe(upframe(upframe(m))).sp; } #define MASKI 0xffffe000 /* mask SUBI reg bits in instruction */ #define MASKHI 0xfffc0000 /* mask SETHI reg bits in instruction */ #define SUBTSP 0x8220400e /* SUB R14, R1; for large stack frames */ #define SUBISP 0x82206000 /* SUBI const, R1 */ #define SETHI 0x1d000000 /* load hi part of R14 with constant << 10 */ #define ADDI 0x9c03a000 /* add low part to R14 */ #include /* * find the label for the frame calling f */ Label upframe(Label f) { ulong *pc; long offset; /* look for MOV R14,R1 or ADDIU const,R1 */ for(pc = (ulong *)f.pc; (*pc & MASKI) != SUBISP; pc--) if(*pc == SUBTSP){ /* look for sethi & optional add low into R14 */ offset = 0; while((*--pc & MASKHI) != SETHI) if((*pc & MASKI) == ADDI){ offset = *pc &~ MASKI; if(offset & 0x1000) offset |= MASKI; } offset += (*pc &~ MASKHI) << 10; break; } /* get the constant */ if((*pc & MASKI) == SUBISP){ offset = *pc &~ MASKI; /* sign extend */ if (offset & 0x1000) offset |= MASKI; } /* return pc = 0(R1) */ f.pc = *(ulong *)f.sp; f.sp += offset; return f; }