/*------------------------------------------------------------------*/
/* D e f i n e s */
/*------------------------------------------------------------------*/
-
-#define NOT_IMPLEMENTED(x) \
- g_error ("FIXME: %s is not yet implemented.", x);
-
#define ALPHA_DEBUG(x) \
if (mini_alpha_verbose_level) \
g_debug ("ALPHA_DEBUG: %s is called.", x);
#include "mini-alpha.h"
#include "inssel.h"
#include "cpu-alpha.h"
+#include "jit-icalls.h"
/*========================= End of Includes ========================*/
gboolean lmf_addr_key_inited = FALSE;
+MonoBreakpointInfo
+mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
+
/*====================== End of Global Variables ===================*/
-static void mono_arch_break(void);
gpointer mono_arch_get_lmf_addr (void);
typedef enum {
ArgInfo args [1];
} CallInfo;
-static CallInfo* get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke);
+static CallInfo* get_call_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke);
static unsigned int *emit_call(MonoCompile *cfg, unsigned int *code,
guint32 patch_type, gconstpointer data);
}
static void
-add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
+add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
gboolean is_return,
guint32 *gr, guint32 *fr, guint32 *stack_size)
{
else if (sig->pinvoke)
size = mono_type_native_stack_size (&klass->byval_arg, NULL);
else
- size = mono_type_stack_size (&klass->byval_arg, NULL);
+ size = mini_type_stack_size (gsctx, &klass->byval_arg, NULL);
if (!sig->pinvoke || (size == 0) || is_return) {
/* Allways pass in memory */
sig = mono_method_signature (cfg->method);
- cinfo = get_call_info (sig, FALSE);
+ cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
if (cinfo->ret.storage == ArgValuetypeInReg)
cfg->ret_var_is_local = TRUE;
/*========================= End of Function ========================*/
-static void
- peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
+// This peephole function is called before "local_regalloc" method
+// TSV_TODO - Check what we need to move here
+void
+mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+ CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE_1 pass\n");
+}
+
+// This peephole function is called after "local_regalloc" method
+void
+mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
{
- MonoInst *ins, *last_ins = NULL;
+ MonoInst *ins, *n, *last_ins = NULL;
ins = bb->code;
- CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE pass\n");
+ CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE_2 pass\n");
- while (ins)
- {
+ MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
switch (ins->opcode)
{
case OP_MOVE:
case OP_FMOVE:
- case OP_SETREG:
/*
* Removes:
*
if (ins->dreg == ins->sreg1 &&
ins->dreg != alpha_at)
{
- if (last_ins)
- last_ins->next = ins->next;
-
- ins = ins->next;
+ MONO_DELETE_INS (bb, ins);
continue;
}
last_ins->dreg != alpha_at &&
ins->dreg == last_ins->sreg1)
{
- last_ins->next = ins->next;
-
- ins = ins->next;
+ MONO_DELETE_INS (bb, ins);
continue;
}
}
else
{
- last_ins->next = ins->next;
- ins = ins->next;
+ MONO_DELETE_INS (bb, ins);
continue;
}
}
{
if (ins->dreg == last_ins->sreg1)
{
- last_ins->next = ins->next;
-
- ins = ins->next;
+ MONO_DELETE_INS (bb, ins);
continue;
}
else
{
if (ins->dreg == last_ins->sreg1)
{
- last_ins->next = ins->next;
-
- ins = ins->next;
+ MONO_DELETE_INS (bb, ins);
continue;
}
else
{
if (ins->dreg == last_ins->dreg)
{
- last_ins->next = ins->next;
-
- ins = ins->next;
+ MONO_DELETE_INS (bb, ins);
continue;
}
else
bb->last_ins = last_ins;
}
-
-
// Convert to opposite branch opcode
static guint16 cvt_branch_opcode(guint16 opcode)
{
* Converts complex opcodes into simpler ones so that each IR instruction
* corresponds to one machine instruction.
*/
-static void
- mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
+void
+mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
{
- MonoInst *ins, *temp, *last_ins = NULL;
+ MonoInst *ins, *n, *temp, *last_ins = NULL;
MonoInst *next;
ins = bb->code;
* cdq.
*/
- while (ins)
- {
+ MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
switch (ins->opcode)
{
case OP_DIV_IMM:
ins->sreg2 = temp->dreg;
// We should try to reevaluate new IR opcode
- continue;
+ //continue;
}
next = ins->next;
ins->sreg2 = temp->dreg;
// We should try to reevaluate new IR opcode
- continue;
+ //continue;
}
next = ins->next;
bb->max_vreg = cfg->rs->next_vreg;
}
-/*------------------------------------------------------------------*/
-/* */
-/* Name - mono_arch_local_regalloc. */
-/* */
-/* Function - We first scan the list of instructions and we */
-/* save the liveness information of each register */
-/* (when the register is first used, when its value */
-/* is set etc.). We also reverse the list of instr- */
-/* uctions (in the InstList list) because assigning */
-/* registers backwards allows for more tricks to be */
-/* used. */
-/* */
-/*------------------------------------------------------------------*/
-
-void
-mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
-{
- CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_local_regalloc");
-
- if (!bb->code)
- return;
-
- mono_arch_lowering_pass (cfg, bb);
-
- mono_local_regalloc(cfg, bb);
-}
-
/*========================= End of Function ========================*/
#define AXP_GENERAL_REGS 6
sig = mono_method_signature (method);
- cinfo = get_call_info (sig, FALSE);
+ cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
if (sig->ret->type != MONO_TYPE_VOID) {
if ((cinfo->ret.storage == ArgInIReg) &&
for (i = 0; i < sig->param_count + sig->hasthis; ++i)
{
ArgInfo *ainfo = &cinfo->args [i];
- MonoInst *inst = cfg->varinfo [i];
+ MonoInst *inst = cfg->args [i];
switch(ainfo->storage)
{
offset = cfg->arch.args_save_area_offset;
- cinfo = get_call_info (sig, FALSE);
+ cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
if (sig->ret->type != MONO_TYPE_VOID)
{
for (i = 0; i < sig->param_count + sig->hasthis; ++i)
{
ArgInfo *ainfo = &cinfo->args [i];
- MonoInst *inst = cfg->varinfo [i];
+ MonoInst *inst = cfg->args [i];
int j;
switch(ainfo->storage)
MonoJitArgumentInfo *arg_info)
{
int k;
- CallInfo *cinfo = get_call_info (csig, FALSE);
+ CallInfo *cinfo = get_call_info (NULL, csig, FALSE);
guint32 args_size = cinfo->stack_usage;
ALPHA_DEBUG("mono_arch_get_argument_info");
CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_output_basic_block");
- if (cfg->opt & MONO_OPT_PEEPHOLE)
- peephole_pass (cfg, bb);
-
CFG_DEBUG(2) g_print ("Basic block %d(%p) starting at offset 0x%x\n",
bb->block_num, bb, bb->native_offset);
mono_debug_open_block (cfg, bb, offset);
- ins = bb->code;
- while (ins)
- {
+ MONO_BB_FOR_EACH_INS (bb, ins) {
offset = ((char *)code) - ((char *)cfg->native_code);
max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
switch (ins->opcode)
{
+ case OP_RELAXED_NOP:
+ break;
case OP_LSHR:
// Shift 64 bit value right
CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr] dreg=%d, sreg1=%d, sreg2=%d\n",
ins->inst_c0 = (char *)code - (char *)cfg->native_code;
break;
- case CEE_BR:
+ case OP_BR:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [br] target: %p, next: %p, curr: %p, last: %p [",
ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
case OP_LCALL:
case OP_VCALL:
case OP_VOIDCALL:
- case CEE_CALL:
+ case OP_CALL:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [fcall/lcall/vcall/voidcall/call] Target: [");
call = (MonoCallInst*)ins;
}
break;
- case CEE_ENDFINALLY:
+ case OP_ENDFINALLY:
{
// Keep in sync with start_handler
CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfinally] basereg=%d, offset=%0lx\n",
alpha_bsr(code, alpha_ra, 0);
}
break;
-
- case CEE_RET:
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [ret]\n");
-
- alpha_ret(code, alpha_ra, 1);
- break;
- case CEE_THROW:
+ case OP_THROW:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [throw] sreg1=%0x\n",
ins->sreg1);
alpha_mov1(code, ins->sreg1, alpha_a0);
(gpointer)"mono_arch_rethrow_exception");
break;
- case CEE_JMP:
+ case OP_JMP:
{
/*
* Note: this 'frame destruction' logic is useful for tail calls,
alpha_mb(code);
break;
- case CEE_CKFINITE:
+ case OP_CKFINITE:
// Float register contains a value which we need to check
- CFG_DEBUG(4) g_print("ALPHA_TODO: [chfinite] sreg1=%d\n", ins->sreg1);
- alpha_cmptun_su(code, ins->sreg1, ins->sreg1, alpha_at);
- alpha_trapb(code);
- EMIT_COND_EXC_BRANCH(fbeq, alpha_at, "ArithmeticException");
+ {
+ double ni = -1.0 / 0.0;
+ double pi = 1.0 / 0.0;
+ AlphaGotData ge_data;
+
+ CFG_DEBUG(4) g_print("ALPHA_TODO: [chfinite] sreg1=%d\n", ins->sreg1);
+ alpha_cmptun_su(code, ins->sreg1, ins->sreg1, alpha_at);
+ alpha_trapb(code);
+ EMIT_COND_EXC_BRANCH(fbne, alpha_at, "ArithmeticException");
+
+ // Negative infinity
+ ge_data.data.d = ni;
+ add_got_entry(cfg, GT_DOUBLE, ge_data,
+ (char *)code - (char *)cfg->native_code,
+ MONO_PATCH_INFO_NONE, 0);
+ alpha_ldt(code, alpha_at, alpha_gp, 0);
+
+ alpha_cmpteq_su(code, ins->sreg1, alpha_at, alpha_at);
+ alpha_trapb(code);
+
+ EMIT_COND_EXC_BRANCH(fbne, alpha_at, "ArithmeticException");
+
+ // Positive infinity
+ ge_data.data.d = pi;
+ add_got_entry(cfg, GT_DOUBLE, ge_data,
+ (char *)code - (char *)cfg->native_code,
+ MONO_PATCH_INFO_NONE, 0);
+ alpha_ldt(code, alpha_at, alpha_gp, 0);
+ alpha_cmpteq_su(code, ins->sreg1, alpha_at, alpha_at);
+ alpha_trapb(code);
+
+ EMIT_COND_EXC_BRANCH(fbne, alpha_at, "ArithmeticException");
+ }
break;
case OP_FDIV:
CFG_DEBUG(4) g_print("ALPHA_TODO: [fdiv] dest=%d, sreg1=%d, sreg2=%d\n",
last_ins = ins;
last_offset = offset;
-
- ins = ins->next;
- }
+ }
cfg->code_len = ((char *)code) - ((char *)cfg->native_code);
}
if (*ip2 != (t_addr & 0xFFFFFFFF) ||
*(ip2+1) != ((t_addr>>32) & 0xFFFFFFFF))
- NOT_IMPLEMENTED("mono_arch_patch_code: MONO_PATCH_INFO_CLASS_INIT");
+ NOT_IMPLEMENTED;
// amd64_call_code (ip2, 0);
break;
}
int this_reg, int this_type, int vt_reg)
{
MonoCallInst *call = (MonoCallInst*)inst;
- CallInfo * cinfo = get_call_info (inst->signature, FALSE);
+ CallInfo * cinfo = get_call_info (cfg->generic_sharing_context, inst->signature, FALSE);
CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_emit_this_vret_args");
//printf("amask: %x, implver: %x", amask, implver);
}
+/*
+ * Initialize architecture specific code.
+ */
+void
+mono_arch_init (void)
+{
+}
+
+/*
+ * Cleanup architecture specific code.
+ */
+void
+mono_arch_cleanup (void)
+{
+}
/*
* get_call_info:
* For x86 win32, see ???.
*/
static CallInfo*
-get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke)
+get_call_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke)
{
guint32 i, gr, fr, *pgr, *pfr;
MonoType *ret_type;
{
guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
- add_valuetype (sig, &cinfo->ret, sig->ret, TRUE,
+ add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE,
&tmp_gr, &tmp_fr, &tmp_stacksize);
if (cinfo->ret.storage == ArgOnStack)
case MONO_TYPE_VALUETYPE:
/* FIXME: */
/* We allways pass valuetypes on the stack */
- add_valuetype (sig, ainfo, sig->params [i],
+ add_valuetype (gsctx, sig, ainfo, sig->params [i],
FALSE, pgr, pfr, &stack_size);
break;
case MONO_TYPE_TYPEDBYREF:
n = sig->param_count + sig->hasthis;
// Collect info about method we age going to call
- cinfo = get_call_info (sig, sig->pinvoke);
+ cinfo = get_call_info (cfg->generic_sharing_context, sig, sig->pinvoke);
CFG_DEBUG(3) g_print("ALPHA: Will call %s method with %d(%d) params. RetType: %s(0x%X)\n",
sig->pinvoke ? "PInvoke" : "Managed",
size = mono_type_native_stack_size (&in->klass->byval_arg,
&align);
else
- size = mono_type_stack_size (&in->klass->byval_arg, &align);
+ size = mini_type_stack_size (cfg->generic_sharing_context, &in->klass->byval_arg, &align);
if (ainfo->storage == ArgAggregate)
{
/*========================= End of Function ========================*/
-/*------------------------------------------------------------------*/
-/* */
-/* Name - mono_arch_break */
-/* */
-/* Function - Process a "break" operation for debugging. */
-/* */
-/*------------------------------------------------------------------*/
-
-static void
-mono_arch_break(void) {
-}
-
-
/*------------------------------------------------------------------*/
/* */
/* Name - mono_arch_register_lowlevel_calls */
{
ALPHA_DEBUG("mono_arch_register_lowlevel_calls");
- mono_register_jit_icall (mono_arch_break, "mono_arch_break", NULL, TRUE);
mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr",
NULL, TRUE);
}
sig = mono_method_signature (cfg->method);
- cinfo = get_call_info (sig, FALSE);
+ cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
for (i = 0; i < sig->param_count + sig->hasthis; ++i)
{
- MonoInst *ins = cfg->varinfo [i];
+ MonoInst *ins = cfg->args [i];
ArgInfo *ainfo = &cinfo->args [i];
CFG_DEBUG(3) g_print("mono_arch_get_inst_for_method: %s\n", cmethod->name);
- if (cmethod->klass == mono_defaults.thread_class &&
- strcmp (cmethod->name, "MemoryBarrier") == 0) {
- MONO_INST_NEW (cfg, ins, OP_MEMORY_BARRIER);
- }
-
return ins;
}
{
ALPHA_DEBUG("mono_arch_create_class_init_trampoline");
- NOT_IMPLEMENTED("mono_arch_create_class_init_trampoline: check MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE define");
+ NOT_IMPLEMENTED;
return 0;
}
/* Allocate a new area on the stack and save arguments there */
sig = mono_method_signature (cfg->method);
- cinfo = get_call_info (sig, FALSE);
+ cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
n = sig->param_count + sig->hasthis;
for (i = 0; i < n; ++i)
{
- inst = cfg->varinfo [i];
+ inst = cfg->args [i];
if (inst->opcode == OP_REGVAR)
{
sig = mono_method_signature (cfg->method);
- cinfo = get_call_info (sig, FALSE);
+ cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
/* if (cfg->arch.omit_fp) {
cfg->flags |= MONO_CFG_HAS_SPILLUP;
// Reserve space for method params
for (i = 0; i < sig->param_count + sig->hasthis; ++i)
{
- inst = cfg->varinfo [i];
+ inst = cfg->args [i];
if (inst->opcode != OP_REGVAR)
{
break;
default:
- NOT_IMPLEMENTED("");
+ NOT_IMPLEMENTED;
}
if (!inreg && (ainfo->storage != ArgOnStack))
return 0;
}
+gpointer
+mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gssize *regs, guint8 *code)
+{
+ unsigned int *pc = (unsigned int *)code;
+
+ ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_this_arg_from_call] code: %p regs: %p",
+ pc, regs);
+
+ if (MONO_TYPE_ISSTRUCT (sig->ret))
+ return (gpointer)regs [alpha_a1];
+ else
+ return (gpointer)regs [alpha_a0];
+}
+
+gpointer
+mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
+{
+ unsigned int *code, *start;
+ MonoDomain *domain = mono_domain_get ();
+ int i;
+
+ ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_delegate_invoke_impl]");
+
+ /* FIXME: Support more cases */
+ if (MONO_TYPE_ISSTRUCT (sig->ret))
+ return NULL;
+
+ return NULL;
+}
guint32
mono_arch_get_patch_offset (guint8 *code)
{
return 3;
}
+
+gpointer
+mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
+{
+ /* FIXME: implement */
+ g_assert_not_reached ();
+}