Long Branches
chris at mimsy.UUCP
chris at mimsy.UUCP
Mon Jan 19 15:34:15 AEST 1987
In article <3950006 at nucsrl.UUCP> ram at nucsrl.UUCP (Raman Renu) writes:
>... using the C compiler and VAX assembler in our local 4.3BSD(VAX) site.
>I have a program which has a huge(>900lines) case statement.
>The assembler chokes on (>32K long) long branches.
This may seem a nit, but no, the assembler chokes on >32K *word*
branches. This is an important distinction. The pseudo-ops `jbr'
expand into one of `brb' or `brw', but not `jmp'. The Vax does
not have a long branch instruction, just a long jump instruction
(the difference is that one takes an offset, the other an address).
>Apparently there is a flag "-J" for such purposes (in the assembler)
>which does not seem to work.
Indeed, it does work. Look more closely at the error messages!
>The ouput of the C compiler was
(To be technical, these errors are from the assembler.)
>Assembler:
>"/tmp/ctm088343", line 2565: brw: Branch too far(50148b): try -J flag
>"/tmp/ctm088343", line 2823: brw: Branch too far(48806b): try -J flag
>"/tmp/ctm088343", line 2922: brw: Branch too far(48313b): try -J flag
>"/tmp/ctm088343", line 12658: Case will branch too far
>"/tmp/ctm088343", line 12659: Case will branch too far
>"/tmp/ctm088343", line 12664: Case will branch too far
Three are `branch too far, try -J'. Three are something else.
>and the ouput of a seperate assembly [with -J] had the same error
>message(predictably).
No, not the same!
>Assembler:
>"prolog.s", line 13337: Case will branch too far
>"prolog.s", line 13338: Case will branch too far
>"prolog.s", line 13339: Case will branch too far
>"prolog.s", line 13340: Case will branch too far
All three `branch too far, try -J's are gone. There is one new `case
will branch too far' message (because the code got bigger).
The problem is that the Vax `case' instruction has only a word offset
for its branches. If you look at the result of compiling a switch
statement, you can see this yourself:
f()
{
extern int sw;
switch (sw) {
#define CASE(n) case n: f/**/n(); break /* kludge; no ## yet */
CASE(0); CASE(1); CASE(2); CASE(3);
CASE(4); CASE(5); CASE(6); CASE(7);
}
}
The switch compiles as:
casel r0,$0,$7 # note that this is a `long' case
L35:
.word L19-L35 # For case 0, branch to L19,
.word L21-L35 # and so on.
.word L23-L35 # Note that these are only word
.word L25-L35 # offsets; no long offsets are
.word L27-L35 # available.
.word L29-L35
.word L31-L35
.word L33-L35
There is nothing the assembler can do at this point. You have
several alternatives: alter the compiler to produce a series of
if/else tests (preferably via a -J flag); edit the assembly to be
a series of if/else tests; or restructure your C code, splitting
up the switch statement or making the cases shorter.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP: seismo!mimsy!chris ARPA/CSNet: chris at mimsy.umd.edu
More information about the Comp.lang.c
mailing list