register parameters via __attribute__((__regparam__("d0(a0,d0)")))

This commit is contained in:
Wolfgang Thaller 2014-09-24 02:52:10 +02:00
parent db62b69fae
commit a055a3faa1
5 changed files with 148 additions and 30 deletions

View File

@ -131,6 +131,12 @@ classifyType tm "long" = Just LongType
classifyType tm "void" = Just VoidType
classifyType tm t = Map.lookup t tm
pprParameterRegs (ParameterRegs mbRet args)
= maybe PP.empty PP.text mbRet
<+> PP.parens (
PP.hsep $ PP.punctuate PP.comma $ map PP.text args
)
hexword = integer tp
outputItem typeMap (CharItem c) = [c]
-- outputItem (FunctionItem cconv rettype name argumentTypes argumentNames words) = "<fun>"
@ -175,15 +181,37 @@ outputItem typeMap (FunctionItem cconv rettype name argumentTypes argumentNames
) $+$ PP.text "}\n\n"
-}
outputItem typeMap (FunctionItem cconv rettype name argumentTypes argumentNames words Nothing)
| True, not (null words), Just retcat <- classifyType typeMap rettype
outputItem typeMap (FunctionItem cconv rettype name argumentTypes argumentNames words mbParamRegs)
-- | True, not (null words), Just retcat <- classifyType typeMap rettype
= let
helper = PP.text "__magic_inline_" <> PP.text name
magic = PP.text "__magic_inline_" <> PP.hcat (PP.punctuate (PP.char '_') (map (PP.text . hexword) words))
hexword w = replicate (4 - length s) '0' ++ s where s = showHex w ""
cconvAttr = case cconv of
Pascal -> PP.text "__attribute__((__pascal__))"
CCall -> PP.empty
cconvAttr = case (mbParamRegs,cconv) of
(Just regs, _) -> PP.text "__attribute__((__regparam__(" <> PP.doubleQuotes regstr <> PP.text ")))"
where regstr = pprParameterRegs regs
(Nothing, Pascal) | not (null words) -> PP.text "__attribute__((__pascal__))"
(Nothing, _) -> PP.empty
isInline = not (null words)
magicAttr | isInline = PP.text "__attribute__((__magicinline__))"
| otherwise = PP.empty
inlineMagic | isInline = PP.text("__asm__") <> PP.parens ( PP.doubleQuotes magic )
| otherwise = PP.empty
in PP.render $
PP.text rettype <+> cconvAttr <+> magicAttr <+> PP.text name
<> PP.parens (PP.hsep $ PP.punctuate PP.comma $ zipWith (\t n -> PP.text t <+> PP.text n) argumentTypes argumentNames)
<+> inlineMagic
<> PP.semi <> PP.text "\n"
{-}
outputItem typeMap (FunctionItem cconv rettype name argumentTypes argumentNames words (Just regs)) =
= let
magic = PP.text "__magic_inline_" <> PP.hcat (PP.punctuate (PP.char '_') (map (PP.text . hexword) words))
hexword w = replicate (4 - length s) '0' ++ s where s = showHex w ""
cconvAttr =
magicAttr = PP.text "__attribute__((__magicinline__))"
in PP.render $
PP.text rettype <+> cconvAttr <+> magicAttr <+> PP.text name
@ -192,9 +220,6 @@ outputItem typeMap (FunctionItem cconv rettype name argumentTypes argumentNames
<> PP.semi <> PP.text "\n"
outputItem typeMap (FunctionItem cconv rettype name argumentTypes argumentNames words mbParamRegs) =
PP.render $
linkage <+> PP.text rettype <+> PP.text name
@ -290,7 +315,7 @@ outputItem typeMap (FunctionItem cconv rettype name argumentTypes argumentNames
dst = case mbReg of
Nothing -> PP.text "%%sp@-"
Just reg -> PP.text reg
-}
outputItem _ _ = ""
collectPragmas xs = evalState (mapM doit xs) Map.empty

View File

@ -62,7 +62,6 @@ extern rtx m68k_legitimize_tls_address (rtx);
extern bool m68k_tls_reference_p (rtx, bool);
extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode);
extern rtx m68k_libcall_value (enum machine_mode);
extern rtx m68k_function_value (const_tree, const_tree);
extern int emit_move_sequence (rtx *, enum machine_mode, rtx);
extern bool m68k_movem_pattern_p (rtx, rtx, HOST_WIDE_INT, bool);
extern const char *m68k_output_movem (rtx *, rtx, HOST_WIDE_INT, bool);

