Unexpected exception vector in MIPS32 in baremetal
05:34 02 Jun 2026

I am working on a MIPS32 SOC system, where there is 32MB DRAM.
I want to setup interrupt and exception handlers for it, per MIPS ISA, I clear the BEV in status register and set IV in cause register of CP0, I would use 0x80000180 and 0x80000200 for exception and interrupt handling. So I worked out a board.ld as follows,

OUTPUT_FORMAT("elf32-tradlittlemips")
OUTPUT_ARCH(mips)
ENTRY(__start)

MEMORY
{
    ram (rwx) : ORIGIN = 0x80100000, LENGTH = 31M
    ramv (rwx) : ORIGIN = 0x80000000, LENGTH = 16K
}

SECTIONS
{
    .start : {
        *(.start)
    } > ram

    .vectors_load : {
        _vectors_load_start = .;

        . = ALIGN(4);
        KEEP(*(.reset))
        . = _vectors_load_start + 0x180;

        . = ALIGN(4);
        KEEP(*(.gen_excpt))
        . = _vectors_load_start + 0x200;

        . = ALIGN(4);
        KEEP(*(.ebase_excpt))
        . = _vectors_load_start + 0x300;

        . = ALIGN(4);
        KEEP(*(.cache_excpt))
        . = _vectors_load_start + 0x380;

        . = ALIGN(4);
        KEEP(*(.bev_excpt))
        . = _vectors_load_start + 0x400;

       . = ALIGN(4);
        KEEP(*(.int_excpt))
        . = _vectors_load_start + 0x480;

        . = ALIGN(4);
        KEEP(*(.dbg_excpt))
        . = _vectors_load_start + 0x500;

        _vectors_load_end = .;
    } > ramv

    .text : {
        _stext = .;
        *(.text .text.*)
......
}

which defined entry point (__start) is 0x80100000, and the vectors are all in 0x80000N00.
From the following in System.map I think the vectors are in the location specified by board.ld.

Memory Configuration

Name             Origin             Length             Attributes
ram              0x0000000080100000 0x0000000001f00000 xrw
ramv             0x0000000080000000 0x0000000000004000 xrw
*default*        0x0000000000000000 0xffffffffffffffff

Linker script and memory map


.start          0x0000000080100000      0x178
 *(.start)
 .start         0x0000000080100000      0x178 my_head.o
                0x0000000080100000                __start

.vectors_load   0x0000000080000000      0x500
                0x0000000080000000                _vectors_load_start = .
                0x0000000080000000                . = ALIGN (0x4)
 *(.reset)
 .reset         0x0000000080000000       0x10 my_head.o
                0x0000000080000000                __reset
                0x0000000080000180                . = (_vectors_load_start + 0x180)
 *fill*         0x0000000080000010      0x170
                0x0000000080000180                . = ALIGN (0x4)
 *(.gen_excpt)
 .gen_excpt     0x0000000080000180       0x10 my_head.o
                0x0000000080000200                . = (_vectors_load_start + 0x200)
 *fill*         0x0000000080000190       0x70
                0x0000000080000200                . = ALIGN (0x4)
 *(.ebase_excpt)
 .ebase_excpt   0x0000000080000200       0x10 my_head.o
                0x0000000080000300                . = (_vectors_load_start + 0x300)
 *fill*         0x0000000080000210       0xf0
                0x0000000080000300                . = ALIGN (0x4)
 *(.cache_excpt)
                0x0000000080000380                . = (_vectors_load_start + 0x380)
 *fill*         0x0000000080000300       0x80
                0x0000000080000380                . = ALIGN (0x4)
 *(.bev_excpt)
 .bev_excpt     0x0000000080000380       0x10 my_head.o
                0x0000000080000400                . = (_vectors_load_start + 0x400)
 *fill*         0x0000000080000390       0x70
                0x0000000080000400                . = ALIGN (0x4)
 *(.int_excpt)
 .int_excpt     0x0000000080000400       0x10 my_head.o
                0x0000000080000480                . = (_vectors_load_start + 0x480)
 *fill*         0x0000000080000410       0x70
                0x0000000080000480                . = ALIGN (0x4)
 *(.dbg_excpt)
                0x0000000080000500                . = (_vectors_load_start + 0x500)
 *fill*         0x0000000080000480       0x80
                0x0000000080000500                _vectors_load_end = .

.text           0x0000000080100180    0x51260
                0x0000000080100180                _stext = .
 *(.text .text.*)

Here is the codes to setup interrupt and exception.

  cp0_putebase(0x80000000);

  /* Set the INTCTL vector spacing to non-zero */

  cp0_putintctl(0x00000020);

  /* Set the IV bit in the CAUSE register */

  regval  = cp0_getcause();
  regval |= CP0_CAUSE_IV;
  cp0_putcause(regval);

  /* Clear the EXL and BEV bits in the STATUS register */
  regval  = cp0_getstatus();
  regval &= ~(CP0_STATUS_EXL | CP0_STATUS_BEV);
  cp0_putstatus(regval);

  __asm__ volatile(
    "sync\n\t"
    "nop\n\t"
    "nop\n\t"
    "nop\n\t"
  );

With JTAG and GDB, I loaded my image to 0x80000000 (so the vectors are well populated), I started running the image from 0x80100000.

To my surprise, I hit the codes in _bev_exception at 0x80000380 instead of 0x80000200 when the interrupt is enabled through status register, which caused no calling of interrupt handler!

I checked the cause and status registers of CP0, when _bev_exception is called, they are,

status: 00000303; cause: 40808100, there seemed be interrupt but why it is trapped to _bev_exception instead of 0x80000200?

c mips interrupt mips32