OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [libgloss/] [mips/] [entry.S] - Diff between revs 158 and 816

Only display areas with differences | Details | Blame | View Log

Rev 158 Rev 816
/* entry.S - exception handler for emulating MIPS16 'entry' and 'exit'
/* entry.S - exception handler for emulating MIPS16 'entry' and 'exit'
   pseudo-instructions.  These instructions are generated by the compiler
   pseudo-instructions.  These instructions are generated by the compiler
   when the -mentry switch is used.  The instructions are not implemented
   when the -mentry switch is used.  The instructions are not implemented
   in the MIPS16 CPU; hence the exception handler that emulates them.
   in the MIPS16 CPU; hence the exception handler that emulates them.
   This module contains the following public functions:
   This module contains the following public functions:
   * void __install_entry_handler(void);
   * void __install_entry_handler(void);
     This function installs the entry/exit exception handler.  It should
     This function installs the entry/exit exception handler.  It should
     be called before executing any MIPS16 functions that were compiled with
     be called before executing any MIPS16 functions that were compiled with
     -mentry, typically before main() is called.
     -mentry, typically before main() is called.
   * void __remove_entry_handler(void);
   * void __remove_entry_handler(void);
     This function removes the entry/exit exception handler.  It should
     This function removes the entry/exit exception handler.  It should
     be called when the program is exiting, or when it is known that no
     be called when the program is exiting, or when it is known that no
     more MIPS16 functions compiled with -mentry will be called.
     more MIPS16 functions compiled with -mentry will be called.
*/
*/
#ifdef __mips16
#ifdef __mips16
/* This file contains 32 bit assembly code.  */
/* This file contains 32 bit assembly code.  */
        .set nomips16
        .set nomips16
#endif
#endif
#include "regs.S"
#include "regs.S"
#define CAUSE_EXCMASK   0x3c    /* mask for ExcCode in Cause Register */
#define CAUSE_EXCMASK   0x3c    /* mask for ExcCode in Cause Register */
#define EXC_RI          0x28    /* 101000 == 10 << 2 */
#define EXC_RI          0x28    /* 101000 == 10 << 2 */
/* Set DEBUG to 1 to enable recording of the last 16 interrupt causes.  */
/* Set DEBUG to 1 to enable recording of the last 16 interrupt causes.  */
#define DEBUG 0
#define DEBUG 0
#if DEBUG
#if DEBUG
        .sdata
        .sdata
int_count:
int_count:
        .space  4                       /* interrupt count modulo 16 */
        .space  4                       /* interrupt count modulo 16 */
int_cause:
int_cause:
        .space  4*16                    /* last 16 interrupt causes */
        .space  4*16                    /* last 16 interrupt causes */
#endif
#endif
        .text
        .text
        .set    noreorder               /* Do NOT reorder instructions */
        .set    noreorder               /* Do NOT reorder instructions */
/* __entry_exit_handler - the reserved instruction exception handler
/* __entry_exit_handler - the reserved instruction exception handler
   that emulates the entry and exit instruction.  */
   that emulates the entry and exit instruction.  */
__entry_exit_handler:
__entry_exit_handler:
        .set    noat                    /* Do NOT use at register */
        .set    noat                    /* Do NOT use at register */
#if DEBUG
#if DEBUG
/* Must avoid using 'la' pseudo-op because it uses gp register, which
/* Must avoid using 'la' pseudo-op because it uses gp register, which
   may not have a good value in an exception handler. */
   may not have a good value in an exception handler. */
#       la      k0, int_count           /* intcount = (intcount + 1) & 0xf */
#       la      k0, int_count           /* intcount = (intcount + 1) & 0xf */
        lui     k0 ,%hi(int_count)
        lui     k0 ,%hi(int_count)
        addiu   k0, k0 ,%lo(int_count)
        addiu   k0, k0 ,%lo(int_count)
        lw      k1, (k0)
        lw      k1, (k0)
        addiu   k1, k1, 1
        addiu   k1, k1, 1
        andi    k1, k1, 0x0f
        andi    k1, k1, 0x0f
        sw      k1, (k0)
        sw      k1, (k0)
#       la      k0, int_cause           /* k1 = &int_cause[intcount] */
#       la      k0, int_cause           /* k1 = &int_cause[intcount] */
        lui     k0, %hi(int_cause)
        lui     k0, %hi(int_cause)
        addiu   k0, k0, %lo(int_cause)
        addiu   k0, k0, %lo(int_cause)
        sll     k1, k1, 2
        sll     k1, k1, 2
        add     k1, k1, k0
        add     k1, k1, k0
#endif
#endif
        mfc0    k0, C0_CAUSE            /* Fetch cause */
        mfc0    k0, C0_CAUSE            /* Fetch cause */
