forked from Github_Repos/cvw
		
	Updated trap handler to check interrupt vectoring before handling them and to use the mscratch instead of sp for a stack.
This commit is contained in:
		
							parent
							
								
									3268f27f7a
								
							
						
					
					
						commit
						590b86147b
					
				@ -41,7 +41,7 @@ RVTEST_CODE_BEGIN
 | 
			
		||||
    //   
 | 
			
		||||
    //   Initialize x6 as a virtual pointer to the test results
 | 
			
		||||
    //   Initialize x16 as a physical pointer to the test results
 | 
			
		||||
    //   Set up stack pointer (sp = x2)
 | 
			
		||||
    //   Set up stack pointer, mscratch, sscratch
 | 
			
		||||
    //   
 | 
			
		||||
	// ---------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -50,8 +50,12 @@ RVTEST_CODE_BEGIN
 | 
			
		||||
    la x16, test_1_res // x16 reserved for the physical address equivalent of x6 to be used in trap handlers
 | 
			
		||||
                        // any time either is used, both must be updated.
 | 
			
		||||
 | 
			
		||||
    // address for stack
 | 
			
		||||
    la sp, top_of_stack
 | 
			
		||||
    // address for normal user stack, mscratch stack, and sscratch stack
 | 
			
		||||
    la sp, mscratch_top
 | 
			
		||||
    csrw mscratch, sp
 | 
			
		||||
    la sp, sscratch_top
 | 
			
		||||
    csrw sscratch, sp
 | 
			
		||||
    la sp, stack_top
 | 
			
		||||
 | 
			
		||||
.endm
 | 
			
		||||
 | 
			
		||||
@ -72,7 +76,7 @@ cause_instr_addr_misaligned:
 | 
			
		||||
 | 
			
		||||
cause_instr_access:
 | 
			
		||||
    la x28, 0x0 // address zero is an address with no memory
 | 
			
		||||
    sd x1, -8(sp) // push the return adress ontot the stack
 | 
			
		||||
    sd x1, -8(sp) // push the return adress onto the stack
 | 
			
		||||
    addi sp, sp, -8
 | 
			
		||||
    jalr x28 // cause instruction access trap
 | 
			
		||||
    ld x1, 0(sp) // pop return adress back from the stack
 | 
			
		||||
@ -83,7 +87,7 @@ cause_illegal_instr:
 | 
			
		||||
    .word 0x00000000 // a 32 bit zros is an illegal instruction
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
cause_breakpnt: // ****
 | 
			
		||||
cause_breakpnt:
 | 
			
		||||
    ebreak
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
@ -128,7 +132,9 @@ cause_time_interrupt:
 | 
			
		||||
    sw x31,4(x29)          // store into most significant word of MTIMECMP
 | 
			
		||||
nowrap:
 | 
			
		||||
    sw x28, 0(x29)         // store into least significant word of MTIMECMP
 | 
			
		||||
    loop: j loop         // wait until interrupt occurs
 | 
			
		||||
loop:
 | 
			
		||||
    wfi 
 | 
			
		||||
    j loop         // wait until interrupt occurs
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
cause_soft_interrupt:
 | 
			
		||||
@ -150,7 +156,7 @@ end_trap_triggers:
 | 
			
		||||
 | 
			
		||||
.macro TRAP_HANDLER MODE, VECTORED=1, DEBUG=0
 | 
			
		||||
    // MODE decides which mode this trap handler will be taken in (M or S mode)
 | 
			
		||||
    // Vectored decides whether interrumpts are handled with the vector table at trap_handler_MODE (1)
 | 
			
		||||
    // Vectored decides whether interrupts are handled with the vector table at trap_handler_MODE (1)
 | 
			
		||||
    //      vs Using the non-vector approach the rest of the trap handler takes (0)
 | 
			
		||||
    // DEBUG decides whether we will print mtval a string with status.mpie, status.mie, and status.mpp to the signature (1)
 | 
			
		||||
    //      vs not saving that info to the signature (0)
 | 
			
		||||
