From 6189a572989970b67d3dcf83a36ad1c5350d7746 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 14 Mar 2001 22:35:58 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 ++++ gcc/config/i386/i386.c | 199 +++++++++++++++++++++++++++++++++++++++++ gcc/config/i386/i386.h | 46 +++++++++- 3 files changed, 259 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e68a5faf135..d4997cb2af5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +Wed Mar 14 22:26:10 CET 2001 Jan Hubicka + + * 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 + + Spot by Matt Kraai: + * i386.h (GENERAL_REG_P): Add missing REG_P. + 2001-03-14 Laurynas Biveinis * configure.in: Use $gcc_cv_as instead of $as. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 70fd21d384a..16dfe454b39 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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 diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index df06a2f3378..02c6e2a03cc 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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= */ extern const char *ix86_arch_string; /* for -march= */ -- 2.30.2