# Copyright (c) 2002, Jason Riffel - TotalEmbedded LLC. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # Neither the name of TotalEmbedded nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # .text .align 2 .globl start .ent start start: .set noat mtc0 $15, $31 # Use R15 as a pointer just to move R0 R1 & R2 out, then switch # and use R1 as the pointer until we are done. lui $15, 0xFF2F ori $15, $15, 0xFF00 sw $0, ($15) addiu $15, $15, 0x04 sw $1, ($15) addiu $15, $15, 0x04 sw $2, ($15) mfc0 $15, $31 mtc0 $1, $31 # Load the pseudo stack address and push R2 lui $1, 0xFF2F ori $1, $1, 0xFFFC sw $2, ($1) # Load the address to resume at lui $1, 0xFF2F ori $1, $1, 0xFF0C sw $3, ($1) addiu $1, $1, 0x04 sw $4, ($1) addiu $1, $1, 0x04 sw $5, ($1) addiu $1, $1, 0x04 sw $6, ($1) addiu $1, $1, 0x04 sw $7, ($1) addiu $1, $1, 0x04 sw $8, ($1) addiu $1, $1, 0x04 sw $9, ($1) addiu $1, $1, 0x04 sw $10, ($1) addiu $1, $1, 0x04 sw $11, ($1) addiu $1, $1, 0x04 sw $12, ($1) addiu $1, $1, 0x04 sw $13, ($1) addiu $1, $1, 0x04 sw $14, ($1) addiu $1, $1, 0x04 sw $15, ($1) addiu $1, $1, 0x04 sw $16, ($1) addiu $1, $1, 0x04 sw $17, ($1) addiu $1, $1, 0x04 sw $18, ($1) addiu $1, $1, 0x04 sw $19, ($1) addiu $1, $1, 0x04 sw $20, ($1) addiu $1, $1, 0x04 sw $21, ($1) addiu $1, $1, 0x04 sw $22, ($1) addiu $1, $1, 0x04 sw $23, ($1) addiu $1, $1, 0x04 sw $24, ($1) addiu $1, $1, 0x04 sw $25, ($1) addiu $1, $1, 0x04 sw $26, ($1) addiu $1, $1, 0x04 sw $27, ($1) addiu $1, $1, 0x04 sw $28, ($1) addiu $1, $1, 0x04 sw $29, ($1) addiu $1, $1, 0x04 sw $30, ($1) addiu $1, $1, 0x04 sw $31, ($1) addiu $1, $1, 0x04 # Now we need to read the special function registers into R2 and store # them like the others. We pushed R2 at the top into the pseudo stack. # STATUS REGISTER mfc0 $2, $12 sw $2, ($1) addiu $1, $1, 0x04 # LO REGISTER mflo $2 sw $2, ($1) addiu $1, $1, 0x04 # HI REGISTER mfhi $2 sw $2, ($1) addiu $1, $1, 0x04 # BAD REGISTER mfc0 $2, $8 sw $2, ($1) addiu $1, $1, 0x04 # CAUSE REGISTER mfc0 $2, $13 sw $2, ($1) addiu $1, $1, 0x04 # PC REGISTER mfc0 $2, $24 sw $2, ($1) addiu $1, $1, 0x04 # Now we need to reload R1 with the pseudo stack location and restore R2 lui $1, 0xFF2F ori $1, $1, 0xFFFC lw $2, ($1) # Restore R1 and we're done. mfc0 $1, $31 # !!! MUST USE BEQ TO RETURN !!! # This is because an absolute jump to 0xFF200200 will not be # encoded properly by the listing from the .S file. The assignment # of physical addresses is done by the linker which is never invoked. # Using of BEQ uses a relative address from the PC which is always # valid. Use a compare of R0 to R0 since its always 0 its always # equal. You must also insert NOP's because the assembler assumes # the valid usage of branch delay slots. The assembler will insert # the previous instruction AFTER the branch because at runtime the # processor uses delay slots (executes an instruction AFTER the branch # because of the pipeline). This doesn't happen in debug mode over # EJTAG so we must insert NOP's to fill the slot and make sure the # instructions are executed in the order we want. nop beq $0, $0, start .end start