@ -216,23 +222,28 @@ trap_handler_\MODE\():
 | 
			
		||||
    // *** ASSUMES that a cause value of 0 for an interrupt is unimplemented
 | 
			
		||||
    // otherwise, a vectored interrupt handler should jump to trap_handler_\MODE\() + 4 * Interrupt cause code
 | 
			
		||||
    // No matter the value of VECTORED, exceptions (not interrupts) are handled in an unvecotred way
 | 
			
		||||
    j soft_interrupt_\MODE\()    // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
 | 
			
		||||
    j s_soft_vector_\MODE\()    // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
 | 
			
		||||
    j segfault_\MODE\()            // 2: reserved
 | 
			
		||||
    j soft_interrupt_\MODE\()    // 3: breakpoint
 | 
			
		||||
    j m_soft_vector_\MODE\()    // 3: breakpoint
 | 
			
		||||
    j segfault_\MODE\()            // 4: reserved
 | 
			
		||||
    j time_interrupt_\MODE\()    // 5: load access fault
 | 
			
		||||
    j s_time_vector_\MODE\()    // 5: load access fault
 | 
			
		||||
    j segfault_\MODE\()            // 6: reserved
 | 
			
		||||
    j time_interrupt_\MODE\()    // 7: store access fault
 | 
			
		||||
    j m_time_vector_\MODE\()    // 7: store access fault
 | 
			
		||||
    j segfault_\MODE\()            // 8: reserved
 | 
			
		||||
    j ext_interrupt_\MODE\()     // 9: ecall from S-mode
 | 
			
		||||
    j s_ext_vector_\MODE\()     // 9: ecall from S-mode
 | 
			
		||||
    j segfault_\MODE\()            // 10: reserved
 | 
			
		||||
    j ext_interrupt_\MODE\()     // 11: ecall from M-mode
 | 
			
		||||
    j m_ext_vector_\MODE\()     // 11: ecall from M-mode
 | 
			
		||||
    // 12 through >=16 are reserved or designated for platform use
 | 
			
		||||
 | 
			
		||||
trap_unvectored_\MODE\():
 | 
			
		||||
    csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
 | 
			
		||||
    // *** NOTE: this means that nested traps will be screwed up but they shouldn't happen in any of these tests
 | 
			
		||||
 | 
			
		||||
trap_stack_saved_\MODE\(): // jump here after handling vectored interupt since we already switch sp and scratch there
 | 
			
		||||
    // save registers on stack before using
 | 
			
		||||
    sd x1, -8(sp)       
 | 
			
		||||
    sd x5, -16(sp)
 | 
			
		||||
    sd x7, -24(sp) 
 | 
			
		||||
 | 
			
		||||
    // Record trap
 | 
			
		||||
    csrr x1, \MODE\()cause     // record the mcause
 | 
			
		||||
@ -262,49 +273,35 @@ trap_unvectored_\MODE\():
 | 
			
		||||
    // Respond to trap based on cause
 | 
			
		||||
    // All interrupts should return after being logged
 | 
			
		||||
    csrr x1, \MODE\()cause
 | 
			
		||||
    slli x1, x1, 3          // multiply cause by 8 to get offset in vector Table
 | 
			
		||||
    li x5, 0x8000000000000000   // if msb is set, it is an interrupt
 | 
			
		||||
    and x5, x5, x1
 | 
			
		||||
    bnez x5, trapreturn_\MODE\()   // return from interrupt
 | 
			
		||||
    bnez x5, interrupt_handler_\MODE\()  // return from interrupt
 | 
			
		||||
    // Other trap handling is specified in the vector Table
 | 
			
		||||
    slli x1, x1, 3      // multiply cause by 8 to get offset in vector Table
 | 
			
		||||
    la x5, exception_vector_table_\MODE\()
 | 
			
		||||
    add x5, x5, x1      // compute address of vector in Table
 | 
			
		||||
    ld x5, 0(x5)        // fectch address of handler from vector Table
 | 
			
		||||
    jr x5               // and jump to the handler
 | 
			
		||||
 | 
			
		||||