View File

@ -167,6 +167,8 @@ static rtx m68k_function_arg (cumulative_args_t, enum machine_mode,
static bool m68k_cannot_force_const_mem (enum machine_mode mode, rtx x);
static bool m68k_output_addr_const_extra (FILE *, rtx);
static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
static rtx m68k_function_value (const_tree, const_tree, bool);
/* Initialize the GCC target structure. */
@ -308,6 +310,9 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
#undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
#define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 128
#undef TARGET_FUNCTION_VALUE
#define TARGET_FUNCTION_VALUE m68k_function_value
static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
@ -318,6 +323,8 @@ static const struct attribute_spec m68k_attribute_table[] =
if they are not variable. */
{ "pascal", 0, 0, false, true, true, m68k_handle_fndecl_attribute,
true },
{ "regparam", 1, 1, false, true, true, m68k_handle_fndecl_attribute,
true },
{ "magicinline", 0, 0, false, true, true, m68k_handle_fndecl_attribute,
false },
{ "interrupt_handler", 0, 0, true, false, false,
@ -1394,9 +1401,9 @@ m68k_ok_for_sibcall_p (tree decl, tree exp)
rtx cfun_value;
rtx call_value;
cfun_value = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (cfun->decl)),
cfun->decl);
call_value = FUNCTION_VALUE (TREE_TYPE (exp), decl);
cfun_value = m68k_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)),
cfun->decl, false);
call_value = m68k_function_value (TREE_TYPE (exp), decl, false);
/* Check that the values are equal or that the result the callee
function returns is superset of what the current function returns. */
@ -1420,15 +1427,83 @@ m68k_ok_for_sibcall_p (tree decl, tree exp)
return false;
}
/* On the m68k all args are always pushed. */
/* On the m68k all args are always pushed - NOT. */
void m68k_init_cumulative_args (CUMULATIVE_ARGS *cum,
const_tree fntype,
rtx libname ATTRIBUTE_UNUSED,
tree indirect ATTRIBUTE_UNUSED,
int n_named_args)
{
cum->bytes = 0;
cum->index = 0;
cum->regparam = false;
if(!fntype)
return;
tree regparam = lookup_attribute ("regparam", TYPE_ATTRIBUTES( fntype ));
cum->regparam = regparam != NULL;
if(regparam)
{
regparam = TREE_VALUE(TREE_VALUE(regparam));
if(TREE_CODE(regparam) == STRING_CST)
{
const char *paramstr = TREE_STRING_POINTER(regparam);
printf("regparam: %s\n", paramstr);
const char *p = paramstr;
bool ok = true;
int idx = 0;
cum->arg_regs[0] = 0;
if(*p == '(')
{
idx = 1;
p++;
}
while(*p)
{
while(*p && (*p == '_' || *p == '%' || *p == ',' || *p == '(' || *p == ')' || *p == ' ' || *p == '\t'))
p++;
if(!*p)
break;
if(*p != 'a' && *p != 'd' && *p != 'A' && *p != 'D')
{ ok = false; break; }
if(p[1] < '0' || p[1] > '7')
{ ok = false; break; }
cum->arg_regs[idx++] = p[1] - '0'
+ (*p == 'a' || *p == 'A' ? 8 : 0);
p += 2;
}
printf("regparam parsed: %d, %d", (int) ok, idx);
// TODO: error checking
cum->total_count = idx - 1;
if(cum->total_count < 0)
cum->total_count = 0;
}
}
}
static rtx
m68k_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED,
m68k_function_arg (cumulative_args_t cum_v,
enum machine_mode mode ATTRIBUTE_UNUSED,
const_tree type ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED)
{
return NULL_RTX;
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
if(!cum->regparam)
return NULL_RTX;
if(cum->index < cum->total_count)
return gen_rtx_REG (mode, cum->arg_regs[cum->index+1]);
else
return NULL_RTX;
//return gen_rtx_REG (mode, 0); // ###
}
static void
@ -1437,9 +1512,10 @@ m68k_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
*cum += (mode != BLKmode
cum->bytes += (mode != BLKmode
? (GET_MODE_SIZE (mode) + 1) & ~1
: (int_size_in_bytes (type) + 1) & ~1);
cum->index ++;
}
/* Convert X to a legitimate function call memory reference and return the
@ -5298,15 +5374,27 @@ m68k_libcall_value (enum machine_mode mode)
return gen_rtx_REG (mode, m68k_libcall_value_in_a0_p ? A0_REG : D0_REG);
}
/* Location in which function value is returned.
NOTE: Due to differences in ABIs, don't call this function directly,
use FUNCTION_VALUE instead. */
/* Location in which function value is returned. */
rtx
m68k_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
m68k_function_value (const_tree valtype, const_tree func_decl_or_type, bool outgoing)
{
enum machine_mode mode;
mode = TYPE_MODE (valtype);
if(func_decl_or_type)
{
CUMULATIVE_ARGS cum;
const_tree type = func_decl_or_type;
if(TREE_CODE(type) == FUNCTION_DECL)
type = TREE_TYPE(type);
m68k_init_cumulative_args(&cum, type, NULL, NULL, -1);
if(cum.regparam)
return gen_rtx_REG (mode, cum.arg_regs[0]);
}
return gen_rtx_REG (mode, D0_REG);
#if 0
switch (mode) {
case SFmode:
case DFmode:
@ -5340,6 +5428,7 @@ m68k_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
return gen_rtx_REG (mode, A0_REG);
else
return gen_rtx_REG (mode, D0_REG);
#endif
}
/* Worker function for TARGET_RETURN_IN_MEMORY. */

View File

@ -508,8 +508,7 @@ extern enum reg_class regno_reg_class[];
#define FIRST_PARM_OFFSET(FNDECL) 8
/* On the m68k the return value defaults to D0. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
gen_rtx_REG (TYPE_MODE (VALTYPE), D0_REG)
// gen_rtx_REG (TYPE_MODE (VALTYPE), D0_REG)
/* On the m68k the return value defaults to D0. */
#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, D0_REG)
@ -525,13 +524,21 @@ extern enum reg_class regno_reg_class[];
/* On the m68k, all arguments are usually pushed on the stack. */
#define FUNCTION_ARG_REGNO_P(N) 0
/* On the m68k, this is a single integer, which is a number of bytes
of arguments scanned so far. */
#define CUMULATIVE_ARGS int
typedef struct {
int bytes; /* number of bytes of arguments scanned so far. */
int total_count;
int index;
bool regparam;
int arg_regs[32];
} CUMULATIVE_ARGS;
extern void m68k_init_cumulative_args (CUMULATIVE_ARGS *cum, const_tree fntype, rtx libname, tree indirect, int n_named_args);
/* On the m68k, the offset starts at 0. */
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
((CUM) = 0)
m68k_init_cumulative_args(&(CUM), (FNTYPE), (LIBNAME), (INDIRECT), (N_NAMED_ARGS));
#define FUNCTION_PROFILER(FILE, LABELNO) \
asm_fprintf (FILE, "\tlea %LLP%d,%Ra0\n\tjsr mcount\n", (LABELNO))

View File

@ -17,8 +17,6 @@
and unions in registers, which is slightly more efficient. */
#define DEFAULT_PCC_STRUCT_RETURN 0
#undef FUNCTION_VALUE
#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
#undef LIBCALL_VALUE
#define LIBCALL_VALUE(MODE) \