#if DEBUG
#if DEBUG
        sw      k0, -4(k1)              /* Save exception cause in buffer */
        sw      k0, -4(k1)              /* Save exception cause in buffer */
#endif
#endif
        mfc0    k1, C0_EPC              /* Check for Reserved Inst. without */
        mfc0    k1, C0_EPC              /* Check for Reserved Inst. without */
        and     k0, CAUSE_EXCMASK       /*   destroying any register */
        and     k0, CAUSE_EXCMASK       /*   destroying any register */
        subu    k0, EXC_RI
        subu    k0, EXC_RI
        bne     k0, zero, check_others  /* Sorry, go do something else */
        bne     k0, zero, check_others  /* Sorry, go do something else */
        and     k0, k1, 1               /* Check for TR mode (pc.0 = 1) */
        and     k0, k1, 1               /* Check for TR mode (pc.0 = 1) */
        beq     k0, zero, ri_in_32      /* Sorry, RI in 32-bit mode */
        beq     k0, zero, ri_in_32      /* Sorry, RI in 32-bit mode */
        xor     k1, 1
        xor     k1, 1
/* Since we now are going to emulate or die, we can use all the T-registers */
/* Since we now are going to emulate or die, we can use all the T-registers */
/* that MIPS16 does not use (at, t0-t8), and we don't have to save them. */
/* that MIPS16 does not use (at, t0-t8), and we don't have to save them. */
        .set    at                      /* Now it's ok to use at again */
        .set    at                      /* Now it's ok to use at again */
#if 0
#if 0
        j       leave
        j       leave
        rfe
        rfe
#endif
#endif
        lhu     t0, 0(k1)               /* Fetch the offending instruction */
        lhu     t0, 0(k1)               /* Fetch the offending instruction */
        xor     t8, k1, 1               /* Prepare t8 for exit */
        xor     t8, k1, 1               /* Prepare t8 for exit */
        and     t1, t0, 0xf81f          /* Check for entry/exit opcode */
        and     t1, t0, 0xf81f          /* Check for entry/exit opcode */
        bne     t1, 0xe809, other_ri
        bne     t1, 0xe809, other_ri
deareg: and     t1, t0, 0x0700          /* Isolate the three a-bits */
deareg: and     t1, t0, 0x0700          /* Isolate the three a-bits */
        srl     t1, 6                   /* Adjust them so x4 is applied */
        srl     t1, 6                   /* Adjust them so x4 is applied */
        slt     t2, t1, 17              /* See if this is the exit instruction */
        slt     t2, t1, 17              /* See if this is the exit instruction */
        beqz    t2, doexit
        beqz    t2, doexit
        la      t2, savea
        la      t2, savea
        subu    t2, t1
        subu    t2, t1
        jr      t2                      /* Jump into the instruction table */
        jr      t2                      /* Jump into the instruction table */
        rfe                             /* We run the rest in user-mode */
        rfe                             /* We run the rest in user-mode */
                                        /* This is the entry instruction! */
                                        /* This is the entry instruction! */
        sw      a3, 12(sp)              /* 4: a0-a3 saved */
        sw      a3, 12(sp)              /* 4: a0-a3 saved */
        sw      a2,  8(sp)              /* 3: a0-a2 saved */
        sw      a2,  8(sp)              /* 3: a0-a2 saved */
        sw      a1,  4(sp)              /* 2: a0-a1 saved */
        sw      a1,  4(sp)              /* 2: a0-a1 saved */
        sw      a0,  0(sp)              /* 1: a0    saved */
        sw      a0,  0(sp)              /* 1: a0    saved */
savea:                                  /* 0: No arg regs saved */
savea:                                  /* 0: No arg regs saved */
dera:   and     t1, t0, 0x0020          /* Isolate the save-ra bit */
dera:   and     t1, t0, 0x0020          /* Isolate the save-ra bit */
        move    t7, sp                  /* Temporary SP */
        move    t7, sp                  /* Temporary SP */
        beq     t1, zero, desreg
        beq     t1, zero, desreg
        subu    sp, 32                  /* Default SP adjustment */
        subu    sp, 32                  /* Default SP adjustment */
        sw      ra, -4(t7)
        sw      ra, -4(t7)
        subu    t7, 4
        subu    t7, 4
desreg: and     t1, t0, 0x00c0          /* Isolate the two s-bits */
desreg: and     t1, t0, 0x00c0          /* Isolate the two s-bits */
        beq     t1, zero, leave
        beq     t1, zero, leave
        subu    t1, 0x0040
        subu    t1, 0x0040
        beq     t1, zero, leave         /* Only one to save... */
        beq     t1, zero, leave         /* Only one to save... */
        sw      s0, -4(t7)              /* Do the first one */
        sw      s0, -4(t7)              /* Do the first one */
        sw      s1, -8(t7)              /* Do the last one */
        sw      s1, -8(t7)              /* Do the last one */
