mirror of
https://github.com/autc04/Retro68.git
synced 2025-01-11 02:30:42 +00:00
register parameters via __attribute__((__regparam__("d0(a0,d0)")))
This commit is contained in:
parent
db62b69fae
commit
a055a3faa1
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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))
|
||||
|
@ -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) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user