This is the mail archive of the crossgcc@cygnus.com mailing list for the crossgcc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Hitachi SH1 egcs1.1 generating braf instuction.


Dave Madsen wrote:

>  It is not a Super 8 but a SuperH1 (SH1) SH7034 and it does not have
> a branch far (braf) instruction.  That was added in the SH2
> instruction set.

> It
> worked great, except a certain path through the code has a very large
> loop ~600 lines (I did not write it) .  When the end of the loop is
> reached the compiler has generated a braf instruction which is not
> valid on this processor and the processor goes off into the weeds
> when trying to execute it.  All of the other opcodes are fine so I
> know that I am set up for the right micro.

Ok, I looked in the source for egcs-1.1 and in the directory
egcs-1.1b/gcc/config/sh

in lib1funcs.asm there are code fragments reading:
    194 #ifdef __sh1__
    195         add     r5,r0
    196         jmp     @r0
    197 #else
    198         braf    r5
    199 #endif

so it's checking for the sh1.

but in sh.c there's the following:

    543 char *
    544 output_far_jump (insn, op)
    545      rtx insn;
    546      rtx op;
    547 {
    548   struct { rtx lab, reg, op; } this;
    549   char *jump;
    550   int far;
    551   int offset = branch_dest (insn) - insn_addresses[INSN_UID
(insn)];
    552 
    553   this.lab = gen_label_rtx ();
    554 
    555   if (offset >= -32764 && offset - get_attr_length (insn) <=
32766)
    556     {
    557       far = 0;
    558       jump = "mov.w     %O0,%1;braf     %1";
    559     }
    560   else
    561     {
    562       far = 1;
    563       jump = "mov.l     %O0,%1;jmp      @%1";
    564     }


where the function output_far_jump will emit a braf instruction
and it isn't checking for sh1's.

You can see the output_far_jump call used in sh.md here:
(which applies to sh1,sh2,sh3 and sh3e targets)

   2377 ;;
------------------------------------------------------------------------
   2378 ;; Jump and linkage insns
   2379 ;;
------------------------------------------------------------------------
   2380 
   2381 (define_insn "jump"
   2382   [(set (pc)
   2383         (label_ref (match_operand 0 "" "")))]
   2384   ""
   2385   "*
   2386 {
   2387   /* The length is 16 if the delay slot is unfilled.  */
   2388   if (get_attr_length(insn) > 4)
   2389     return output_far_jump(insn, operands[0]);
   2390   else
   2391     return   \"bra      %l0%#\";
   2392 }"
   2393   [(set_attr "type" "jump")
   2394    (set_attr "needs_delay_slot" "yes")])


Yup, looks like there may be a problem with egcs for SH1
possibly generating a braf under certain conditions.

The bad news is I don't know how to fix it myself.  Probably
ouput_far jump needs to do something like the code in lib1funcs.asm
but I don't know which registers are valid at that point.

I believe the maintainer for this part of egcs is
Jeffrey A Law law@cygnus.com, he might know for sure if it's
really a compiler bug and what to do about it.  You might
want to try submitting this as a bug report.  In the mean time,
you might try breaking up the code within the "big loop" and
that should work around causing the braf call for now.

cheers
randall

-- 
|\/|
|/\|  randall@elgar.com
|\/|  rsl@zanshinsys.com http://www.zanshinsys.com
_______________________________________________
New CrossGCC FAQ: http://www.objsw.com/CrossGCC
_______________________________________________
To remove yourself from the crossgcc list, send
mail to crossgcc-request@cygnus.com with the
text 'unsubscribe' (without the quotes) in the
body of the message.