interrupt_handler_\MODE\():
 | 
			
		||||
    la x5, interrupt_vector_table_\MODE\() // NOTE THIS IS NOT THE SAME AS VECTORED INTERRUPTS!!!
 | 
			
		||||
    add x5, x5, x1      // compute address of vector in Table
 | 
			
		||||
    ld x5, 0(x5)        // fectch address of handler from vector Table
 | 
			
		||||
    jr x5               // and jump to the handler
 | 
			
		||||
 | 
			
		||||
segfault_\MODE\():
 | 
			
		||||
    ld x5, -16(sp)      // restore registers from stack before faulting
 | 
			
		||||
    sd x7, -24(sp)  // restore registers from stack before faulting 
 | 
			
		||||
    ld x5, -16(sp)
 | 
			
		||||
    ld x1, -8(sp)       
 | 
			
		||||
    j terminate_test          // halt program.
 | 
			
		||||
 | 
			
		||||
trapreturn_\MODE\():
 | 
			
		||||
    // look at the instruction to figure out whether to add 2 or 4 bytes to PC, or go to address specified in a1
 | 
			
		||||
    csrr x1, \MODE\()epc       // get the mepc
 | 
			
		||||
    addi x1, x1, 4 // *** should be 2 for compressed instructions, see note.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ****** KMG: the following is no longer as easy to determine. mepc gets the virtual address of the trapped instruction, 
 | 
			
		||||
// ********     but in the handler, we work in M mode with physical addresses
 | 
			
		||||
//              This means the address in mepc is suddenly pointing somewhere else.
 | 
			
		||||
//              to get this to work, We could either retranslate the vaddr back into a paddr (probably on the scale of difficult to intractible)
 | 
			
		||||
//              or we could come up with some other ingenious way to stay in M mode and see if the instruction was compressed.
 | 
			
		||||
 | 
			
		||||
//     lw x5, 0(x1)        // read the faulting instruction
 | 
			
		||||
//     li x1, 3            // check bottom 2 bits of instruction to see if compressed
 | 
			
		||||
//     and x5, x5, x1      // mask the other bits
 | 
			
		||||
//     beq x5, x1, trapreturn_uncompressed_\MODE\()  // if 11, the instruction is return_uncompressed
 | 
			
		||||
 | 
			
		||||
// trapreturn_compressed_\MODE\():
 | 
			
		||||
//     csrr x1, mepc       // get the mepc again
 | 
			
		||||
//     addi x1, x1, 2      // add 2 to find the next instruction
 | 
			
		||||
//     j trapreturn_specified_\MODE\() // and return
 | 
			
		||||
 | 
			
		||||
// trapreturn_uncompressed_\MODE\():
 | 
			
		||||
//      csrr x1, mepc       // get the mepc again    
 | 
			
		||||
//      addi x1, x1, 4      // add 4 to find the next instruction
 | 
			
		||||
    csrr x1, \MODE\()epc
 | 
			
		||||
    addi x1, x1, 4 // return to the address AFTER the trapping instruction
 | 
			
		||||
 | 
			
		||||
trapreturn_specified_\MODE\():
 | 
			
		||||
    // reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
 | 
			
		||||
    // note that we don't need to change x7 since it was a temporary register with no important address in it.
 | 
			
		||||
    // so that when we return to a new virtual address, they're all in the right spot as well.
 | 
			
		||||
 | 
			
		||||
    beqz a1, trapreturn_finished_\MODE\() // either update values, of go to default return address.
 | 
			
		||||
@ -318,13 +315,13 @@ trapreturn_specified_\MODE\():
 | 
			
		||||
    sll x5, x5, a2
 | 
			
		||||
    addi x5, x5, -1 // x5 = mask bits for offset into current pagetype
 | 
			
		||||
 | 
			
		||||
    // reset the top of the stack, x1
 | 
			
		||||
    // reset the top of the stack, which will be put into ra
 | 
			
		||||
    ld x7, -8(sp) 
 | 
			
		||||
    and x7, x5, x7 // x7 = offset for x1
 | 
			
		||||
    add x7, x7, a1 // x7 = new address for x1
 | 
			
		||||
    sd x7, -8(sp)
 | 
			
		||||
 | 
			
		||||
    // reset the second spot in the stack, x5
 | 
			
		||||
    // reset the second spot in the stack, which will be put into x5
 | 
			
		||||
    ld x7, -16(sp)
 | 
			
		||||
    and x7, x5, x7 // x7 = offset for x5
 | 
			
		||||
    add x7, x7, a1 // x7 = new address for x5
 | 
			
		||||
