aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorHans-Peter Nilsson <hp@bitrange.com>2003-03-09 01:32:42 +0000
committerHans-Peter Nilsson <hp@gcc.gnu.org>2003-03-09 01:32:42 +0000
commita3600c718eb2abf543cd17458e98899958cdd839 (patch)
tree5939b9c628058a9aab673e2656bd7d35a9246792 /gcc/expr.c
parenta6e464ae019d39af515fe0e2be9a949ed75bce92 (diff)
downloadgcc-a3600c718eb2abf543cd17458e98899958cdd839.zip
gcc-a3600c718eb2abf543cd17458e98899958cdd839.tar.gz
gcc-a3600c718eb2abf543cd17458e98899958cdd839.tar.bz2
optabs.c (gen_move_insn): Move logic for synthesizing MODE_CC moves from here ...
* optabs.c (gen_move_insn): Move logic for synthesizing MODE_CC moves from here ... * expr.c (emit_move_insn_1): ... to here. From-SVN: r64015
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index c0119af..46b264e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -3384,6 +3384,61 @@ emit_move_insn_1 (x, y)
return get_last_insn ();
}
+ /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
+ find a mode to do it in. If we have a movcc, use it. Otherwise,
+ find the MODE_INT mode of the same width. */
+ else if (GET_MODE_CLASS (mode) == MODE_CC
+ && mov_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
+ {
+ enum insn_code insn_code;
+ enum machine_mode tmode = VOIDmode;
+ rtx x1 = x, y1 = y;
+
+ if (mode != CCmode
+ && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
+ tmode = CCmode;
+ else
+ for (tmode = QImode; tmode != VOIDmode;
+ tmode = GET_MODE_WIDER_MODE (tmode))
+ if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
+ break;
+
+ if (tmode == VOIDmode)
+ abort ();
+
+ /* Get X and Y in TMODE. We can't use gen_lowpart here because it
+ may call change_address which is not appropriate if we were
+ called when a reload was in progress. We don't have to worry
+ about changing the address since the size in bytes is supposed to
+ be the same. Copy the MEM to change the mode and move any
+ substitutions from the old MEM to the new one. */
+
+ if (reload_in_progress)
+ {
+ x = gen_lowpart_common (tmode, x1);
+ if (x == 0 && GET_CODE (x1) == MEM)
+ {
+ x = adjust_address_nv (x1, tmode, 0);
+ copy_replacements (x1, x);
+ }
+
+ y = gen_lowpart_common (tmode, y1);
+ if (y == 0 && GET_CODE (y1) == MEM)
+ {
+ y = adjust_address_nv (y1, tmode, 0);
+ copy_replacements (y1, y);
+ }
+ }
+ else
+ {
+ x = gen_lowpart (tmode, x);
+ y = gen_lowpart (tmode, y);
+ }
+
+ insn_code = mov_optab->handlers[(int) tmode].insn_code;
+ return emit_insn (GEN_FCN (insn_code) (x, y));
+ }
+
/* This will handle any multi-word or full-word mode that lacks a move_insn
pattern. However, you will get better code if you define such patterns,
even if they must turn into multiple assembler instructions. */