leave:  jr      t8                      /* Exit to unmodified EPC */
leave:  jr      t8                      /* Exit to unmodified EPC */
        nop                             /* Urgh - the only nop!! */
        nop                             /* Urgh - the only nop!! */
doexf0: mtc1    v0,$f0                  /* Copy float value */
doexf0: mtc1    v0,$f0                  /* Copy float value */
        b       doex2
        b       doex2
doexf1: mtc1    v1,$f0                  /* Copy double value */
doexf1: mtc1    v1,$f0                  /* Copy double value */
        mtc1    v0,$f1
        mtc1    v0,$f1
        b       doex2
        b       doex2
doexit: slt     t2, t1, 21
doexit: slt     t2, t1, 21
        beq     t2, zero, doexf0
        beq     t2, zero, doexf0
        slt     t2, t1, 25
        slt     t2, t1, 25
        beq     t2, zero, doexf1
        beq     t2, zero, doexf1
doex2:  and     t1, t0, 0x0020          /* Isolate ra bit */
doex2:  and     t1, t0, 0x0020          /* Isolate ra bit */
        beq     t1, zero, dxsreg        /* t1 holds ra-bit */
        beq     t1, zero, dxsreg        /* t1 holds ra-bit */
        addu    t7, sp, 32              /* Temporary SP */
        addu    t7, sp, 32              /* Temporary SP */
        lw      ra, -4(t7)
        lw      ra, -4(t7)
        subu    t7, 4
        subu    t7, 4
dxsreg: and     t1, t0, 0x00c0          /* Isolate the two s-bits */
dxsreg: and     t1, t0, 0x00c0          /* Isolate the two s-bits */
        beq     t1, zero, leavex
        beq     t1, zero, leavex
        subu    t1, 0x0040
        subu    t1, 0x0040
        beq     t1, zero, leavex        /* Only one to save... */
        beq     t1, zero, leavex        /* Only one to save... */
        lw      s0, -4(t7)              /* Do the first one */
        lw      s0, -4(t7)              /* Do the first one */
        lw      s1, -8(t7)              /* Do the last one */
        lw      s1, -8(t7)              /* Do the last one */
leavex: jr      ra                      /* Exit to ra */
leavex: jr      ra                      /* Exit to ra */
        addu    sp, 32                  /* Clean up stack pointer */
        addu    sp, 32                  /* Clean up stack pointer */
/* Come here for exceptions we can't handle.  */
/* Come here for exceptions we can't handle.  */
ri_in_32:
ri_in_32:
other_ri:
other_ri:
check_others:                           /* call the previous handler */
check_others:                           /* call the previous handler */
        la      k0,__previous
        la      k0,__previous
        jr      k0
        jr      k0
        nop
        nop
__exception_code:
__exception_code:
        .set noreorder
        .set noreorder
        la      k0, __entry_exit_handler
        la      k0, __entry_exit_handler
#       lui     k0, %hi(exception)
#       lui     k0, %hi(exception)
#       addiu   k0, k0, %lo(exception)
#       addiu   k0, k0, %lo(exception)
        jr      k0
        jr      k0
        nop
        nop
        .set reorder
        .set reorder
__exception_code_end:
__exception_code_end:
        .data
        .data
__previous:
__previous:
        .space  (__exception_code_end - __exception_code)
        .space  (__exception_code_end - __exception_code)
        .text
        .text
/* void __install_entry_handler(void)
/* void __install_entry_handler(void)
   Install our entry/exit reserved instruction exception handler.
   Install our entry/exit reserved instruction exception handler.
*/
*/
        .ent    __install_entry_handler
        .ent    __install_entry_handler
        .globl  __install_entry_handler
        .globl  __install_entry_handler
__install_entry_handler:
__install_entry_handler:
        .set noreorder
        .set noreorder
        mfc0    a0,C0_SR
        mfc0    a0,C0_SR
        nop
        nop
        li      a1,SR_BEV
        li      a1,SR_BEV
        and     a1,a1,a0
        and     a1,a1,a0
        beq     a1,$0,baseaddr
        beq     a1,$0,baseaddr
        lui     a0,0x8000       /* delay slot */
        lui     a0,0x8000       /* delay slot */
        lui     a0,0xbfc0
        lui     a0,0xbfc0
        addiu   a0,a0,0x0100
        addiu   a0,a0,0x0100
baseaddr:
baseaddr:
        addiu   a0,a0,0x080     /* a0 = base vector table address */
        addiu   a0,a0,0x080     /* a0 = base vector table address */
        li      a1,(__exception_code_end - __exception_code)
        li      a1,(__exception_code_end - __exception_code)
        la      a2,__exception_code
        la      a2,__exception_code
        la      a3,__previous
        la      a3,__previous
