avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] May avr-gcc emit EIJMP/EICALL?


From: Georg-Johann Lay
Subject: Re: [avr-gcc-list] May avr-gcc emit EIJMP/EICALL?
Date: Thu, 13 Oct 2011 13:30:38 +0200
User-agent: Thunderbird 2.0.0.24 (X11/20100302)

Boyapati, Anitha schrieb:
> 
>> -----Original Message-----
>> From: address@hidden
>> [mailto:address@hidden On
>> Behalf Of Georg-Johann Lay
>> Sent: Thursday, October 13, 2011 1:55 AM
>> To: address@hidden
>> Cc: Jörg Wunsch; Denis Chertykov
>> Subject: [avr-gcc-list] May avr-gcc emit EIJMP/EICALL?
>>
>> avr-gcc currenly emits EICALL/EIJMP instructions without caring for
>> EIND, e.g. avr.md:3630:
>>
>> (define_insn "call_insn"
>>   [...]
>>   ""
>>   "@
>>     %!icall
>>     %~call %x0
>>     %!ijmp
>>     %~jmp %x0"
>>     ...)
>>
>> where %! resolves to 'e' for targets with > 128k of flash.
>>
>> IMO that is not okay because the compiler does not care for EIND and
>> even if he (or the user) did that approch is it not IRQ-save.
>>
> 
> Yes. This is a bug. 'EIND' register is not set. 
> 
> Actually I have more such issues in queue:
> 
> -> 'ELPM' instruction, emitted for functions in libgcc.S do not set RAMPZ 
> registers.
> -> The case for generating ELPM instructions is not considered for 
> 'tablejump' patterns.

RAMPZ is a different issue, we shouldn't mix them up and solve the problems
independently.

RAMPZ is set in __do_copy_data, __do_global_ctors and __do_global_dtors and
thus set appropriately in __tablejump_elpm__.

__tablejump__ does not use ELPM and assumes that jump tables are located in the
lower segment as arranged by the linker script, see section .progmem.gcc*.

The jump targets in jump tables from switch_case/.ctors/.dtors are located in
lower flash and their entries are gs() and use relaxation magic to have jumping
pads generated.

Or did I miss something?

>> Instead, programs for big targets should use linker relaxation and jump
>> to the generated jumping pad by means of IJMP/ICALL instead.
>>
>> Thoughts?
> 
> But this works only when the range is below 128K bytes. EIJMP/EICALL are
> required beyond that. I think a proper fix will be to generate {EIND,
> EIJMP/EICALL} instructions and then apply relaxation.

Why that? Indirect jump IJMP/ICALL will jump to a jumping pad located in the
lower segment which redirects to the final jump target by a direct jump that
might target all of the address space.  The overhead an time is 2 ticks which
is no worse that fiddling with EIND.

That's the intention of relaxation and jumping pads and the mechanism is
knocked out be EI instructions.

Bottom line is that there is no need to ever touch or use EI gadgets, and EI
should be removed from the compiler like so:

Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md   (revision 179843)
+++ config/avr/avr.md   (working copy)
@@ -3635,9 +3635,9 @@ (define_insn "call_insn"
   ;; Operand 2 is 1 for tail-call, 0 otherwise.
   ""
   "@
-    %!icall
+    icall
     %~call %x0
-    %!ijmp
+    ijmp
     %~jmp %x0"
   [(set_attr "cc" "clobber")
    (set_attr_alternative "length"
@@ -3659,9 +3659,9 @@ (define_insn "call_value_insn"
   ;; Operand 3 is 1 for tail-call, 0 otherwise.
   ""
   "@
-    %!icall
+    icall
     %~call %x1
-    %!ijmp
+    ijmp
     %~jmp %x1"
   [(set_attr "cc" "clobber")
    (set_attr_alternative "length"
Index: config/avr/libgcc.S
===================================================================
--- config/avr/libgcc.S (revision 179842)
+++ config/avr/libgcc.S (working copy)
@@ -740,11 +740,7 @@ DEFUN __prologue_saves__
        out     __SP_H__,r29
        out     __SREG__,__tmp_reg__
        out     __SP_L__,r28
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
-       eijmp
-#else
        ijmp
-#endif

 ENDF __prologue_saves__
 #endif /* defined (L_prologue) */

Johann

> 
> Anitha
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]