len = 1;
}
- /* Direct Addressing. */
+ /* Direct Addressing. In 64-bit mode mod 00 r/m 5
+ is not disp32, but disp32(%rip), so for disp32
+ SIB byte is needed, unless print_operand_address
+ optimizes it into disp32(%rip) or (%rip) is implied
+ by UNSPEC. */
else if (disp && !base && !index)
- len = 4;
+ {
+ len = 4;
+ if (TARGET_64BIT)
+ {
+ rtx symbol = disp;
+
+ if (GET_CODE (disp) == CONST)
+ symbol = XEXP (disp, 0);
+ if (GET_CODE (symbol) == PLUS
+ && CONST_INT_P (XEXP (symbol, 1)))
+ symbol = XEXP (symbol, 0);
+
+ if (GET_CODE (symbol) != LABEL_REF
+ && (GET_CODE (symbol) != SYMBOL_REF
+ || SYMBOL_REF_TLS_MODEL (symbol) != 0)
+ && (GET_CODE (symbol) != UNSPEC
+ || (XINT (symbol, 1) != UNSPEC_GOTPCREL
+ && XINT (symbol, 1) != UNSPEC_GOTNTPOFF)))
+ len += 1;
+ }
+ }
else
{
/* ebp always wants a displacement. Similarly r13. */
else if (REG_P (base)
&& (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
- len = 1;
+ len = 1;
/* An index requires the two-byte modrm form.... */
if (index
len += 1;
}
+ switch (parts.seg)
+ {
+ case SEG_FS:
+ case SEG_GS:
+ len += 1;
+ break;
+ default:
+ break;
+ }
+
return len;
}
for (i = recog_data.n_operands - 1; i >= 0; --i)
if (CONSTANT_P (recog_data.operand[i]))
{
+ enum attr_mode mode = get_attr_mode (insn);
+
gcc_assert (!len);
- if (shortform && satisfies_constraint_K (recog_data.operand[i]))
- len = 1;
- else
+ if (shortform && CONST_INT_P (recog_data.operand[i]))
{
- switch (get_attr_mode (insn))
+ HOST_WIDE_INT ival = INTVAL (recog_data.operand[i]);
+ switch (mode)
{
- case MODE_QI:
- len+=1;
- break;
- case MODE_HI:
- len+=2;
- break;
- case MODE_SI:
- len+=4;
- break;
- /* Immediates for DImode instructions are encoded as 32bit sign extended values. */
- case MODE_DI:
- len+=4;
- break;
- default:
- fatal_insn ("unknown insn mode", insn);
+ case MODE_QI:
+ len = 1;
+ continue;
+ case MODE_HI:
+ ival = trunc_int_for_mode (ival, HImode);
+ break;
+ case MODE_SI:
+ ival = trunc_int_for_mode (ival, SImode);
+ break;
+ default:
+ break;
+ }
+ if (IN_RANGE (ival, -128, 127))
+ {
+ len = 1;
+ continue;
}
}
+ switch (mode)
+ {
+ case MODE_QI:
+ len = 1;
+ break;
+ case MODE_HI:
+ len = 2;
+ break;
+ case MODE_SI:
+ len = 4;
+ break;
+ /* Immediates for DImode instructions are encoded as 32bit sign extended values. */
+ case MODE_DI:
+ len = 4;
+ break;
+ default:
+ fatal_insn ("unknown insn mode", insn);
+ }
}
return len;
}
for (i = recog_data.n_operands - 1; i >= 0; --i)
if (MEM_P (recog_data.operand[i]))
{
+ constrain_operands_cached (reload_completed);
+ if (which_alternative != -1)
+ {
+ const char *constraints = recog_data.constraints[i];
+ int alt = which_alternative;
+
+ while (*constraints == '=' || *constraints == '+')
+ constraints++;
+ while (alt-- > 0)
+ while (*constraints++ != ',')
+ ;
+ /* Skip ignored operands. */
+ if (*constraints == 'X')
+ continue;
+ }
return memory_address_length (XEXP (recog_data.operand[i], 0));
- break;
}
return 0;
}
if (REG_P (recog_data.operand[i]))
{
/* REX.W bit uses 3 byte VEX prefix. */
- if (GET_MODE (recog_data.operand[i]) == DImode)
+ if (GET_MODE (recog_data.operand[i]) == DImode
+ && GENERAL_REG_P (recog_data.operand[i]))
return 3 + 1;
}
else