Weird SPSR behaviour

I was trying to write a register context saving/restoring when I came across a weird behaviour.

My code (sorry, tried to format tens of times, but the editor WANTS to make asm a table):

asm volatile (
...
"pop {r0 - r3}"
"push {r0 - r3}"
"mov r0, r3"
"bl dbg_out" - outputs 60000013
"pop {r0 - r3}"
"msr cpsr_fsxc, r2"
"@dsb"
"@isb"
"msr spsr_fsxc, r3" - set value
"@dsb"
"@isb"
"mov lr, r1"
"mov sp, r0"
"push {r0 - r4, lr}"
"mov r0, lr"
"bl dbg_out"
"mov r0, sp"
"bl dbg_out"
"mrs r2, cpsr"
"mrs r3, spsr" - read value
"mov r0, r2"
"bl dbg_out"
"mov r0, r3" - outputs 00000002
"bl dbg_out"
...
);

When the exception is returned from, the calling function:

asm volatile ("svc #0\n\t");

    msg = "returned from SVC\r\n";

    serial_io.put_string(msg, util_str_len(msg)+1);

    asm volatile (

"mrs %[retreg], cpsr\n\t"
:[retreg] "=r" (tmp1) ::

    );

    msg = "cpsr = ";

    serial_io.put_string(msg, util_str_len(msg)+1);

    util_word_to_hex(scratchpad, tmp1);

    serial_io.put_string(scratchpad, 9);

    serial_io.put_string("\r\n", 3);

outputs "returned from SVC" and "cpsr = 60000013".

Why the "00000002"? the barriers don't seem to have any effect.

Parents Reply Children
  • No, it's not position independent, but linked like:

    MEMORY
    {
        LOAD (rwx) : ORIGIN = 0x00008000, LENGTH = 512k /* initial */
        EXEC (rwx) : ORIGIN = 0x1f000000, LENGTH = 512k /* runtime */
    }
    
    SECTIONS
    {
        /* Starts at LOADER_ADDR. */
        . = 0x8000;
        __text_start = .;
        .text :
        {
            *(.init)
            *start1.o(.text)
            *start1.o(.data)
            *start1.o(.bss)
            *(.text.startup)
        } >LOAD
    
        /* .text2 ALIGN(0x1000):  - the ">EXEC AT>LOAD" didn't like "ALIGN(0x1000)" */
        .text2 :
        {
            . = ALIGN(.,0x8);
            *loader.o(.text)
            *rpi2.o(.text)
            *serial.o(.text)
            *util.o(EXCLUDE_FILE(*instr_util.o).text)
            *gdb.o(.text)
            *(.text)
        } >EXEC AT>LOAD
        __text_end = .;
        __load_start = LOADADDR(.text2);
        __code_begin = ADDR(.text2);
    ...
    
    
    
    

    The memory map is flat - just 1st level table with sections:

    #define MMU_SECT_ATTR_NORMAL 0x00090c0a
    #define MMU_SECT_ATTR_DEV 0x00090c06
    #define MMU_SECT_ENTRY(addr_meg, attr) ((addr_meg << 20) | attr)
    ...
    // program RAM
    for (tmp=0; tmp<0x3b0; tmp++)
    {
        master_xlat_tbl[tmp] = MMU_SECT_ENTRY(tmp, MMU_SECT_ATTR_NORMAL);
    }
    // video RAM (?)
    for (tmp=0x3b0; tmp<0x3f0; tmp++)
    {
        master_xlat_tbl[tmp] = MMU_SECT_ENTRY(tmp, MMU_SECT_ATTR_DEV);
    }
    // peripherals
    for (tmp=0x3f0; tmp<0xfff; tmp++)
    {
        master_xlat_tbl[tmp] = MMU_SECT_ENTRY(tmp, MMU_SECT_ATTR_DEV);
    }
    
    
    
    

    And since it's write-through, I don't clean the caches, I just invalidate them.

    Oh, and the copying is done before the MMU and caches are turned on.

  • I think this thread has passed its purpose long ago.

    There were no answers to that, but the problem went away, and the next best thing to an answer was Jens' LED idea, so I'm marking it as a solution.