This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

Re: SH3 problem with switch branch tables



I think I understand the real problem now. It seems the "braf" 
instruction is used incorrectly.

To explain:

1) The SH manual indicates BRAF Rn performs "PC + 4 + Rn => PC".

2) The offset is calculated relative to the table start (L1302)

This isn't the proper calculation. Since BRAF is PC relative, the proper 
displacements should be calculated relative to the BRAF instruction 
itself, not the table start.

The current code works fine as long as the "braf" instruction is 
generated on a 4 byte alignment. If this happens, then the table is 
generated at braf_pc + 4 (due to the following nop) and the first ".align 2" 
directive generates no padding.

The problem occurs when the "braf" instruction is generated at an address 
that's not 4 byte aligned. What this happens, the following nop generates 
two bytes, then the ".align 2" directive generates 2 bytes of padding.
The table winds up at PC + 6 and the offsets are incorrect, because
they're generated relative to the table start (PC + 6) instead 
relative to the correct address (PC + 4):

 2988 1aa2 0123               braf r1			<- braf @ 0x1aa2
 2989 1aa4 0009               nop
 2990 1aa6 0009               .align 2
 2991               L1302:
 2992                    .align 2
 2993               L1300:
 2994 1aa8 0A                 .byte      L1289-L1302	<- table @ 0x1aa8
 2995 1aa9 58                 .byte      L1292-L1302
 2996 1aaa A8                 .byte      L1295-L1302
 2997 1aab D8                 .byte      L1299-L1302
 2998 1aac E8                 .byte      L1287-L1302
 2999 1aad E8                 .byte      L1287-L1302
 3000 1aae 08                 .byte      L1288-L1302

In this instance, the table winds up at braf_pc + 6 so all the offsets 
are off by two bytes.

I can think of two ways to fix this problem:

1) The right way. Generate label for the "braf" instruction, and calculate
   the table values relative to the "braf" label.

2) The kludgy way. Disable the "braf" usage.

I'll let Joern fix it properly, but here's a kludge which will hopefully 
fix your problem:

*** sh.md.bak   Thu Mar 25 11:34:40 1999
--- sh.md       Thu Mar 25 11:35:20 1999
***************
*** 3292,3298 ****
    emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], 
operands[4],
                           reg));
    emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
!   if (TARGET_SH2)
      {
        rtx lab = gen_label_rtx ();
        emit_jump_insn (gen_casesi_jump_2 (reg2,
--- 3292,3301 ----
    emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], 
operands[4],
                           reg));
    emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
! 
!   /* Temporarily disabled because "braf" is used incorrectly in
!      the casesi_jump_2 insn (no label) */
!   if (0)
      {
        rtx lab = gen_label_rtx ();
        emit_jump_insn (gen_casesi_jump_2 (reg2,

Toshi


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