@ -334,7 +331,7 @@ trapreturn_specified_\MODE\():
 | 
			
		||||
    and x7, x5, x6 // x7 = offset for x6
 | 
			
		||||
    add x6, x7, a1 // x6 = new address for the result pointer
 | 
			
		||||
    
 | 
			
		||||
    // set return address, stored temporarily in x1, to the next instruction, but in the new virtual page.
 | 
			
		||||
    // reset x1, which temporarily holds the return address that will be written to mepc.
 | 
			
		||||
    and x1, x5, x1 // x1 = offset for the return address
 | 
			
		||||
    add x1, x1, a1 // x1 = new return address.
 | 
			
		||||
 | 
			
		||||
@ -342,10 +339,10 @@ trapreturn_specified_\MODE\():
 | 
			
		||||
    li a2, 0 // reset trapreturn inputs to the trap handler
 | 
			
		||||
 | 
			
		||||
trapreturn_finished_\MODE\():
 | 
			
		||||
    csrw \MODE\()epc, x1       // update the epc with address of next instruction
 | 
			
		||||
    ld x5, -16(sp)      // restore registers from stack before returning
 | 
			
		||||
    csrw \MODE\()epc, x1            // update the epc with address of next instruction
 | 
			
		||||
    ld x7, -24(sp)     // restore registers from stack before returning
 | 
			
		||||
    ld x5, -16(sp)
 | 
			
		||||
    ld x1, -8(sp)
 | 
			
		||||
    // *** this should be handled by indirectly clearing this bit csrw \MODE\()ip, 0x0 // clear interrupt pending register to indicate interrupt has been handled
 | 
			
		||||
    \MODE\()ret  // return from trap
 | 
			
		||||
 | 
			
		||||
ecallhandler_\MODE\():
 | 
			
		||||
@ -380,18 +377,17 @@ ecallhandler_changetousermode_\MODE\():
 | 
			
		||||
    j trapreturn_\MODE\()
 | 
			
		||||
 | 
			
		||||
instrpagefault_\MODE\():
 | 
			
		||||
    ld x1, -8(sp) // load return address int x1 (the address AFTER the jal to the faulting address)
 | 
			
		||||
    ld x1, -8(sp) // load return address from stack into ra (the address AFTER the jal to the faulting address)
 | 
			
		||||
    j trapreturn_finished_\MODE\() // puts x1 into mepc, restores stack and returns to program (outside of faulting page)
 | 
			
		||||
 | 
			
		||||
instrfault_\MODE\():
 | 
			
		||||
    ld x1, -8(sp) // load return address int x1 (the address AFTER the jal to the faulting address)
 | 
			
		||||
    j trapreturn_finished_\MODE\() // return to the code after recording the mcause
 | 
			
		||||
    ld x1, -8(sp) // load return address from stack into ra (the address AFTER the jal to the faulting address)
 | 
			
		||||
    j trapreturn_finished_\MODE\() // return to the code at ra value from before trap
 | 
			
		||||
 | 
			
		||||
illegalinstr_\MODE\():
 | 
			
		||||
    j trapreturn_\MODE\() // return to the code after recording the mcause
 | 
			
		||||
 | 
			
		||||
accessfault_\MODE\():
 | 
			
		||||
    // *** What do I have to do here?
 | 
			
		||||
    j trapreturn_\MODE\()
 | 
			
		||||
 | 
			
		||||
addr_misaligned_\MODE\():
 | 
			
		||||
@ -400,36 +396,67 @@ addr_misaligned_\MODE\():
 | 
			
		||||
breakpt_\MODE\():
 | 
			
		||||
    j trapreturn_\MODE\()
 | 
			
		||||
 | 
			
		||||
