const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON | m_K6;
const int x86_cmove = m_PPRO | m_ATHLON | m_PENT4;
const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON | m_PENT4;
+const int x86_branch_hints = m_PENT4;
const int x86_use_sahf = m_PPRO | m_K6 | m_PENT4;
const int x86_partial_reg_stall = m_PPRO;
const int x86_use_loop = m_K6;
if (ASSEMBLER_DIALECT == 0 || USER_LABEL_PREFIX[0] == 0)
putc ('%', file);
- if (code == 'w')
+ if (code == 'w' || MMX_REG_P (x))
code = 2;
else if (code == 'b')
code = 1;
code = 3;
else if (code == 'h')
code = 0;
- else if (code == 'm' || MMX_REG_P (x))
- code = 5;
else
code = GET_MODE_SIZE (GET_MODE (x));
abort ();
switch (code)
{
- case 5:
+ case 0:
error ("Extended registers have no high halves\n");
break;
case 1:
}
switch (code)
{
- case 5:
- fputs (hi_reg_name[REGNO (x)], file);
- break;
case 3:
if (STACK_TOP_P (x))
{
L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
C -- print opcode suffix for set/cmov insn.
c -- like C, but print reversed condition
+ F,f -- likewise, but for floating-point.
R -- print the prefix for register names.
z -- print the opcode suffix for the size of the current operand.
* -- print a star (in certain assembler syntax)
w -- likewise, print the HImode name of the register.
k -- likewise, print the SImode name of the register.
q -- likewise, print the DImode 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.
- m -- print "st(n)" as an mmx 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.
D -- print condition for SSE cmp instruction.
+ P -- if PIC, print an @PLT suffix.
+ X -- don't print any sort of PIC '@' suffix for a symbol.
*/
void
case 'q':
case 'h':
case 'y':
- case 'm':
case 'X':
case 'P':
break;
case 'f':
put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 1, file);
return;
+ case '+':
+ {
+ rtx x;
+ if (!optimize || optimize_size || !TARGET_BRANCH_PREDICTION_HINTS)
+ return;
+
+ x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
+ if (x)
+ {
+ int pred_val = INTVAL (XEXP (x, 0));
+
+ if (pred_val < REG_BR_PROB_BASE * 45 / 100
+ || pred_val > REG_BR_PROB_BASE * 55 / 100)
+ {
+ int taken = pred_val > REG_BR_PROB_BASE / 2;
+ int cputaken = final_forward_branch_p (current_output_insn) == 0;
+
+ /* Emit hints only in the case default branch prediction
+ heruistics would fail. */
+ if (taken != cputaken)
+ {
+ /* We use 3e (DS) prefix for taken branches and
+ 2e (CS) prefix for not taken branches. */
+ if (taken)
+ fputs ("ds ; ", file);
+ else
+ fputs ("cs ; ", file);
+ }
+ }
+ }
+ return;
+ }
default:
{
char str[50];
#define CPUMASK (1 << ix86_cpu)
extern const int x86_use_leave, x86_push_memory, x86_zero_extend_with_and;
extern const int x86_use_bit_test, x86_cmove, x86_deep_branch;
-extern const int x86_unroll_strlen;
+extern const int x86_branch_hints, x86_unroll_strlen;
extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx;
extern const int x86_use_loop, x86_use_fiop, x86_use_mov0;
extern const int x86_use_cltd, x86_read_modify_write;
safe to enable all CMOVE instructions. */
#define TARGET_CMOVE ((x86_cmove & (1 << ix86_arch)) || TARGET_SSE)
#define TARGET_DEEP_BRANCH_PREDICTION (x86_deep_branch & CPUMASK)
+#define TARGET_BRANCH_PREDICTION_HINTS (x86_branch_hints & CPUMASK)
#define TARGET_DOUBLE_WITH_ADD (x86_double_with_add & CPUMASK)
#define TARGET_USE_SAHF ((x86_use_sahf & CPUMASK) && !TARGET_64BIT)
#define TARGET_MOVX (x86_movx & CPUMASK)
For float regs, the stack top is sometimes referred to as "%st(0)"
instead of just "%st". PRINT_REG handles this with the "y" code. */
-#define HI_REGISTER_NAMES \
-{"ax","dx","cx","bx","si","di","bp","sp", \
- "st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)","", \
- "flags","fpsr", "dirflag", "frame" }
-
#undef HI_REGISTER_NAMES
#define HI_REGISTER_NAMES \
{"ax","dx","cx","bx","si","di","bp","sp", \
#define QI_HIGH_REGISTER_NAMES \
{"ah", "dh", "ch", "bh", }
-#define MMX_REGISTER_NAMES \
-{0,0,0,0,0,0,0,0,"mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"}
-
/* How to renumber registers for dbx and gdb. */
#define DBX_REGISTER_NUMBER(n) \
\f
/* Print operand X (an rtx) in assembler syntax to file FILE.
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
- The CODE z takes the size of operand from the following digit, and
- outputs b,w,or l respectively.
-
- On the 80386, we use several such letters:
- f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
- L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
- R -- print the prefix for register names.
- z -- print the opcode suffix for the size of the current operand.
- * -- print a star (in certain assembler syntax)
- A -- print an absolute memory reference.
- P -- if PIC, print an @PLT suffix.
- X -- don't print any sort of PIC '@' suffix for a symbol.
- s -- ??? something to do with double shifts. not actually used, afaik.
- C -- print a conditional move suffix corresponding to the op code.
- c -- likewise, but reverse the condition.
- F,f -- likewise, but for floating-point. */
+ Effect of various CODE letters is described in i386.c near
+ print_operand function. */
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
- ((CODE) == '*')
+ ((CODE) == '*' || (CODE) == '+')
/* Print the name of a register based on its machine mode and number.
If CODE is 'w', pretend the mode is HImode.
If CODE is 'b', pretend the mode is QImode.
If CODE is 'k', pretend the mode is SImode.
- If CODE is 'd', pretend the mode is DImode.
+ If CODE is 'q', pretend the mode is DImode.
If CODE is 'h', pretend the reg is the `high' byte register.
- If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */
+ If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */
#define PRINT_REG(X, CODE, FILE) \
print_reg (X, CODE, FILE)
"TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
"
{
- if (TARGET_SSE2)
+ if (TARGET_SSE2 && TARGET_64BIT)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
emit_insn (gen_fix_truncdfdi_sse (out, operands[1]));
"TARGET_80387 || (TARGET_SSE && TARGET_64BIT)"
"
{
- if (TARGET_SSE2)
+ if (TARGET_SSE2 && TARGET_64BIT)
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
emit_insn (gen_fix_truncsfdi_sse (out, operands[1]));
"(TARGET_SSE && TARGET_64BIT) || TARGET_80387"
"")
+(define_insn "*floatdisf2_i387_only"
+ [(set (match_operand:SF 0 "register_operand" "=f,?f")
+ (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
+ "TARGET_80387 && (!TARGET_SSE || !TARGET_64BIT || TARGET_MIX_SSE_I387)"
+ "@
+ fild%z1\\t%1
+ #"
+ [(set_attr "type" "fmov,multi")
+ (set_attr "mode" "SF")
+ (set_attr "fp_int_src" "true")])
+
(define_insn "*floatdisf2_i387"
[(set (match_operand:SF 0 "register_operand" "=f,?f,x")
(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,mr")))]
- "TARGET_80387 && (!TARGET_SSE || !TARGET_64BIT || TARGET_MIX_SSE_I387)"
+ "TARGET_80387 && TARGET_64BIT && (!TARGET_SSE || TARGET_MIX_SSE_I387)"
"@
fild%z1\\t%1
#
"TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
"")
+(define_insn "*floatdidf2_i387_only"
+ [(set (match_operand:DF 0 "register_operand" "=f,?f")
+ (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
+ "TARGET_80387 && (!TARGET_SSE2 || !TARGET_64BIT)"
+ "@
+ fild%z1\\t%1
+ #"
+ [(set_attr "type" "fmov,multi")
+ (set_attr "mode" "DF")
+ (set_attr "fp_int_src" "true")])
+
(define_insn "*floatdidf2_i387"
[(set (match_operand:DF 0 "register_operand" "=f,?f,Y")
(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,mr")))]
- "TARGET_80387 && (!TARGET_SSE2 || !TARGET_64BIT || TARGET_MIX_SSE_I387)"
+ "TARGET_80387 && TARGET_64BIT && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)"
"@
fild%z1\\t%1
#
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
+ /* Avoid overflows. */
+ && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
+ /* Avoid overflows. */
+ && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
+ /* Avoid overflows. */
+ && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if ((INTVAL (operands[2]) == -128
|| (INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) != 128)))
+ && INTVAL (operands[2]) != 128))
+ /* Avoid overflows. */
+ && ((INTVAL (operands[2]) & ((1 << 31) - 1))))
return \"sub{q}\\t{%2, %0|%0, %2}\";
operands[2] = GEN_INT (-INTVAL (operands[2]));
return \"add{q}\\t{%2, %0|%0, %2}\";
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
+ /* Avoid overflows. */
+ && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
&& (INTVAL (operands[2]) == 128
|| (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) != -128)))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "j%C1\\t%l0"
+ "%+j%C1\\t%l0"
[(set_attr "type" "ibr")
(set (attr "prefix_0f")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "j%c1\\t%l0"
+ "%+j%c1\\t%l0"
[(set_attr "type" "ibr")
(set (attr "prefix_0f")
(if_then_else (and (ge (minus (match_dup 0) (pc))
if (which_alternative != 0)
return \"#\";
if (get_attr_length (insn) == 2)
- return \"loop\\t%l0\";
+ return \"%+loop\\t%l0\";
else
- return \"dec{l}\\t%1\;jne\\t%l0\";
+ return \"dec{l}\\t%1\;%+jne\\t%l0\";
}"
[(set_attr "ppro_uops" "many")
(set (attr "type")
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:DF 4 "nonimmediate_operand" "")))
(clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed"
+ "SSE_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (match_dup 0)
(if_then_else:SF (lt (match_dup 1)
(match_dup 2))
(match_dup 2)))])
;; We can't represent the LT test directly. Do this by swapping the operands.
+
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "register_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed"
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:DF 4 "register_operand" "")))
+ (clobber (reg:CC 17))]
+ "FP_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP 17)
(compare:CCFP (match_dup 2)
(match_dup 1)))
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:DF 4 "nonimmediate_operand" "")))
(clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed"
+ "SSE_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (match_dup 0)
(if_then_else:DF (lt (match_dup 1)
(match_dup 2))
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "register_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed"
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:DF 4 "register_operand" "")))
+ (clobber (reg:CC 17))]
+ "FP_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP 17)
(compare:CCFP (match_dup 2)
(match_dup 2)))
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
+ (match_operand:SF 3 "register_operand" "")
+ (match_operand:SF 4 "nonimmediate_operand" "")))
(clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed"
+ "SSE_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (match_dup 0)
(if_then_else:SF (gt (match_dup 1)
(match_dup 2))
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "register_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed"
+ (match_operand:SF 3 "register_operand" "")
+ (match_operand:SF 4 "register_operand" "")))
+ (clobber (reg:CC 17))]
+ "FP_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP 17)
(compare:CCFP (match_dup 1)
(match_dup 2)))
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:DF 4 "nonimmediate_operand" "")))
(clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed"
+ "SSE_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (match_dup 0)
(if_then_else:DF (gt (match_dup 1)
(match_dup 2))
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "register_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed"
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:DF 4 "register_operand" "")))
+ (clobber (reg:CC 17))]
+ "FP_REG_P (operands[0]) && reload_completed
+ && ((operands_match_p (operands[1], operands[3])
+ && operands_match_p (operands[2], operands[4]))
+ || (operands_match_p (operands[1], operands[4])
+ && operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP 17)
(compare:CCFP (match_dup 1)
(match_dup 2)))