[fpc-devel] Is there a way to make Register Allocation inside of Interrupt Service Routines more efficient when using inline-assembler?

Michael Ring mail at michael-ring.org
Sun Aug 21 10:49:28 CEST 2016


Thank you, your comments made me think (and write some more test code).

This is how I understand things right now:

The problem for Interrupt routines is that whenenever a procedure is 
called the default list of Non-Volatile registers is allocated.
This is a no-issue in normal code as those registers never end up on the 
stack because they get filtered out in g_proc_enter and g_proc_exit

For an interrupt things are a little different, all registers that get 
touched need to get saved on the stack. So each time a procedure is 
called in an interrupt routine the list of non-volatile registers gets 
saved on the stack because for this case I changed 
tcpuparamanager.get_volatile_registers_int() to return [].

So unless there is a way to find out which registers get used by a 
procedure the only thing I can do to make interrupt routines as lean as 
possible is to not use procedures in them if possible.

Fortunately inline assembler inside of the interrupt routine works just 
fine (It seems I did something wrong when testing this):

The simple test program below saves only 3 registers on the stack when I 
comment out the call of the procedure ($vo,$v1,$a0), the moment I remove 
the comment the following registers get saved:

at,v0,v1,a0,a1,a2,a3,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,ra,fp and I guess I 
must live with this fact.....

But I am good with this because using inline assember in the interrupt 
works and so I can streamline the interrrupt routines.


Thank you both for your valuable help,


Michael


program test;
{$MODE OBJFPC}
var
  a : longWord;

procedure test;
begin
   inc(a);
end;

procedure test_interrupt; interrupt;
begin
   inc(a);
   asm
     nop
   end ['a0'];
   //test;
end;

begin
   a := 0;
end.

Am 19.08.16 um 23:00 schrieb Jonas Maebe:
> On 19/08/16 22:49, Michael Ring wrote:
>>
>> Am 19.08.16 um 14:49 schrieb Jonas Maebe:
>>>
>>> Michael Ring wrote on Sat, 13 Aug 2016:
>>>
>>>> I am trying to bring interrupt handling routine size down (and speed
>>>> up) for mipsel-embedded target.
>>>>
>>>> I need to use inline assembler routines like this one
>>>>
>>>> procedure TSystemCore.setCoreTimerComp(value : longWord); assembler;
>>>> nostackframe;
>>>> asm
>>>>   mtc0 $a1,$11,0
>>>> end ['a1'];
>>>
>>> Mentioning changed registers at the end of a pure assembler routine
>>> has no effect. The compiler normally prints a warning about this. The
>>> set of changed registers by a routine always only depends on its
>>> calling convention. On most platforms we only support the official
>>> ABI's calling convention, which is also the default.
>>
>> I also tried also something like this:
>>
>> procedure TSystemCore.setCoreTimerComp(value : longWord);
>> begin
>>   asm
>>     mtc0 $a1,$11,0
>>   end ['a1'];
>> end;
>>
>> with same result, all registers are saved. intead of only a few.
>
> It is not clear what you mean by this. In your original message, you 
> said that all registers were saved "as soon as I include the call to 
> this procedure". As explained, the registers that are saved when 
> calling a routine only depend on what the ABI says are 
> volatile/callee-saved registers. Which registers are actually used by 
> the called routine have no influence at all.
>
>>>> Same is true if I put the asm block directly inside of the interrupt
>>>> handler.
>>>
>>> In that case, the list of changed registers should be taken into
>>> account. OTOH, using an inline assembler blocks disables the use the
>>> use of register variables for that routine by the compiler, but that
>>> should result in less registers getting saved rather than more.
>>
>> Do you remember where this is coded or for what I should search in the
>> fpc sourcecode? Then I can try to find out what is going on in the mips
>> case.
>
> It's the last part of the _asm_statement function in 
> compiler/pstatemnt.pas
>
> FWIW, tcpuparamanager.get_volatile_registers_int() in mips/cpupara.pas 
> suggests that all integer registers except for R16-R23 are volatile, 
> so no matter what you do, if any of those registers contains a value 
> that is still needed after a call, they will be saved and restored.
>
>
> Jonas
> _______________________________________________
> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel




More information about the fpc-devel mailing list