Commit 4af3895e by James Van Artsdalen

*** empty log message ***

From-SVN: r731
parent dcfedcd0
...@@ -976,8 +976,6 @@ print_operand (file, x, code) ...@@ -976,8 +976,6 @@ print_operand (file, x, code)
putc ('*', file); putc ('*', file);
return; return;
case 'D':
PUT_OP_SIZE (code, 'l', file);
case 'L': case 'L':
PUT_OP_SIZE (code, 'l', file); PUT_OP_SIZE (code, 'l', file);
return; return;
...@@ -998,10 +996,6 @@ print_operand (file, x, code) ...@@ -998,10 +996,6 @@ print_operand (file, x, code)
PUT_OP_SIZE (code, 's', file); PUT_OP_SIZE (code, 's', file);
return; return;
case 'R':
fprintf (file, "%s", RP);
return;
case 'z': case 'z':
/* 387 opcodes don't get size suffixes if the operands are /* 387 opcodes don't get size suffixes if the operands are
registers. */ registers. */
...@@ -1037,6 +1031,17 @@ print_operand (file, x, code) ...@@ -1037,6 +1031,17 @@ print_operand (file, x, code)
PUT_OP_SIZE ('Q', 'l', file); PUT_OP_SIZE ('Q', 'l', file);
return; return;
} }
case 'b':
case 'w':
case 'k':
case 'h':
case 'y':
case 'P':
break;
default:
abort ();
} }
} }
if (GET_CODE (x) == REG) if (GET_CODE (x) == REG)
...@@ -1063,13 +1068,8 @@ print_operand (file, x, code) ...@@ -1063,13 +1068,8 @@ print_operand (file, x, code)
u.i[0] = CONST_DOUBLE_LOW (x); u.i[0] = CONST_DOUBLE_LOW (x);
u.i[1] = CONST_DOUBLE_HIGH (x); u.i[1] = CONST_DOUBLE_HIGH (x);
u1.f = u.d; u1.f = u.d;
if (code == 'f') PRINT_IMMED_PREFIX (file);
fprintf (file, "%.22e", u1.f); fprintf (file, "0x%x", u1.i);
else
{
PRINT_IMMED_PREFIX (file);
fprintf (file, "0x%x", u1.i);
}
} }
else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
{ {
...@@ -1080,7 +1080,7 @@ print_operand (file, x, code) ...@@ -1080,7 +1080,7 @@ print_operand (file, x, code)
} }
else else
{ {
if (code != 'c' && code != 'P') if (code != 'P')
{ {
if (GET_CODE (x) == CONST_INT) if (GET_CODE (x) == CONST_INT)
PRINT_IMMED_PREFIX (file); PRINT_IMMED_PREFIX (file);
......
...@@ -19,37 +19,41 @@ ...@@ -19,37 +19,41 @@
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
;;- instruction definitions ;; The original PO technology requires these to be ordered by speed,
;; so that assigner will pick the fastest.
;;- @@The original PO technology requires these to be ordered by speed, ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;- @@ so that assigner will pick the fastest.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. ;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code
;; updates for most instructions.
;;- When naming insn's (operand 0 of define_insn) be careful about using ;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register
;;- names from other targets machine descriptions. ;; constraint letters.
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.
;;- Operand classes for the register allocator:
;;- 'a' for eax
;;- 'd' for edx
;;- 'c' for ecx
;;- 'b' for ebx
;;- 'f' for anything in FLOAT_REGS
;;- 'r' any (non-floating-point) register
;;- 'q' regs that allow byte operations (A, B, C and D)
;;- 'A' A and D registers
;; the special asm out single letter directives following a '%' are: ;; the special asm out single letter directives following a '%' are:
;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of operands[1] ;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of
;; 's' output a '*' ;; operands[1].
;; 'w' If the operand is a REG, it uses the mode size to determine the ;; 'L' Print the opcode suffix for a 32-bit integer opcode.
;; printing of the reg ;; 'W' Print the opcode suffix for a 16-bit integer opcode.
;; 'B' Print the opcode suffix for an 8-bit integer opcode.
;; 'S' Print the opcode suffix for a 32-bit float opcode.
;; 'Q' Print the opcode suffix for a 64-bit float opcode.
;; 'b' Print the QImode name of the register for the indicated operand.
;; %b0 would print %al if operands[0] is reg 0.
;; 'w' Likewise, print the HImode name of the register.
;; 'k' Likewise, print the SImode name of the register.
;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
;; 'y' Print "st(0)" instead of "st" as a register.
;; UNSPEC usage:
;; 0 This is a `scas' operation. The mode of the UNSPEC is always SImode.
;; operand 0 is the memory address to scan.
;; operand 1 is a register containing the value to scan for. The mode
;; of the scas opcode will be the same as the mode of this operand.
;; operand 2 is the known alignment of operand 0.
;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". ;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".
;; But restricting MEM here would mean that gcc could not remove a redundant ;; But restricting MEM here would mean that gcc could not remove a redundant
;; test in cases like "incl MEM / je TARGET". ;; test in cases like "incl MEM / je TARGET".
...@@ -2573,9 +2577,9 @@ ...@@ -2573,9 +2577,9 @@
(define_insn "" (define_insn ""
[(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm") [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm")
(const_int 1) (const_int 1)
(match_operand:SI 2 "nonimmediate_operand" "r")) (match_operand:SI 2 "general_operand" "r"))
(match_operand:SI 3 "immediate_operand" "i"))] (match_operand:SI 3 "immediate_operand" "i"))]
"! TARGET_486" "! TARGET_486 && GET_CODE (operands[2]) != CONST_INT"
"* "*
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
...@@ -2593,7 +2597,7 @@ ...@@ -2593,7 +2597,7 @@
(xor:SI (ashift:SI (const_int 1) (xor:SI (ashift:SI (const_int 1)
(match_operand:SI 1 "general_operand" "r")) (match_operand:SI 1 "general_operand" "r"))
(match_dup 0)))] (match_dup 0)))]
"! TARGET_486" "! TARGET_486 && GET_CODE (operands[1]) != CONST_INT"
"* "*
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
...@@ -2629,117 +2633,14 @@ ...@@ -2629,117 +2633,14 @@
;; constraint. ;; constraint.
(define_insn "" (define_insn ""
[(set (cc0) (zero_extract (match_operand:QI 0 "register_operand" "q")
(const_int 1)
(match_operand:SI 1 "general_operand" "ri")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT)
{
operands[1] = gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (operands[1]));
output_asm_insn (AS2 (test%B0,%1,%0), operands);
}
else
{
operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]));
cc_status.flags |= CC_Z_IN_NOT_C;
output_asm_insn (AS2 (bt%L0,%1,%0), operands);
}
RET;
}")
;; ??? The first argument of a zero_extract must not be reloaded, so
;; don't allow a MEM in the operand predicate without allowing it in the
;; constraint.
(define_insn ""
[(set (cc0) (zero_extract (match_operand:HI 0 "register_operand" "r")
(const_int 1)
(match_operand:SI 1 "general_operand" "ri")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT)
{
if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 8)
{
cc_status.flags |= CC_NOT_NEGATIVE;
operands[1] = gen_rtx (CONST_INT, VOIDmode,
1 << INTVAL (operands[1]));
output_asm_insn (AS2 (test%B0,%1,%b0), operands);
}
else if (QI_REG_P (operands[0]))
{
operands[1] = gen_rtx (CONST_INT, VOIDmode,
1 << (INTVAL (operands[1]) - 8));
output_asm_insn (AS2 (test%B0,%1,%h0), operands);
}
else
{
/* ??? This will never set CC to negative, even if we test
the sign bit of the HImode reg. But CC0 is only tested
for EQ and NE after this insn. */
operands[1] = gen_rtx (CONST_INT, VOIDmode,
1 << INTVAL (operands[1]));
output_asm_insn (AS2 (test%L0,%1,%k0), operands);
}
}
else
{
cc_status.flags |= CC_Z_IN_NOT_C;
output_asm_insn (AS2 (bt%W0,%1,%0), operands);
}
RET;
}")
;; ??? The first argument of a zero_extract must not be reloaded, so
;; don't allow a MEM in the operand predicate without allowing it in the
;; constraint.
(define_insn ""
[(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
(const_int 1) (const_int 1)
(match_operand:SI 1 "general_operand" "ri")))] (match_operand:SI 1 "general_operand" "r")))]
"" "GET_CODE (operands[1]) != CONST_INT"
"* "*
{ {
if (GET_CODE (operands[1]) == CONST_INT) cc_status.flags |= CC_Z_IN_NOT_C;
{ return AS2 (bt%L0,%1,%0);
if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 8)
{
cc_status.flags |= CC_NOT_NEGATIVE;
operands[1] = gen_rtx (CONST_INT, VOIDmode,
1 << INTVAL (operands[1]));
output_asm_insn (AS2 (test%B0,%1,%b0), operands);
}
else if (QI_REG_P (operands[0]) && INTVAL (operands[1]) < 16)
{
cc_status.flags |= CC_NOT_NEGATIVE;
operands[1] = gen_rtx (CONST_INT, VOIDmode,
1 << (INTVAL (operands[1]) - 8));
output_asm_insn (AS2 (test%B0,%1,%h0), operands);
}
else
{
operands[1] = gen_rtx (CONST_INT, VOIDmode,
1 << INTVAL (operands[1]));
output_asm_insn (AS2 (test%L0,%1,%0), operands);
}
}
else
{
cc_status.flags |= CC_Z_IN_NOT_C;
output_asm_insn (AS2 (bt%L0,%1,%0), operands);
}
RET;
}") }")
;; Store-flag instructions. ;; Store-flag instructions.
......
...@@ -2204,6 +2204,8 @@ store_constructor (exp, target) ...@@ -2204,6 +2204,8 @@ store_constructor (exp, target)
tree exp; tree exp;
rtx target; rtx target;
{ {
tree type = TREE_TYPE (exp);
/* We know our target cannot conflict, since safe_from_p has been called. */ /* We know our target cannot conflict, since safe_from_p has been called. */
#if 0 #if 0
/* Don't try copying piece by piece into a hard register /* Don't try copying piece by piece into a hard register
...@@ -2218,19 +2220,25 @@ store_constructor (exp, target) ...@@ -2218,19 +2220,25 @@ store_constructor (exp, target)
} }
#endif #endif
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
|| TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
{ {
register tree elt; register tree elt;
if (TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE) /* Inform later passes that the whole union value is dead. */
/* Inform later passes that the whole union value is dead. */ if (TREE_CODE (type) == UNION_TYPE)
emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
/* If we are building a static constructor into a register,
set the initial value as zero so we can fold the value into
a constant. */
else if (GET_CODE (target) == REG && TREE_STATIC (exp))
emit_move_insn (target, const0_rtx);
/* If the constructor has fewer fields than the structure, /* If the constructor has fewer fields than the structure,
clear the whole structure first. */ clear the whole structure first. */
else if (list_length (CONSTRUCTOR_ELTS (exp)) else if (list_length (CONSTRUCTOR_ELTS (exp))
!= list_length (TYPE_FIELDS (TREE_TYPE (exp)))) != list_length (TYPE_FIELDS (type)))
clear_storage (target, int_size_in_bytes (TREE_TYPE (exp))); clear_storage (target, int_size_in_bytes (type));
else else
/* Inform later passes that the old value is dead. */ /* Inform later passes that the old value is dead. */
emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
...@@ -2262,23 +2270,25 @@ store_constructor (exp, target) ...@@ -2262,23 +2270,25 @@ store_constructor (exp, target)
/* The alignment of TARGET is /* The alignment of TARGET is
at least what its type requires. */ at least what its type requires. */
VOIDmode, 0, VOIDmode, 0,
TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT, TYPE_ALIGN (type) / BITS_PER_UNIT,
int_size_in_bytes (TREE_TYPE (exp))); int_size_in_bytes (type));
} }
} }
else if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) else if (TREE_CODE (type) == ARRAY_TYPE)
{ {
register tree elt; register tree elt;
register int i; register int i;
tree domain = TYPE_DOMAIN (TREE_TYPE (exp)); tree domain = TYPE_DOMAIN (type);
int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)); int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)); int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
tree elttype = TREE_TYPE (TREE_TYPE (exp)); tree elttype = TREE_TYPE (type);
/* If the constructor has fewer fields than the structure, /* If the constructor has fewer fields than the structure,
clear the whole structure first. */ clear the whole structure first. Similarly if this this is
static constructor of a non-BLKmode object. */
if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1) if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1
|| (GET_CODE (target) == REG && TREE_STATIC (exp)))
clear_storage (target, maxelt - minelt + 1); clear_storage (target, maxelt - minelt + 1);
else else
/* Inform later passes that the old value is dead. */ /* Inform later passes that the old value is dead. */
...@@ -2306,8 +2316,8 @@ store_constructor (exp, target) ...@@ -2306,8 +2316,8 @@ store_constructor (exp, target)
/* The alignment of TARGET is /* The alignment of TARGET is
at least what its type requires. */ at least what its type requires. */
VOIDmode, 0, VOIDmode, 0,
TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT, TYPE_ALIGN (type) / BITS_PER_UNIT,
int_size_in_bytes (TREE_TYPE (exp))); int_size_in_bytes (type));
} }
} }
...@@ -2930,7 +2940,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -2930,7 +2940,7 @@ expand_expr (exp, target, tmode, modifier)
if (DECL_RTL (exp) == 0) if (DECL_RTL (exp) == 0)
{ {
error_with_decl (exp, "prior parameter's size depends on `%s'"); error_with_decl (exp, "prior parameter's size depends on `%s'");
return const0_rtx; return CONST0_RTX (mode);
} }
case FUNCTION_DECL: case FUNCTION_DECL:
...@@ -2968,6 +2978,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -2968,6 +2978,7 @@ expand_expr (exp, target, tmode, modifier)
addr = fix_lexical_addr (addr, exp); addr = fix_lexical_addr (addr, exp);
return change_address (DECL_RTL (exp), mode, addr); return change_address (DECL_RTL (exp), mode, addr);
} }
/* This is the case of an array whose size is to be determined /* This is the case of an array whose size is to be determined
from its initializer, while the initializer is still being parsed. from its initializer, while the initializer is still being parsed.
See expand_decl. */ See expand_decl. */
...@@ -3125,10 +3136,11 @@ expand_expr (exp, target, tmode, modifier) ...@@ -3125,10 +3136,11 @@ expand_expr (exp, target, tmode, modifier)
return RTL_EXPR_RTL (exp); return RTL_EXPR_RTL (exp);
case CONSTRUCTOR: case CONSTRUCTOR:
/* All elts simple constants => refer to a constant in memory. */ /* All elts simple constants => refer to a constant in memory. But
if (TREE_STATIC (exp)) if this is a non-BLKmode mode, let it store a field at a time
/* For aggregate types with non-BLKmode modes, since that should make a CONST_INT or CONST_DOUBLE when we
this should ideally construct a CONST_INT. */ fold. */
if (TREE_STATIC (exp) && (mode == BLKmode || TREE_ADDRESSABLE (exp)))
{ {
rtx constructor = output_constant_def (exp); rtx constructor = output_constant_def (exp);
if (! memory_address_p (GET_MODE (constructor), if (! memory_address_p (GET_MODE (constructor),
...@@ -3290,13 +3302,36 @@ expand_expr (exp, target, tmode, modifier) ...@@ -3290,13 +3302,36 @@ expand_expr (exp, target, tmode, modifier)
} }
/* If this is a constant index into a constant array, /* If this is a constant index into a constant array,
just get the value from the array. */ just get the value from the array. Handle both the cases when
if (TREE_READONLY (TREE_OPERAND (exp, 0)) we have an explicit constructor and when our operand is a variable
&& ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) that was declared const. */
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE
&& TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL if (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
&& DECL_INITIAL (TREE_OPERAND (exp, 0)) && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
&& TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0))) != ERROR_MARK) {
tree index = fold (TREE_OPERAND (exp, 1));
if (TREE_CODE (index) == INTEGER_CST
&& TREE_INT_CST_HIGH (index) == 0)
{
int i = TREE_INT_CST_LOW (index);
tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
while (elem && i--)
elem = TREE_CHAIN (elem);
if (elem)
return expand_expr (fold (TREE_VALUE (elem)), target,
tmode, modifier);
}
}
else if (TREE_READONLY (TREE_OPERAND (exp, 0))
&& ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE
&& TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
&& DECL_INITIAL (TREE_OPERAND (exp, 0))
&& optimize >= 1
&& (TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0)))
!= ERROR_MARK))
{ {
tree index = fold (TREE_OPERAND (exp, 1)); tree index = fold (TREE_OPERAND (exp, 1));
if (TREE_CODE (index) == INTEGER_CST if (TREE_CODE (index) == INTEGER_CST
...@@ -3328,6 +3363,19 @@ expand_expr (exp, target, tmode, modifier) ...@@ -3328,6 +3363,19 @@ expand_expr (exp, target, tmode, modifier)
case COMPONENT_REF: case COMPONENT_REF:
case BIT_FIELD_REF: case BIT_FIELD_REF:
/* If the operand is a CONSTRUCTOR, we can just extract the
appropriate field if it is present. */
if (code != ARRAY_REF
&& TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR)
{
tree elt;
for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
elt = TREE_CHAIN (elt))
if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1))
return expand_expr (TREE_VALUE (elt), target, tmode, modifier);
}
{ {
enum machine_mode mode1; enum machine_mode mode1;
int bitsize; int bitsize;
...@@ -4736,7 +4784,10 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -4736,7 +4784,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
lab2 = gen_label_rtx (); lab2 = gen_label_rtx ();
/* By default check the arguments. If flag_fast_math is turned on, /* By default check the arguments. If flag_fast_math is turned on,
then assume sqrt will always be called with valid arguments. */ then assume sqrt will always be called with valid arguments.
Note changing the test below from "> 0" to ">= 0" would cause
incorrect results when computing sqrt(-0.0). */
if (! flag_fast_math) if (! flag_fast_math)
{ {
/* By checking op > 0 we are able to catch all of the /* By checking op > 0 we are able to catch all of the
...@@ -4745,8 +4796,11 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -4745,8 +4796,11 @@ expand_builtin (exp, target, subtarget, mode, ignore)
GET_MODE (op0), 0, 0); GET_MODE (op0), 0, 0);
emit_jump_insn (gen_bgt (lab1)); emit_jump_insn (gen_bgt (lab1));
/* The argument was not in the domain; do this via library call. */ /* The argument was not in the domain; do this via library call.
Pop the arguments right away in case the call gets deleted. */
NO_DEFER_POP;
expand_call (exp, target, 0, 0); expand_call (exp, target, 0, 0);
OK_DEFER_POP;
/* Branch around open coded version */ /* Branch around open coded version */
emit_jump_insn (gen_jump (lab2)); emit_jump_insn (gen_jump (lab2));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment