This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to write a versatile ISFP?

Anonymous
Anonymous

Hi,

 

I would like to ask some questions on the writing of an ISFP (Interrupt Service Fetch Packet). By "versatile" I mean the ISFP uses register branch the range is not restricted to a constant displacement. All questions revolve around an example 6455 Starter Project.zip which Brad Griffis posted on 10-19-2009.

 

INT4:

                        b          _my_isr

                        NOP

                        NOP

                        NOP

                        NOP

                        NOP

                        NOP

                        NOP

 

Note that I did it "lazy" in this code and just used a relative branch.  The "proper" way would be to push a register, move the complete address into the register, branch to that address, pop original contents during delay slots.  The "lazy" way will work as long as the table and ISR are both in the internal RAM (4 MB reach?)

 

I have some questions on the above regarding ISTP (Interrupt Service Fetch Packet):

 

Question I:

 

 

Branch using a displacement has a 21 bit constant, which will be shifted left by 2 bits to generate the address. Therefore, it should be 23 bits address, 2^23=8MB, not 4MB.

 

Question II:

Does Brad mean a singular "content" rather than the plural "contents"? There is only one register to save and restore during this.

 

Question III:

Each ISFP (Interrupt Service Fetch Packet) should be exactly 8 words long, so can the "diligent" version, in contrary to his "lazy" version, be fit into the 8 words long packet, especially when .nocmp is used to prevent compact instruction from being used?

 

I tried to complete the “due diligence” below, and in the code R could be any arbitrary general purpose register:

 

 

stw       R, *--SP

;

Stack grow lower, store

mvkl     target_address, R

;

Low 16 bit

mvkh    target_address, R

;

High 16 bit

b           R

;

Branching using a register

ldw       *SP++, R

;

Restore

nop      2

;

 

nop      1

;

2+1+1 = 4 delay slots = delay (ldw);

nop      1

;

1(ldw)+2+2+1 = 5 delay slots = delay (b)

 

 

I probably made a mistake with SP: I am not familiar with assembly and assumed SP points to the top element of the stack, but I have also read elsewhere that SP points to the address over (logically; physically below) the top element. If this is the case, then the code has to be modified accordingly.

 

Could anyone comment on the all the questions above? And please point out if my code has any problem.

 

And I still have an additional question: is there a register dedicated as stack pointer? Are there assembly commands or CPU instructions provided specifically for push and pop? I searched the spru732j, TMS320C64x-C64x+ DSP CPU and Instruction Set Reference Guide, but didn't find any.

 

 

 

Zheng

  • 1) Signed 21 bits with a left shift of 2 gives a total range of 8MB, or a reach of +/-4MB.

    2) Yes, there is 1 register to save/restore.  It is perfectly acceptable to say restore the "contents" of a single register

    3) Stack pointer is usually assigned to B15, but I can't recall the reference for that factoid.  Add this line to your assembly:

        .asg B15, SP    ; Stack pointer is in B15

    Finally, try this code instead:

        STW    B0, *SP--[2]
        MVKL   target, B0
        MVKH  target, B0
        B          B0
        LDW   *++SP[2], B0
        NOP   4
        NOP
        NOP

    Note the difference in the SP operations line.

  • Anonymous
    0 Anonymous in reply to MattLipsey

    Matt,

    Matt Lipsey said:

    STW    B0, *SP--[2]

    LDW   *++SP[2], B0

    Why do you use increment of two words to replace my one word version? Doesn't one each stack element occupy one word space? Could you explain the reason?

     

     

    Zheng

  • From spru187 section 7.5.1:

    SP Semantics
    Note: The stack pointer must always be 8-byte aligned. This is automatically performed by the C
    compiler and system initialization code in the run-time-support libraries. Any hand assembly
    code that has interrupts enabled or calls a function defined in C or linear assembly source
    should also reserve a multiple of 8 bytes on the stack.

     

  • Anonymous
    0 Anonymous in reply to MattLipsey

    Matt,

    According to the semantics 8-byte = two words, so this is the reason you use STW/LDW with increments of [2]?

    I am also curious on why it must be 8-byte aligned rather than 4-byte. All registers are 4-byte, isn't it more natural to make SP 4-byte aligned? If 8-byte aligned, isn't half of the space wasted?

    Or is it because of the existence of 40-bit and 64-bit (long long) integers, so the compiler simply uses the longest length of all as the unit increment of SP?

     

    However I still have a question:

    MattLipsey said:

    STW    B0, *SP--[2]

    Why are you using post-increment? Won't STW overwrite the content of the top element of the stack by B0? I think pre-increment is more reasonable.

     

     

    Zheng

     

  • You might think that, but the stack pointer points to the next empty slot in the stack at all times, so writing a value and then decrementing the pointer is the way to do it.  I don't know of a reference for this off the top of my head.  Your original code would leave the sp pointing to the last filled slot, and the c compiler would promptly wipe it out if you called a c routine from your isr.

    EDIT: I take that last part back, I think the delay slots in this case would make everything work either way you did it, but given your desire to probe every detail, you should get this one right.

  • Anonymous
    0 Anonymous in reply to MattLipsey

    Matt,

    If the stack pointer is 8-byte aligned, then first I have to adjust my increment to [2] as you did. After that, I think both of our code would work.

    Thanks for all the explanation.

     

    Zheng