/*------------------------------------------------------------------*/
/* 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 ========================*/
int mini_alpha_verbose_level = 0;
static int bwx_supported = 0;
-static const char*const * ins_spec = alpha_desc;
-
static gboolean tls_offset_inited = FALSE;
static int appdomain_tls_offset = -1,
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)
{
- guint32 size, i;
+ guint32 size;
MonoClass *klass;
MonoMarshalType *info;
- gboolean is_hfa = TRUE;
- guint32 hfa_type = 0;
+ //gboolean is_hfa = TRUE;
+ //guint32 hfa_type = 0;
klass = mono_class_from_mono_type (type);
if (type->type == MONO_TYPE_TYPEDBYREF)
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;
- if (bb->max_ireg > cfg->rs->next_vireg)
- cfg->rs->next_vireg = bb->max_ireg;
- if (bb->max_freg > cfg->rs->next_vfreg)
- cfg->rs->next_vfreg = bb->max_freg;
+ if (bb->max_vreg > cfg->rs->next_vreg)
+ cfg->rs->next_vreg = bb->max_vreg;
/*
* FIXME: Need to add more instructions, but the current machine
* 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->last_ins = last_ins;
- bb->max_ireg = cfg->rs->next_vireg;
- bb->max_freg = cfg->rs->next_vfreg;
-}
-
-/*------------------------------------------------------------------*/
-/* */
-/* 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);
+ bb->max_vreg = cfg->rs->next_vreg;
}
/*========================= End of Function ========================*/
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)
{
CFG_DEBUG(3) g_print("ALPHA: Saved aggregate arg reg %d at offset: %0lx\n",
ainfo->reg + j, inst->inst_offset + (8*j));
- alpha_stq(code, ainfo->reg+j, inst->inst_basereg,
+ alpha_stq(code, (ainfo->reg+j), inst->inst_basereg,
(inst->inst_offset + (8*j)));
offset += 8;
}
offset = cfg->arch.reg_save_area_offset;
/*
- for (i = 0; i < MONO_MAX_IREGS; ++i)
+ for (i = 0; i < MONO_MAX_VREGS; ++i)
if (ALPHA_IS_CALLEE_SAVED_REG (i) &&
(cfg->used_int_regs & (1 << i)) &&
!( ALPHA_ARGS_REGS & (1 << i)) )
guint32
mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
{
+ MonoInst *ins = cfg->varinfo [vmv->idx];
+
/* FIXME: */
CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_regalloc_cost");
- MonoInst *ins = cfg->varinfo [vmv->idx];
if (cfg->method->save_lmf)
/* The register is already saved */
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");
mono_arch_emit_epilog (MonoCompile *cfg)
{
MonoMethod *method = cfg->method;
- int quad, offset, i;
+ int offset, i;
unsigned int *code;
int max_epilog_size = 128;
int stack_size = cfg->arch.stack_size;
- CallInfo *cinfo;
+ // CallInfo *cinfo;
gint32 lmf_offset = cfg->arch.lmf_offset;
CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_emit_epilog");
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_spec [ins->opcode])[MONO_INST_LEN];
+ max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
if (offset > (cfg->code_size - max_len - 16))
{
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",
CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shl] dreg=%d, sreg1=%d, sreg2=%d\n",
ins->dreg, ins->sreg1, ins->sreg2);
alpha_sll(code, ins->sreg1, ins->sreg2, ins->dreg);
+ alpha_addl_(code, ins->dreg, 0, ins->dreg);
break;
case OP_ISHL_IMM:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shl_imm] dreg=%d, sreg1=%d, const=%ld\n",
ins->dreg, ins->sreg1, ins->inst_imm);
alpha_sll_(code, ins->sreg1, ins->inst_imm, ins->dreg);
+ alpha_addl_(code, ins->dreg, 0, ins->dreg);
break;
case OP_SHL_IMM:
// Shift 32 bit unsigned value right
CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shr_un] dreg=%d, sreg1=%d, sreg2=%d\n",
ins->dreg, ins->sreg1, ins->sreg2);
- alpha_zap_(code, ins->sreg1, 0xF0, ins->dreg);
- alpha_srl(code, ins->dreg, ins->sreg2, ins->dreg);
+ alpha_zap_(code, ins->sreg1, 0xF0, alpha_at /*ins->dreg*/);
+ alpha_srl(code, alpha_at /*ins->dreg*/, ins->sreg2, ins->dreg);
break;
case OP_ISHR_UN_IMM:
// Shift 32 bit unassigned value rigth by constant
g_assert(alpha_is_imm(ins->inst_imm));
CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shr_un_imm] dreg=%d, sreg1=%d, const=%ld\n",
- ins->dreg, ins->sreg1, ins->inst_imm);
- alpha_zap_(code, ins->sreg1, 0xF0, ins->dreg);
- alpha_srl_(code, ins->dreg, ins->inst_imm, ins->dreg);
+ ins->dreg, ins->sreg1, ins->inst_imm);
+ alpha_zap_(code, ins->sreg1, 0xF0, alpha_at /*ins->dreg*/);
+ alpha_srl_(code, alpha_at /*ins->dreg*/, ins->inst_imm, ins->dreg);
break;
case OP_LSHR_UN_IMM:
// Valid only for storing 0
// storei1_membase_reg will do the rest
- CFG_DEBUG(4) g_printf("ALPHA_CHECK: [storei1_membase_imm(0)] const=%0lx, destbasereg=%d, offset=%0lx\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei1_membase_imm(0)] const=%0lx, destbasereg=%d, offset=%0lx\n",
ins->inst_imm, ins->inst_destbasereg, ins->inst_offset);
g_assert(ins->inst_imm == 0);
// Now work only for storing 0
// For now storei2_membase_reg will do the work
- CFG_DEBUG(4) g_printf("ALPHA_CHECK: [storei2_membase_imm(0)] const=%0lx, destbasereg=%d, offset=%0lx\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei2_membase_imm(0)] const=%0lx, destbasereg=%d, offset=%0lx\n",
ins->inst_imm, ins->inst_destbasereg, ins->inst_offset);
g_assert(ins->inst_imm == 0);
// Later check different rounding and exc modes
CFG_DEBUG(4) g_print("ALPHA_CHECK: [float_add] sreg1=%d, sreg2=%d, dreg=%d\n",
ins->sreg1, ins->sreg2, ins->dreg);
- alpha_addt(code, ins->sreg1, ins->sreg2, ins->dreg);
+ alpha_addt_su(code, ins->sreg1, ins->sreg2, ins->dreg);
+ alpha_trapb(code);
break;
case OP_FSUB:
// Later check different rounding and exc modes
CFG_DEBUG(4) g_print("ALPHA_CHECK: [float_sub] sreg1=%d, sreg2=%d, dreg=%d\n",
ins->sreg1, ins->sreg2, ins->dreg);
- alpha_subt(code, ins->sreg1, ins->sreg2, ins->dreg);
+ alpha_subt_su(code, ins->sreg1, ins->sreg2, ins->dreg);
+ alpha_trapb(code);
break;
case OP_FMUL:
break;
case OP_ALPHA_CMP_IMM_ULE:
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_ule] sreg1=%d, const=%0lX, dreg=%\d\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_ule] sreg1=%d, const=%0lX, dreg=%d\n",
ins->sreg1, ins->inst_imm, ins->dreg);
alpha_cmpule_(code, ins->sreg1, ins->inst_imm, alpha_at);
break;
case OP_ALPHA_CMP_IMM_LE:
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_le] sreg1=%d, const=%0lX, dreg=%\d\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_le] sreg1=%d, const=%0lX, dreg=%d\n",
ins->sreg1, ins->inst_imm, ins->dreg);
alpha_cmple_(code, ins->sreg1, ins->inst_imm, alpha_at);
break;
alpha_ldt(code, ins->dreg, alpha_sp, 0);
alpha_lda(code, alpha_sp, alpha_sp, 8);
alpha_cvtqs(code, ins->dreg, ins->dreg);
+ alpha_trapb(code);
break;
case CEE_CONV_R8:
alpha_ldt(code, ins->dreg, alpha_sp, 0);
alpha_lda(code, alpha_sp, alpha_sp, 8);
alpha_cvtqt(code, ins->dreg, ins->dreg);
+ alpha_trapb(code);
break;
case OP_FCONV_TO_R4:
// Convert 64 bit float to 32 bit float (T -> S)
CFG_DEBUG(4) g_print("ALPHA_CHECK: [fconv_r4] sreg=%d, dreg=%d\n",
ins->sreg1, ins->dreg);
- alpha_cvtts(code, ins->sreg1, ins->dreg);
+ alpha_cvtts_su(code, ins->sreg1, ins->dreg);
+ alpha_trapb(code);
break;
case OP_LOCALLOC:
// top of stack is used for call params
CFG_DEBUG(4) g_print("ALPHA_CHECK: [localloc] sreg=%d, dreg=%d\n",
ins->sreg1, ins->dreg);
- alpha_addq_(code, ins->sreg1, (MONO_ARCH_FRAME_ALIGNMENT - 1), ins->sreg1);
- alpha_and_(code, ins->sreg1, ~(MONO_ARCH_FRAME_ALIGNMENT - 1), ins->sreg1);
+
+ alpha_addq_(code, ins->sreg1, (MONO_ARCH_LOCALLOC_ALIGNMENT - 1), ins->sreg1);
+ alpha_bic_(code, ins->sreg1, (MONO_ARCH_LOCALLOC_ALIGNMENT - 1), ins->sreg1);
+ if (ins->flags & MONO_INST_INIT)
+ alpha_mov1(code, ins->sreg1, ins->sreg2);
+
alpha_subq(code, alpha_sp, ins->sreg1, alpha_sp);
- alpha_lda(code, ins->dreg, alpha_zero, (cfg->arch.params_stack_size));
- alpha_addq(code, alpha_sp, ins->dreg, ins->dreg);
+ if (cfg->arch.params_stack_size > 0)
+ {
+ alpha_lda(code, ins->dreg, alpha_zero,
+ (cfg->arch.params_stack_size));
+ alpha_addq(code, alpha_sp, ins->dreg, ins->dreg);
+ }
+ else
+ alpha_mov1(code, alpha_sp, ins->dreg);
+
+ if (ins->flags & MONO_INST_INIT)
+ {
+ // TODO: Optimize it later
+ alpha_lda(code, ins->sreg2, ins->sreg2,
+ -(MONO_ARCH_LOCALLOC_ALIGNMENT));
+ alpha_blt(code, ins->sreg2, 3);
+ alpha_addq(code, ins->sreg2, ins->dreg, alpha_at);
+ alpha_stq(code, alpha_zero, alpha_at, 0);
+ alpha_br(code, alpha_zero, -5);
+ }
+
break;
case OP_MOVE:
EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
break;
+ case OP_FBGE:
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbge] [");
+ alpha_fbne(code, (alpha_at+1), 1);
+ EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
+ break;
+
case OP_FBLE_UN:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [fble_un] [");
alpha_fbeq(code, (alpha_at+1), 1);
EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
break;
+ case OP_FBLE:
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [fble] [");
+ alpha_fbne(code, (alpha_at+1), 1);
+ EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
+ break;
+
case OP_FBLT_UN:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [fblt_un] [");
alpha_fbeq(code, (alpha_at+1), 1);
EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
break;
+ case OP_FBLT:
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [fblt] [");
+ alpha_fbne(code, (alpha_at+1), 1);
+ EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
+ break;
+
case OP_FBGT_UN:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbgt_un] [");
alpha_fbeq(code, (alpha_at+1), 1);
EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
break;
+ case OP_FBGT:
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbgt] [");
+ alpha_fbne(code, (alpha_at+1), 1);
+ EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
+ break;
+
case OP_IBEQ:
CFG_DEBUG(4) g_print("ALPHA_CHECK: [ibeq] [");
EMIT_ALPHA_BRANCH(ins, alpha_at, beq);
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;
// of by call_filter. There should be difference. For now just
// handle - call_handler
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [start_handler] basereg=%d, offset=%0x\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [start_handler] basereg=%d, offset=%0lx\n",
ins->inst_left->inst_basereg, ins->inst_left->inst_offset);
alpha_stq(code, alpha_ra, ins->inst_left->inst_basereg,
}
break;
- case CEE_ENDFINALLY:
+ case OP_ENDFINALLY:
{
// Keep in sync with start_handler
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfinally] basereg=%d, offset=%0x\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfinally] basereg=%d, offset=%0lx\n",
ins->inst_left->inst_basereg, ins->inst_left->inst_offset);
alpha_ldq(code, alpha_ra, ins->inst_left->inst_basereg,
case OP_ENDFILTER:
{
// Keep in sync with start_handler
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfilter] sreg1=%d, basereg=%d, offset=%0x\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfilter] sreg1=%d, basereg=%d, offset=%0lx\n",
ins->sreg1, ins->inst_left->inst_basereg, ins->inst_left->inst_offset);
alpha_ldq(code, alpha_ra, ins->inst_left->inst_basereg,
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:
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [throw] sreg1=%0lx\n",
+ case OP_THROW:
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [throw] sreg1=%0x\n",
ins->sreg1);
alpha_mov1(code, ins->sreg1, alpha_a0);
code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
break;
case OP_RETHROW:
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [rethrow] sreg1=%0lx\n",
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [rethrow] sreg1=%0x\n",
ins->sreg1);
alpha_mov1(code, ins->sreg1, alpha_a0);
code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
(gpointer)"mono_arch_rethrow_exception");
break;
- case CEE_JMP:
+ case OP_JMP:
{
- CFG_DEBUG(4) g_print("ALPHA_CHECK: [jmp] %p\n", ins->inst_p0);
/*
- * Note: this 'frame destruction' logic is useful for tail calls, too.
- * Keep in sync with the code in emit_epilog.
+ * Note: this 'frame destruction' logic is useful for tail calls,
+ too. Keep in sync with the code in emit_epilog.
*/
- int pos = 0, i, offset;
+ int offset;
AlphaGotData ge_data;
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [jmp] %p\n", ins->inst_p0);
+
/* FIXME: no tracing support... */
if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
code = mono_arch_instrument_epilog (cfg,
mono_add_patch_info (cfg, offset,
(MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
break;
-
+
+ case OP_MEMORY_BARRIER:
+ CFG_DEBUG(4) g_print("ALPHA_CHECK: [mb]\n");
+ alpha_mb(code);
+ break;
+
+ case OP_CKFINITE:
+ // Float register contains a value which we need to check
+ {
+ 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",
+ ins->dreg, ins->sreg1, ins->sreg2);
+ alpha_divt_su(code, ins->sreg1, ins->sreg2, ins->dreg);
+ alpha_trapb(code);
+
+ break;
default:
g_warning ("unknown opcode %s in %s()\n",
mono_inst_name (ins->opcode), __FUNCTION__);
last_ins = ins;
last_offset = offset;
-
- ins = ins->next;
- }
+ }
cfg->code_len = ((char *)code) - ((char *)cfg->native_code);
}
case MONO_PATCH_INFO_GOT_OFFSET:
{
- unsigned int *ip2 = ip;
+ unsigned int *ip2 = (unsigned int *)ip;
unsigned int inst = *ip2;
unsigned int off = patch_info->data.offset & 0xFFFFFFFF;
case MONO_PATCH_INFO_CLASS_INIT:
{
/* Might already been changed to a nop */
- unsigned int* ip2 = ip;
+ unsigned int* ip2 = (unsigned int *)ip;
unsigned long t_addr = (unsigned long)target;
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",
if ((i >= sig->hasthis) &&
(MONO_TYPE_ISSTRUCT(arg_type)))
{
- gint align;
+ guint align;
guint32 size;
if (arg_type->type == MONO_TYPE_TYPEDBYREF) {
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);
}
/*========================= End of Function ========================*/
-static gboolean
-is_regsize_var (MonoType *t)
-{
- if (t->byref)
- return TRUE;
-
- t = mono_type_get_underlying_type (t);
- switch (t->type) {
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_BOOLEAN:
- return TRUE;
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- return TRUE;
- case MONO_TYPE_VALUETYPE:
- return FALSE;
- }
-
- return FALSE;
-}
-
-
-
-
/*------------------------------------------------------------------*/
/* */
/* Name - mono_arch_get_allocatable_int_vars */
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];
(ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
continue;
- if (is_regsize_var (ins->inst_vtype))
+ if (mono_is_regsize_var (ins->inst_vtype))
{
g_assert (MONO_VARINFO (cfg, i)->reg == -1);
g_assert (i == vmv->idx);
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;
}
}
- g_free (offsets);
-
// TODO check how offsets[i] are calculated
// it seems they are points to the end on data. Like 8, but it actually - 0
// 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))
pc, regs);
// Check if we have parameters on stack
- if (pc[-2] & 0xFFFF0000 == 0x23DE0000) // lda sp,-n(sp)
+ if ((pc[-2] & 0xFFFF0000) == 0x23DE0000) // lda sp,-n(sp)
start_index = -3;
// Check for (call_membase):
// -4: mov v0,a0 - load this ???
- // -3: ldq v0,0(v0) - load vtable
+ // -3: ldq v0,0(v0) - load vtable
// -2: ldq t12,64(v0) - load method (object->vtable->vtable[method->slot])
- if ((pc[start_index-1] & 0xFFFFFFFF) == 0xA4000000 &&
+ if ((pc[start_index-1] & 0xFC00FFFF) == 0xA4000000 &&
(pc[start_index] & 0xFFFF0000) == 0xA7600000
)
{
disp = pc[start_index] & 0xFFFF;
- reg = 0; // For now
+ reg = (pc[start_index-1] >> AXP_REG1_SHIFT) & AXP_REG_MASK;
+ //reg = 0; // For now
ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_vcall_slot_addr callvirt] call_membase");
// -4: ldq v0,0(v0)
// -3: ldq v0,-n(v0)
// -2: ldq t12,0(v0)
- if ((pc[start_index-2] & 0xFFFFFFFF) == 0xA4000000 &&
+ if ((pc[start_index-2] & 0xFC00FFFF) == 0xA4000000 &&
(pc[start_index-1] & 0xFFFF0000) == 0xA4000000 &&
(pc[start_index] & 0xFFFF0000) == 0xA7600000
)
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 ();
+}