X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmini%2Fmini-alpha.c;h=404227abb5c60ba28ecb5a93dc23fe4e39493e84;hb=6c5018fd88223dd357d8dec1a7dd65258e807290;hp=9eb5cac89f55445791a0255566b2f48533513a40;hpb=669beaed8380fa592533c8755f72593b4422d01d;p=mono.git diff --git a/mono/mini/mini-alpha.c b/mono/mini/mini-alpha.c index 9eb5cac89f5..404227abb5c 100644 --- a/mono/mini/mini-alpha.c +++ b/mono/mini/mini-alpha.c @@ -18,10 +18,6 @@ /*------------------------------------------------------------------*/ /* 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); @@ -34,14 +30,6 @@ insert_after_ins (bb, last_ins, (dest)); \ } while (0) -#define NEW_ICONST(cfg,dest,val) do { \ - (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \ - (dest)->opcode = OP_ICONST; \ - (dest)->inst_c0 = (val); \ - (dest)->type = STACK_I4; \ - } while (0) - - #undef DEBUG #define DEBUG(a) if (cfg->verbose_level > 1) a @@ -71,8 +59,8 @@ #include "trace.h" #include "mini-alpha.h" -#include "inssel.h" #include "cpu-alpha.h" +#include "jit-icalls.h" /*========================= End of Includes ========================*/ @@ -82,8 +70,7 @@ static int indent_level = 0; int mini_alpha_verbose_level = 0; - -static const char*const * ins_spec = alpha_desc; +static int bwx_supported = 0; static gboolean tls_offset_inited = FALSE; @@ -95,9 +82,11 @@ pthread_key_t lmf_addr_key; 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 { @@ -135,7 +124,7 @@ typedef struct { 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); @@ -196,15 +185,15 @@ add_float (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo, } 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) @@ -212,7 +201,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type, 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 */ @@ -395,7 +384,7 @@ mono_arch_create_vars (MonoCompile *cfg) 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; @@ -440,19 +429,28 @@ mono_arch_free_jit_tls_data (MonoJitTlsData *tls) /*========================= 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) { - MonoInst *ins, *last_ins = NULL; + 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, *n, *last_ins = NULL; ins = bb->code; - while (ins) - { + CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE_2 pass\n"); + + MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) { switch (ins->opcode) { case OP_MOVE: case OP_FMOVE: - case OP_SETREG: /* * Removes: * @@ -461,10 +459,7 @@ static void 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; } @@ -479,9 +474,7 @@ static void last_ins->dreg != alpha_at && ins->dreg == last_ins->sreg1) { - last_ins->next = ins->next; - - ins = ins->next; + MONO_DELETE_INS (bb, ins); continue; } @@ -497,8 +490,7 @@ static void } else { - last_ins->next = ins->next; - ins = ins->next; + MONO_DELETE_INS (bb, ins); continue; } } @@ -506,6 +498,7 @@ static void break; case OP_LOADI8_MEMBASE: + case OP_LOAD_MEMBASE: /* * Note: if reg1 = reg2 the load op is removed * @@ -515,15 +508,15 @@ static void * OP_STOREI8_MEMBASE_REG reg1, offset(basereg) * OP_MOVE reg1, reg2 */ - if (last_ins && (last_ins->opcode == OP_STOREI8_MEMBASE_REG) && + if (last_ins && + (last_ins->opcode == OP_STOREI8_MEMBASE_REG || + last_ins->opcode == OP_STORE_MEMBASE_REG) && ins->inst_basereg == last_ins->inst_destbasereg && ins->inst_offset == last_ins->inst_offset) { if (ins->dreg == last_ins->sreg1) { - last_ins->next = ins->next; - - ins = ins->next; + MONO_DELETE_INS (bb, ins); continue; } else @@ -554,9 +547,7 @@ static void { if (ins->dreg == last_ins->sreg1) { - last_ins->next = ins->next; - - ins = ins->next; + MONO_DELETE_INS (bb, ins); continue; } else @@ -585,9 +576,7 @@ static void { if (ins->dreg == last_ins->dreg) { - last_ins->next = ins->next; - - ins = ins->next; + MONO_DELETE_INS (bb, ins); continue; } else @@ -609,8 +598,6 @@ static void bb->last_ins = last_ins; } - - // Convert to opposite branch opcode static guint16 cvt_branch_opcode(guint16 opcode) { @@ -942,27 +929,21 @@ static void cvt_cmp_branch(MonoInst *curr, MonoInst *next) * 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; - /* * FIXME: Need to add more instructions, but the current machine * description can't model some parts of the composite instructions like * cdq. */ - while (ins) - { + MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) { switch (ins->opcode) { case OP_DIV_IMM: @@ -972,7 +953,7 @@ static void case OP_MUL_IMM: NEW_INS (cfg, temp, OP_I8CONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); switch (ins->opcode) { @@ -1015,12 +996,12 @@ static void { NEW_INS (cfg, temp, OP_I8CONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); ins->opcode = OP_COMPARE; ins->sreg2 = temp->dreg; // We should try to reevaluate new IR opcode - continue; + //continue; } next = ins->next; @@ -1034,12 +1015,12 @@ static void { NEW_INS (cfg, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); ins->opcode = OP_ICOMPARE; ins->sreg2 = temp->dreg; // We should try to reevaluate new IR opcode - continue; + //continue; } next = ins->next; @@ -1048,29 +1029,13 @@ static void break; - /* - case OP_LOAD_MEMBASE: - case OP_LOADI8_MEMBASE: - if (!amd64_is_imm32 (ins->inst_offset)) - { - - NEW_INS (cfg, temp, OP_I8CONST); - temp->inst_c0 = ins->inst_offset; - temp->dreg = mono_regstate_next_int (cfg->rs); - ins->opcode = OP_AMD64_LOADI8_MEMINDEX; - ins->inst_indexreg = temp->dreg; - } - - break; - */ - case OP_STORE_MEMBASE_IMM: case OP_STOREI8_MEMBASE_IMM: if (ins->inst_imm != 0) { NEW_INS (cfg, temp, OP_I8CONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); ins->opcode = OP_STOREI8_MEMBASE_REG; ins->sreg1 = temp->dreg; } @@ -1082,29 +1047,31 @@ static void MonoInst *temp; NEW_INS (cfg, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); ins->opcode = OP_STOREI4_MEMBASE_REG; ins->sreg1 = temp->dreg; } break; case OP_STOREI1_MEMBASE_IMM: + if (ins->inst_imm != 0 || !bwx_supported) { MonoInst *temp; NEW_INS (cfg, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); ins->opcode = OP_STOREI1_MEMBASE_REG; ins->sreg1 = temp->dreg; } break; case OP_STOREI2_MEMBASE_IMM: + if (ins->inst_imm != 0 || !bwx_supported) { MonoInst *temp; NEW_INS (cfg, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); ins->opcode = OP_STOREI2_MEMBASE_REG; ins->sreg1 = temp->dreg; } @@ -1123,7 +1090,7 @@ static void MonoInst *temp; NEW_INS (cfg, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); switch(ins->opcode) { @@ -1166,7 +1133,7 @@ static void MonoInst *temp; NEW_INS (cfg, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int (cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); switch(ins->opcode) { @@ -1195,10 +1162,23 @@ static void MonoInst *temp; NEW_INS(cfg, temp, OP_ICONST); temp->inst_c0 = ins->inst_imm; - temp->dreg = mono_regstate_next_int(cfg->rs); + temp->dreg = mono_alloc_ireg (cfg); ins->sreg2 = temp->dreg; ins->opcode = OP_LSHR; } + break; + case OP_LSHL_IMM: + if (!alpha_is_imm(ins->inst_imm)) + { + MonoInst *temp; + NEW_INS(cfg, temp, OP_ICONST); + temp->inst_c0 = ins->inst_imm; + temp->dreg = mono_alloc_ireg (cfg); + ins->sreg2 = temp->dreg; + ins->opcode = OP_LSHL; + } + break; + default: break; } @@ -1209,35 +1189,7 @@ static void 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->next_vreg; } /*========================= End of Function ========================*/ @@ -1341,7 +1293,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, unsigned int *code) 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) && @@ -1355,7 +1307,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, unsigned int *code) 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) { @@ -1482,12 +1434,25 @@ mono_arch_emit_prolog (MonoCompile *cfg) // Save method alpha_stq(code, alpha_pv, alpha_fp, (lmf_offset + G_STRUCT_OFFSET(MonoLMF, method))); - } + + /* Save (global) regs */ + offset = cfg->arch.reg_save_area_offset; + + for (i = 0; i < MONO_MAX_IREGS; ++i) + if (ALPHA_IS_CALLEE_SAVED_REG (i) && + (cfg->used_int_regs & (1 << i)) && + !( ALPHA_ARGS_REGS & (1 << i)) ) + { + alpha_stq(code, i, alpha_fp, offset); + CFG_DEBUG(3) g_print("ALPHA: Saved caller reg %d at offset: %0x\n", + i, offset); + offset += 8; + } 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) { @@ -1504,32 +1469,47 @@ mono_arch_emit_prolog (MonoCompile *cfg) 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) { case ArgInIReg: // We need to save all used a0-a5 params - //for (i=0; ireg_usage) { - //alpha_stq(code, ainfo->reg, alpha_fp, offset); - alpha_stq(code, ainfo->reg, inst->inst_basereg, inst->inst_offset); + if (inst->opcode == OP_REGVAR) + { + alpha_mov1(code, ainfo->reg, inst->dreg); + CFG_DEBUG(3) g_print("ALPHA: Saved int arg reg %d in reg %d\n", + ainfo->reg, inst->dreg); + } + else + { + alpha_stq(code, ainfo->reg, inst->inst_basereg, + inst->inst_offset); - CFG_DEBUG(3) g_print("ALPHA: Saved int arg reg %d at offset: %0lx\n", - ainfo->reg, inst->inst_offset/*offset*/); + CFG_DEBUG(3) g_print("ALPHA: Saved int arg reg %d at offset: %0lx\n", + ainfo->reg, inst->inst_offset); - offset += 8; + offset += 8; + } + } + break; + case ArgAggregate: + { + for(j=0; jnregs; j++) + { + 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, + (inst->inst_offset + (8*j))); + offset += 8; + } } - //} break; case ArgInDoubleReg: case ArgInFloatReg: // We need to save all used af0-af5 params - //for (i=0; ifreg_usage) { switch(cinfo->args[i].storage) { @@ -1554,8 +1534,9 @@ mono_arch_emit_prolog (MonoCompile *cfg) } 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)) ) @@ -1565,7 +1546,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) i, offset); offset += 8; } - + */ // TODO - check amd64 code for "Might need to attach the thread to the JIT" if (method->save_lmf) @@ -1641,10 +1622,18 @@ mono_arch_flush_register_windows (void) 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"); - return 2; + if (cfg->method->save_lmf) + /* The register is already saved */ + /* substract 1 for the invisible store in the prolog */ + return (ins->opcode == OP_ARG) ? 1 : 0; + else + /* push+pop */ + return (ins->opcode == OP_ARG) ? 2 : 1; } /*========================= End of Function ========================*/ @@ -1705,7 +1694,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, 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"); @@ -1743,11 +1732,11 @@ void 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"); @@ -2117,26 +2106,6 @@ mono_arch_emit_exceptions (MonoCompile *cfg) #define EMIT_ALPHA_BRANCH(Tins, PRED_REG, ALPHA_BR) \ offset = ((char *)code - \ (char *)cfg->native_code); \ - if (Tins->flags & MONO_INST_BRLABEL) \ - { \ - if (Tins->inst_i0->inst_c0) \ - { \ - CFG_DEBUG(3) g_print("inst_c0: %0lX, data: %p]\n", \ - Tins->inst_i0->inst_c0, \ - cfg->native_code + Tins->inst_i0->inst_c0); \ - alpha_##ALPHA_BR (code, PRED_REG, 0); \ - } \ - else \ - { \ - CFG_DEBUG(3) g_print("add patch info: MONO_PATCH_INFO_LABEL offset: %0X, inst_i0: %p]\n", \ - offset, Tins->inst_i0); \ - mono_add_patch_info (cfg, offset, \ - MONO_PATCH_INFO_LABEL, Tins->inst_i0); \ - alpha_##ALPHA_BR (code, PRED_REG, 0); \ - } \ - } \ - else \ - { \ if (Tins->inst_true_bb->native_offset) \ { \ long br_offset = (char *)cfg->native_code + \ @@ -2155,8 +2124,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg) MONO_PATCH_INFO_BB, \ Tins->inst_true_bb); \ alpha_##ALPHA_BR (code, PRED_REG, 0); \ - } \ - } + } #define EMIT_COND_EXC_BRANCH(ALPHA_BR, PRED_REG, EXC_NAME) \ @@ -2202,9 +2170,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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); @@ -2214,12 +2179,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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)) { @@ -2236,19 +2199,28 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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->dreg, ins->sreg1, ins->sreg2); - alpha_srl(code, ins->sreg1, ins->sreg2, ins->dreg); + alpha_sra(code, ins->sreg1, ins->sreg2, ins->dreg); break; + case OP_LSHR_UN: + // Shift 64 bit value right + CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr_un] dreg=%d, sreg1=%d, sreg2=%d\n", + ins->dreg, ins->sreg1, ins->sreg2); + alpha_srl(code, ins->sreg1, ins->sreg2, ins->dreg); + break; + case OP_LSHR_IMM: // Shift 64 bit value right by constant g_assert(alpha_is_imm(ins->inst_imm)); - CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr] dreg=%d, sreg1=%d, const=%ld\n", + CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr_imm] dreg=%d, sreg1=%d, const=%ld\n", ins->dreg, ins->sreg1, ins->inst_imm); - alpha_srl_(code, ins->sreg1, ins->inst_imm, ins->dreg); + alpha_sra_(code, ins->sreg1, ins->inst_imm, ins->dreg); break; case OP_ISHL: @@ -2256,6 +2228,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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: @@ -2264,6 +2237,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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: @@ -2273,6 +2247,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) alpha_sll_(code, ins->sreg1, ins->inst_imm, ins->dreg); break; + case OP_LSHL_IMM: + g_assert(alpha_is_imm(ins->inst_imm)); + CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_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); + break; + + case CEE_SHL: // Shift 32 bit value left CFG_DEBUG(4) g_print("ALPHA_CHECK: [shl] dreg=%d, sreg1=%d, sreg2=%d\n", @@ -2280,6 +2262,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) alpha_sll(code, ins->sreg1, ins->sreg2, ins->dreg); break; + case OP_LSHL: + // Shift 64 bit value left + CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shl] dreg=%d, sreg1=%d, sreg2=%d\n", + ins->dreg, ins->sreg1, ins->sreg2); + alpha_sll(code, ins->sreg1, ins->sreg2, ins->dreg); + break; + case OP_ISHR: // Shift 32 bit value right @@ -2302,17 +2291,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) // 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: @@ -2709,10 +2698,15 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) // Load unassigned byte from REGOFFSET CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadu1_membase] dreg=%d, basereg=%d, offset=%0lx\n", ins->dreg, ins->inst_basereg, ins->inst_offset); - - alpha_ldq_u(code, alpha_r25, ins->inst_basereg, ins->inst_offset); - alpha_lda(code, alpha_at, ins->inst_basereg, ins->inst_offset); - alpha_extbl(code, alpha_r25, alpha_at, ins->dreg); + if (bwx_supported) + alpha_ldbu(code, ins->dreg, ins->inst_basereg, ins->inst_offset); + else + { + alpha_ldq_u(code, alpha_r25, ins->inst_basereg, + ins->inst_offset); + alpha_lda(code, alpha_at, ins->inst_basereg, ins->inst_offset); + alpha_extbl(code, alpha_r25, alpha_at, ins->dreg); + } break; case OP_LOADU2_MEMBASE: @@ -2720,14 +2714,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadu2_membase] dreg=%d, basereg=%d, offset=%0lx\n", ins->dreg, ins->inst_basereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r24, ins->inst_basereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r25, ins->inst_basereg, - (ins->inst_offset+1)); - alpha_lda(code, alpha_at, ins->inst_basereg, ins->inst_offset); - alpha_extwl(code, alpha_r24, alpha_at, ins->dreg); - alpha_extwh(code, alpha_r25, alpha_at, alpha_r25); - alpha_bis(code, alpha_r25, ins->dreg, ins->dreg); - + if (bwx_supported) + alpha_ldwu(code, ins->dreg, ins->inst_basereg, ins->inst_offset); + else + { + alpha_ldq_u(code, alpha_r24, ins->inst_basereg, + ins->inst_offset); + alpha_ldq_u(code, alpha_r25, ins->inst_basereg, + (ins->inst_offset+1)); + alpha_lda(code, alpha_at, ins->inst_basereg, ins->inst_offset); + alpha_extwl(code, alpha_r24, alpha_at, ins->dreg); + alpha_extwh(code, alpha_r25, alpha_at, alpha_r25); + alpha_bis(code, alpha_r25, ins->dreg, ins->dreg); + } break; case OP_LOAD_MEMBASE: @@ -2752,71 +2751,104 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) // Load sign-extended byte from REGOFFSET CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadi1_membase] dreg=%d, basereg=%d, offset=%0lx\n", ins->dreg, ins->inst_basereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r25, ins->inst_basereg, ins->inst_offset); - alpha_lda(code, alpha_at, ins->inst_basereg, (ins->inst_offset+1)); - alpha_extqh(code, alpha_r25, alpha_at, ins->dreg); - alpha_sra_(code, ins->dreg, 56, ins->dreg); + if (bwx_supported) + { + alpha_ldbu(code, ins->dreg, ins->inst_basereg, + ins->inst_offset); + alpha_sextb(code, ins->dreg, ins->dreg); + } + else + { + alpha_ldq_u(code, alpha_r25, ins->inst_basereg, + ins->inst_offset); + alpha_lda(code, alpha_at, ins->inst_basereg, + (ins->inst_offset+1)); + alpha_extqh(code, alpha_r25, alpha_at, ins->dreg); + alpha_sra_(code, ins->dreg, 56, ins->dreg); + } break; case OP_LOADI2_MEMBASE: // Load sign-extended word from REGOFFSET CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadi2_membase] dreg=%d, basereg=%d, offset=%0lx\n", ins->dreg, ins->inst_basereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r24, ins->inst_basereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r25, ins->inst_basereg, - (ins->inst_offset+1)); - alpha_lda(code, alpha_at, ins->inst_basereg, (ins->inst_offset+2)); - alpha_extql(code, alpha_r24, alpha_at, ins->dreg); - alpha_extqh(code, alpha_r25, alpha_at, alpha_r25); - alpha_bis(code, alpha_r25, ins->dreg, ins->dreg); - alpha_sra_(code, ins->dreg, 48, ins->dreg); - + if (bwx_supported) + { + alpha_ldwu(code, ins->dreg, ins->inst_basereg, + ins->inst_offset); + alpha_sextw(code, ins->dreg, ins->dreg); + } + else + { + alpha_ldq_u(code, alpha_r24, ins->inst_basereg, + ins->inst_offset); + alpha_ldq_u(code, alpha_r25, ins->inst_basereg, + (ins->inst_offset+1)); + alpha_lda(code, alpha_at, ins->inst_basereg, + (ins->inst_offset+2)); + alpha_extql(code, alpha_r24, alpha_at, ins->dreg); + alpha_extqh(code, alpha_r25, alpha_at, alpha_r25); + alpha_bis(code, alpha_r25, ins->dreg, ins->dreg); + alpha_sra_(code, ins->dreg, 48, ins->dreg); + } break; case OP_STOREI1_MEMBASE_IMM: // Store signed byte at REGOFFSET - // For now storei1_membase_reg will do the work - g_assert_not_reached(); - /* - printf("ALPHA_TODO: [storei1_membase_imm] const=%0lx, destbasereg=%d, offset=%0lx\n", + // Valid only for storing 0 + // storei1_membase_reg will do the rest + + 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(alpha_is_imm(ins->inst_imm)); + g_assert(ins->inst_imm == 0); - alpha_lda(code, alpha_r25, alpha_zero, ins->inst_imm); + if (bwx_supported) + alpha_stb(code, alpha_zero, ins->inst_destbasereg, + ins->inst_offset); + else + g_assert_not_reached(); - alpha_lda(code, alpha_at, ins->inst_destbasereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r24, ins->inst_destbasereg, ins->inst_offset); - alpha_insbl(code, alpha_r25, alpha_at, alpha_r23); - alpha_mskbl(code, alpha_r24, alpha_at, alpha_r24); - alpha_bis(code, alpha_r24, alpha_r23, alpha_r24); - alpha_stq_u(code, alpha_r24, ins->inst_destbasereg, ins->inst_offset); - */ break; case OP_STOREI1_MEMBASE_REG: // Store byte at REGOFFSET CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei1_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lx\n", ins->sreg1, ins->inst_destbasereg, ins->inst_offset); - - alpha_lda(code, alpha_at, ins->inst_destbasereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r25, ins->inst_destbasereg, - ins->inst_offset); - alpha_insbl(code, ins->sreg1, alpha_at, alpha_r24); - alpha_mskbl(code, alpha_r25, alpha_at, alpha_r25); - alpha_bis(code, alpha_r25, alpha_r24, alpha_r25); - alpha_stq_u(code, alpha_r25, ins->inst_destbasereg, - ins->inst_offset); - + if (bwx_supported) + { + alpha_stb(code, ins->sreg1, ins->inst_destbasereg, + ins->inst_offset); + } + else + { + alpha_lda(code, alpha_at, ins->inst_destbasereg, + ins->inst_offset); + alpha_ldq_u(code, alpha_r25, ins->inst_destbasereg, + ins->inst_offset); + alpha_insbl(code, ins->sreg1, alpha_at, alpha_r24); + alpha_mskbl(code, alpha_r25, alpha_at, alpha_r25); + alpha_bis(code, alpha_r25, alpha_r24, alpha_r25); + alpha_stq_u(code, alpha_r25, ins->inst_destbasereg, + ins->inst_offset); + } break; case OP_STOREI2_MEMBASE_IMM: // Store signed word at REGOFFSET + // Now work only for storing 0 // For now storei2_membase_reg will do the work - g_assert_not_reached(); - /* - printf("ALPHA_TODO: [storei2_membase_imm] 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); + + if (bwx_supported) + alpha_stw(code, alpha_zero, ins->inst_destbasereg, + ins->inst_offset); + else + g_assert_not_reached(); + break; case OP_STOREI2_MEMBASE_REG: @@ -2824,21 +2856,30 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei2_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lx\n", ins->sreg1, ins->inst_destbasereg, ins->inst_offset); - alpha_lda(code, alpha_at, ins->inst_destbasereg, ins->inst_offset); - alpha_ldq_u(code, alpha_r25, ins->inst_destbasereg, - (ins->inst_offset+1)); - alpha_ldq_u(code, alpha_r24, ins->inst_destbasereg, - ins->inst_offset); - alpha_inswh(code, ins->sreg1, alpha_at, alpha_r23); - alpha_inswl(code, ins->sreg1, alpha_at, alpha_r22); - alpha_mskwh(code, alpha_r25, alpha_at, alpha_r25); - alpha_mskwl(code, alpha_r24, alpha_at, alpha_r24); - alpha_bis(code, alpha_r25, alpha_r23, alpha_r25); - alpha_bis(code, alpha_r24, alpha_r22, alpha_r24); - alpha_stq_u(code, alpha_r25, ins->inst_destbasereg, - (ins->inst_offset+1)); - alpha_stq_u(code, alpha_r24, ins->inst_destbasereg, - ins->inst_offset); + if (bwx_supported) + { + alpha_stw(code, ins->sreg1, ins->inst_destbasereg, + ins->inst_offset); + } + else + { + alpha_lda(code, alpha_at, ins->inst_destbasereg, + ins->inst_offset); + alpha_ldq_u(code, alpha_r25, ins->inst_destbasereg, + (ins->inst_offset+1)); + alpha_ldq_u(code, alpha_r24, ins->inst_destbasereg, + ins->inst_offset); + alpha_inswh(code, ins->sreg1, alpha_at, alpha_r23); + alpha_inswl(code, ins->sreg1, alpha_at, alpha_r22); + alpha_mskwh(code, alpha_r25, alpha_at, alpha_r25); + alpha_mskwl(code, alpha_r24, alpha_at, alpha_r24); + alpha_bis(code, alpha_r25, alpha_r23, alpha_r25); + alpha_bis(code, alpha_r24, alpha_r22, alpha_r24); + alpha_stq_u(code, alpha_r25, ins->inst_destbasereg, + (ins->inst_offset+1)); + alpha_stq_u(code, alpha_r24, ins->inst_destbasereg, + ins->inst_offset); + } break; @@ -2888,14 +2929,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) // 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: @@ -3033,7 +3076,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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; @@ -3064,7 +3107,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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; @@ -3164,18 +3207,28 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) // Read about sextb CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_i1] sreg=%d, dreg=%d\n", ins->sreg1, ins->dreg); - alpha_sll_(code, ins->sreg1, 24, alpha_at); - alpha_addl(code, alpha_at, alpha_zero, ins->dreg); - alpha_sra_(code, ins->dreg, 24, ins->dreg); + if (bwx_supported) + alpha_sextb(code, ins->sreg1, ins->dreg); + else + { + alpha_sll_(code, ins->sreg1, 24, alpha_at); + alpha_addl(code, alpha_at, alpha_zero, ins->dreg); + alpha_sra_(code, ins->dreg, 24, ins->dreg); + } break; case CEE_CONV_I2: // Move I2 (word) to dreg(64 bits) and sign extend it CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_i2] sreg=%d, dreg=%d\n", ins->sreg1, ins->dreg); - alpha_sll_(code, ins->sreg1, 16, alpha_at); - alpha_addl(code, alpha_at, alpha_zero, ins->dreg); - alpha_sra_(code, ins->dreg, 16, ins->dreg); + if (bwx_supported) + alpha_sextw(code, ins->sreg1, ins->dreg); + else + { + alpha_sll_(code, ins->sreg1, 16, alpha_at); + alpha_addl(code, alpha_at, alpha_zero, ins->dreg); + alpha_sra_(code, ins->dreg, 16, ins->dreg); + } break; case CEE_CONV_I4: @@ -3300,6 +3353,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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: @@ -3312,26 +3366,50 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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: // Allocate sreg1 bytes on stack, round bytes by 8, // modify SP, set dreg to end of current stack frame // top of stack is used for call params - CFG_DEBUG(4) g_print("ALPHA_FIX: [localloc] sreg=%d, dreg=%d\n", + 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: @@ -3443,6 +3521,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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); @@ -3450,6 +3534,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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); @@ -3457,6 +3547,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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); @@ -3464,6 +3560,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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); @@ -3489,55 +3591,33 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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); - if (ins->flags & MONO_INST_BRLABEL) + if (ins->inst_target_bb->native_offset) { - if (ins->inst_i0->inst_c0) - { - CFG_DEBUG(4) g_print("inst_c0: %0lX, data: %p]\n", - ins->inst_i0->inst_c0, - cfg->native_code + ins->inst_i0->inst_c0); - alpha_br(code, alpha_zero, 0); - } - else - { - CFG_DEBUG(4) g_print("add patch info: MONO_PATCH_INFO_LABEL offset: %0X, inst_i0: %p]\n", - offset, ins->inst_i0); - mono_add_patch_info (cfg, offset, - MONO_PATCH_INFO_LABEL, ins->inst_i0); - - alpha_br(code, alpha_zero, 0); - } + // Somehow native offset is offset from + // start of the code. So convert it to + // offset branch + long br_offset = (char *)cfg->native_code + + ins->inst_target_bb->native_offset - 4 - (char *)code; + + CFG_DEBUG(4) g_print("jump to: native_offset: %0X, address %p]\n", + ins->inst_target_bb->native_offset, + cfg->native_code + + ins->inst_target_bb->native_offset); + alpha_br(code, alpha_zero, br_offset/4); } else { - if (ins->inst_target_bb->native_offset) - { - // Somehow native offset is offset from - // start of the code. So convert it to - // offset branch - long br_offset = (char *)cfg->native_code + - ins->inst_target_bb->native_offset - 4 - (char *)code; - - CFG_DEBUG(4) g_print("jump to: native_offset: %0X, address %p]\n", - ins->inst_target_bb->native_offset, - cfg->native_code + - ins->inst_target_bb->native_offset); - alpha_br(code, alpha_zero, br_offset/4); - } - else - { - CFG_DEBUG(4) g_print("add patch info: MONO_PATCH_INFO_BB offset: %0X, target_bb: %p]\n", - offset, ins->inst_target_bb); - - mono_add_patch_info (cfg, offset, - MONO_PATCH_INFO_BB, - ins->inst_target_bb); - alpha_br(code, alpha_zero, 0); - } + CFG_DEBUG(4) g_print("add patch info: MONO_PATCH_INFO_BB offset: %0X, target_bb: %p]\n", + offset, ins->inst_target_bb); + + mono_add_patch_info (cfg, offset, + MONO_PATCH_INFO_BB, + ins->inst_target_bb); + alpha_br(code, alpha_zero, 0); } break; @@ -3553,7 +3633,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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; @@ -3647,7 +3727,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) // 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, @@ -3655,10 +3735,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } 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, @@ -3666,12 +3746,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) alpha_ret(code, alpha_ra, 1); - } - break; + } + break; 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, @@ -3697,18 +3777,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) MONO_PATCH_INFO_BB, ins->inst_target_bb); 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, @@ -3716,26 +3789,28 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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_profiler_method_leave, code, FALSE); + code = mono_arch_instrument_epilog (cfg, + mono_profiler_method_leave, code, FALSE); g_assert (!cfg->method->save_lmf); alpha_mov1( code, alpha_fp, alpha_sp ); @@ -3762,7 +3837,56 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) 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__); @@ -3785,9 +3909,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) last_ins = ins; last_offset = offset; - - ins = ins->next; - } + } cfg->code_len = ((char *)code) - ((char *)cfg->native_code); } @@ -3949,7 +4071,7 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, 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; @@ -3964,12 +4086,12 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, 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; } @@ -4088,7 +4210,7 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, 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"); @@ -4115,7 +4237,7 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, { MONO_INST_NEW (cfg, vtarg, OP_MOVE); vtarg->sreg1 = vt_reg; - vtarg->dreg = mono_regstate_next_int (cfg->rs); + vtarg->dreg = mono_alloc_ireg (cfg); mono_bblock_add_inst (cfg->cbb, vtarg); mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg, @@ -4130,7 +4252,7 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, MONO_INST_NEW (cfg, this, OP_MOVE); this->type = this_type; this->sreg1 = this_reg; - this->dreg = mono_regstate_next_int (cfg->rs); + this->dreg = mono_alloc_ireg (cfg); mono_bblock_add_inst (cfg->cbb, this); mono_call_inst_add_outarg_reg (cfg, call, this->dreg, @@ -4198,9 +4320,37 @@ mono_arch_setup_jit_tls_data (MonoJitTlsData *tls) void mono_arch_cpu_init (void) { - ALPHA_DEBUG("mono_arch_cpu_init"); + unsigned long amask, implver; + register long v0 __asm__("$0") = -1; + + ALPHA_DEBUG("mono_arch_cpu_init"); + + __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0)); + amask = ~v0; + __asm__ (".long 0x47e03d80" : "=r"(v0)); + implver = v0; + + if (amask & 1) + bwx_supported = 1; + + //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: @@ -4213,7 +4363,7 @@ mono_arch_cpu_init (void) * 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; @@ -4272,7 +4422,7 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke) cinfo->ret.reg = alpha_f0; break; case MONO_TYPE_GENERICINST: - if (!mono_type_generic_inst_is_valuetype (sig->ret)) + if (!mono_type_generic_inst_is_valuetype (ret_type)) { cinfo->ret.storage = ArgInIReg; cinfo->ret.reg = alpha_r0; @@ -4283,7 +4433,7 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke) { 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) @@ -4375,7 +4525,7 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke) add_general (pgr, &stack_size, ainfo); break; case MONO_TYPE_GENERICINST: - if (!mono_type_generic_inst_is_valuetype (sig->params [i])) + if (!mono_type_generic_inst_is_valuetype (ptype)) { add_general (pgr, &stack_size, ainfo); break; @@ -4384,7 +4534,7 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke) 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: @@ -4542,7 +4692,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, 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", @@ -4623,7 +4773,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(arg_type))) { - gint align; + guint align; guint32 size; if (arg_type->type == MONO_TYPE_TYPEDBYREF) { @@ -4635,7 +4785,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, 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) { @@ -4838,19 +4988,6 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, /*========================= 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 */ @@ -4864,7 +5001,6 @@ mono_arch_register_lowlevel_calls (void) { 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); } @@ -4886,9 +5022,9 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_get_global_int_regs"); - regs = g_list_prepend (regs, (gpointer)alpha_r9); - regs = g_list_prepend (regs, (gpointer)alpha_r10); - regs = g_list_prepend (regs, (gpointer)alpha_r11); +// regs = g_list_prepend (regs, (gpointer)alpha_r9); +// regs = g_list_prepend (regs, (gpointer)alpha_r10); +// regs = g_list_prepend (regs, (gpointer)alpha_r11); regs = g_list_prepend (regs, (gpointer)alpha_r12); regs = g_list_prepend (regs, (gpointer)alpha_r13); regs = g_list_prepend (regs, (gpointer)alpha_r14); @@ -4898,42 +5034,6 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) /*========================= 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 */ @@ -4953,15 +5053,15 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_get_allocatable_int_vars"); - header = mono_method_get_header (cfg->method); + header = cfg->header; 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]; @@ -4990,7 +5090,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) (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); @@ -5030,31 +5130,6 @@ mono_arch_get_domain_intrinsic (MonoCompile* cfg) /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_get_thread_intrinsic */ -/* */ -/* Function - */ -/* */ -/* Returns - */ -/* */ -/*------------------------------------------------------------------*/ - -MonoInst * -mono_arch_get_thread_intrinsic (MonoCompile* cfg) -{ - MonoInst *ins; - - if (thread_tls_offset == -1) - return NULL; - - MONO_INST_NEW (cfg, ins, OP_TLS_GET); - ins->inst_offset = thread_tls_offset; - return (ins); -} - -/*========================= End of Function ========================*/ - /*------------------------------------------------------------------*/ /* */ /* Name - mono_arch_get_inst_for_method */ @@ -5074,11 +5149,6 @@ mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, 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; } @@ -5105,7 +5175,7 @@ mono_arch_create_class_init_trampoline (MonoVTable *vtable) { 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; } @@ -5139,7 +5209,7 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, /* 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; @@ -5151,7 +5221,7 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, for (i = 0; i < n; ++i) { - inst = cfg->varinfo [i]; + inst = cfg->args [i]; if (inst->opcode == OP_REGVAR) { @@ -5220,8 +5290,7 @@ enum { /*------------------------------------------------------------------*/ void* -mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, - gboolean enable_arguments) +mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers) { unsigned int *code = p; int save_mode = SAVE_NONE; @@ -5384,11 +5453,11 @@ mono_arch_allocate_vars (MonoCompile *cfg) CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_allocate_vars"); - header = mono_method_get_header (cfg->method); + header = cfg->header; 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; @@ -5515,8 +5584,6 @@ mono_arch_allocate_vars (MonoCompile *cfg) } } - 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 @@ -5546,13 +5613,24 @@ mono_arch_allocate_vars (MonoCompile *cfg) CFG_DEBUG(3) g_print ("ALPHA: args_save_area_offset at %d(%x)\n", offset, offset); - // Consider floats passed in regs too - for (i = 0; i < (PARAM_REGS*2); ++i) - if (i < (sig->param_count + sig->hasthis)) - //(cfg->used_int_regs & (1 << param_regs[i]))) - { - offset += sizeof (gpointer); - } + for (i = 0; i < sig->param_count + sig->hasthis; ++i) + { + ArgInfo *ainfo = &cinfo->args [i]; + + switch(ainfo->storage) + { + case ArgInIReg: + case ArgInFloatReg: + case ArgInDoubleReg: + offset += sizeof (gpointer); + break; + case ArgAggregate: + offset += ainfo->nregs * sizeof (gpointer); + break; + default: + ; + } + } CFG_DEBUG(3) g_print ("ALPHA: Stack size is %d(%x)\n", offset, offset); @@ -5560,7 +5638,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) // 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) { @@ -5622,7 +5700,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) break; default: - NOT_IMPLEMENTED(""); + NOT_IMPLEMENTED; } if (!inreg && (ainfo->storage != ArgOnStack)) @@ -5703,7 +5781,7 @@ mono_arch_print_tree (MonoInst *tree, int arity) */ gpointer* -mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs) +mono_arch_get_vcall_slot_addr (guint8* code, mgreg_t *regs) { unsigned int *pc = (unsigned int *)code; guint32 reg, disp; @@ -5713,19 +5791,20 @@ mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs) 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"); @@ -5737,7 +5816,7 @@ mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs) // -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 ) @@ -5753,9 +5832,45 @@ mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs) return 0; } +gpointer +mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, mgreg_t *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 (); +}