soft_interrupt_\MODE\():
 | 
			
		||||
    li x5, 0x7EC // write 0x7EC (looks like VEC) to the output before the mcause and extras to indicate that this trap was handled with a vector table. 
 | 
			
		||||
    sd x5, 0(x16)
 | 
			
		||||
s_soft_vector_\MODE\():
 | 
			
		||||
    csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
 | 
			
		||||
    sd x5, -8(sp) // put x5 on the scratch stack before messing with it
 | 
			
		||||
    li x5, 0x7EC01 // write 0x7ec01 (for "VEC"tored and 01 for the interrupt code)
 | 
			
		||||
    j vectored_int_end_\MODE\()
 | 
			
		||||
 | 
			
		||||
m_soft_vector_\MODE\():
 | 
			
		||||
    csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
 | 
			
		||||
    sd x5, -8(sp) // put x5 on the scratch stack before messing with it
 | 
			
		||||
    li x5, 0x7EC03 // write 0x7ec03 (for "VEC"tored and 03 for the interrupt code)
 | 
			
		||||
    j vectored_int_end_\MODE\()
 | 
			
		||||
 | 
			
		||||
s_time_vector_\MODE\():
 | 
			
		||||
    csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
 | 
			
		||||
    sd x5, -8(sp) // put x5 on the scratch stack before messing with it
 | 
			
		||||
    li x5, 0x7EC05 // write 0x7ec05 (for "VEC"tored and 05 for the interrupt code)
 | 
			
		||||
    j vectored_int_end_\MODE\()
 | 
			
		||||
 | 
			
		||||
m_time_vector_\MODE\():
 | 
			
		||||
    csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
 | 
			
		||||
    sd x5, -8(sp) // put x5 on the scratch stack before messing with it
 | 
			
		||||
    li x5, 0x7EC07 // write 0x7ec07 (for "VEC"tored and 07 for the interrupt code)
 | 
			
		||||
    j vectored_int_end_\MODE\()
 | 
			
		||||
 | 
			
		||||
s_ext_vector_\MODE\():
 | 
			
		||||
    csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
 | 
			
		||||
    sd x5, -8(sp) // put x5 on the scratch stack before messing with it
 | 
			
		||||
    li x5, 0x7EC09 // write 0x7ec09 (for "VEC"tored and 08 for the interrupt code)
 | 
			
		||||
    j vectored_int_end_\MODE\()
 | 
			
		||||
 | 
			
		||||
m_ext_vector_\MODE\():
 | 
			
		||||
    csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
 | 
			
		||||
    sd x5, -8(sp) // put x5 on the scratch stack before messing with it
 | 
			
		||||
    li x5, 0x7EC0B // write 0x7ec0B (for "VEC"tored and 0B for the interrupt code)
 | 
			
		||||
    j vectored_int_end_\MODE\()
 | 
			
		||||
 | 
			
		||||
vectored_int_end_\MODE\():
 | 
			
		||||
    sd x5, 0(x16) // store to signature to show vectored interrupts succeeded. 
 | 
			
		||||
    addi x6, x6, 8
 | 
			
		||||
    addi x16, x16, 8
 | 
			
		||||
    ld x5, -8(sp) // restore x5 before continuing to handle trap in case its needed.
 | 
			
		||||
    j trap_stack_saved_\MODE\()
 | 
			
		||||
 | 
			
		||||
soft_interrupt_\MODE\():
 | 
			
		||||
    la x28, 0x02000000 // Reset by clearing MSIP interrupt from CLINT
 | 
			
		||||
    sw x0, 0(x28)
 | 
			
		||||
    j trap_unvectored_\MODE\()
 | 
			
		||||
    j trapreturn_\MODE\()
 | 
			
		||||
 | 
			
		||||
time_interrupt_\MODE\():
 | 
			
		||||
    li x5, 0x7EC
 | 
			
		||||
    sd x5, 0(x16)
 | 
			
		||||
    addi x6, x6, 8
 | 
			
		||||
    addi x16, x16, 8
 | 
			
		||||
 | 
			
		||||
    la x29, 0x02004000    // MTIMECMP register in CLINT
 | 
			
		||||
    li x30, 0xFFFFFFFF
 | 
			
		||||
    sd x30, 0(x29) // reset interrupt by setting mtimecmp to 0xFFFFFFFF
 | 
			
		||||
    
 | 
			
		||||
    j trap_unvectored_\MODE\()
 | 
			
		||||
    ld x1, -8(sp) // load return address from stack into ra (the address AFTER the jal to the faulting address)
 | 
			
		||||
    j trapreturn_finished_\MODE\() // return to the code at ra value from before trap
 | 
			
		||||
 | 
			
		||||
