diff options
author | Richard Henderson <rth@redhat.com> | 2004-11-08 11:18:16 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2004-11-08 11:18:16 -0800 |
commit | 14c8e213350820ffc12ac6b8528c81732e7b6a90 (patch) | |
tree | 05875fc07773a13ef841f991578d7e0b84c9a533 /gcc | |
parent | c66a43689eeb6a9014b2b6cbd49b2c745e3d7d69 (diff) | |
download | gcc-14c8e213350820ffc12ac6b8528c81732e7b6a90.zip gcc-14c8e213350820ffc12ac6b8528c81732e7b6a90.tar.gz gcc-14c8e213350820ffc12ac6b8528c81732e7b6a90.tar.bz2 |
expmed.c (extract_force_align_mem_bit_field): Correct handling at the end of a page.
* expmed.c (extract_force_align_mem_bit_field): Correct handling at
the end of a page.
From-SVN: r90288
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/expmed.c | 16 |
2 files changed, 17 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index da58911..3e43541 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2004-11-08 Richard Henderson <rth@redhat.com> + + * expmed.c (extract_force_align_mem_bit_field): Correct handling at + the end of a page. + 2004-11-08 Kazu Hirata <kazu@cs.umass.edu> * sched-deps.c (add_insn_mem_dependence): Make it static. diff --git a/gcc/expmed.c b/gcc/expmed.c index a108efa..191df72 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1891,11 +1891,16 @@ extract_force_align_mem_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, if (STRICT_ALIGNMENT) { base = plus_constant (XEXP (op0, 0), bitpos / BITS_PER_UNIT); - base = force_operand (base, NULL); bitpos %= BITS_PER_UNIT; - /* Force alignment of the address; load two sequential values. */ - a1 = expand_simple_binop (Pmode, AND, base, + /* We load two values to be concatenate. There's an edge condition + that bears notice -- an aligned value at the end of a page can + only load one value lest we segfault. So the two values we load + are at "base & -size" and "(base + size - 1) & -size". If base + is unaligned, the addresses will be aligned and sequential; if + base is aligned, the addresses will both be equal to base. */ + + a1 = expand_simple_binop (Pmode, AND, force_operand (base, NULL), GEN_INT (-(HOST_WIDE_INT)m_size), NULL, true, OPTAB_LIB_WIDEN); mark_reg_pointer (a1, m_bitsize); @@ -1903,7 +1908,10 @@ extract_force_align_mem_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, set_mem_align (v1, m_bitsize); v1 = force_reg (mode, validize_mem (v1)); - a2 = plus_constant (a1, GET_MODE_SIZE (mode)); + a2 = plus_constant (base, GET_MODE_SIZE (mode) - 1); + a2 = expand_simple_binop (Pmode, AND, force_operand (a2, NULL), + GEN_INT (-(HOST_WIDE_INT)m_size), + NULL, true, OPTAB_LIB_WIDEN); v2 = gen_rtx_MEM (mode, a2); set_mem_align (v2, m_bitsize); v2 = force_reg (mode, validize_mem (v2)); |