/* there must be a better way of doing this???? */
/* there must be a better way of doing this???? */
copyloop:
copyloop:
        lw      v0,0(a0)
        lw      v0,0(a0)
        sw      v0,0(a3)
        sw      v0,0(a3)
        lw      v0,0(a2)
        lw      v0,0(a2)
        sw      v0,0(a0)
        sw      v0,0(a0)
        addiu   a0,a0,4
        addiu   a0,a0,4
        addiu   a2,a2,4
        addiu   a2,a2,4
        addiu   a3,a3,4
        addiu   a3,a3,4
        subu    a1,a1,4
        subu    a1,a1,4
        bne     a1,$0,copyloop
        bne     a1,$0,copyloop
        nop
        nop
        j       ra
        j       ra
        nop
        nop
        .set reorder
        .set reorder
        .end    __install_entry_handler
        .end    __install_entry_handler
/* void __remove_entry_handler(void);
/* void __remove_entry_handler(void);
   Remove our entry/exit reserved instruction exception handler.
   Remove our entry/exit reserved instruction exception handler.
*/
*/
        .ent    __remove_entry_handler
        .ent    __remove_entry_handler
        .globl  __remove_entry_handler
        .globl  __remove_entry_handler
__remove_entry_handler:
__remove_entry_handler:
        .set noreorder
        .set noreorder
        mfc0    a0,C0_SR
        mfc0    a0,C0_SR
        nop
        nop
        li      a1,SR_BEV
        li      a1,SR_BEV
        and     a1,a1,a0
        and     a1,a1,a0
        beq     a1,$0,res_baseaddr
        beq     a1,$0,res_baseaddr
        lui     a0,0x8000       /* delay slot */
        lui     a0,0x8000       /* delay slot */
        lui     a0,0xbfc0
        lui     a0,0xbfc0
        addiu   a0,a0,0x0200
        addiu   a0,a0,0x0200
res_baseaddr:
res_baseaddr:
        addiu   a0,a0,0x0180    /* a0 = base vector table address */
        addiu   a0,a0,0x0180    /* a0 = base vector table address */
        li      a1,(__exception_code_end - __exception_code)
        li      a1,(__exception_code_end - __exception_code)
        la      a3,__previous
        la      a3,__previous
/* there must be a better way of doing this???? */
/* there must be a better way of doing this???? */
res_copyloop:
res_copyloop:
        lw      v0,0(a3)
        lw      v0,0(a3)
        sw      v0,0(a0)
        sw      v0,0(a0)
        addiu   a0,a0,4
        addiu   a0,a0,4
        addiu   a3,a3,4
        addiu   a3,a3,4
        subu    a1,a1,4
        subu    a1,a1,4
        bne     a1,$0,res_copyloop
        bne     a1,$0,res_copyloop
        nop
        nop
        j       ra
        j       ra
        nop
        nop
        .set reorder
        .set reorder
        .end    __remove_entry_handler
        .end    __remove_entry_handler
/* software_init_hook - install entry/exit handler and arrange to have it
/* software_init_hook - install entry/exit handler and arrange to have it
   removed at exit.  This function is called by crt0.S.  */
   removed at exit.  This function is called by crt0.S.  */
        .text
        .text
        .globl  software_init_hook
        .globl  software_init_hook
        .ent    software_init_hook
        .ent    software_init_hook
software_init_hook:
software_init_hook:
        .set    noreorder
        .set    noreorder
        subu    sp, sp, 8                       /* allocate stack space */
        subu    sp, sp, 8                       /* allocate stack space */
        sw      ra, 4(sp)                       /* save return address */
        sw      ra, 4(sp)                       /* save return address */
        jal     __install_entry_handler         /* install entry/exit handler */
        jal     __install_entry_handler         /* install entry/exit handler */
        nop
        nop
        lui     a0, %hi(__remove_entry_handler) /* arrange for exit to */
        lui     a0, %hi(__remove_entry_handler) /* arrange for exit to */
        jal     atexit                          /*  de-install handler */
        jal     atexit                          /*  de-install handler */
        addiu   a0, a0, %lo(__remove_entry_handler)     /* delay slot */
        addiu   a0, a0, %lo(__remove_entry_handler)     /* delay slot */
        lw      ra, 4(sp)                       /* get return address */
        lw      ra, 4(sp)                       /* get return address */
        j       ra                              /* return */
        j       ra                              /* return */
        addu    sp, sp, 8                       /* deallocate stack */
        addu    sp, sp, 8                       /* deallocate stack */
        .set    reorder
        .set    reorder
        .end    software_init_hook
        .end    software_init_hook
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.