Commit 6189a572 by Jan Hubicka Committed by Jan Hubicka

i386.c (ix86_cmodel_string, [...]): Define.

	* i386.c (ix86_cmodel_string, ix86_cmodel): Define.
	(override_options): Parse cmodel string.
	(x86_64_sign_extended_value, x86_64_zero_extended_value): New.
	* i386.h (TARGET_OPTIONS): Add "cmodel".
	(EXTRA_CONSTRAINT): Recognize 'e' and 'Z'.
	(enum cmodel): New.
	(ix86_cmodel_string, ix86_cmodel): Declare.


	Spot by Matt Kraai:
	* i386.h (GENERAL_REG_P): Add missing REG_P.

From-SVN: r40474
parent 4cf6b384
Wed Mar 14 22:26:10 CET 2001 Jan Hubicka <jh@suse.cz>
* i386.c (ix86_cmodel_string, ix86_cmodel): Define.
(override_options): Parse cmodel string.
(x86_64_sign_extended_value, x86_64_zero_extended_value): New.
* i386.h (TARGET_OPTIONS): Add "cmodel".
(EXTRA_CONSTRAINT): Recognize 'e' and 'Z'.
(enum cmodel): New.
(ix86_cmodel_string, ix86_cmodel): Declare.
Wed Mar 14 22:26:54 CET 2001 Jan Hubicka <jh@suse.cz>
Spot by Matt Kraai:
* i386.h (GENERAL_REG_P): Add missing REG_P.
2001-03-14 Laurynas Biveinis <lauras@softhome.net>
* configure.in: Use $gcc_cv_as instead of $as.
......
......@@ -487,6 +487,11 @@ struct ix86_frame
HOST_WIDE_INT stack_pointer_offset;
};
/* Code model option as passed by user. */
const char *ix86_cmodel_string;
/* Parsed value. */
enum cmodel ix86_cmodel;
/* which cpu are we scheduling for */
enum processor_type ix86_cpu;
......@@ -659,6 +664,35 @@ override_options ()
ix86_arch = PROCESSOR_I386;
ix86_cpu = (enum processor_type) TARGET_CPU_DEFAULT;
if (ix86_cmodel_string != 0)
{
if (!strcmp (ix86_cmodel_string, "small"))
ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
else if (flag_pic)
sorry ("Code model %s not supported in PIC mode", ix86_cmodel_string);
else if (!strcmp (ix86_cmodel_string, "32"))
ix86_cmodel = CM_32;
else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
ix86_cmodel = CM_KERNEL;
else if (!strcmp (ix86_cmodel_string, "medium") && !flag_pic)
ix86_cmodel = CM_MEDIUM;
else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
ix86_cmodel = CM_LARGE;
else
error ("bad value (%s) for -mcmodel= switch", ix86_cmodel_string);
}
else
{
ix86_cmodel = CM_32;
if (TARGET_64BIT)
ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
}
if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32))
error ("Code model `%s' not supported in the %s bit mode.",
ix86_cmodel_string, TARGET_64BIT ? "64" : "32");
if (ix86_cmodel == CM_LARGE)
sorry ("Code model `large' not supported yet.");
if (ix86_arch_string != 0)
{
for (i = 0; i < pta_size; i++)
......@@ -1793,6 +1827,171 @@ ix86_can_use_return_insn_p ()
ix86_compute_frame_layout (&frame);
return frame.to_allocate == 0 && frame.nregs == 0;
}
/* Return 1 if VALUE can be stored in the sign extended immediate field. */
int
x86_64_sign_extended_value (value)
rtx value;
{
switch (GET_CODE (value))
{
/* CONST_DOUBLES never match, since HOST_BITS_PER_WIDE_INT is known
to be at least 32 and this all acceptable constants are
represented as CONST_INT. */
case CONST_INT:
if (HOST_BITS_PER_WIDE_INT == 32)
return 1;
else
{
HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (value), DImode);
return (HOST_WIDE_INT)(int)val == val;
}
break;
/* For certain code models, the symbolic references are known to fit. */
case SYMBOL_REF:
return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL;
/* For certain code models, the code is near as well. */
case LABEL_REF:
return ix86_cmodel != CM_LARGE && ix86_cmodel != CM_SMALL_PIC;
/* We also may accept the offsetted memory references in certain special
cases. */
case CONST:
if (GET_CODE (XEXP (value, 0)) == UNSPEC
&& XVECLEN (XEXP (value, 0), 0) == 1
&& XINT (XEXP (value, 0), 1) == 15)
return 1;
else if (GET_CODE (XEXP (value, 0)) == PLUS)
{
rtx op1 = XEXP (XEXP (value, 0), 0);
rtx op2 = XEXP (XEXP (value, 0), 1);
HOST_WIDE_INT offset;
if (ix86_cmodel == CM_LARGE)
return 0;
if (GET_CODE (op2) != CONST_INT)
return 0;
offset = trunc_int_for_mode (INTVAL (op2), DImode);
switch (GET_CODE (op1))
{
case SYMBOL_REF:
/* For CM_SMALL assume that latest object is 1MB before
end of 31bits boundary. We may also accept pretty
large negative constants knowing that all objects are
in the positive half of address space. */
if (ix86_cmodel == CM_SMALL
&& offset < 1024*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
/* For CM_KERNEL we know that all object resist in the
negative half of 32bits address space. We may not
accept negative offsets, since they may be just off
and we may accept pretty large possitive ones. */
if (ix86_cmodel == CM_KERNEL
&& offset > 0
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
break;
case LABEL_REF:
/* These conditions are similar to SYMBOL_REF ones, just the
constraints for code models differ. */
if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
&& offset < 1024*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
if (ix86_cmodel == CM_KERNEL
&& offset > 0
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
break;
default:
return 0;
}
}
return 0;
default:
return 0;
}
}
/* Return 1 if VALUE can be stored in the zero extended immediate field. */
int
x86_64_zero_extended_value (value)
rtx value;
{
switch (GET_CODE (value))
{
case CONST_DOUBLE:
if (HOST_BITS_PER_WIDE_INT == 32)
return (GET_MODE (value) == VOIDmode
&& !CONST_DOUBLE_HIGH (value));
else
return 0;
case CONST_INT:
if (HOST_BITS_PER_WIDE_INT == 32)
return INTVAL (value) >= 0;
else
return !(INTVAL (value) & ~(HOST_WIDE_INT)0xffffffff);
break;
/* For certain code models, the symbolic references are known to fit. */
case SYMBOL_REF:
return ix86_cmodel == CM_SMALL;
/* For certain code models, the code is near as well. */
case LABEL_REF:
return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM;
/* We also may accept the offsetted memory references in certain special
cases. */
case CONST:
if (GET_CODE (XEXP (value, 0)) == PLUS)
{
rtx op1 = XEXP (XEXP (value, 0), 0);
rtx op2 = XEXP (XEXP (value, 0), 1);
if (ix86_cmodel == CM_LARGE)
return 0;
switch (GET_CODE (op1))
{
case SYMBOL_REF:
return 0;
/* For small code model we may accept pretty large possitive
offsets, since one bit is available for free. Negative
offsets are limited by the size of NULL pointer area
specified by the ABI. */
if (ix86_cmodel == CM_SMALL
&& GET_CODE (op2) == CONST_INT
&& trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
&& (trunc_int_for_mode (INTVAL (op2), SImode)
== INTVAL (op2)))
return 1;
/* ??? For the kernel, we may accept adjustment of
-0x10000000, since we know that it will just convert
negative address space to possitive, but perhaps this
is not worthwhile. */
break;
case LABEL_REF:
/* These conditions are similar to SYMBOL_REF ones, just the
constraints for code models differ. */
if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
&& GET_CODE (op2) == CONST_INT
&& trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
&& (trunc_int_for_mode (INTVAL (op2), SImode)
== INTVAL (op2)))
return 1;
break;
default:
return 0;
}
}
return 0;
default:
return 0;
}
}
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms may
......
......@@ -393,6 +393,8 @@ extern int ix86_arch;
N_("Attempt to keep stack aligned to this power of 2") }, \
{ "branch-cost=", &ix86_branch_cost_string, \
N_("Branches are this expensive (1-5, arbitrary units)") }, \
{ "cmodel=", &ix86_cmodel_string, \
N_("Use given x86-64 code model") }, \
SUBTARGET_OPTIONS \
}
......@@ -1138,7 +1140,7 @@ enum reg_class
((n) < 8 || REX_INT_REGNO_P (n))
#define GENERAL_REG_P(X) \
(REG_P (X) && GENERAL_REGNO_P (X))
(REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
#define ANY_QI_REG_P(X) (TARGET_64BIT ? GENERAL_REG_P(X) : QI_REG_P (X))
......@@ -1247,6 +1249,23 @@ enum reg_class
((C) == 'G' ? standard_80387_constant_p (VALUE) \
: ((C) == 'H' ? standard_sse_constant_p (VALUE) : 0))
/* A C expression that defines the optional machine-dependent
constraint letters that can be used to segregate specific types of
operands, usually memory references, for the target machine. Any
letter that is not elsewhere defined and not matched by
`REG_CLASS_FROM_LETTER' may be used. Normally this macro will not
be defined.
If it is required for a particular target machine, it should
return 1 if VALUE corresponds to the operand type represented by
the constraint letter C. If C is not defined as an extra
constraint, the value returned should be 0 regardless of VALUE. */
#define EXTRA_CONSTRAINT(VALUE, C) \
((C) == 'e' ? x86_64_sign_extended_value (VALUE) \
: (C) == 'Z' ? x86_64_zero_extended_value (VALUE) \
: 0)
/* Place additional restrictions on the register class to use when it
is necessary to be able to hold a value of mode MODE in a reload
register for which class CLASS would ordinarily be used. */
......@@ -3051,6 +3070,31 @@ do { long l; \
#define SPECIAL_MODE_PREDICATES \
"ext_register_operand",
/* CM_32 is used by 32bit ABI
CM_SMALL is small model assuming that all code and data fits in the first
31bits of address space.
CM_KERNEL is model assuming that all code and data fits in the negative
31bits of address space.
CM_MEDIUM is model assuming that code fits in the first 31bits of address
space. Size of data is unlimited.
CM_LARGE is model making no assumptions about size of particular sections.
CM_SMALL_PIC is model for PIC libraries assuming that code+data+got/plt
tables first in 31bits of address space.
*/
enum cmodel {
CM_32,
CM_SMALL,
CM_KERNEL,
CM_MEDIUM,
CM_LARGE,
CM_SMALL_PIC
};
/* Valud of -mcmodel specified by user. */
extern const char *ix86_cmodel_string;
extern enum cmodel ix86_cmodel;
/* Variables in i386.c */
extern const char *ix86_cpu_string; /* for -mcpu=<xxx> */
extern const char *ix86_arch_string; /* for -march=<xxx> */
......
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