This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][m68k] Fix 'value out of range' error for jump table references
- From: Maxim Kuvyrkov <maxim at codesourcery dot com>
- To: Andreas Schwab <schwab at suse dot de>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 09 Sep 2008 15:48:35 +0200
- Subject: Re: [PATCH][m68k] Fix 'value out of range' error for jump table references
- References: <479CCAF2.3070902@codesourcery.com> <jezlum2njz.fsf@sykes.suse.de>
Andreas Schwab wrote:
Maxim Kuvyrkov <maxim@codesourcery.com> writes:
Hello, Andreas,
The below patch forbids use of addressing mode 7 (PC-relative indexed with
offset) for jump table references on certain targets.
On ColdFire the offset in mode 7 must fit within 1 byte. If the jump
table is big enough (i.e., case's in switch statement contain big chunks
of code) the offset might overflow 127 bytes limit which will result in
value out of range' error at assembly-time.
That mode should only be used to address the jump table, which should be
located directly after the insn, thus the offset should be guarateed to
fit.
After a long delay I've came upon a testcase which exposes the problem.
m68k uses the following sequence to generate a tablejump:
<snip>
move.w <table>(%pc, <index> * 2), <reg>
jmp %pc@(<reg>)
(barrier)
<table>:
.word <label1> - <table>
...
.word <labelN> - <table>
</snip>
The important thing here is that move.w instruction should be close
enough to <table>. After the expand the above holds true, but
optimization passes don't see anything special about move.w <label> and,
in some cases, can move this instruction so far, that the offset to
<table> won't fit into reserved space and the assembler will fail.
I'm not sure what is the best fix in this situation. One option is to
forbid such addressing mode as per patch attached in the previous
message. Another alternative is to combine both move.w and jmp into one
define_insn. Any other suggestions?
The particular testcase I'm looking at is compiled with
m68k-uclinux-gcc -mcpu=5329 gcc.c-torture/compile/pr34688.c -c -O3
-fomit-frame-pointer -mid-shared-library
and the resultant code looks like this:
php_conv_qprint_decode_convert:
<CUT>
move.w .L7(%pc,%a0.l*2),%d3
.L14:
<CUT>
.L15:
ext.l %d3
jmp %pc@(2,%d3:l)
.balignw 2,0x284c
.L7:
.word .L3-.L7
.word .L4-.L7
.word .L5-.L7
.word .L6-.L7
.word .L6-.L7
.L4:
<CUT>
.L5:
<CUT>
.L6:
<CUT>
.L3:
<CUT>
.L17:
<CUT>
move.w .L7(%pc,%a4.l*2),%d3
jra .L15
.L18:
<CUT>
move.w .L7(%pc,%d5.l*2),%d3
jra .L15
.L10:
<CUT>
move.w .L7(%pc,%d6.l*2),%d3
jra .L14
Thanks,
Maxim