Pass QI/HI structures like the MIPS compiler; define SIZE_TYPE to be int by default.

From-SVN: r2893
This commit is contained in:
Michael Meissner 1992-12-18 23:27:55 +00:00
parent d45820250a
commit 3f1f8d8c04
3 changed files with 192 additions and 82 deletions

View File

@ -2413,6 +2413,7 @@ init_cumulative_args (cum, fntype, libname)
tree fntype; /* tree ptr for function decl */
rtx libname; /* SYMBOL_REF of library name or 0 */
{
static CUMULATIVE_ARGS zero_cum;
tree param, next_param;
if (TARGET_DEBUG_E_MODE)
@ -2430,9 +2431,7 @@ init_cumulative_args (cum, fntype, libname)
}
}
cum->gp_reg_found = 0;
cum->arg_number = 0;
cum->arg_words = 0;
*cum = zero_cum;
/* Determine if this function has variable arguments. This is
indicated by the last argument being 'void_type_mode' if there
@ -2461,7 +2460,7 @@ function_arg_advance (cum, mode, type, named)
{
if (TARGET_DEBUG_E_MODE)
fprintf (stderr,
"function_adv( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d )\n",
"function_adv( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d )\n\n",
cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode),
type, named);
@ -2512,8 +2511,12 @@ function_arg (cum, mode, type, named)
tree type; /* type of the argument or 0 if lib support */
int named; /* != 0 for normal args, == 0 for ... args */
{
rtx ret;
int regbase = -1;
int bias = 0;
int struct_p = ((type != (tree)0)
&& (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE));
if (TARGET_DEBUG_E_MODE)
fprintf (stderr,
@ -2567,18 +2570,42 @@ function_arg (cum, mode, type, named)
if (cum->arg_words >= MAX_ARGS_IN_REGISTERS)
{
if (TARGET_DEBUG_E_MODE)
fprintf (stderr, "<stack>\n");
fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : "");
return 0;
ret = (rtx)0;
}
else
{
if (regbase == -1)
abort ();
ret = gen_rtx (REG, mode, regbase + cum->arg_words + bias);
if (TARGET_DEBUG_E_MODE)
fprintf (stderr, "%s%s\n", reg_names[regbase + cum->arg_words + bias],
struct_p ? ", [struct]" : "");
/* The following is a hack in order to pass 1 byte structures
the same way that the MIPS compiler does (namely by passing
the structure in the high byte or half word of the register).
This also makes varargs work. If we have such a structure,
we save the adjustment RTL, and the call define expands will
emit them. For the VOIDmode argument (argument after the
last real argument, pass back a parallel vector holding each
of the adjustments. */
if (struct_p && (mode == QImode || mode == HImode))
{
rtx amount = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (mode));
rtx reg = gen_rtx (REG, SImode, regbase + cum->arg_words + bias);
cum->adjust[ cum->num_adjusts++ ] = gen_ashlsi3 (reg, reg, amount);
}
}
if (regbase == -1)
abort ();
if (mode == VOIDmode && cum->num_adjusts > 0)
ret = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (cum->num_adjusts, cum->adjust));
if (TARGET_DEBUG_E_MODE)
fprintf (stderr, "%s\n", reg_names[regbase + cum->arg_words + bias]);
return gen_rtx (REG, mode, regbase + cum->arg_words + bias);
return ret;
}
@ -4237,20 +4264,56 @@ mips_expand_prologue ()
{
int regno;
long tsize;
tree fndecl = current_function_decl; /* current... is tooo long */
tree fntype = TREE_TYPE (fndecl);
tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE)
? DECL_ARGUMENTS (fndecl)
: 0;
tree next_arg;
tree cur_arg;
rtx tmp_rtx = (rtx)0;
char *arg_name = (char *)0;
tree fndecl = current_function_decl;
tree fntype = TREE_TYPE (fndecl);
tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE)
? DECL_ARGUMENTS (fndecl)
: 0;
rtx next_arg_reg;
int i;
tree next_arg;
tree cur_arg;
CUMULATIVE_ARGS args_so_far;
/* Determine the last argument, and get its name. */
INIT_CUMULATIVE_ARGS (args_so_far, fntype, (rtx)0);
regno = GP_ARG_FIRST;
for (cur_arg = fnargs; cur_arg != (tree)0; cur_arg = next_arg)
{
tree type = DECL_ARG_TYPE (cur_arg);
enum machine_mode passed_mode = TYPE_MODE (type);
rtx entry_parm = FUNCTION_ARG (args_so_far,
passed_mode,
DECL_ARG_TYPE (cur_arg),
1);
if (entry_parm)
{
int words;
/* passed in a register, so will get homed automatically */
if (GET_MODE (entry_parm) == BLKmode)
words = (int_size_in_bytes (type) + 3) / 4;
else
words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
regno = REGNO (entry_parm) + words - 1;
}
else
{
regno = GP_ARG_LAST+1;
break;
}
FUNCTION_ARG_ADVANCE (args_so_far,
passed_mode,
DECL_ARG_TYPE (cur_arg),
1);
next_arg = TREE_CHAIN (cur_arg);
if (next_arg == (tree)0)
{
@ -4261,52 +4324,39 @@ mips_expand_prologue ()
}
}
/* In order to pass small structures by value in registers
compatibly with the MIPS compiler, we need to shift the value
into the high part of the register. Function_arg has encoded a
PARALLEL rtx, holding a vector of adjustments to be made as the
next_arg_reg variable, so we split up the insns, and emit them
separately. */
next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
if (next_arg_reg != (rtx)0 && GET_CODE (next_arg_reg) == PARALLEL)
{
rtvec adjust = XVEC (next_arg_reg, 0);
int num = GET_NUM_ELEM (adjust);
for (i = 0; i < num; i++)
{
rtx pattern = RTVEC_ELT (adjust, i);
if (GET_CODE (pattern) != SET
|| GET_CODE (SET_SRC (pattern)) != ASHIFT)
abort_with_insn (pattern, "Insn is not a shift");
PUT_CODE (SET_SRC (pattern), ASHIFTRT);
emit_insn (pattern);
}
}
/* If this function is a varargs function, store any registers that
would normally hold arguments ($4 - $7) on the stack. */
if ((TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node))
|| (arg_name
&& (strcmp (arg_name, "__builtin_va_alist") == 0
|| strcmp (arg_name, "va_alist") == 0)))
|| (arg_name != (char *)0
&& ((arg_name[0] == '_' && strcmp (arg_name, "__builtin_va_alist") == 0)
|| (arg_name[0] == 'v' && strcmp (arg_name, "va_alist") == 0))))
{
tree parm;
regno = GP_ARG_FIRST;
INIT_CUMULATIVE_ARGS (args_so_far, fntype, (rtx)0);
for (parm = fnargs; (parm && (regno <= GP_ARG_LAST)); parm = TREE_CHAIN (parm))
{
rtx entry_parm;
enum machine_mode passed_mode;
tree type;
type = DECL_ARG_TYPE (parm);
passed_mode = TYPE_MODE (type);
entry_parm = FUNCTION_ARG (args_so_far, passed_mode,
DECL_ARG_TYPE (parm), 1);
if (entry_parm)
{
int words;
/* passed in a register, so will get homed automatically */
if (GET_MODE (entry_parm) == BLKmode)
words = (int_size_in_bytes (type) + 3) / 4;
else
words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
regno = REGNO (entry_parm) + words - 1;
}
else
{
regno = GP_ARG_LAST+1;
break;
}
FUNCTION_ARG_ADVANCE (args_so_far, passed_mode,
DECL_ARG_TYPE (parm), 1);
}
for (; regno <= GP_ARG_LAST; regno++)
{
rtx ptr = stack_pointer_rtx;

View File

@ -483,7 +483,7 @@ while (0)
/* Print subsidiary information on the compiler version in use. */
#define MIPS_VERSION "[AL 1.1, MM 32]"
#define MIPS_VERSION "[AL 1.1, MM 33]"
#ifndef MACHINE_TYPE
#define MACHINE_TYPE "BSD Mips"
@ -1809,9 +1809,12 @@ extern struct mips_frame_info current_frame_info;
*/
typedef struct mips_args {
int gp_reg_found;
int arg_number;
int arg_words;
int gp_reg_found; /* whether a gp register was found yet */
int arg_number; /* argument number */
int arg_words; /* # total words the arguments take */
int num_adjusts; /* number of adjustments made */
/* Adjustments made to args pass in regs. */
struct rtx_def *adjust[MAX_ARGS_IN_REGISTERS];
} CUMULATIVE_ARGS;
/* Initialize a variable CUM of type CUMULATIVE_ARGS
@ -3525,3 +3528,15 @@ while (0)
#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
#define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
/* Default definitions for size_t and ptrdiff_t. */
#ifndef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
#endif
#ifndef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
#endif

View File

@ -4043,17 +4043,41 @@ move\\t%0,%z4\\n\\
(define_expand "call"
[(parallel [(call (match_operand 0 "memory_operand" "m")
(match_operand 1 "" "i"))
(clobber (match_operand 2 "" ""))])] ;; overwrite op2 with $31
(clobber (reg:SI 31))
(use (match_operand 2 "" "")) ;; next_arg_reg
(use (match_operand 3 "" ""))])] ;; struct_value_size_rtx
""
"
{
rtx addr;
operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);
if (operands[0]) /* eliminate unused code warnings */
{
addr = XEXP (operands[0], 0);
if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
XEXP (operands[0], 0) = force_reg (FUNCTION_MODE, addr);
addr = XEXP (operands[0], 0);
if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
XEXP (operands[0], 0) = force_reg (FUNCTION_MODE, addr);
/* In order to pass small structures by value in registers
compatibly with the MIPS compiler, we need to shift the value
into the high part of the register. Function_arg has encoded
a PARALLEL rtx, holding a vector of adjustments to be made
as the next_arg_reg variable, so we split up the insns,
and emit them separately. */
if (operands[2] != (rtx)0 && GET_CODE (operands[2]) == PARALLEL)
{
rtvec adjust = XVEC (operands[2], 0);
int num = GET_NUM_ELEM (adjust);
int i;
for (i = 0; i < num; i++)
emit_insn (RTVEC_ELT (adjust, i));
}
emit_call_insn (gen_call_internal (operands[0], operands[1],
gen_rtx (REG, Pmode, GP_REG_FIRST + 31)));
DONE;
}
}")
(define_insn "call_internal"
@ -4071,15 +4095,13 @@ move\\t%0,%z4\\n\\
else if (GET_CODE (target) == CONST_INT)
{
operands[0] = target;
operands[1] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);
return \"%*%[li\\t%@,%0\\n\\tjal\\t%1,%@%]\";
return \"%*%[li\\t%@,%0\\n\\tjal\\t%2,%@%]\";
}
else
{
operands[0] = target;
operands[1] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);
return \"%*jal\\t%1,%0\";
return \"%*jal\\t%2,%0\";
}
}"
[(set_attr "type" "call")
@ -4092,17 +4114,42 @@ move\\t%0,%z4\\n\\
[(parallel [(set (match_operand 0 "register_operand" "=df")
(call (match_operand 1 "memory_operand" "m")
(match_operand 2 "" "i")))
(clobber (match_operand 3 "" ""))])] ;; overwrite op3 with $31
(clobber (reg:SI 31))
(use (match_operand 3 "" ""))])] ;; next_arg_reg
""
"
{
rtx addr;
operands[3] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);
if (operands[0]) /* eliminate unused code warning */
{
addr = XEXP (operands[1], 0);
if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
XEXP (operands[1], 0) = force_reg (FUNCTION_MODE, addr);
/* In order to pass small structures by value in registers
compatibly with the MIPS compiler, we need to shift the value
into the high part of the register. Function_arg has encoded
a PARALLEL rtx, holding a vector of adjustments to be made
as the next_arg_reg variable, so we split up the insns,
and emit them separately. */
if (operands[3] != (rtx)0 && GET_CODE (operands[3]) == PARALLEL)
{
rtvec adjust = XVEC (operands[3], 0);
int num = GET_NUM_ELEM (adjust);
int i;
for (i = 0; i < num; i++)
emit_insn (RTVEC_ELT (adjust, i));
}
emit_call_insn (gen_call_value_internal (operands[0], operands[1], operands[2],
gen_rtx (REG, Pmode, GP_REG_FIRST + 31)));
DONE;
}
addr = XEXP (operands[1], 0);
if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
XEXP (operands[1], 0) = force_reg (FUNCTION_MODE, addr);
}")
(define_insn "call_value_internal"
@ -4121,15 +4168,13 @@ move\\t%0,%z4\\n\\
else if (GET_CODE (target) == CONST_INT)
{
operands[1] = target;
operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);
return \"%*%[li\\t%@,%1\\n\\tjal\\t%2,%@%]\";
return \"%*%[li\\t%@,%1\\n\\tjal\\t%3,%@%]\";
}
else
{
operands[1] = target;
operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);
return \"%*jal\\t%2,%1\";
return \"%*jal\\t%3,%1\";
}
}"
[(set_attr "type" "call")