diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-10-09 15:50:25 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-10-09 15:50:25 +0000 |
commit | 86cde393d905d784e6808e01d199675dfa3d6fcd (patch) | |
tree | dcc7d4ffbedc5308ac113fce833c31a0318fd188 /gcc | |
parent | 3cf7d3b94b2170181803828fe49030a91087a9bc (diff) | |
download | gcc-86cde393d905d784e6808e01d199675dfa3d6fcd.tar.gz |
* expmed.c (store_bit_field): Pun non-integral str_rtx modes.
Take extra care for op0 now possibly being a subreg.
(extract_bit_field): Likewise.
* function.c (purge_addressof_1): Revert Oct 4 change. Drop
the reg to memory if there is no equal sized integral mode.
* stor-layout.c (int_mode_for_mode): New function.
* machmode.h: Prototype it.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22962 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/expmed.c | 62 | ||||
-rw-r--r-- | gcc/function.c | 14 | ||||
-rw-r--r-- | gcc/machmode.h | 5 | ||||
-rw-r--r-- | gcc/stor-layout.c | 31 |
5 files changed, 106 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 436cd1d33a2..2a0bd663641 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +Fri Oct 9 15:49:29 1998 Richard Henderson <rth@cygnus.com> + + * expmed.c (store_bit_field): Pun non-integral str_rtx modes. + Take extra care for op0 now possibly being a subreg. + (extract_bit_field): Likewise. + * function.c (purge_addressof_1): Revert Oct 4 change. Drop + the reg to memory if there is no equal sized integral mode. + * stor-layout.c (int_mode_for_mode): New function. + * machmode.h: Prototype it. + Fri Oct 9 14:26:44 1998 Jeffrey A Law (law@cygnus.com) * global.c (build_insn_chain): Verify no real insns exist past the diff --git a/gcc/expmed.c b/gcc/expmed.c index f9bd9ad20be..9b285d0e23f 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -261,6 +261,21 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) op0 = SUBREG_REG (op0); } + /* Make sure we are playing with integral modes. Pun with subregs + if we aren't. */ + { + enum machine_mode imode = int_mode_for_mode (GET_MODE (op0)); + if (imode != GET_MODE (op0)) + { + if (GET_CODE (op0) == MEM) + op0 = change_address (op0, imode, NULL_RTX); + else if (imode != BLKmode) + op0 = gen_lowpart (imode, op0); + else + abort (); + } + } + /* If OP0 is a register, BITPOS must count within a word. But as we have it, it counts within whatever size OP0 now has. On a bigendian machine, these are not the same, so convert. */ @@ -287,6 +302,18 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) can be done with just SUBREG. */ if (GET_MODE (op0) != fieldmode) { + if (GET_CODE (op0) == SUBREG) + { + if (GET_MODE (SUBREG_REG (op0)) == fieldmode + || GET_MODE_CLASS (fieldmode) == MODE_INT + || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT) + op0 = SUBREG_REG (op0); + else + /* Else we've got some float mode source being extracted into + a different float mode destination -- this combination of + subregs results in Severe Tire Damage. */ + abort (); + } if (GET_CODE (op0) == REG) op0 = gen_rtx_SUBREG (fieldmode, op0, offset); else @@ -955,6 +982,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, op0 = SUBREG_REG (op0); } + /* Make sure we are playing with integral modes. Pun with subregs + if we aren't. */ + { + enum machine_mode imode = int_mode_for_mode (GET_MODE (op0)); + if (imode != GET_MODE (op0)) + { + if (GET_CODE (op0) == MEM) + op0 = change_address (op0, imode, NULL_RTX); + else if (imode != BLKmode) + op0 = gen_lowpart (imode, op0); + else + abort (); + } + } + /* ??? We currently assume TARGET is at least as big as BITSIZE. If that's wrong, the solution is to test for it and set TARGET to 0 if needed. */ @@ -973,7 +1015,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, So too extracting a subword value in the least significant part of the register. */ - if (((GET_CODE (op0) == REG + if (((GET_CODE (op0) != MEM && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode), GET_MODE_BITSIZE (GET_MODE (op0)))) || (GET_CODE (op0) == MEM @@ -996,6 +1038,18 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, if (mode1 != GET_MODE (op0)) { + if (GET_CODE (op0) == SUBREG) + { + if (GET_MODE (SUBREG_REG (op0)) == mode1 + || GET_MODE_CLASS (mode1) == MODE_INT + || GET_MODE_CLASS (mode1) == MODE_PARTIAL_INT) + op0 = SUBREG_REG (op0); + else + /* Else we've got some float mode source being extracted into + a different float mode destination -- this combination of + subregs results in Severe Tire Damage. */ + abort (); + } if (GET_CODE (op0) == REG) op0 = gen_rtx_SUBREG (mode1, op0, offset); else @@ -1088,12 +1142,12 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, /* OFFSET is the number of words or bytes (UNIT says which) from STR_RTX to the first word or byte containing part of the field. */ - if (GET_CODE (op0) == REG) + if (GET_CODE (op0) != MEM) { if (offset != 0 || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD) - op0 = gen_rtx_SUBREG (TYPE_MODE (type_for_size (BITS_PER_WORD, 0)), - op0, offset); + op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0), + op0, offset); offset = 0; } else diff --git a/gcc/function.c b/gcc/function.c index 5e607597f4f..5ad113cfc93 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2874,24 +2874,14 @@ purge_addressof_1 (loc, insn, force, store) /* Don't even consider working with paradoxical subregs, or the moral equivalent seen here. */ - if (size_x < size_sub) + if (size_x < size_sub + && int_mode_for_mode (GET_MODE (sub)) != BLKmode) { /* Do a bitfield insertion to mirror what would happen in memory. */ rtx val, seq; - /* We cannot do this if we are trying to pick out - an integral piece, smaller than a word, of a - floating point value. */ - if (INTEGRAL_MODE_P (GET_MODE (x)) - && GET_MODE_SIZE (GET_MODE (x)) < UNITS_PER_WORD - && FLOAT_MODE_P (GET_MODE (sub))) - { - put_addressof_into_stack (XEXP (x, 0)); - return; - } - if (store) { /* If we can't replace with a register, be afraid. */ diff --git a/gcc/machmode.h b/gcc/machmode.h index 119950c4348..e8c17e01642 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -211,6 +211,11 @@ extern unsigned char mode_wider_mode[]; extern enum machine_mode mode_for_size PROTO((unsigned int, enum mode_class, int)); +/* Return an integer mode of the exact same size as the input mode, + or BLKmode on failure. */ + +extern enum machine_mode int_mode_for_mode PROTO((enum machine_mode)); + /* Find the best mode to use to access a bit field. */ extern enum machine_mode get_best_mode PROTO((int, int, int, enum machine_mode, int)); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 3c7cf23d7d3..a6bf053ba76 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -176,6 +176,37 @@ smallest_mode_for_size (size, class) abort (); } +/* Find an integer mode of the exact same size, or BLKmode on failure. */ + +enum machine_mode +int_mode_for_mode (mode) + enum machine_mode mode; +{ + switch (GET_MODE_CLASS (mode)) + { + case MODE_INT: + case MODE_PARTIAL_INT: + break; + + case MODE_COMPLEX_INT: + case MODE_COMPLEX_FLOAT: + case MODE_FLOAT: + mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0); + break; + + case MODE_RANDOM: + if (mode == BLKmode) + break; + /* FALLTHRU */ + + case MODE_CC: + default: + abort(); + } + + return mode; +} + /* Return the value of VALUE, rounded up to a multiple of DIVISOR. */ tree |