ext_interrupt_\MODE\():
 | 
			
		||||
    li x5, 0x7EC
 | 
			
		||||
    sd x5, 0(x16)
 | 
			
		||||
    addi x6, x6, 8
 | 
			
		||||
    addi x16, x16, 8
 | 
			
		||||
    li x28, 0x10060000 // reset interrupt by clearing all the GPIO bits
 | 
			
		||||
    sw x0, 8(x28) // disable the first pin as an output
 | 
			
		||||
    sw x0, 40(x28) // write a 0 to the first output pin (reset interrupt)
 | 
			
		||||
    j trap_unvectored_\MODE\()
 | 
			
		||||
    j trapreturn_\MODE\()
 | 
			
		||||
 | 
			
		||||
    // Table of trap behavior
 | 
			
		||||
    // lists what to do on each exception (not interrupts)
 | 
			
		||||
@ -455,6 +482,21 @@ exception_vector_table_\MODE\():
 | 
			
		||||
    .8byte segfault_\MODE\()      // 14: reserved
 | 
			
		||||
    .8byte trapreturn_\MODE\()    // 15: store page fault
 | 
			
		||||
 | 
			
		||||
    .align 3 // aligns this data table to an 8 byte boundary
 | 
			
		||||
interrupt_vector_table_\MODE\():
 | 
			
		||||
    .8byte segfault_\MODE\()            // 0: reserved
 | 
			
		||||
    .8byte s_soft_vector_\MODE\()    // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
 | 
			
		||||
    .8byte segfault_\MODE\()            // 2: reserved
 | 
			
		||||
    .8byte m_soft_vector_\MODE\()    // 3: breakpoint
 | 
			
		||||
    .8byte segfault_\MODE\()            // 4: reserved
 | 
			
		||||
    .8byte s_time_vector_\MODE\()    // 5: load access fault
 | 
			
		||||
    .8byte segfault_\MODE\()            // 6: reserved
 | 
			
		||||
    .8byte m_time_vector_\MODE\()    // 7: store access fault
 | 
			
		||||
    .8byte segfault_\MODE\()            // 8: reserved
 | 
			
		||||
    .8byte s_ext_vector_\MODE\()     // 9: ecall from S-mode
 | 
			
		||||
    .8byte segfault_\MODE\()            // 10: reserved
 | 
			
		||||
    .8byte m_ext_vector_\MODE\()     // 11: ecall from M-mode
 | 
			
		||||
 | 
			
		||||
.align 3
 | 
			
		||||
trap_return_pagetype_table_\MODE\():
 | 
			
		||||
    .8byte 0xC  // 0: kilopage has 12 offset bits
 | 
			
		||||
@ -1051,9 +1093,20 @@ rvtest_data:
 | 
			
		||||
RVTEST_DATA_END
 | 
			
		||||
 | 
			
		||||
.align 3 // align stack to 8 byte boundary
 | 
			
		||||
bottom_of_stack:
 | 
			
		||||
stack_bottom:
 | 
			
		||||
    .fill 1024, 4, 0xdeadbeef 
 | 
			
		||||
top_of_stack:
 | 
			
		||||
stack_top:
 | 
			
		||||
 | 
			
		||||
.align 3
 | 
			
		||||
mscratch_bottom:
 | 
			
		||||
    .fill 512, 4, 0xdeadbeef
 | 
			
		||||
mscratch_top:
 | 
			
		||||
 | 
			
		||||
.align 3
 | 
			
		||||
sscratch_bottom:
 | 
			
		||||
    .fill 512, 4, 0xdeadbeef
 | 
			
		||||
sscratch_top:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RVMODEL_DATA_BEGIN
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user