a34535eef80538532dffa56dfee8e4144ea84595
[mono.git] / mono / mini / mini-alpha.c
1 /*------------------------------------------------------------------*/
2 /*                                                                  */
3 /* Name        - mini-alpha.c                                       */
4 /*                                                                  */
5 /* Function    - Alpha backend for the Mono code generator.         */
6 /*                                                                  */
7 /* Name        - Sergey Tikhonov (tsv@solvo.ru)                     */
8 /*                                                                  */
9 /* Date        - January, 2006                                      */
10 /*                                                                  */
11 /* Derivation  - From mini-am64 & mini-ia64 & mini-s390 by -        */
12 /*               Paolo Molaro (lupus@ximian.com)                    */
13 /*               Dietmar Maurer (dietmar@ximian.com)                */
14 /*               Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
15 /*                                                                  */
16 /*------------------------------------------------------------------*/
17
18 /*------------------------------------------------------------------*/
19 /*                 D e f i n e s                                    */
20 /*------------------------------------------------------------------*/
21 #define ALPHA_DEBUG(x) \
22    if (mini_alpha_verbose_level) \
23         g_debug ("ALPHA_DEBUG: %s is called.", x);
24
25 #define ALPHA_PRINT if (mini_alpha_verbose_level)
26
27 #define NEW_INS(cfg,ins,dest,op) do {                                   \
28    (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
29    (dest)->opcode = (op);  \
30    MONO_INST_LIST_ADD_TAIL (&(dest)->node, &(ins)->node);
31 } while (0)
32
33 #define NEW_ICONST(cfg,dest,val) do {                                   \
34     (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));   \
35     (dest)->opcode = OP_ICONST;                                         \
36     (dest)->inst_c0 = (val);                                            \
37     (dest)->type = STACK_I4;                                            \
38   } while (0)
39
40
41 #undef DEBUG
42 #define DEBUG(a) if (cfg->verbose_level > 1) a
43
44 #define CFG_DEBUG(LVL) if (cfg->verbose_level > LVL)
45
46 //#define ALPHA_IS_CALLEE_SAVED_REG(reg) (MONO_ARCH_CALLEE_SAVED_REGS & (1 << (reg)))
47 #define ALPHA_ARGS_REGS ((regmask_t)0x03F0000)
48 #define ARGS_OFFSET 16
49
50 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
51 #define alpha_is_imm(X) ((X >= 0 && X <= 255))
52 #define ALPHA_LOAD_GP(IP) { AlphaGotData ge_data;  add_got_entry(cfg, GT_LD_GTADDR, ge_data, IP, MONO_PATCH_INFO_NONE, 0); }
53
54 /*========================= End of Defines =========================*/
55
56 /*------------------------------------------------------------------*/
57 /*                 I n c l u d e s                                  */
58 /*------------------------------------------------------------------*/
59
60 #include "mini.h"
61 #include <string.h>
62
63 #include <mono/metadata/appdomain.h>
64 #include <mono/metadata/debug-helpers.h>
65 #include <mono/metadata/profiler-private.h>
66 #include <mono/utils/mono-math.h>
67
68 #include "trace.h"
69 #include "mini-alpha.h"
70 #include "inssel.h"
71 #include "cpu-alpha.h"
72 #include "jit-icalls.h"
73
74 /*========================= End of Includes ========================*/
75
76 /*------------------------------------------------------------------*/
77 /*                 G l o b a l   V a r i a b l e s                  */
78 /*------------------------------------------------------------------*/
79 static int indent_level = 0;
80
81 int mini_alpha_verbose_level = 0;
82 static int bwx_supported = 0;
83
84 static gboolean tls_offset_inited = FALSE;
85
86 static int appdomain_tls_offset = -1,
87   lmf_tls_offset = -1,
88   thread_tls_offset = -1;
89
90 pthread_key_t lmf_addr_key;
91
92 gboolean lmf_addr_key_inited = FALSE;
93
94 /*====================== End of Global Variables ===================*/
95
96 gpointer mono_arch_get_lmf_addr (void);
97
98 typedef enum {
99         ArgInIReg,
100         ArgInFloatReg,
101         ArgInDoubleReg,
102         ArgOnStack,
103         ArgValuetypeInReg, // ??
104         ArgAggregate,
105         ArgNone
106 } ArgStorage;
107
108
109 typedef struct {
110   gint16 offset;
111   gint8  reg;
112   ArgStorage storage;
113
114   /* Only if storage == ArgAggregate */
115   int nregs, nslots;
116   //AggregateType atype; // So far use only AggregateNormal
117 } ArgInfo;
118
119 typedef struct {
120    int nargs;
121    guint32 stack_usage;
122 //        guint32 struct_ret; /// ???
123
124    guint32 reg_usage;
125    guint32 freg_usage;
126    gboolean need_stack_align;
127
128    ArgInfo ret;
129    ArgInfo sig_cookie;
130    ArgInfo args [1];
131 } CallInfo;
132
133 static CallInfo* get_call_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke);
134 static unsigned int *emit_call(MonoCompile *cfg, unsigned int *code,
135                                guint32 patch_type, gconstpointer data);
136
137 #define PARAM_REGS 6
138 static int param_regs [] =
139
140   alpha_a0, alpha_a1,
141   alpha_a2, alpha_a3,
142   alpha_a4, alpha_a5
143 };
144
145 //static AMD64_Reg_No return_regs [] = { AMD64_RAX, AMD64_RDX };
146
147 static void inline
148 add_general (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo)
149 {
150    ainfo->offset = *stack_size;
151
152    if (*gr >= PARAM_REGS)
153      {
154        ainfo->storage = ArgOnStack;
155        (*stack_size) += sizeof (gpointer);
156      }
157    else
158      {
159        ainfo->storage = ArgInIReg;
160        ainfo->reg = param_regs [*gr];
161        (*gr) ++;
162      }
163 }
164
165 #define FLOAT_PARAM_REGS 6
166 static int fparam_regs [] = { alpha_fa0, alpha_fa1, alpha_fa2, alpha_fa3,
167                              alpha_fa4, alpha_fa5 };
168
169 static void inline
170 add_float (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo,
171            gboolean is_double)
172 {
173    ainfo->offset = *stack_size;
174    
175    if (*gr >= FLOAT_PARAM_REGS) 
176    {
177      ainfo->storage = ArgOnStack;
178      (*stack_size) += sizeof (gpointer);
179    }
180    else
181    {
182      /* A double register */
183      if (is_double)
184        ainfo->storage = ArgInDoubleReg;
185      else
186        ainfo->storage = ArgInFloatReg;
187
188      ainfo->reg = fparam_regs [*gr];
189      (*gr) += 1;
190    }
191 }
192
193 static void
194 add_valuetype (MonoGenericSharingContext *ctx, MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
195                gboolean is_return,
196                guint32 *gr, guint32 *fr, guint32 *stack_size)
197 {
198   guint32 size;
199   MonoClass *klass;
200   MonoMarshalType *info;
201   //gboolean is_hfa = TRUE;
202   //guint32 hfa_type = 0;
203
204   klass = mono_class_from_mono_type (type);
205   if (type->type == MONO_TYPE_TYPEDBYREF)
206     size = 3 * sizeof (gpointer);
207   else if (sig->pinvoke)
208     size = mono_type_native_stack_size (&klass->byval_arg, NULL);
209   else
210     size = mini_type_stack_size (gsctx, &klass->byval_arg, NULL);
211
212   if (!sig->pinvoke || (size == 0) || is_return) {
213     /* Allways pass in memory */
214     ainfo->offset = *stack_size;
215     *stack_size += ALIGN_TO (size, 8);
216     ainfo->storage = ArgOnStack;
217
218     return;
219   }
220
221   info = mono_marshal_load_type_info (klass);
222   g_assert (info);
223
224   ainfo->storage = ArgAggregate;
225   //ainfo->atype = AggregateNormal;
226
227 #if 0
228   /* This also handles returning of TypedByRef used by some icalls */
229   if (is_return) {
230     if (size <= 32) {
231       ainfo->reg = IA64_R8;
232       ainfo->nregs = (size + 7) / 8;
233       ainfo->nslots = ainfo->nregs;
234       return;
235     }
236     NOT_IMPLEMENTED;
237   }
238 #endif
239
240   ainfo->reg =  param_regs [*gr];
241   ainfo->offset = *stack_size;
242   ainfo->nslots = (size + 7) / 8;
243
244   if (((*gr) + ainfo->nslots) <= 6) {
245     /* Fits entirely in registers */
246     ainfo->nregs = ainfo->nslots;
247     (*gr) += ainfo->nregs;
248     return;
249   }
250
251   ainfo->nregs = 6 - (*gr);
252   (*gr) = 6;
253   (*stack_size) += (ainfo->nslots - ainfo->nregs) * 8;
254
255 }
256
257 // This function is called from mono_arch_call_opcode and
258 // should determine which registers will be used to do the call
259 // For Alpha we could calculate number of parameter used for each
260 // call and allocate space in stack only for whose "a0-a5" registers
261 // that will be used in calls
262 static void
263 add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, MonoInst *arg,
264                 ArgStorage storage, int reg, MonoInst *tree)
265 {
266   switch (storage)
267     {
268     case ArgInIReg:
269       arg->opcode = OP_OUTARG_REG;
270       arg->inst_left = tree;
271       arg->inst_right = (MonoInst*)call;
272       arg->backend.reg3 = reg;
273       call->used_iregs |= 1 << reg;
274       break;
275     case ArgInFloatReg:
276       arg->opcode = OP_OUTARG_FREG;
277       arg->inst_left = tree;
278       arg->inst_right = (MonoInst*)call;
279       arg->backend.reg3 = reg;
280       call->used_fregs |= 1 << reg;
281       break;
282     case ArgInDoubleReg:
283       arg->opcode = OP_OUTARG_FREG;
284       arg->inst_left = tree;
285       arg->inst_right = (MonoInst*)call;
286       arg->backend.reg3 = reg;
287       call->used_fregs |= 1 << reg;
288       break;
289     default:
290       g_assert_not_reached ();
291     }
292 }
293
294 static void add_got_entry(MonoCompile *cfg, AlphaGotType ge_type,
295                           AlphaGotData ge_data,
296                           int ip, MonoJumpInfoType type, gconstpointer target)
297 {
298   AlphaGotEntry *AGE = mono_mempool_alloc (cfg->mempool,
299                                            sizeof (AlphaGotEntry));
300
301   AGE->type = ge_type;
302
303   switch(ge_type)
304     {
305     case GT_INT:
306       AGE->value.data.i = ge_data.data.i;
307       break;
308     case GT_LONG:
309       AGE->value.data.l = ge_data.data.l;
310       break;
311     case GT_PTR:
312       AGE->value.data.p = ge_data.data.p;
313       break;
314     case GT_FLOAT:
315       AGE->value.data.f = ge_data.data.f;
316       break;
317     case GT_DOUBLE:
318       AGE->value.data.d = ge_data.data.d;
319       break;
320     case GT_LD_GTADDR:
321       AGE->value.data.l = ip;
322       break;
323     default:
324       AGE->type = GT_NONE;
325     }
326   
327   if (type != MONO_PATCH_INFO_NONE)
328     {
329       mono_add_patch_info(cfg, ip, type, target);
330       AGE->patch_info = cfg->patch_info;
331     }
332   else
333     AGE->patch_info = 0;
334
335   if (AGE->type != GT_LD_GTADDR)
336   {
337       mono_add_patch_info(cfg, ip, MONO_PATCH_INFO_GOT_OFFSET, 0);
338       AGE->got_patch_info = cfg->patch_info;
339   }
340
341   AGE->next = cfg->arch.got_data;
342
343   cfg->arch.got_data = AGE;
344 }
345
346 /*------------------------------------------------------------------*/
347 /*                                                                  */
348 /* Name         - mono_arch_create_vars                             */
349 /*                                                                  */
350 /* Function     -                                                   */
351 /*                                                                  */
352 /* Returns      - 
353  * 
354  * Params:
355  *  cfg - pointer to compile unit
356  *
357  * TSV (guess)
358  * This method is called right before starting converting compiled
359  * method to IR. I guess we could find out how many arguments we
360  * should expect, what type and what return value would be.
361  * After that we could correct "cfg" structure, or "arch" part of
362  * that structure.
363  */
364 /*                                                                  */
365 /*------------------------------------------------------------------*/
366
367 void
368 mono_arch_create_vars (MonoCompile *cfg)
369 {   
370   MonoMethodSignature *sig;
371   CallInfo *cinfo;
372
373   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_create_vars");
374    
375   sig = mono_method_signature (cfg->method);
376    
377   cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
378    
379   if (cinfo->ret.storage == ArgValuetypeInReg)
380     cfg->ret_var_is_local = TRUE;
381   
382   g_free (cinfo);
383 }
384
385
386 /*------------------------------------------------------------------*/
387 /*                                                                  */
388 /* Name         - mono_arch_get_lmf_addr                            */
389 /*                                                                  */
390 /* Function     -                                                   */
391 /*                                                                  */
392 /* Returns      -                                                   */
393 /*                                                                  */
394 /*------------------------------------------------------------------*/
395
396 gpointer
397 mono_arch_get_lmf_addr (void)
398 {
399   ALPHA_DEBUG("mono_arch_get_lmf_addr");
400    
401   return pthread_getspecific (lmf_addr_key);
402 }
403
404 /*========================= End of Function ========================*/
405
406 /*------------------------------------------------------------------*/
407 /*                                                                  */
408 /* Name         - mono_arch_free_jit_tls_data                       */
409 /*                                                                  */
410 /* Function     - Free tls data.                                    */
411 /*                                                                  */
412 /*------------------------------------------------------------------*/
413
414 void
415 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
416 {
417   ALPHA_DEBUG("mono_arch_free_jit_tls_data");
418 }
419
420 /*========================= End of Function ========================*/
421
422 void
423 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
424 {
425 }
426
427 void
428 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
429 {
430   MonoInst *ins, *n;
431    
432   CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE pass\n");
433
434   MONO_INST_LIST_FOR_EACH_ENTRY_SAFE (ins, n, &bb->ins_list, node) {
435       MonoInst *last_ins = mono_inst_list_prev (&ins->node, &bb->ins_list);
436       switch (ins->opcode) 
437         {        
438         case OP_MOVE:
439         case OP_FMOVE:
440           /*
441            * Removes:
442            *
443            * OP_MOVE reg, reg except special case (mov at, at)
444            */
445           if (ins->dreg == ins->sreg1 &&
446               ins->dreg != alpha_at) 
447             {
448               MONO_DEL_INS (ins);
449               continue;
450             }
451           
452           /*
453            * Removes:
454            *
455            * OP_MOVE sreg, dreg
456            * OP_MOVE dreg, sreg
457            */
458           if (last_ins && last_ins->opcode == OP_MOVE &&
459               ins->sreg1 == last_ins->dreg &&
460               last_ins->dreg != alpha_at &&
461               ins->dreg == last_ins->sreg1) 
462             {
463               MONO_DEL_INS (ins);
464               continue;
465             }
466           
467           break;
468         case OP_MUL_IMM:
469         case OP_IMUL_IMM:
470           /* remove unnecessary multiplication with 1 */
471           if (ins->inst_imm == 1) 
472             {
473               if (ins->dreg != ins->sreg1) 
474                 {
475                   ins->opcode = OP_MOVE;
476                 }
477               else 
478                 {
479                   MONO_DEL_INS (ins);
480                   continue;
481                 }
482             }
483           
484           break;
485
486         case OP_LOADI8_MEMBASE:
487         case OP_LOAD_MEMBASE:
488           /*
489            * Note: if reg1 = reg2 the load op is removed
490            *
491            * OP_STOREI8_MEMBASE_REG reg1, offset(basereg)
492            * OP_LOADI8_MEMBASE offset(basereg), reg2
493            * -->
494            * OP_STOREI8_MEMBASE_REG reg1, offset(basereg)
495            * OP_MOVE reg1, reg2
496            */
497           if (last_ins &&
498               (last_ins->opcode == OP_STOREI8_MEMBASE_REG ||
499                 last_ins->opcode == OP_STORE_MEMBASE_REG) &&
500               ins->inst_basereg == last_ins->inst_destbasereg &&
501               ins->inst_offset == last_ins->inst_offset)
502             {
503               if (ins->dreg == last_ins->sreg1)
504                 {
505                   MONO_DEL_INS (ins);
506                   continue;
507                 }
508               else
509                 {
510                   //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
511                   ins->opcode = OP_MOVE;
512                   ins->sreg1 = last_ins->sreg1;
513                 }
514             }
515           break;
516
517 #if 0
518         case OP_LOAD_MEMBASE:
519         case OP_LOADI4_MEMBASE:
520           /*
521            * Note: if reg1 = reg2 the load op is removed
522            *
523            * OP_STORE_MEMBASE_REG reg1, offset(basereg)
524            * OP_LOAD_MEMBASE offset(basereg), reg2
525            * -->
526            * OP_STORE_MEMBASE_REG reg1, offset(basereg)
527            * OP_MOVE reg1, reg2
528            */
529           if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG
530                            /*|| last_ins->opcode == OP_STORE_MEMBASE_REG*/) &&
531               ins->inst_basereg == last_ins->inst_destbasereg &&
532               ins->inst_offset == last_ins->inst_offset)
533             {
534               if (ins->dreg == last_ins->sreg1)
535                 {
536                   MONO_DEL_INS (ins);
537                   continue;
538                 }
539               else
540                 {
541                   //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
542                   ins->opcode = OP_MOVE;
543                   ins->sreg1 = last_ins->sreg1;
544                 }
545             }
546           /*
547            * Note: reg1 must be different from the basereg in the second load
548            * Note: if reg1 = reg2 is equal then second load is removed
549            *
550            * OP_LOAD_MEMBASE offset(basereg), reg1
551            * OP_LOAD_MEMBASE offset(basereg), reg2
552            * -->
553            * OP_LOAD_MEMBASE offset(basereg), reg1
554            * OP_MOVE reg1, reg2
555            */
556
557           if (last_ins && (last_ins->opcode == OP_LOADI4_MEMBASE
558                            || last_ins->opcode == OP_LOAD_MEMBASE) &&
559               ins->inst_basereg != last_ins->dreg &&
560               ins->inst_basereg == last_ins->inst_basereg &&
561               ins->inst_offset == last_ins->inst_offset)
562             {
563               if (ins->dreg == last_ins->dreg)
564                 {
565                   MONO_DEL_INS (ins);
566                   continue;
567                 }
568               else
569                 {
570                   ins->opcode = OP_MOVE;
571                   ins->sreg1 = last_ins->dreg;
572                 }
573
574               //g_assert_not_reached ();
575             }
576           break;      
577 #endif
578         }
579     }
580 }
581
582 // Convert to opposite branch opcode
583 static guint16 cvt_branch_opcode(guint16 opcode)
584 {
585   switch (opcode)
586     {
587     case CEE_BEQ:
588       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BEQ -> CEE_BNE_UN\n");
589       return CEE_BNE_UN;
590
591
592       //case CEE_CGT_UN:
593       //printf("ALPHA: Branch cvt: CEE_CGT_UN -> OP_IBEQ\n");
594       //return OP_IBEQ;
595
596       //case OP_LCGT_UN:
597       //printf("ALPHA: Branch cvt: OP_LCGT_UN -> OP_IBEQ\n");
598       //return OP_IBEQ;
599
600       //    case OP_CGT_UN:
601       //printf("ALPHA: Branch cvt: OP_CGT_UN -> OP_IBEQ\n");
602       //return OP_IBEQ;
603
604     case OP_IBEQ:
605       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBEQ -> OP_IBNE_UN\n");
606       return OP_IBNE_UN;
607
608     case OP_FBEQ:
609       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_FBEQ -> OP_FBNE_UN\n");
610       return OP_FBNE_UN;
611
612     case OP_FBNE_UN:
613       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_FBNE_UN -> OP_FBEQ\n");
614       return OP_FBEQ;
615                 
616     case OP_IBNE_UN:
617       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBNE_UN -> OP_IBEQ\n");
618       return OP_IBEQ;
619                 
620     case CEE_BNE_UN:
621       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BNE_UN -> OP_IBEQ\n");
622       return OP_IBEQ;
623
624     case OP_IBLE:
625       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBLE -> OP_IBNE_UN\n");
626       return OP_IBNE_UN;
627
628     case OP_IBLE_UN:
629       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBLE_UN -> OP_IBNE_UN\n");
630       return OP_IBNE_UN;
631
632     case CEE_BLE:
633       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BLE -> OP_IBNE_UN\n");
634       return OP_IBNE_UN;
635
636     case CEE_BLE_UN:
637       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BLE_UN -> OP_IBNE_UN\n");
638       return OP_IBNE_UN;
639
640     case OP_IBLT:
641       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBLT -> OP_IBNE_UN\n");
642       return OP_IBNE_UN;
643
644     case CEE_BLT:
645       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BLT -> OP_IBNE_UN\n");
646       return OP_IBNE_UN;
647
648     case CEE_BLT_UN:
649       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BLT_UN -> OP_IBNE_UN\n");
650       return OP_IBNE_UN;
651
652     case OP_IBLT_UN:
653       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBLT_UN -> OP_IBNE_UN\n");
654       return OP_IBNE_UN;
655
656     case OP_IBGE:
657       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBGE -> OP_IBEQ\n");
658       return OP_IBEQ;
659
660     case CEE_BGE:
661       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BGE -> OP_IBEQ\n");
662       return OP_IBEQ;
663
664     case CEE_BGT:
665       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BGT -> OP_IBEQ\n");
666       return OP_IBEQ;
667
668     case OP_IBGT:
669       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBGT -> OP_IBEQ\n");
670       return OP_IBEQ;
671
672     case CEE_BGT_UN:
673       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BGT_UN -> OP_IBEQ\n");
674       return OP_IBEQ;
675
676     case OP_IBGT_UN:
677       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBGT_UN -> OP_IBEQ\n");
678       return OP_IBEQ;
679
680     case CEE_BGE_UN:
681       ALPHA_PRINT g_debug("ALPHA: Branch cvt: CEE_BGE_UN -> OP_IBEQ\n");
682       return OP_IBEQ;
683
684     case OP_IBGE_UN:
685       ALPHA_PRINT g_debug("ALPHA: Branch cvt: OP_IBGE_UN -> OP_IBEQ\n");
686       return OP_IBEQ;
687
688     default:
689       break;
690     }
691
692   ALPHA_PRINT g_debug("ALPHA: WARNING: No Branch cvt for: %d\n", opcode);
693    
694   return opcode;
695 }
696
697 typedef enum { EQ, ULE, LE, LT, ULT } ALPHA_CMP_OPS;
698
699 static guint16 cvt_cmp_opcode(guint16 opcode, ALPHA_CMP_OPS cond)
700 {
701   guint16 ret_opcode;
702
703   switch (opcode)
704     {
705       /* Use inssel-alpha.brg to handle cmp+b<cond> -> cmp<cond>+b<cond> cvt */
706     case OP_FCOMPARE:
707       break;
708
709     case OP_COMPARE:
710     case OP_ICOMPARE:
711     case OP_LCOMPARE:
712       {
713         switch(cond)
714           {
715           case EQ:
716             return OP_ALPHA_CMP_EQ;
717           case ULE:
718             return OP_ALPHA_CMP_ULE;
719           case LE:
720             return OP_ALPHA_CMP_LE;
721           case LT:
722             return OP_ALPHA_CMP_LT;
723           case ULT:
724             return OP_ALPHA_CMP_ULT;
725           }
726       }
727       break;
728
729     case OP_ICOMPARE_IMM:
730     case OP_COMPARE_IMM:
731       {
732         switch(cond)
733           {
734           case EQ:
735             return OP_ALPHA_CMP_IMM_EQ;
736           case ULE:
737             return OP_ALPHA_CMP_IMM_ULE;
738           case LE:
739             return OP_ALPHA_CMP_IMM_LE;
740           case LT:
741             return OP_ALPHA_CMP_IMM_LT;
742           case ULT:
743             return OP_ALPHA_CMP_IMM_ULT;
744           }
745       }
746     }
747
748   g_assert_not_reached();
749
750   return ret_opcode;
751 }
752
753 static void cvt_cmp_branch(MonoInst *curr, MonoInst *next)
754 {
755    // Instead of compare+b<cond>,
756    // Alpha has compare<cond>+br<cond>
757    // we need to convert
758    // Handle floating compare here too
759    
760   switch(next->opcode)
761     {
762     case CEE_BEQ:
763     case OP_IBEQ:
764       // Convert cmp + beq -> cmpeq + bne
765       curr->opcode = cvt_cmp_opcode(curr->opcode, EQ);
766       next->opcode = cvt_branch_opcode(next->opcode);
767       break;
768                 
769     case OP_IBNE_UN:
770     case CEE_BNE_UN:
771       // cmp + ibne_un -> cmpeq + beq
772       curr->opcode = cvt_cmp_opcode(curr->opcode, EQ);
773       next->opcode = cvt_branch_opcode(next->opcode);
774       break;
775
776     case OP_IBLE:
777     case CEE_BLE:
778       // cmp + ible -> cmple + bne, lcmp + ble -> cmple + bne
779       curr->opcode = cvt_cmp_opcode(curr->opcode, LE);
780       next->opcode = cvt_branch_opcode(next->opcode);
781       break;
782
783     case CEE_BLE_UN:
784     case OP_IBLE_UN:
785       // cmp + ible_un -> cmpule + bne, lcmp + ble.un -> cmpule + bne
786       curr->opcode = cvt_cmp_opcode(curr->opcode, ULE);
787       next->opcode = cvt_branch_opcode(next->opcode);
788       break;
789
790     case OP_IBLT:
791     case CEE_BLT:
792       // cmp + iblt -> cmplt + bne, lcmp + blt -> cmplt + bne
793       curr->opcode = cvt_cmp_opcode(curr->opcode, LT);
794       next->opcode = cvt_branch_opcode(next->opcode);
795       break;
796
797     case CEE_BLT_UN:
798     case OP_IBLT_UN:
799       // lcmp + blt.un -> cmpult + bne
800       curr->opcode = cvt_cmp_opcode(curr->opcode, ULT);
801       next->opcode = cvt_branch_opcode(next->opcode);
802       break;
803
804     case OP_IBGE:
805     case CEE_BGE:
806       // cmp + ibge -> cmplt + beq, lcmp + bge -> cmplt + beq
807       curr->opcode = cvt_cmp_opcode(curr->opcode, LT);
808       next->opcode = cvt_branch_opcode(next->opcode);
809       break;
810
811     case CEE_BGE_UN:
812     case OP_IBGE_UN:
813       //lcmp + bge.un -> cmpult + beq
814       curr->opcode = cvt_cmp_opcode(curr->opcode, ULT);
815       next->opcode = cvt_branch_opcode(next->opcode);
816       break;
817
818     case OP_IBGT:
819     case CEE_BGT:
820       // lcmp + bgt -> cmple + beq, cmp + ibgt -> cmple + beq
821       curr->opcode = cvt_cmp_opcode(curr->opcode, LE);
822       next->opcode = cvt_branch_opcode(next->opcode);
823       break;
824
825     case CEE_BGT_UN:
826     case OP_IBGT_UN:
827       // lcmp + bgt -> cmpule + beq, cmp + ibgt -> cmpule + beq
828       curr->opcode = cvt_cmp_opcode(curr->opcode, ULE);
829       next->opcode = cvt_branch_opcode(next->opcode);
830       break;
831
832       //    case CEE_CGT_UN:
833     case OP_CGT_UN:
834     case OP_ICGT_UN:
835       // cmp + cgt_un -> cmpule + beq
836       curr->opcode = cvt_cmp_opcode(curr->opcode, ULE);
837       break;
838
839     case OP_ICEQ:
840     case OP_CEQ:
841       // cmp + iceq -> cmpeq + bne
842       curr->opcode = cvt_cmp_opcode(curr->opcode, EQ);
843       break;
844
845     case OP_ICGT:
846     case OP_CGT:
847       // cmp + int_cgt -> cmple + beq
848       curr->opcode = cvt_cmp_opcode(curr->opcode, LE);
849       break;
850
851     case OP_ICLT:
852     case OP_CLT:
853       // cmp + int_clt -> cmplt + bne
854       curr->opcode = cvt_cmp_opcode(curr->opcode, LT);
855       break;
856
857     case OP_ICLT_UN:
858     case OP_CLT_UN:
859       // cmp + int_clt_un -> cmpult + bne
860       curr->opcode = cvt_cmp_opcode(curr->opcode, ULT);
861       break;
862
863
864     // The conditional exceptions will be handled in
865     // output_basic_blocks. Here we just determine correct
866     // cmp
867     case OP_COND_EXC_GT:
868       curr->opcode = cvt_cmp_opcode(curr->opcode, LE);
869       break;
870
871     case OP_COND_EXC_GT_UN:
872       curr->opcode = cvt_cmp_opcode(curr->opcode, ULE);
873       break;
874
875     case OP_COND_EXC_LT:
876       curr->opcode = cvt_cmp_opcode(curr->opcode, LT);
877       break;
878
879     case OP_COND_EXC_LT_UN:
880       curr->opcode = cvt_cmp_opcode(curr->opcode, ULT);
881       break;
882
883     case OP_COND_EXC_LE_UN:
884       curr->opcode = cvt_cmp_opcode(curr->opcode, ULE);
885       break;
886
887     case OP_COND_EXC_NE_UN:
888       curr->opcode = cvt_cmp_opcode(curr->opcode, EQ);
889       break;
890
891     case OP_COND_EXC_EQ:
892       curr->opcode = cvt_cmp_opcode(curr->opcode, EQ);
893       break;
894
895
896     default:
897       g_warning("cvt_cmp_branch called with %s(%0X) br opcode",
898                 mono_inst_name(next->opcode), next->opcode);
899
900       //      g_assert_not_reached();
901
902       break;
903     }
904 }
905
906
907 /*
908  * mono_arch_lowering_pass:
909  *
910  * Converts complex opcodes into simpler ones so that each IR instruction
911  * corresponds to one machine instruction.
912  */
913 static void
914   mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
915 {   
916    MonoInst *ins, *n, *next, *temp;
917    
918    if (bb->max_vreg > cfg->rs->next_vreg)
919          cfg->rs->next_vreg = bb->max_vreg;
920    
921    /*
922     * FIXME: Need to add more instructions, but the current machine
923     * description can't model some parts of the composite instructions like
924     * cdq.
925     */
926    
927    MONO_INST_LIST_FOR_EACH_ENTRY_SAFE (ins, n, &bb->ins_list, node) {
928        switch (ins->opcode) 
929          {       
930          case OP_DIV_IMM:
931          case OP_REM_IMM:
932          case OP_IDIV_IMM:
933          case OP_IREM_IMM:
934          case OP_MUL_IMM:
935            NEW_INS (cfg, ins, temp, OP_I8CONST);
936            temp->inst_c0 = ins->inst_imm;
937            temp->dreg = mono_regstate_next_int (cfg->rs);
938            
939            switch (ins->opcode) 
940              {
941              case OP_MUL_IMM:
942                ins->opcode = CEE_MUL;
943                break;
944              case OP_DIV_IMM:
945                ins->opcode = OP_LDIV;
946                break;
947              case OP_REM_IMM:
948                ins->opcode = OP_LREM;
949                break;
950              case OP_IDIV_IMM:
951                ins->opcode = OP_IDIV;
952                break;
953              case OP_IREM_IMM:
954                ins->opcode = OP_IREM;
955                break;
956              }
957                          
958            ins->sreg2 = temp->dreg;
959            break;
960
961          case OP_COMPARE:
962          case OP_ICOMPARE:
963          case OP_LCOMPARE:
964          case OP_FCOMPARE:
965            {
966              // Instead of compare+b<cond>/fcompare+b<cond>,
967              // Alpha has compare<cond>+br<cond>/fcompare<cond>+br<cond>
968              // we need to convert
969              next = mono_inst_list_next (&ins->node, &bb->ins_list);
970              g_assert(next);
971
972              cvt_cmp_branch(ins, next);
973            }
974            break;
975
976          case OP_COMPARE_IMM:
977            if (!alpha_is_imm (ins->inst_imm)) 
978              {    
979                NEW_INS (cfg, ins, temp, OP_I8CONST);
980                temp->inst_c0 = ins->inst_imm;
981                temp->dreg = mono_regstate_next_int (cfg->rs);
982                ins->opcode = OP_COMPARE;
983                ins->sreg2 = temp->dreg;
984                                   
985                // We should try to reevaluate new IR opcode
986                continue;
987              }
988            
989            next = mono_inst_list_next (&ins->node, &bb->ins_list);
990            g_assert(next);
991            
992            cvt_cmp_branch(ins, next);
993                          
994            break;
995
996          case OP_ICOMPARE_IMM:
997            if (!alpha_is_imm (ins->inst_imm))
998              {
999                NEW_INS (cfg, ins, temp, OP_ICONST);
1000                temp->inst_c0 = ins->inst_imm;
1001                temp->dreg = mono_regstate_next_int (cfg->rs);
1002                ins->opcode = OP_ICOMPARE;
1003                ins->sreg2 = temp->dreg;
1004
1005                // We should try to reevaluate new IR opcode
1006                continue;
1007              }
1008
1009            next = mono_inst_list_next (&ins->node, &bb->ins_list);
1010            g_assert(next);
1011
1012            cvt_cmp_branch(ins, next);
1013
1014            break;
1015
1016          case OP_STORE_MEMBASE_IMM:
1017          case OP_STOREI8_MEMBASE_IMM:
1018            if (ins->inst_imm != 0) 
1019              {    
1020                NEW_INS (cfg, ins, temp, OP_I8CONST);
1021                temp->inst_c0 = ins->inst_imm;
1022                temp->dreg = mono_regstate_next_int (cfg->rs);
1023                ins->opcode = OP_STOREI8_MEMBASE_REG;
1024                ins->sreg1 = temp->dreg;
1025              }
1026            break;
1027
1028          case OP_STOREI4_MEMBASE_IMM:
1029            if (ins->inst_imm != 0)
1030              {
1031                MonoInst *temp;
1032                NEW_INS (cfg, ins, temp, OP_ICONST);
1033                temp->inst_c0 = ins->inst_imm;
1034                temp->dreg = mono_regstate_next_int (cfg->rs);
1035                ins->opcode = OP_STOREI4_MEMBASE_REG;
1036                ins->sreg1 = temp->dreg;
1037              }
1038            break;
1039
1040          case OP_STOREI1_MEMBASE_IMM:
1041            if (ins->inst_imm != 0 || !bwx_supported)
1042              {
1043                MonoInst *temp;
1044                NEW_INS (cfg, ins, temp, OP_ICONST);
1045                temp->inst_c0 = ins->inst_imm;
1046                temp->dreg = mono_regstate_next_int (cfg->rs);
1047                ins->opcode = OP_STOREI1_MEMBASE_REG;
1048                ins->sreg1 = temp->dreg;
1049              }
1050            break;
1051
1052          case OP_STOREI2_MEMBASE_IMM:
1053            if (ins->inst_imm != 0 || !bwx_supported)
1054            {
1055              MonoInst *temp;
1056              NEW_INS (cfg, ins, temp, OP_ICONST);
1057              temp->inst_c0 = ins->inst_imm;
1058              temp->dreg = mono_regstate_next_int (cfg->rs);
1059              ins->opcode = OP_STOREI2_MEMBASE_REG;
1060              ins->sreg1 = temp->dreg;
1061            }
1062            break;
1063                          
1064          case OP_IADD_IMM:
1065          case OP_ISUB_IMM:
1066          case OP_IAND_IMM:
1067          case OP_IOR_IMM:
1068          case OP_IXOR_IMM:
1069          case OP_ISHL_IMM:
1070          case OP_ISHR_IMM:
1071          case OP_ISHR_UN_IMM:
1072            if (!alpha_is_imm(ins->inst_imm))
1073              {
1074                MonoInst *temp;
1075                NEW_INS (cfg, ins, temp, OP_ICONST);
1076                temp->inst_c0 = ins->inst_imm;
1077                temp->dreg = mono_regstate_next_int (cfg->rs);
1078                                   
1079                switch(ins->opcode)
1080                  {
1081                  case OP_IADD_IMM:
1082                    ins->opcode = OP_IADD;
1083                    break;
1084                  case OP_ISUB_IMM:
1085                    ins->opcode = OP_ISUB;
1086                    break;
1087                  case OP_IAND_IMM:
1088                    ins->opcode = OP_IAND;
1089                    break;
1090                  case OP_IOR_IMM:
1091                    ins->opcode = OP_IOR;
1092                    break;
1093                  case OP_IXOR_IMM:
1094                    ins->opcode = OP_IXOR;
1095                    break;
1096                  case OP_ISHL_IMM:
1097                    ins->opcode = OP_ISHL;
1098                    break;
1099                  case OP_ISHR_IMM:
1100                    ins->opcode = OP_ISHR;
1101                    break;
1102                  case OP_ISHR_UN_IMM:
1103                    ins->opcode = OP_ISHR_UN;
1104
1105                  default:
1106                    break;
1107                  }
1108                
1109                ins->sreg2 = temp->dreg;
1110              }
1111            break;
1112          case OP_ADD_IMM:
1113          case OP_AND_IMM:
1114          case OP_SHL_IMM:
1115            if (!alpha_is_imm(ins->inst_imm))
1116              {
1117                MonoInst *temp;
1118                NEW_INS (cfg, ins, temp, OP_ICONST);
1119                temp->inst_c0 = ins->inst_imm;
1120                temp->dreg = mono_regstate_next_int (cfg->rs);
1121                
1122                switch(ins->opcode)
1123                  {
1124                  case OP_ADD_IMM:
1125                    ins->opcode = CEE_ADD;
1126                    break;
1127                  case OP_ISUB_IMM:
1128                    ins->opcode = CEE_SUB;
1129                    break;
1130                  case OP_AND_IMM:
1131                    ins->opcode = CEE_AND;
1132                    break;
1133                  case OP_SHL_IMM:
1134                    ins->opcode = CEE_SHL;
1135                    break;
1136                  default:
1137                    break;
1138                  }
1139                
1140                ins->sreg2 = temp->dreg;
1141              }
1142            break;
1143          case OP_LSHR_IMM:
1144            if (!alpha_is_imm(ins->inst_imm))
1145              {
1146                MonoInst *temp;
1147                NEW_INS(cfg, ins, temp, OP_ICONST);
1148                temp->inst_c0 = ins->inst_imm;
1149                temp->dreg = mono_regstate_next_int(cfg->rs);
1150                ins->sreg2 = temp->dreg;
1151                ins->opcode = OP_LSHR;
1152              }
1153            break;
1154          case OP_LSHL_IMM:
1155            if (!alpha_is_imm(ins->inst_imm))
1156              {
1157                MonoInst *temp;
1158                NEW_INS(cfg, ins, temp, OP_ICONST);
1159                temp->inst_c0 = ins->inst_imm;
1160                temp->dreg = mono_regstate_next_int(cfg->rs);
1161                ins->sreg2 = temp->dreg;
1162                ins->opcode = OP_LSHL;
1163              }
1164            break;
1165
1166          default:
1167            break;
1168          }
1169      }
1170    
1171    bb->max_vreg = cfg->rs->next_vreg;
1172 }
1173
1174 /*========================= End of Function ========================*/
1175
1176 #define AXP_GENERAL_REGS     6
1177 #define AXP_MIN_STACK_SIZE   24
1178
1179 /* A typical Alpha stack frame looks like this */
1180 /*
1181 fun:                         // called from outside the module.
1182         ldgp gp,0(pv)        // load the global pointer
1183 fun..ng:                     // called from inside the module.
1184         lda sp, -SIZE( sp )  // grow the stack downwards.
1185
1186         stq ra, 0(sp)        // save the return address.
1187
1188         stq s0, 8(sp)        // callee-saved registers.
1189         stq s1, 16(sp)       // ...
1190
1191         // Move the arguments to the argument registers...
1192
1193         mov addr, pv         // Load the callee address
1194         jsr  ra, (pv)        // call the method.
1195         ldgp gp, 0(ra)       // restore gp
1196
1197         // return value is in v0
1198
1199         ldq ra, 0(sp)        // free stack frame
1200         ldq s0, 8(sp)        // restore callee-saved registers.
1201         ldq s1, 16(sp)
1202         ldq sp, 32(sp)       // restore stack pointer
1203
1204         ret zero, (ra), 1    // return.
1205
1206 // min SIZE = 48
1207 // our call must look like this.
1208
1209 call_func:
1210         ldgp gp, 0(pv)
1211 call_func..ng:
1212         .prologue
1213         lda sp, -SIZE(sp)  // grow stack SIZE bytes.
1214         stq ra, SIZE-48(sp)   // store ra
1215         stq fp, SIZE-40(sp)   // store fp (frame pointer)
1216         stq a0, SIZE-32(sp)   // store args. a0 = func
1217         stq a1, SIZE-24(sp)   // a1 = retval
1218         stq a2, SIZE-16(sp)   // a2 = this
1219         stq a3, SIZE-8(sp)    // a3 = args
1220         mov sp, fp            // set frame pointer
1221         mov pv, a0            // func
1222
1223         .calling_arg_this
1224         mov a1, a2
1225
1226         .calling_arg_6plus
1227         ldq t0, POS(a3)
1228         stq t0, 0(sp)
1229         ldq t1, POS(a3)
1230         stq t1, 8(sp)
1231         ... SIZE-56 ...
1232
1233         mov zero,a1
1234         mov zero,a2
1235         mov zero,a3
1236         mov zero,a4
1237         mov zero,a5
1238
1239         .do_call
1240         jsr ra, (pv)    // call func
1241         ldgp gp, 0(ra)  // restore gp.
1242         mov v0, t1      // move return value into t1
1243
1244         .do_store_retval
1245         ldq t0, SIZE-24(fp) // load retval into t2
1246         stl t1, 0(t0)       // store value.
1247
1248         .finished
1249         mov fp,sp
1250         ldq ra,SIZE-48(sp)
1251         ldq fp,SIZE-40(sp)
1252         lda sp,SIZE(sp)
1253         ret zero,(ra),1
1254 */
1255
1256 /*
1257  * emit_load_volatile_arguments:
1258  *
1259  *  Load volatile arguments from the stack to the original input registers.
1260  * Required before a tail call.
1261  */
1262 static unsigned int*
1263 emit_load_volatile_arguments (MonoCompile *cfg, unsigned int *code)
1264 {
1265   MonoMethod *method = cfg->method;
1266   MonoMethodSignature *sig;
1267   MonoInst *inst;
1268   CallInfo *cinfo;
1269   guint32 i;
1270
1271   /* FIXME: Generate intermediate code instead */
1272
1273   sig = mono_method_signature (method);
1274
1275   cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
1276
1277   if (sig->ret->type != MONO_TYPE_VOID) {
1278     if ((cinfo->ret.storage == ArgInIReg) &&
1279         (cfg->ret->opcode != OP_REGVAR))
1280       {
1281         alpha_ldq(code, cinfo->ret.reg, cfg->ret->inst_basereg,
1282                   cfg->ret->inst_offset);
1283       }
1284   }
1285
1286   for (i = 0; i < sig->param_count + sig->hasthis; ++i)
1287     {
1288       ArgInfo *ainfo = &cinfo->args [i];
1289       MonoInst *inst = cfg->args [i];
1290
1291       switch(ainfo->storage)
1292         {
1293         case ArgInIReg:
1294           // We need to save all used a0-a5 params
1295           //for (i=0; i<PARAM_REGS; i++)
1296           //  {
1297           //    if (i < cinfo->reg_usage)
1298           {
1299             //alpha_stq(code, ainfo->reg, alpha_fp, offset);
1300             alpha_ldq(code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
1301
1302             CFG_DEBUG(3) g_print("ALPHA: Saved int arg reg %d at offset: %0lx\n",
1303                                  ainfo->reg, inst->inst_offset/*offset*/);
1304           }
1305           //}
1306           break;
1307         case ArgInDoubleReg:
1308         case ArgInFloatReg:
1309           // We need to save all used af0-af5 params
1310           //for (i=0; i<PARAM_REGS; i++)
1311           //  {
1312           //    if (i < cinfo->freg_usage)
1313           {
1314             switch(cinfo->args[i].storage)
1315               {
1316               case ArgInFloatReg:
1317                 //alpha_sts(code, ainfo->reg, alpha_fp, offset);
1318                 alpha_lds(code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
1319                 break;
1320               case ArgInDoubleReg:
1321                 //alpha_stt(code, ainfo->reg, alpha_fp, offset);
1322                 alpha_ldt(code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
1323                 break;
1324               default:
1325                 ;
1326               }
1327
1328             CFG_DEBUG(3) g_print("ALPHA: Saved float arg reg %d at offset: %0lx\n",
1329                                  ainfo->reg, /*offset*/inst->inst_offset);
1330           }
1331         }
1332     }
1333   g_free (cinfo);
1334
1335   return code;
1336 }
1337
1338 /*------------------------------------------------------------------*/
1339 /*                                                                  */
1340 /* Name         - mono_arch_emit_prolog                             */
1341 /*                                                                  */
1342 /* Function     - Create the instruction sequence for a function    */
1343 /*                prolog.                                           */
1344 /*
1345  * How to handle consts and method addreses: 
1346  * For method we will allocate array of qword after method epiloge.
1347  * These qword will hold readonly info to method to properly to run.
1348  * For example: qword constants, method addreses
1349  * GP will point to start of data. Offsets to the data will be equal
1350  * to "address" of data - start of GP. (GP = 0 during method jiting). 
1351  * GP is easily calculated from passed PV (method start address).
1352  * The patch will update GP loadings.
1353  * The GOT section should be more than 32Kb.
1354  * The patch code should put proper offset since the real position of
1355  * qword array will be known after the function epiloge.
1356  */
1357 /*------------------------------------------------------------------*/
1358
1359 guint8 *
1360 mono_arch_emit_prolog (MonoCompile *cfg)
1361 {
1362    MonoMethod *method = cfg->method;
1363    MonoMethodSignature *sig = mono_method_signature (method);
1364    //int alloc_size, code_size, max_offset, quad;
1365    unsigned int *code;
1366    CallInfo *cinfo;
1367    int  i, stack_size, offset;
1368    gint32 lmf_offset = cfg->arch.lmf_offset;
1369
1370    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_emit_prolog");
1371    
1372    // FIXME: Use just one field to hold calculated stack size
1373    cfg->arch.stack_size = stack_size = cfg->stack_offset;
1374    cfg->arch.got_data = 0;
1375
1376    cfg->code_size = 512;
1377    
1378    code = (unsigned int *)g_malloc(cfg->code_size);
1379    cfg->native_code = (void *)code;
1380    
1381    // Emit method prolog
1382    // Calculate GP from passed PV, allocate stack
1383    ALPHA_LOAD_GP(0)
1384    alpha_ldah( code, alpha_gp, alpha_pv, 0 );
1385    alpha_lda( code, alpha_gp, alpha_gp, 0 );     // ldgp gp, 0(pv)
1386    alpha_lda( code, alpha_sp, alpha_sp, -(stack_size) );
1387
1388    offset = cfg->arch.params_stack_size;
1389
1390    /* store call convention parameters on stack */
1391    alpha_stq( code, alpha_ra, alpha_sp, (offset + 0) ); // RA
1392    alpha_stq( code, alpha_fp, alpha_sp, (offset + 8) ); // FP
1393    
1394    /* set the frame pointer */
1395    alpha_mov1( code, alpha_sp, alpha_fp );
1396
1397    /* Save LMF */
1398    if (method->save_lmf)
1399      {
1400        // Save IP
1401        alpha_stq(code, alpha_pv, alpha_fp,
1402                  (lmf_offset + G_STRUCT_OFFSET(MonoLMF, eip)));
1403        // Save SP
1404        alpha_stq(code, alpha_sp, alpha_fp,
1405                  (lmf_offset + G_STRUCT_OFFSET(MonoLMF, rsp)));
1406        // Save FP
1407        alpha_stq(code, alpha_fp, alpha_fp,
1408                  (lmf_offset + G_STRUCT_OFFSET(MonoLMF, ebp)));
1409        // Save GP
1410        alpha_stq(code, alpha_gp, alpha_fp,
1411                  (lmf_offset + G_STRUCT_OFFSET(MonoLMF, rgp)));
1412
1413        // Save method
1414        alpha_stq(code, alpha_pv, alpha_fp,
1415                  (lmf_offset + G_STRUCT_OFFSET(MonoLMF, method)));
1416      }
1417
1418    /* Save (global) regs */
1419    offset = cfg->arch.reg_save_area_offset;
1420
1421    for (i = 0; i < MONO_MAX_IREGS; ++i)
1422      if (ALPHA_IS_CALLEE_SAVED_REG (i) &&
1423          (cfg->used_int_regs & (1 << i)) &&
1424          !( ALPHA_ARGS_REGS & (1 << i)) )
1425        {
1426          alpha_stq(code, i, alpha_fp, offset);
1427          CFG_DEBUG(3) g_print("ALPHA: Saved caller reg %d at offset: %0x\n",
1428                               i, offset);
1429          offset += 8;
1430        }
1431    
1432    offset = cfg->arch.args_save_area_offset;
1433
1434    cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
1435
1436    if (sig->ret->type != MONO_TYPE_VOID)
1437      {
1438        if ((cinfo->ret.storage == ArgInIReg) &&
1439            (cfg->ret->opcode != OP_REGVAR))
1440          {
1441            /* Save volatile arguments to the stack */
1442            alpha_stq(code, cinfo->ret.reg, cfg->ret->inst_basereg,
1443                      cfg->ret->inst_offset);
1444          }
1445      }
1446
1447    /* Keep this in sync with emit_load_volatile_arguments */
1448    for (i = 0; i < sig->param_count + sig->hasthis; ++i)
1449      {
1450        ArgInfo *ainfo = &cinfo->args [i];
1451        MonoInst *inst = cfg->args [i];
1452        int j;
1453
1454        switch(ainfo->storage)
1455          {
1456          case ArgInIReg:
1457            // We need to save all used a0-a5 params
1458            {
1459              if (inst->opcode == OP_REGVAR)
1460                {
1461                  alpha_mov1(code, ainfo->reg, inst->dreg);
1462                  CFG_DEBUG(3) g_print("ALPHA: Saved int arg reg %d in reg %d\n",
1463                                       ainfo->reg, inst->dreg);
1464                }
1465              else
1466                {
1467                  alpha_stq(code, ainfo->reg, inst->inst_basereg,
1468                            inst->inst_offset);
1469                    
1470                  CFG_DEBUG(3) g_print("ALPHA: Saved int arg reg %d at offset: %0lx\n",
1471                                       ainfo->reg, inst->inst_offset);
1472                    
1473                  offset += 8;
1474                }
1475            }
1476            break;
1477          case ArgAggregate:
1478            {
1479              for(j=0; j<ainfo->nregs; j++)
1480                {
1481                  CFG_DEBUG(3) g_print("ALPHA: Saved aggregate arg reg %d at offset: %0lx\n",
1482                                       ainfo->reg + j, inst->inst_offset + (8*j));
1483                  alpha_stq(code, (ainfo->reg+j), inst->inst_basereg,
1484                            (inst->inst_offset + (8*j)));
1485                  offset += 8;
1486                }
1487            }
1488            break;
1489          case ArgInDoubleReg:
1490          case ArgInFloatReg:
1491            // We need to save all used af0-af5 params
1492            {
1493              switch(cinfo->args[i].storage)
1494                {
1495                case ArgInFloatReg:
1496                  //alpha_sts(code, ainfo->reg, alpha_fp, offset);
1497                  alpha_sts(code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
1498                  break;
1499                case ArgInDoubleReg:
1500                  //alpha_stt(code, ainfo->reg, alpha_fp, offset);
1501                  alpha_stt(code, ainfo->reg, inst->inst_basereg, inst->inst_offset);
1502                  break;
1503                default:
1504                  ;
1505                }
1506                    
1507              CFG_DEBUG(3) g_print("ALPHA: Saved float arg reg %d at offset: %0lx\n",
1508                                   ainfo->reg, /*offset*/inst->inst_offset);
1509                    
1510              offset += 8;
1511            }
1512          }
1513      }
1514
1515    offset = cfg->arch.reg_save_area_offset;
1516
1517    /*   
1518    for (i = 0; i < MONO_MAX_VREGS; ++i)
1519      if (ALPHA_IS_CALLEE_SAVED_REG (i) &&
1520          (cfg->used_int_regs & (1 << i)) &&
1521          !( ALPHA_ARGS_REGS & (1 << i)) )
1522        {  
1523          alpha_stq(code, i, alpha_fp, offset);
1524          CFG_DEBUG(3) g_print("ALPHA: Saved caller reg %d at offset: %0x\n",
1525                 i, offset);
1526          offset += 8;
1527        }
1528    */
1529    // TODO - check amd64 code for "Might need to attach the thread to the JIT"
1530
1531    if (method->save_lmf)
1532      {
1533        /*
1534         * The call might clobber argument registers, but they are already
1535         * saved to the stack/global regs.
1536         */
1537
1538        code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
1539                          (gpointer)"mono_get_lmf_addr");
1540
1541        // Save lmf_addr
1542        alpha_stq(code, alpha_r0, alpha_fp,
1543                  (lmf_offset + G_STRUCT_OFFSET(MonoLMF, lmf_addr)));
1544        // Load "previous_lmf" member of MonoLMF struct
1545        alpha_ldq(code, alpha_r1, alpha_r0, 0);
1546
1547        // Save it to MonoLMF struct
1548        alpha_stq(code, alpha_r1, alpha_fp,
1549                  (lmf_offset + G_STRUCT_OFFSET(MonoLMF, previous_lmf)));
1550        
1551        // Set new LMF
1552        alpha_lda(code, alpha_r1, alpha_fp, lmf_offset);
1553        alpha_stq(code, alpha_r1, alpha_r0, 0);
1554      }
1555
1556    g_free (cinfo);
1557
1558    if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
1559      code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method,
1560                                          code, TRUE);
1561         
1562    cfg->code_len = ((char *)code) - ((char *)cfg->native_code);
1563    
1564    g_assert (cfg->code_len < cfg->code_size);
1565    
1566    return (gint8 *)code;
1567 }
1568
1569 /*========================= End of Function ========================*/
1570
1571 /*------------------------------------------------------------------*/
1572 /*                                                                  */
1573 /* Name         - mono_arch_flush_register_windows                  */
1574 /*                                                                  */
1575 /* Function     -                                                   */
1576 /*                                                                  */
1577 /* Returns      -                                                   */
1578 /*                                                                  */
1579 /*------------------------------------------------------------------*/
1580
1581 void
1582 mono_arch_flush_register_windows (void)
1583 {
1584    ALPHA_DEBUG("mono_arch_flush_register_windows");
1585 }
1586 /*========================= End of Function ========================*/
1587
1588 /*------------------------------------------------------------------*/
1589 /*                                                                  */
1590 /* Name         - mono_arch_regalloc_cost                           */
1591 /*                                                                  */
1592 /* Function     - Determine the cost, in the number of memory       */
1593 /*                references, of the action of allocating the var-  */
1594 /*                iable VMV into a register during global register  */
1595 /*                allocation.                                       */
1596 /*                                                                  */
1597 /* Returns      - Cost                                              */
1598 /*                                                                  */
1599 /*------------------------------------------------------------------*/
1600
1601 guint32
1602 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
1603 {
1604   MonoInst *ins = cfg->varinfo [vmv->idx];
1605
1606    /* FIXME: */
1607   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_regalloc_cost");
1608
1609   if (cfg->method->save_lmf)
1610     /* The register is already saved */
1611     /* substract 1 for the invisible store in the prolog */
1612     return (ins->opcode == OP_ARG) ? 1 : 0;
1613   else
1614     /* push+pop */
1615     return (ins->opcode == OP_ARG) ? 2 : 1;
1616 }
1617
1618 /*========================= End of Function ========================*/
1619
1620 /*
1621 ** 
1622 ** This method emits call sequience
1623 **
1624 */
1625 static unsigned int *
1626 emit_call(MonoCompile *cfg, unsigned int *code,
1627           guint32 patch_type, gconstpointer data)
1628 {
1629   int offset;
1630   AlphaGotData ge_data;
1631   
1632   offset = (char *)code - (char *)cfg->native_code;
1633
1634   ge_data.data.p = (void *)data;
1635   add_got_entry(cfg, GT_PTR, ge_data,
1636                 offset, patch_type, data);
1637
1638   // Load call address into PV
1639   alpha_ldq(code, alpha_pv, alpha_gp, 0);
1640
1641   // Call method
1642   alpha_jsr(code, alpha_ra, alpha_pv, 0);
1643   
1644   offset = (char *)code - (char *)cfg->native_code;
1645   
1646   // Restore GP
1647   ALPHA_LOAD_GP(offset)
1648   alpha_ldah(code, alpha_gp, alpha_ra, 0);
1649   alpha_lda(code, alpha_gp, alpha_gp, 0);
1650
1651   return code;
1652 }
1653
1654 /*------------------------------------------------------------------*/
1655 /*                                                                  */
1656 /* Name         - arch_get_argument_info                            */
1657 /*                                                                  */
1658 /* Function     - Gathers information on parameters such as size,   */
1659 /*                alignment, and padding. arg_info should be large  */
1660 /*                enough to hold param_count + 1 entries.           */
1661 /*                                                                  */
1662 /* Parameters   - @csig - Method signature                          */
1663 /*                @param_count - No. of parameters to consider      */
1664 /*                @arg_info - An array to store the result info     */
1665 /*                                                                  */
1666 /* Returns      - Size of the activation frame                      */
1667 /*                                                                  */
1668 /*------------------------------------------------------------------*/
1669
1670 int
1671 mono_arch_get_argument_info (MonoMethodSignature *csig,
1672                              int param_count,
1673                              MonoJitArgumentInfo *arg_info)
1674 {
1675   int k;
1676   CallInfo *cinfo = get_call_info (NULL, csig, FALSE);
1677   guint32 args_size = cinfo->stack_usage;
1678
1679   ALPHA_DEBUG("mono_arch_get_argument_info");
1680
1681   /* The arguments are saved to a stack area in mono_arch_instrument_prolog */
1682   if (csig->hasthis) 
1683     {
1684       arg_info [0].offset = 0;
1685     }
1686
1687   for (k = 0; k < param_count; k++) 
1688     {
1689       arg_info [k + 1].offset = ((k + csig->hasthis) * 8);
1690
1691       /* FIXME: */
1692       // Set size to 1
1693       // The size is checked only for valuetype in trace.c
1694       arg_info [k + 1].size = 8;
1695     }
1696   
1697   g_free (cinfo);
1698   
1699   return args_size;
1700 }
1701
1702 /*------------------------------------------------------------------*/
1703 /*                                                                  */
1704 /* Name         - mono_arch_emit_epilog                             */
1705 /*                                                                  */
1706 /* Function     - Emit the instructions for a function epilog.      */
1707 /*                                                                  */
1708 /*------------------------------------------------------------------*/
1709
1710 void
1711 mono_arch_emit_epilog (MonoCompile *cfg)
1712 {
1713   MonoMethod *method = cfg->method;
1714   int offset, i;
1715   unsigned int *code;
1716   int max_epilog_size = 128;
1717   int stack_size = cfg->arch.stack_size;
1718   //  CallInfo *cinfo;
1719   gint32 lmf_offset = cfg->arch.lmf_offset;
1720   
1721   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_emit_epilog");
1722    
1723   while (cfg->code_len + max_epilog_size > (cfg->code_size - 16))
1724     {
1725       cfg->code_size *= 2;
1726       cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
1727       mono_jit_stats.code_reallocs++;
1728     }
1729   
1730   code = (unsigned int *)(cfg->native_code + cfg->code_len);
1731   
1732   if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
1733     code = mono_arch_instrument_epilog (cfg, mono_trace_leave_method,
1734                                         code, TRUE);
1735
1736   if (method->save_lmf)
1737     {
1738       /* Restore previous lmf */
1739       alpha_ldq(code, alpha_at, alpha_fp,
1740                 (lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf)));
1741       alpha_ldq(code, alpha_ra, alpha_fp,
1742                 (lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr)));
1743       alpha_stq(code, alpha_at, alpha_ra, 0);
1744     }
1745   
1746   // 5 instructions.
1747   alpha_mov1( code, alpha_fp, alpha_sp );
1748    
1749   // Restore saved regs
1750   offset = cfg->arch.reg_save_area_offset;
1751    
1752   for (i = 0; i < MONO_MAX_IREGS; ++i)
1753     if (ALPHA_IS_CALLEE_SAVED_REG (i) &&
1754         (cfg->used_int_regs & (1 << i)) &&
1755         !( ALPHA_ARGS_REGS & (1 << i)) )
1756       {
1757         alpha_ldq(code, i, alpha_sp, offset);
1758         CFG_DEBUG(3) g_print("ALPHA: Restored caller reg %d at offset: %0x\n",
1759                i, offset);
1760         offset += 8;
1761       }
1762   
1763   /* restore fp, ra, sp */
1764   offset = cfg->arch.params_stack_size;
1765
1766   alpha_ldq( code, alpha_ra, alpha_sp, (offset + 0) );
1767   alpha_ldq( code, alpha_fp, alpha_sp, (offset + 8) );
1768   alpha_lda( code, alpha_sp, alpha_sp, stack_size );
1769   
1770   /* return */
1771   alpha_ret( code, alpha_ra, 1 );
1772   
1773   cfg->code_len = ((char *)code) - ((char *)cfg->native_code);
1774   
1775   g_assert (cfg->code_len < cfg->code_size);
1776 }
1777
1778 /*========================= End of Function ========================*/
1779
1780 /*------------------------------------------------------------------*/
1781 /*                                                                  */
1782 /* Name         - mono_arch_emit_exceptions                         */
1783 /*                                                                  */
1784 /* Function     - Emit the blocks to handle exception conditions.   */
1785 /*                                                                  */
1786 /*------------------------------------------------------------------*/
1787
1788 void
1789 mono_arch_emit_exceptions (MonoCompile *cfg)
1790 {
1791   MonoJumpInfo *patch_info;
1792   int nthrows, i;
1793   unsigned int *code, *got_start;
1794   unsigned long *corlib_exc_adr;
1795   MonoClass *exc_classes [16];
1796   guint8 *exc_throw_start [16], *exc_throw_end [16];
1797   guint32 code_size = 8;  // Reserve space for address to mono_arch_throw_corlib_exception
1798   AlphaGotEntry *got_data;
1799
1800   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_emit_exceptions");
1801
1802   /* Compute needed space */
1803   for (patch_info = cfg->patch_info; patch_info;
1804        patch_info = patch_info->next)
1805     {
1806       if (patch_info->type == MONO_PATCH_INFO_EXC)
1807         code_size += 40;
1808       if (patch_info->type == MONO_PATCH_INFO_R8)
1809         code_size += 8 + 7; /* sizeof (double) + alignment */
1810       if (patch_info->type == MONO_PATCH_INFO_R4)
1811         code_size += 4 + 7; /* sizeof (float) + alignment */
1812     }
1813
1814   // Reserve space for GOT entries
1815   for (got_data = cfg->arch.got_data; got_data;
1816        got_data = got_data->next)
1817     {
1818        // Reserve space for 8 byte const (for now)
1819        if (got_data->type != GT_LD_GTADDR)
1820            code_size += 8;
1821     }
1822
1823   while (cfg->code_len + code_size > (cfg->code_size - 16))
1824     {
1825       cfg->code_size *= 2;
1826       cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
1827       mono_jit_stats.code_reallocs++;
1828     }
1829   
1830   code = (unsigned int *)((char *)cfg->native_code + cfg->code_len);
1831
1832   // Set code alignment
1833   if (((unsigned long)code) % 8)
1834       code++;
1835
1836   got_start = code; 
1837
1838   /* Add code to store conts and modify patch into to store offset in got */
1839   for (got_data = cfg->arch.got_data; got_data;
1840        got_data = got_data->next)
1841     {
1842       unsigned long data = got_data->value.data.l;
1843       MonoJumpInfo *got_ref = got_data->got_patch_info;
1844       
1845       // Modify loading of GP
1846       if (got_data->type == GT_LD_GTADDR)
1847       {
1848         short high_off, low_off;
1849         unsigned int *ldgp_code =
1850                 (unsigned int *)(cfg->native_code + got_data->value.data.l);
1851         unsigned int got_off = (char *)got_start - (char *)ldgp_code;
1852
1853         high_off = got_off / 0x10000;
1854         low_off = got_off % 0x10000;
1855         if (low_off < 0)
1856           high_off++;
1857         
1858         // Set offset from current point to GOT array
1859         // modify the following code sequence
1860         // ldah gp, 0(pv) or ldah gp, 0(ra)
1861         // lda  gp, 0(gp) 
1862         *ldgp_code = (*ldgp_code | (high_off & 0xFFFF));
1863         ldgp_code++;
1864         *ldgp_code = (*ldgp_code | (low_off & 0xFFFF));
1865
1866         continue;
1867       }
1868
1869       patch_info = got_data->patch_info;
1870
1871       // Check code alignment
1872       if (((unsigned long)code) % 8)
1873         code++;
1874
1875       got_ref->data.offset = ((char *)code - (char *)got_start);
1876
1877       if (patch_info)
1878         patch_info->ip.i = ((char *)code - (char *)cfg->native_code);
1879
1880       *code = (unsigned int)(data & 0xFFFFFFFF);
1881       code++;
1882       *code = (unsigned int)((data >> 32) & 0xFFFFFFFF);
1883       code++;
1884       
1885     }
1886
1887   corlib_exc_adr = (unsigned long *)code;
1888
1889   /* add code to raise exceptions */
1890   nthrows = 0;
1891   for (patch_info = cfg->patch_info; patch_info;
1892        patch_info = patch_info->next)
1893     {
1894       switch (patch_info->type)
1895         {
1896         case MONO_PATCH_INFO_EXC:
1897           {
1898             MonoClass *exc_class;
1899             unsigned int *buf, *buf2;
1900             guint32 throw_ip;
1901             
1902             if (nthrows == 0)
1903               {
1904                 // Add patch info to call mono_arch_throw_corlib_exception
1905                 // method to raise corlib exception
1906                 // Will be added at the begining of the patch info list
1907                 mono_add_patch_info(cfg,
1908                                     ((char *)code - (char *)cfg->native_code),
1909                                     MONO_PATCH_INFO_INTERNAL_METHOD,
1910                                     "mono_arch_throw_corlib_exception");
1911                 
1912                 // Skip longword before starting the code
1913                 *code++ = 0;
1914                 *code++ = 0;
1915               }
1916             
1917             exc_class = mono_class_from_name (mono_defaults.corlib,
1918                                               "System", patch_info->data.name);
1919
1920             g_assert (exc_class);
1921             throw_ip = patch_info->ip.i;
1922             
1923             //x86_breakpoint (code);
1924             /* Find a throw sequence for the same exception class */
1925             for (i = 0; i < nthrows; ++i)
1926               if (exc_classes [i] == exc_class)
1927                 break;
1928
1929             if (i < nthrows)
1930               {
1931                 int br_offset;
1932
1933                 // Patch original branch (patch info) to jump here
1934                 patch_info->type = MONO_PATCH_INFO_METHOD_REL;
1935                 patch_info->data.target = 
1936                   (char *)code - (char *)cfg->native_code;
1937
1938                 alpha_lda(code, alpha_a1, alpha_zero,
1939                           -((short)((((char *)exc_throw_end[i] -
1940                                     (char *)cfg->native_code)) - throw_ip) - 4) );
1941
1942                 br_offset = ((char *)exc_throw_start[i] - (char *)code - 4)/4;
1943
1944                 alpha_bsr(code, alpha_zero, br_offset);
1945               }
1946             else
1947               {
1948                 buf = code;
1949
1950                 // Save exception token type as first 32bit word for new
1951                 // exception handling jump code
1952                 *code = exc_class->type_token;
1953                 code++;
1954
1955                 // Patch original branch (patch info) to jump here
1956                 patch_info->type = MONO_PATCH_INFO_METHOD_REL;
1957                 patch_info->data.target = 
1958                   (char *)code - (char *)cfg->native_code;
1959
1960                 buf2 = code;
1961                 alpha_lda(code, alpha_a1, alpha_zero, 0);
1962
1963                 if (nthrows < 16)
1964                   {
1965                     exc_classes [nthrows] = exc_class;
1966                     exc_throw_start [nthrows] = code;
1967                   }
1968                 
1969                 // Load exception token
1970                 alpha_ldl(code, alpha_a0, alpha_gp,
1971                           ((char *)buf - (char *)got_start /*cfg->native_code*/));
1972                 // Load corlib exception raiser code address
1973                 alpha_ldq(code, alpha_pv, alpha_gp,
1974                           ((char *)corlib_exc_adr -
1975                            (char *)got_start /*cfg->native_code*/));
1976
1977                 //amd64_mov_reg_imm (code, AMD64_RDI, exc_class->type_token);
1978                 //patch_info->data.name = "mono_arch_throw_corlib_exception";
1979                 //**patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
1980                 //patch_info->type = MONO_PATCH_INFO_NONE;
1981                 //patch_info->ip.i = (char *)code - (char *)cfg->native_code;
1982                 
1983                 if (cfg->compile_aot)
1984                   {
1985                     // amd64_mov_reg_membase (code, GP_SCRATCH_REG, AMD64_RIP, 0, 8);
1986                     //amd64_call_reg (code, GP_SCRATCH_REG);
1987                   } else {
1988                   /* The callee is in memory allocated using
1989                      the code manager */
1990                   alpha_jsr(code, alpha_ra, alpha_pv, 0);
1991                 }
1992                 
1993                 alpha_lda(buf2, alpha_a1, alpha_zero,
1994                           -((short)(((char *)code - (char *)cfg->native_code) -
1995                                     throw_ip)-4) );
1996
1997                 if (nthrows < 16)
1998                   {
1999                     exc_throw_end [nthrows] = code;
2000                     nthrows ++;
2001                   }
2002               }
2003             break;
2004           }
2005         default:
2006           /* do nothing */
2007           break;
2008         }
2009     }
2010   
2011   /* Handle relocations with RIP relative addressing */
2012   for (patch_info = cfg->patch_info; patch_info;
2013        patch_info = patch_info->next)
2014     {
2015       gboolean remove = FALSE;
2016
2017       switch (patch_info->type)
2018         {
2019         case MONO_PATCH_INFO_R8:
2020           {
2021             guint8 *pos;
2022
2023             code = (guint8*)ALIGN_TO (code, 8);
2024
2025             pos = cfg->native_code + patch_info->ip.i;
2026
2027             *(double*)code = *(double*)patch_info->data.target;
2028
2029             //      if (use_sse2)
2030             //  *(guint32*)(pos + 4) = (guint8*)code - pos - 8;
2031             //else
2032               *(guint32*)(pos + 3) = (guint8*)code - pos - 7;
2033             code += 8;
2034             
2035             remove = TRUE;
2036             break;
2037           }
2038         case MONO_PATCH_INFO_R4:
2039           {
2040             guint8 *pos;
2041             
2042             code = (guint8*)ALIGN_TO (code, 8);
2043             
2044             pos = cfg->native_code + patch_info->ip.i;
2045             
2046             *(float*)code = *(float*)patch_info->data.target;
2047             
2048             //if (use_sse2)
2049             //  *(guint32*)(pos + 4) = (guint8*)code - pos - 8;
2050             //else
2051               *(guint32*)(pos + 3) = (guint8*)code - pos - 7;
2052             code += 4;
2053             
2054             remove = TRUE;
2055             break;
2056           }
2057         default:
2058           break;
2059         }
2060       
2061       if (remove)
2062         {
2063           if (patch_info == cfg->patch_info)
2064             cfg->patch_info = patch_info->next;
2065           else
2066             {
2067               MonoJumpInfo *tmp;
2068
2069               for (tmp = cfg->patch_info; tmp->next != patch_info;
2070                    tmp = tmp->next)
2071                 ;
2072               tmp->next = patch_info->next;
2073             }
2074         }
2075     }
2076   
2077   cfg->code_len = (char *)code - (char *)cfg->native_code;
2078
2079   g_assert (cfg->code_len < cfg->code_size);
2080
2081 }
2082
2083 /*========================= End of Function ========================*/
2084
2085 #define EMIT_ALPHA_BRANCH(Tins, PRED_REG, ALPHA_BR)     \
2086   offset = ((char *)code -                      \
2087             (char *)cfg->native_code);          \
2088   if (Tins->flags & MONO_INST_BRLABEL)          \
2089     {                                           \
2090       if (Tins->inst_i0->inst_c0)               \
2091         {                                                               \
2092           CFG_DEBUG(3) g_print("inst_c0: %0lX, data: %p]\n",            \
2093                  Tins->inst_i0->inst_c0,                                \
2094                  cfg->native_code + Tins->inst_i0->inst_c0);            \
2095           alpha_##ALPHA_BR (code, PRED_REG, 0);                         \
2096         }                                                               \
2097       else                                                              \
2098         {                                                               \
2099           CFG_DEBUG(3) g_print("add patch info: MONO_PATCH_INFO_LABEL offset: %0X, inst_i0: %p]\n", \
2100                  offset, Tins->inst_i0);                                \
2101           mono_add_patch_info (cfg, offset,                             \
2102                                MONO_PATCH_INFO_LABEL, Tins->inst_i0);   \
2103           alpha_##ALPHA_BR (code, PRED_REG, 0);                         \
2104         }                                                               \
2105     }                                                                   \
2106   else                                                                  \
2107     {                                                                   \
2108       if (Tins->inst_true_bb->native_offset)                            \
2109         {                                                               \
2110           long br_offset = (char *)cfg->native_code +                   \
2111             Tins->inst_true_bb->native_offset - 4 - (char *)code;       \
2112           CFG_DEBUG(3) g_print("jump to: native_offset: %0X, address %p]\n", \
2113                  Tins->inst_target_bb->native_offset,                   \
2114                  cfg->native_code +                                     \
2115                  Tins->inst_true_bb->native_offset);                    \
2116           alpha_##ALPHA_BR (code, PRED_REG, br_offset/4);               \
2117         }                                                               \
2118       else                                                              \
2119         {                                                               \
2120           CFG_DEBUG(3) g_print("add patch info: MONO_PATCH_INFO_BB offset: %0X, target_bb: %p]\n", \
2121                  offset, Tins->inst_target_bb);                         \
2122           mono_add_patch_info (cfg, offset,                             \
2123                                MONO_PATCH_INFO_BB,                      \
2124                                Tins->inst_true_bb);                     \
2125           alpha_##ALPHA_BR (code, PRED_REG, 0);                         \
2126         }                                                               \
2127     }
2128
2129
2130 #define EMIT_COND_EXC_BRANCH(ALPHA_BR, PRED_REG, EXC_NAME)              \
2131   do                                                                    \
2132     {                                                                   \
2133       MonoInst *tins = mono_branch_optimize_exception_target (cfg,      \
2134                                                               bb,       \
2135                                                               EXC_NAME); \
2136       if (tins == NULL)                                                 \
2137         {                                                               \
2138           mono_add_patch_info (cfg,                                     \
2139                                ((char *)code -                          \
2140                                 (char *)cfg->native_code),              \
2141                                MONO_PATCH_INFO_EXC, EXC_NAME);          \
2142           alpha_##ALPHA_BR(code, PRED_REG, 0);                          \
2143         }                                                               \
2144       else                                                              \
2145         {                                                               \
2146           EMIT_ALPHA_BRANCH(tins, PRED_REG, ALPHA_BR);                  \
2147         }                                                               \
2148     } while(0);
2149
2150
2151 /*------------------------------------------------------------------*/
2152 /*                                                                  */
2153 /* Name         - mono_arch_output_basic_block                      */
2154 /*                                                                  */
2155 /* Function     - Perform the "real" work of emitting instructions  */
2156 /*                that will do the work of in the basic block.      */
2157 /*                                                                  */
2158 /*------------------------------------------------------------------*/
2159
2160 void
2161 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2162 {
2163    MonoInst *ins;
2164    MonoCallInst *call;
2165    guint offset;
2166    unsigned int *code = (unsigned int *)(cfg->native_code + cfg->code_len);
2167    guint last_offset = 0;
2168    int max_len, cpos;
2169    
2170    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_output_basic_block");
2171    
2172    CFG_DEBUG(2) g_print ("Basic block %d(%p) starting at offset 0x%x\n",
2173                          bb->block_num, bb, bb->native_offset);
2174    
2175    cpos = bb->max_offset;
2176    
2177    offset = ((char *)code) - ((char *)cfg->native_code);
2178
2179    mono_debug_open_block (cfg, bb, offset);
2180    
2181    MONO_BB_FOR_EACH_INS (bb, ins) {
2182        offset = ((char *)code) - ((char *)cfg->native_code);
2183           
2184        max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2185           
2186        if (offset > (cfg->code_size - max_len - 16))
2187          {
2188            cfg->code_size *= 2;
2189            cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2190            code = (unsigned int *)(cfg->native_code + offset);
2191            mono_jit_stats.code_reallocs++;
2192          }
2193           
2194        mono_debug_record_line_number (cfg, ins, offset);
2195
2196        CFG_DEBUG(3) g_print("ALPHA: Emiting [%s] opcode\n",
2197                             mono_inst_name(ins->opcode));
2198           
2199        switch (ins->opcode)
2200          {
2201          case OP_LSHR:
2202            // Shift 64 bit value right
2203            CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr] dreg=%d, sreg1=%d, sreg2=%d\n",
2204                   ins->dreg, ins->sreg1, ins->sreg2);
2205            alpha_sra(code, ins->sreg1, ins->sreg2, ins->dreg);
2206            break;
2207
2208         case OP_LSHR_UN:
2209            // Shift 64 bit value right
2210            CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr_un] dreg=%d, sreg1=%d, sreg2=%d\n",
2211                   ins->dreg, ins->sreg1, ins->sreg2);
2212            alpha_srl(code, ins->sreg1, ins->sreg2, ins->dreg);
2213            break;
2214
2215          case OP_LSHR_IMM:
2216            // Shift 64 bit value right by constant
2217            g_assert(alpha_is_imm(ins->inst_imm));
2218            CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr_imm] dreg=%d, sreg1=%d, const=%ld\n",
2219                   ins->dreg, ins->sreg1, ins->inst_imm);
2220            alpha_sra_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2221            break;
2222
2223          case OP_ISHL:
2224            // Shift 32 bit value left
2225            CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shl] dreg=%d, sreg1=%d, sreg2=%d\n",
2226                   ins->dreg, ins->sreg1, ins->sreg2);
2227            alpha_sll(code, ins->sreg1, ins->sreg2, ins->dreg);
2228            alpha_addl_(code, ins->dreg, 0, ins->dreg);
2229            break;
2230
2231          case OP_ISHL_IMM:
2232            // Shift 32 bit value left by constant
2233            g_assert(alpha_is_imm(ins->inst_imm));
2234            CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shl_imm] dreg=%d, sreg1=%d, const=%ld\n",
2235                   ins->dreg, ins->sreg1, ins->inst_imm);
2236            alpha_sll_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2237            alpha_addl_(code, ins->dreg, 0, ins->dreg);
2238            break;
2239
2240          case OP_SHL_IMM:
2241            g_assert(alpha_is_imm(ins->inst_imm));
2242            CFG_DEBUG(4) g_print("ALPHA_CHECK: [shl_imm] dreg=%d, sreg1=%d, const=%ld\n",
2243                   ins->dreg, ins->sreg1, ins->inst_imm);
2244            alpha_sll_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2245            break;
2246
2247          case OP_LSHL_IMM:
2248            g_assert(alpha_is_imm(ins->inst_imm));
2249            CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shl_imm] dreg=%d, sreg1=%d, const=%ld\n",
2250                   ins->dreg, ins->sreg1, ins->inst_imm);
2251            alpha_sll_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2252            break;
2253
2254
2255          case CEE_SHL:
2256            // Shift 32 bit value left
2257            CFG_DEBUG(4) g_print("ALPHA_CHECK: [shl] dreg=%d, sreg1=%d, sreg2=%d\n",
2258                   ins->dreg, ins->sreg1, ins->sreg2);
2259            alpha_sll(code, ins->sreg1, ins->sreg2, ins->dreg);
2260            break;
2261
2262          case OP_LSHL:
2263            // Shift 64 bit value left
2264            CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shl] dreg=%d, sreg1=%d, sreg2=%d\n",
2265                   ins->dreg, ins->sreg1, ins->sreg2);
2266            alpha_sll(code, ins->sreg1, ins->sreg2, ins->dreg);
2267            break;
2268
2269
2270          case OP_ISHR:
2271            // Shift 32 bit value right
2272            CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shr] dreg=%d, sreg1=%d, sreg2=%d\n",
2273                   ins->dreg, ins->sreg1, ins->sreg2);
2274            //alpha_zap_(code, ins->sreg1, 0xF0, ins->dreg);
2275            alpha_sra(code, ins->sreg1, ins->sreg2, ins->dreg);
2276            break;
2277
2278          case OP_ISHR_IMM:
2279            // Shift 32 bit value rigth by constant
2280            g_assert(alpha_is_imm(ins->inst_imm));
2281            CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shr_imm] dreg=%d, sreg1=%d, const=%ld\n",
2282                   ins->dreg, ins->sreg1, ins->inst_imm);
2283            //alpha_zap_(code, ins->sreg1, 0xF0, ins->dreg);
2284            alpha_sra_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2285            break;
2286
2287          case OP_ISHR_UN:
2288            // Shift 32 bit unsigned value right
2289            CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shr_un] dreg=%d, sreg1=%d, sreg2=%d\n",
2290                   ins->dreg, ins->sreg1, ins->sreg2);
2291            alpha_zap_(code, ins->sreg1, 0xF0, alpha_at /*ins->dreg*/);
2292            alpha_srl(code, alpha_at /*ins->dreg*/, ins->sreg2, ins->dreg);
2293            break;
2294
2295          case OP_ISHR_UN_IMM:
2296            // Shift 32 bit unassigned value rigth by constant
2297            g_assert(alpha_is_imm(ins->inst_imm));
2298            CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_shr_un_imm] dreg=%d, sreg1=%d, const=%ld\n",
2299                                 ins->dreg, ins->sreg1, ins->inst_imm);
2300            alpha_zap_(code, ins->sreg1, 0xF0, alpha_at /*ins->dreg*/);
2301            alpha_srl_(code, alpha_at /*ins->dreg*/, ins->inst_imm, ins->dreg);
2302            break;
2303
2304          case OP_LSHR_UN_IMM:
2305            // Shift 64 bit unassigned value rigth by constant
2306            g_assert(alpha_is_imm(ins->inst_imm));
2307            CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr_un_imm] dreg=%d, sreg1=%d, const=%ld\n",
2308                                 ins->dreg, ins->sreg1, ins->inst_imm);
2309            alpha_srl_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2310            break;
2311
2312          case CEE_ADD:
2313            // Sum two 64 bits regs
2314            CFG_DEBUG(4) g_print("ALPHA_CHECK: [add] dreg=%d, sreg1=%d, sreg2=%d\n",
2315                   ins->dreg, ins->sreg1, ins->sreg2);
2316            alpha_addq(code, ins->sreg1, ins->sreg2, ins->dreg);
2317            break;
2318
2319          case CEE_SUB:
2320            // Subtract two 64 bit regs
2321            CFG_DEBUG(4) g_print("ALPHA_CHECK: [sub] dreg=%d, sreg1=%d, sreg2=%d\n",
2322                   ins->dreg, ins->sreg1, ins->sreg2);
2323            alpha_subq(code, ins->sreg1, ins->sreg2, ins->dreg);
2324            break;
2325
2326          case OP_ADD_IMM:
2327            // Add imm value to 64 bits int
2328            g_assert(alpha_is_imm(ins->inst_imm));
2329            CFG_DEBUG(4) g_print("ALPHA_CHECK: [add_imm] dreg=%d, sreg1=%d, imm=%ld\n",
2330                   ins->dreg, ins->sreg1, ins->inst_imm);
2331            alpha_addq_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2332            break;
2333
2334          case OP_IADD:
2335            // Add two 32 bit ints
2336            CFG_DEBUG(4) g_print("ALPHA_CHECK: [iadd] dreg=%d, sreg1=%d, sreg2=%d\n",
2337                   ins->dreg, ins->sreg1, ins->sreg2);
2338            alpha_addl(code, ins->sreg1, ins->sreg2, ins->dreg);
2339            break;
2340
2341          case OP_IADDCC:
2342            // Add two 32 bit ints with overflow detection
2343            // Use AT to hold flag of signed overflow
2344            // Use t12(PV) to hold unsigned overflow
2345            // Use RA to hold intermediate result
2346            CFG_DEBUG(4) g_print("ALPHA_CHECK: [iaddcc] dreg=%d, sreg1=%d, sreg2=%d\n",
2347                   ins->dreg, ins->sreg1, ins->sreg2);
2348            alpha_addl(code, ins->sreg1, ins->sreg2, alpha_ra);
2349            alpha_ble(code, ins->sreg2, 2);
2350
2351            /* (sreg2 > 0) && (res < ins->sreg1) => signed overflow */
2352            alpha_cmplt(code, alpha_ra, ins->sreg1, alpha_at);
2353            alpha_br(code, alpha_zero, 1);
2354
2355            /* (sreg2 <= 0) && (res > ins->sreg1) => signed overflow */
2356            alpha_cmplt(code, ins->sreg1, alpha_ra, alpha_at);
2357
2358            /* res <u sreg1 => unsigned overflow */
2359            alpha_cmpult(code, alpha_ra, ins->sreg1, alpha_pv);
2360
2361            alpha_mov1(code, alpha_ra, ins->dreg);
2362            break;
2363
2364          case OP_ADDCC:
2365            // Add two 64 bit ints with overflow detection
2366            // Use AT to hold flag of signed overflow
2367            // Use t12(PV) to hold unsigned overflow
2368            // Use RA to hold intermediate result
2369            CFG_DEBUG(4) g_print("ALPHA_CHECK: [addcc] dreg=%d, sreg1=%d, sreg2=%d\n",
2370                                 ins->dreg, ins->sreg1, ins->sreg2);
2371            alpha_addq(code, ins->sreg1, ins->sreg2, alpha_ra);
2372            alpha_ble(code, ins->sreg2, 2);
2373
2374            /* (sreg2 > 0) && (res < ins->sreg1) => signed overflow */
2375            alpha_cmplt(code, alpha_ra, ins->sreg1, alpha_at);
2376            alpha_br(code, alpha_zero, 1);
2377
2378            /* (sreg2 <= 0) && (res > ins->sreg1) => signed overflow */
2379            alpha_cmplt(code, ins->sreg1, alpha_ra, alpha_at);
2380
2381            /* res <u sreg1 => unsigned overflow */
2382            alpha_cmpult(code, alpha_ra, ins->sreg1, alpha_pv);
2383
2384            alpha_mov1(code, alpha_ra, ins->dreg);
2385            break;
2386
2387          case OP_IADD_IMM:
2388            // Add imm value to 32 bits int
2389            g_assert(alpha_is_imm(ins->inst_imm));
2390            CFG_DEBUG(4) g_print("ALPHA_CHECK: [iadd_imm] dreg=%d, sreg1=%d, imm=%ld\n",
2391                   ins->dreg, ins->sreg1, ins->inst_imm);
2392            alpha_addl_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2393            break;
2394                  
2395          case OP_ISUB:
2396            // Substract to 32 bit ints
2397            CFG_DEBUG(4) g_print("ALPHA_CHECK: [isub] dreg=%d, sreg1=%d, sreg2=%d\n",
2398                   ins->dreg, ins->sreg1, ins->sreg2);
2399            alpha_subl(code, ins->sreg1, ins->sreg2, ins->dreg);
2400            break;
2401                  
2402          case OP_ISUB_IMM:
2403            // Sub imm value from 32 bits int
2404            g_assert(alpha_is_imm(ins->inst_imm));
2405            CFG_DEBUG(4) g_print("ALPHA_CHECK: [isub_imm] dreg=%d, sreg1=%d, imm=%ld\n",
2406                   ins->dreg, ins->sreg1, ins->inst_imm);
2407            alpha_subl_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2408            break;
2409
2410          case OP_ISUBCC:
2411            // Sub to 32 bit ints with overflow detection
2412            CFG_DEBUG(4) g_print("ALPHA_CHECK: [isubcc] dreg=%d, sreg1=%d, sreg2=%d\n",
2413                   ins->dreg, ins->sreg1, ins->sreg2);
2414            alpha_subl(code, ins->sreg1, ins->sreg2, alpha_ra);
2415            alpha_ble(code, ins->sreg2, 2);
2416
2417            /* (sreg2 > 0) && (res > ins->sreg1) => signed overflow */
2418            alpha_cmplt(code, ins->sreg1, alpha_ra, alpha_at);
2419            alpha_br(code, alpha_zero, 1);
2420
2421            /* (sreg2 <= 0) && (res < ins->sreg1) => signed overflow */
2422            alpha_cmplt(code, alpha_ra, ins->sreg1, alpha_at);
2423
2424            /* sreg1 <u sreg2 => unsigned overflow */
2425            alpha_cmpult(code, ins->sreg1, ins->sreg2, alpha_pv);
2426
2427            alpha_mov1(code, alpha_ra, ins->dreg);
2428            break;
2429
2430          case OP_SUBCC:
2431            // Sub to 64 bit ints with overflow detection
2432            CFG_DEBUG(4) g_print("ALPHA_CHECK: [subcc] dreg=%d, sreg1=%d, sreg2=%d\n",
2433                                 ins->dreg, ins->sreg1, ins->sreg2);
2434
2435            alpha_subq(code, ins->sreg1, ins->sreg2, alpha_ra);
2436            alpha_ble(code, ins->sreg2, 2);
2437
2438            /* (sreg2 > 0) && (res > ins->sreg1) => signed overflow */
2439            alpha_cmplt(code, ins->sreg1, alpha_ra, alpha_at);
2440            alpha_br(code, alpha_zero, 1);
2441
2442            /* (sreg2 <= 0) && (res < ins->sreg1) => signed overflow */
2443            alpha_cmplt(code, alpha_ra, ins->sreg1, alpha_at);
2444
2445            /* sreg1 <u sreg2 => unsigned overflow */
2446            alpha_cmpult(code, ins->sreg1, ins->sreg2, alpha_pv);
2447
2448            alpha_mov1(code, alpha_ra, ins->dreg);
2449            break;
2450
2451          case OP_IAND:
2452          case CEE_AND:
2453            // AND to 32 bit ints
2454            CFG_DEBUG(4) g_print("ALPHA_CHECK: [iand/and] dreg=%d, sreg1=%d, sreg2=%d\n",
2455                   ins->dreg, ins->sreg1, ins->sreg2);
2456            alpha_and(code, ins->sreg1, ins->sreg2, ins->dreg);
2457            break;
2458            
2459          case OP_IAND_IMM:
2460          case OP_AND_IMM:
2461            // AND imm value with 32 bit int
2462            CFG_DEBUG(4) g_print("ALPHA_CHECK: [iand_imm/and_imm] dreg=%d, sreg1=%d, imm=%ld\n",
2463                   ins->dreg, ins->sreg1, ins->inst_imm);
2464
2465            g_assert(alpha_is_imm(ins->inst_imm));
2466            alpha_and_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2467
2468            break;
2469
2470          case OP_IOR:
2471          case CEE_OR:
2472            // OR two 32/64 bit ints
2473            CFG_DEBUG(4) g_print("ALPHA_CHECK: [ior/or] dreg=%d, sreg1=%d, sreg2=%d\n",
2474                   ins->dreg, ins->sreg1, ins->sreg2);
2475            alpha_bis(code, ins->sreg1, ins->sreg2, ins->dreg);
2476            break;
2477
2478          case OP_IOR_IMM:
2479            // OR imm value with 32 bit int
2480            CFG_DEBUG(4) g_print("ALPHA_CHECK: [ior_imm] dreg=%d, sreg1=%d, imm=%ld\n",
2481                   ins->dreg, ins->sreg1, ins->inst_imm);
2482
2483            g_assert(alpha_is_imm(ins->inst_imm));
2484            alpha_bis_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2485
2486            break;
2487
2488          case OP_IXOR:
2489          case CEE_XOR:
2490            // XOR two 32/64 bit ints
2491            CFG_DEBUG(4) g_print("ALPHA_CHECK: [ixor/xor] dreg=%d, sreg1=%d, sreg2=%d\n",
2492                   ins->dreg, ins->sreg1, ins->sreg2);
2493            alpha_xor(code, ins->sreg1, ins->sreg2, ins->dreg);
2494            break;
2495
2496          case OP_IXOR_IMM:
2497            // XOR imm value with 32 bit int
2498            CFG_DEBUG(4) g_print("ALPHA_CHECK: [ixor_imm] dreg=%d, sreg1=%d, imm=%ld\n",
2499                   ins->dreg, ins->sreg1, ins->inst_imm);
2500
2501            g_assert(alpha_is_imm(ins->inst_imm));
2502            alpha_xor_(code, ins->sreg1, ins->inst_imm, ins->dreg);
2503
2504            break;
2505
2506          case OP_INEG:
2507            // NEG 32 bit reg
2508            CFG_DEBUG(4) g_print("ALPHA_CHECK: [ineg] dreg=%d, sreg1=%d\n",
2509                   ins->dreg, ins->sreg1);
2510            alpha_subl(code, alpha_zero, ins->sreg1, ins->dreg);
2511            break;
2512
2513          case CEE_NEG:
2514            // NEG 64 bit reg
2515            CFG_DEBUG(4) g_print("ALPHA_CHECK: [neg] dreg=%d, sreg1=%d\n",
2516                                 ins->dreg, ins->sreg1);
2517            alpha_subq(code, alpha_zero, ins->sreg1, ins->dreg);
2518            break;
2519
2520          case OP_INOT:
2521          case CEE_NOT:
2522            // NOT 32/64 bit reg
2523            CFG_DEBUG(4) g_print("ALPHA_CHECK: [inot/not] dreg=%d, sreg1=%d\n",
2524                   ins->dreg, ins->sreg1);
2525            alpha_not(code, ins->sreg1, ins->dreg);
2526            break;
2527
2528            
2529          case OP_IDIV:
2530          case OP_IREM:
2531          case OP_IMUL:
2532          case OP_IMUL_OVF:
2533          case OP_IMUL_OVF_UN:
2534          case OP_IDIV_UN:
2535          case OP_IREM_UN:
2536            CFG_DEBUG(4) g_print("ALPHA_TODO: [idiv/irem/imul/imul_ovf/imul_ovf_un/idiv_un/irem_un] dreg=%d, sreg1=%d, sreg2=%d\n",
2537                   ins->dreg, ins->sreg1, ins->sreg2);
2538            break;
2539            
2540          case CEE_MUL:
2541            CFG_DEBUG(4) g_print("ALPHA_CHECK: [mul] dreg=%d, sreg1=%d, sreg2=%d\n",
2542                   ins->dreg, ins->sreg1, ins->sreg2);
2543            alpha_mull(code, ins->sreg1, ins->sreg2, ins->dreg);
2544            break;
2545              
2546          case OP_IMUL_IMM:
2547            CFG_DEBUG(4) g_print("ALPHA_TODO: [imul_imm] dreg=%d, sreg1=%d, imm=%ld\n",
2548                   ins->dreg, ins->sreg1, ins->inst_imm);
2549            break;
2550            
2551          case OP_CHECK_THIS:
2552            CFG_DEBUG(4) g_print("ALPHA_CHECK: [check_this] sreg1=%d\n",
2553                   ins->sreg1);
2554            alpha_ldl(code, alpha_at, ins->sreg1, 0);
2555            break;
2556
2557          case OP_SEXT_I1:
2558            CFG_DEBUG(4) g_print("ALPHA_CHECK: [sext_i1] dreg=%d, sreg1=%d\n",
2559                   ins->dreg, ins->sreg1);
2560            alpha_sll_(code, ins->sreg1, 56, ins->dreg);
2561            alpha_sra_(code, ins->dreg, 56, ins->dreg);
2562            break;
2563
2564          case OP_SEXT_I2:
2565            CFG_DEBUG(4) g_print("ALPHA_CHECK: [sext_i2] dreg=%d, sreg1=%d\n",
2566                   ins->dreg, ins->sreg1);
2567            alpha_sll_(code, ins->sreg1, 48, ins->dreg);
2568            alpha_sra_(code, ins->dreg, 48, ins->dreg);
2569            break;
2570
2571          case OP_SEXT_I4:
2572            CFG_DEBUG(4) g_print("ALPHA_CHECK: [sext_i4] dreg=%d, sreg1=%d\n",
2573                   ins->dreg, ins->sreg1);
2574            alpha_sll_(code, ins->sreg1, 32, ins->dreg);
2575            alpha_sra_(code, ins->dreg, 32, ins->dreg);
2576            break;
2577
2578          case OP_ICONST:
2579            // Actually ICONST is 32 bits long
2580            CFG_DEBUG(4) g_print("ALPHA_CHECK: [iconst] dreg=%d, const=%0lX\n",
2581                   ins->dreg, ins->inst_c0);
2582
2583            // if const = 0
2584            if (ins->inst_c0 == 0)
2585              {
2586                alpha_clr(code, ins->dreg);
2587                break;
2588              }
2589
2590            // if -32768 < const <= 32767
2591            if (ins->inst_c0 > -32768 && ins->inst_c0 <= 32767)
2592              {
2593                alpha_lda( code, ins->dreg, alpha_zero, ins->inst_c0);
2594                //if (ins->inst_c0 & 0xFFFFFFFF00000000L)
2595                //        alpha_zap_(code, ins->dreg, 0xF0, ins->dreg);
2596              }
2597            else
2598              {
2599                int lo = (char *)code - (char *)cfg->native_code;
2600                AlphaGotData ge_data;
2601
2602                //ge_data.data.l = (ins->inst_c0 & 0xFFFFFFFF);
2603                ge_data.data.l = ins->inst_c0;
2604
2605                add_got_entry(cfg, GT_LONG, ge_data,
2606                              lo, MONO_PATCH_INFO_NONE, 0);
2607                //mono_add_patch_info(cfg, lo, MONO_PATCH_INFO_GOT_OFFSET,
2608                //                  ins->inst_c0);
2609                //alpha_ldl(code, ins->dreg, alpha_gp, 0);
2610                alpha_ldq(code, ins->dreg, alpha_gp, 0);
2611              }
2612
2613            break;
2614          case OP_I8CONST:
2615            {
2616              int lo;
2617              
2618              // To load 64 bit values we will have to use ldah/lda combination
2619              // and temporary register. As temporary register use r28
2620              // Divide 64 bit value in two parts and load upper 32 bits into
2621              // temp reg, lower 32 bits into dreg. Later set higher 32 bits in
2622              // dreg from temp reg
2623              // the 32 bit value could be loaded with ldah/lda
2624              CFG_DEBUG(4) g_print("ALPHA_CHECK: [i8conts] dreg=%d, const=%0lX\n",
2625                     ins->dreg, ins->inst_c0);
2626              
2627              // if const = 0
2628              if (ins->inst_c0 == 0)
2629                {
2630                  alpha_clr(code, ins->dreg);
2631                  break;
2632                }
2633
2634              // if -32768 < const <= 32767 
2635              if (ins->inst_c0 > -32768 && ins->inst_c0 <= 32767)
2636                alpha_lda( code, ins->dreg, alpha_zero, ins->inst_c0);
2637              else
2638                {
2639                  AlphaGotData ge_data;
2640
2641                  lo = (char *)code - (char *)cfg->native_code;
2642                  
2643                  ge_data.data.l = ins->inst_c0;
2644
2645                  add_got_entry(cfg, GT_LONG, ge_data,
2646                                lo, MONO_PATCH_INFO_NONE, 0);
2647                  alpha_ldq(code, ins->dreg, alpha_gp, 0);
2648                }
2649              break;
2650            }
2651
2652          case OP_R8CONST:
2653            {
2654              double d = *(double *)ins->inst_p0;
2655              AlphaGotData ge_data;
2656
2657              CFG_DEBUG(4) g_print("ALPHA_CHECK: [r8const] dreg=%d, r8const=%g\n",
2658                     ins->dreg, d);
2659
2660              ge_data.data.d = d;
2661              add_got_entry(cfg, GT_DOUBLE, ge_data,
2662                            (char *)code - (char *)cfg->native_code,
2663                            MONO_PATCH_INFO_NONE, 0);
2664              alpha_ldt(code, ins->dreg, alpha_gp, 0);
2665
2666              break;
2667            }
2668
2669          case OP_R4CONST:
2670            {
2671              float d = *(float *)ins->inst_p0;
2672              AlphaGotData ge_data;
2673
2674              CFG_DEBUG(4) g_print("ALPHA_CHECK: [r4const] dreg=%d, r4const=%f\n",
2675                     ins->dreg, d);
2676
2677              ge_data.data.f = d;
2678              add_got_entry(cfg, GT_FLOAT, ge_data,
2679                            (char *)code - (char *)cfg->native_code,
2680                            MONO_PATCH_INFO_NONE, 0);
2681              alpha_lds(code, ins->dreg, alpha_gp, 0);
2682
2683              break;
2684            }
2685
2686          case OP_LOADU4_MEMBASE:
2687            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadu4_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2688                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2689
2690            alpha_ldl(code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2691            //      alpha_zapnot_(code, ins->dreg, 0x0F, ins->dreg);
2692            break;
2693            
2694          case OP_LOADU1_MEMBASE:
2695            // Load unassigned byte from REGOFFSET
2696            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadu1_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2697                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2698            if (bwx_supported)
2699              alpha_ldbu(code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2700            else
2701              {
2702                alpha_ldq_u(code, alpha_r25, ins->inst_basereg,
2703                            ins->inst_offset);
2704                alpha_lda(code, alpha_at, ins->inst_basereg, ins->inst_offset);
2705                alpha_extbl(code, alpha_r25, alpha_at, ins->dreg);
2706              }
2707            break;
2708            
2709          case OP_LOADU2_MEMBASE:
2710            // Load unassigned word from REGOFFSET
2711            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadu2_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2712                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2713
2714            if (bwx_supported)
2715              alpha_ldwu(code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2716            else
2717              {
2718                alpha_ldq_u(code, alpha_r24, ins->inst_basereg,
2719                            ins->inst_offset);
2720                alpha_ldq_u(code, alpha_r25, ins->inst_basereg,
2721                            (ins->inst_offset+1));
2722                alpha_lda(code, alpha_at, ins->inst_basereg, ins->inst_offset);
2723                alpha_extwl(code, alpha_r24, alpha_at, ins->dreg);
2724                alpha_extwh(code, alpha_r25, alpha_at, alpha_r25);
2725                alpha_bis(code, alpha_r25, ins->dreg, ins->dreg);
2726              }
2727            break;
2728            
2729          case OP_LOAD_MEMBASE:
2730            CFG_DEBUG(4) g_print("ALPHA_CHECK: [load_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2731                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2732            alpha_ldq( code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2733            break;
2734
2735          case OP_LOADI8_MEMBASE:
2736            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadi8_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2737                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2738            alpha_ldq( code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2739            break;
2740
2741          case OP_LOADI4_MEMBASE:
2742            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadi4_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2743                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2744            alpha_ldl( code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2745            break;
2746            
2747          case OP_LOADI1_MEMBASE:
2748            // Load sign-extended byte from REGOFFSET
2749            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadi1_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2750                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2751            if (bwx_supported)
2752              {
2753                alpha_ldbu(code, ins->dreg, ins->inst_basereg,
2754                           ins->inst_offset);
2755                alpha_sextb(code, ins->dreg, ins->dreg);
2756              }
2757            else
2758              {
2759                alpha_ldq_u(code, alpha_r25, ins->inst_basereg,
2760                            ins->inst_offset);
2761                alpha_lda(code, alpha_at, ins->inst_basereg,
2762                          (ins->inst_offset+1));
2763                alpha_extqh(code, alpha_r25, alpha_at, ins->dreg);
2764                alpha_sra_(code, ins->dreg, 56, ins->dreg);
2765              }
2766            break;
2767            
2768          case OP_LOADI2_MEMBASE:
2769            // Load sign-extended word from REGOFFSET
2770            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadi2_membase] dreg=%d, basereg=%d, offset=%0lx\n",
2771                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2772            if (bwx_supported)
2773              {
2774                alpha_ldwu(code, ins->dreg, ins->inst_basereg,
2775                           ins->inst_offset);
2776                alpha_sextw(code, ins->dreg, ins->dreg);
2777              }
2778            else
2779              {
2780                alpha_ldq_u(code, alpha_r24, ins->inst_basereg,
2781                            ins->inst_offset);
2782                alpha_ldq_u(code, alpha_r25, ins->inst_basereg,
2783                            (ins->inst_offset+1));
2784                alpha_lda(code, alpha_at, ins->inst_basereg,
2785                          (ins->inst_offset+2));
2786                alpha_extql(code, alpha_r24, alpha_at, ins->dreg);
2787                alpha_extqh(code, alpha_r25, alpha_at, alpha_r25);
2788                alpha_bis(code, alpha_r25, ins->dreg, ins->dreg);
2789                alpha_sra_(code, ins->dreg, 48, ins->dreg);
2790              }
2791            break;                        
2792            
2793          case OP_STOREI1_MEMBASE_IMM:
2794            // Store signed byte at REGOFFSET
2795            // Valid only for storing 0
2796            // storei1_membase_reg will do the rest
2797            
2798            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei1_membase_imm(0)] const=%0lx, destbasereg=%d, offset=%0lx\n",
2799                   ins->inst_imm, ins->inst_destbasereg, ins->inst_offset);
2800            g_assert(ins->inst_imm == 0);
2801
2802            if (bwx_supported)
2803                 alpha_stb(code, alpha_zero, ins->inst_destbasereg,
2804                         ins->inst_offset);
2805            else
2806                 g_assert_not_reached();
2807
2808            break;
2809
2810          case OP_STOREI1_MEMBASE_REG:
2811            // Store byte at REGOFFSET
2812            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei1_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lx\n",
2813                   ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2814            if (bwx_supported)
2815              {
2816                alpha_stb(code, ins->sreg1, ins->inst_destbasereg,
2817                          ins->inst_offset);
2818              }
2819            else
2820              {
2821                alpha_lda(code, alpha_at, ins->inst_destbasereg,
2822                          ins->inst_offset);
2823                alpha_ldq_u(code, alpha_r25, ins->inst_destbasereg,
2824                            ins->inst_offset);
2825                alpha_insbl(code, ins->sreg1, alpha_at, alpha_r24);
2826                alpha_mskbl(code, alpha_r25, alpha_at, alpha_r25);
2827                alpha_bis(code, alpha_r25, alpha_r24, alpha_r25);
2828                alpha_stq_u(code, alpha_r25, ins->inst_destbasereg,
2829                            ins->inst_offset);
2830              }
2831            break;
2832            
2833          case OP_STOREI2_MEMBASE_IMM:
2834            // Store signed word at REGOFFSET
2835            // Now work only for storing 0
2836            // For now storei2_membase_reg will do the work
2837            
2838            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei2_membase_imm(0)] const=%0lx, destbasereg=%d, offset=%0lx\n",
2839                   ins->inst_imm, ins->inst_destbasereg, ins->inst_offset);
2840            
2841            g_assert(ins->inst_imm == 0);
2842            
2843            if (bwx_supported)
2844                 alpha_stw(code, alpha_zero, ins->inst_destbasereg,
2845                         ins->inst_offset);
2846            else
2847                 g_assert_not_reached();
2848
2849            break;
2850            
2851          case OP_STOREI2_MEMBASE_REG:
2852            // Store signed word from reg to REGOFFSET
2853            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei2_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lx\n",
2854                   ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2855            
2856            if (bwx_supported)
2857              {
2858                alpha_stw(code, ins->sreg1, ins->inst_destbasereg,
2859                          ins->inst_offset);
2860              }
2861            else
2862              {
2863                alpha_lda(code, alpha_at, ins->inst_destbasereg,
2864                          ins->inst_offset);
2865                alpha_ldq_u(code, alpha_r25, ins->inst_destbasereg,
2866                            (ins->inst_offset+1));
2867                alpha_ldq_u(code, alpha_r24, ins->inst_destbasereg,
2868                            ins->inst_offset);
2869                alpha_inswh(code, ins->sreg1, alpha_at, alpha_r23);
2870                alpha_inswl(code, ins->sreg1, alpha_at, alpha_r22);
2871                alpha_mskwh(code, alpha_r25, alpha_at, alpha_r25);
2872                alpha_mskwl(code, alpha_r24, alpha_at, alpha_r24);
2873                alpha_bis(code, alpha_r25, alpha_r23, alpha_r25);
2874                alpha_bis(code, alpha_r24, alpha_r22, alpha_r24);
2875                alpha_stq_u(code, alpha_r25, ins->inst_destbasereg,
2876                            (ins->inst_offset+1));
2877                alpha_stq_u(code, alpha_r24, ins->inst_destbasereg,
2878                            ins->inst_offset);
2879              }
2880
2881            break;
2882            
2883          case OP_STOREI4_MEMBASE_IMM:
2884            // We will get here only with ins->inst_imm = 0
2885            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei4_membase_imm(0)] const=%0lx, destbasereg=%d, offset=%0lx\n",
2886                   ins->inst_imm, ins->inst_destbasereg, ins->inst_offset);
2887            
2888            g_assert(ins->inst_imm == 0);
2889            
2890            alpha_stl(code, alpha_zero,
2891                      ins->inst_destbasereg, ins->inst_offset);
2892            break;
2893
2894          case OP_STORER4_MEMBASE_REG:
2895            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storer4_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lX\n",
2896                   ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2897            alpha_sts(code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2898            break;
2899
2900          case OP_STORER8_MEMBASE_REG:
2901            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storer8_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lX\n",
2902                   ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2903            alpha_stt(code, ins->sreg1, ins->inst_destbasereg,
2904                      ins->inst_offset);
2905            break;
2906           
2907          case OP_LOADR4_MEMBASE:
2908            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadr4_membase] dreg=%d basereg=%d offset=%0lX\n",
2909                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2910            alpha_lds(code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2911            break;
2912
2913          case OP_LOADR8_MEMBASE:
2914            CFG_DEBUG(4) g_print("ALPHA_CHECK: [loadr8_membase] dreg=%d basereg=%d offset=%0lX\n",
2915                   ins->dreg, ins->inst_basereg, ins->inst_offset);
2916            alpha_ldt(code, ins->dreg, ins->inst_basereg, ins->inst_offset);
2917            break;
2918
2919          case OP_FMOVE:
2920            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fmove] sreg1=%d, dreg=%d\n",
2921                   ins->sreg1, ins->dreg);
2922            alpha_cpys(code, ins->sreg1, ins->sreg1, ins->dreg);
2923            break;
2924
2925          case OP_FADD:
2926            // Later check different rounding and exc modes
2927            CFG_DEBUG(4) g_print("ALPHA_CHECK: [float_add] sreg1=%d, sreg2=%d, dreg=%d\n",
2928                   ins->sreg1, ins->sreg2, ins->dreg);
2929            alpha_addt_su(code, ins->sreg1, ins->sreg2, ins->dreg);
2930            alpha_trapb(code);
2931            break;
2932
2933          case OP_FSUB:
2934            // Later check different rounding and exc modes
2935            CFG_DEBUG(4) g_print("ALPHA_CHECK: [float_sub] sreg1=%d, sreg2=%d, dreg=%d\n",
2936                                  ins->sreg1, ins->sreg2, ins->dreg);
2937            alpha_subt_su(code, ins->sreg1, ins->sreg2, ins->dreg);
2938            alpha_trapb(code);
2939            break;
2940
2941          case OP_FMUL:
2942            // Later check different rounding and exc modes
2943            CFG_DEBUG(4) g_print("ALPHA_CHECK: [float_sub] sreg1=%d, sreg2=%d, dreg=%d\n",
2944                                  ins->sreg1, ins->sreg2, ins->dreg);
2945            alpha_mult(code, ins->sreg1, ins->sreg2, ins->dreg);
2946            break;
2947
2948          case OP_FNEG:
2949            CFG_DEBUG(4) g_print("ALPHA_CHECK: [float_neg] sreg1=%d, dreg=%d\n",
2950                                  ins->sreg1, ins->dreg);
2951            alpha_cpysn(code, ins->sreg1, ins->sreg1, ins->dreg);
2952            break;
2953
2954          case OP_ALPHA_TRAPB:
2955            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_trapb]\n");
2956            alpha_trapb(code);
2957            break;
2958
2959          case OP_ABS:
2960            CFG_DEBUG(4) g_print("ALPHA_CHECK: [float_abs] sreg1=%d, dreg=%d\n",
2961                                 ins->sreg1, ins->dreg);
2962            alpha_cpys(code, alpha_f31, ins->sreg1, ins->dreg);
2963            break;
2964
2965          case OP_STORE_MEMBASE_IMM:
2966          case OP_STOREI8_MEMBASE_IMM:
2967            CFG_DEBUG(4) g_print("ALPHA_CHECK: [store_membase_imm/storei8_membase_imm] const=%0lx, destbasereg=%d, offset=%0lx\n",
2968                   ins->inst_imm, ins->inst_destbasereg, ins->inst_offset);
2969            g_assert(ins->inst_imm == 0);
2970
2971            alpha_stq(code, alpha_zero,
2972                      ins->inst_destbasereg, ins->inst_offset); 
2973
2974            break;
2975          case OP_STORE_MEMBASE_REG:
2976          case OP_STOREI8_MEMBASE_REG:
2977            CFG_DEBUG(4) g_print("ALPHA_CHECK: [store_membase_reg/storei8_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lx\n",
2978                   ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2979            alpha_stq( code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2980            break;
2981            
2982          case OP_STOREI4_MEMBASE_REG:
2983            CFG_DEBUG(4) g_print("ALPHA_CHECK: [storei4_membase_reg] sreg1=%d, destbasereg=%d, offset=%0lx\n",
2984                   ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2985            alpha_stl( code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
2986            break;
2987            
2988          case OP_ICOMPARE_IMM:
2989            CFG_DEBUG(4) g_print("ALPHA_CHECK: [icompare_imm] sreg1=%d, dreg=%d, const=%0lX\n",
2990                   ins->sreg1, ins->dreg, ins->inst_imm);
2991
2992            g_assert_not_reached();
2993            
2994            break;
2995            
2996          case OP_COMPARE_IMM:
2997            CFG_DEBUG(4) g_print("ALPHA_CHECK: [compare_imm] sreg1=%d, dreg=%d, const=%0lX\n",
2998                   ins->sreg1, ins->dreg, ins->inst_imm);
2999            
3000            g_assert_not_reached();
3001
3002            break;
3003            
3004          case OP_COMPARE:  // compare two 32 bit regs
3005          case OP_LCOMPARE: // compare two 64 bit regs
3006          case OP_FCOMPARE: // compare two floats
3007            CFG_DEBUG(4) g_print("ALPHA_FIX: [compare/lcompare/fcompare] sreg1=%d, sreg2=%d, dreg=%d\n",
3008                   ins->sreg1, ins->sreg2, ins->dreg);
3009
3010            g_assert_not_reached();
3011            
3012            break;
3013
3014          case OP_ALPHA_CMPT_UN:
3015            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_un] sreg1=%d, sreg2=%d, dreg=%d\n",
3016                                 ins->sreg1, ins->sreg2, ins->dreg);
3017            alpha_cmptun(code, ins->sreg1, ins->sreg2, (alpha_at+1));
3018            break;
3019
3020          case OP_ALPHA_CMPT_UN_SU:
3021            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_un_su] sreg1=%d, sreg2=%d, dreg=%d\n",
3022                                 ins->sreg1, ins->sreg2, ins->dreg);
3023            alpha_cmptun_su(code, ins->sreg1, ins->sreg2, (alpha_at+1));
3024            break;
3025
3026          case OP_ALPHA_CMPT_EQ:
3027            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_eq] sreg1=%d, sreg2=%d, dreg=%d\n",
3028                                  ins->sreg1, ins->sreg2, ins->dreg);
3029            alpha_cmpteq(code, ins->sreg1, ins->sreg2, alpha_at);
3030            break;
3031
3032          case OP_ALPHA_CMPT_EQ_SU:
3033            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_eq_su] sreg1=%d, sreg2=%d, dreg=%d\n",
3034                                 ins->sreg1, ins->sreg2, ins->dreg);
3035            alpha_cmpteq_su(code, ins->sreg1, ins->sreg2, alpha_at);
3036            break;
3037
3038
3039          case OP_ALPHA_CMPT_LT:
3040            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_lt] sreg1=%d, sreg2=%d, dreg=%d\n",
3041                                 ins->sreg1, ins->sreg2, ins->dreg);
3042            alpha_cmptlt(code, ins->sreg1, ins->sreg2, alpha_at);
3043            break;
3044
3045          case OP_ALPHA_CMPT_LT_SU:
3046            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_lt_su] sreg1=%d, sreg2=%d, dreg=%d\n",
3047                                 ins->sreg1, ins->sreg2, ins->dreg);
3048            alpha_cmptlt_su(code, ins->sreg1, ins->sreg2, alpha_at);
3049            break;
3050
3051          case OP_ALPHA_CMPT_LE:
3052            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_le] sreg1=%d, sreg2=%d, dreg=%d\n",
3053                                 ins->sreg1, ins->sreg2, ins->dreg);
3054            alpha_cmptle(code, ins->sreg1, ins->sreg2, alpha_at);
3055            break;
3056
3057          case OP_ALPHA_CMPT_LE_SU:
3058            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmpt_le_su] sreg1=%d, sreg2=%d, dreg=%d\n",
3059                                 ins->sreg1, ins->sreg2, ins->dreg);
3060            alpha_cmptle_su(code, ins->sreg1, ins->sreg2, alpha_at);
3061            break;
3062
3063          case OP_ALPHA_CMP_EQ:
3064            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_eq] sreg1=%d, sreg2=%d, dreg=%d\n",
3065                   ins->sreg1, ins->sreg2, ins->dreg);
3066            alpha_cmpeq(code, ins->sreg1, ins->sreg2, alpha_at);
3067            break;
3068            
3069          case OP_ALPHA_CMP_IMM_EQ:
3070            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_eq] sreg1=%d, const=%0lX, dreg=%d\n",
3071                   ins->sreg1, ins->inst_imm, ins->dreg);
3072            alpha_cmpeq_(code, ins->sreg1, ins->inst_imm, alpha_at);
3073            break;
3074
3075          case OP_ALPHA_CMP_IMM_ULE:
3076            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_ule] sreg1=%d, const=%0lX, dreg=%d\n",
3077                   ins->sreg1, ins->inst_imm, ins->dreg);
3078            alpha_cmpule_(code, ins->sreg1, ins->inst_imm, alpha_at);
3079            break;
3080
3081          case OP_ALPHA_CMP_ULT:
3082            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_ult] sreg1=%d, sreg2=%d, dreg=%d\n",
3083                   ins->sreg1, ins->sreg2, ins->dreg);
3084            alpha_cmpult(code, ins->sreg1, ins->sreg2, alpha_at);
3085            break;
3086
3087          case OP_ALPHA_CMP_IMM_ULT:
3088            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_ult] sreg1=%d, const=%0lX, dreg=%d\n",
3089                   ins->sreg1, ins->inst_imm, ins->dreg);
3090            alpha_cmpult_(code, ins->sreg1, ins->inst_imm, alpha_at);
3091            break;
3092
3093          case OP_ALPHA_CMP_LE:
3094            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_le] sreg1=%d, sreg2=%d, dreg=%d\n",
3095                   ins->sreg1, ins->sreg2, ins->dreg);
3096            alpha_cmple(code, ins->sreg1, ins->sreg2, alpha_at);
3097            break;
3098
3099          case OP_ALPHA_CMP_ULE:
3100            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_ule] sreg1=%d, sreg2=%d, dreg=%d\n",
3101                                 ins->sreg1, ins->sreg2, ins->dreg);
3102            alpha_cmpule(code, ins->sreg1, ins->sreg2, alpha_at);
3103            break;
3104
3105
3106          case OP_ALPHA_CMP_IMM_LE:
3107            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_le] sreg1=%d, const=%0lX, dreg=%d\n",
3108                   ins->sreg1, ins->inst_imm, ins->dreg);
3109            alpha_cmple_(code, ins->sreg1, ins->inst_imm, alpha_at);
3110            break;
3111
3112          case OP_ALPHA_CMP_LT:
3113            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_lt] sreg1=%d, sreg2=%d, dreg=%d\n",
3114                   ins->sreg1, ins->sreg2, ins->dreg);
3115            alpha_cmplt(code, ins->sreg1, ins->sreg2, alpha_at);
3116            break;
3117
3118          case OP_ALPHA_CMP_IMM_LT:
3119            CFG_DEBUG(4) g_print("ALPHA_CHECK: [alpha_cmp_imm_lt] sreg1=%d, const=%0lX, dreg=%d\n",
3120                   ins->sreg1, ins->inst_imm, ins->dreg);
3121            alpha_cmplt_(code, ins->sreg1, ins->inst_imm, alpha_at);
3122            break;
3123
3124          case OP_COND_EXC_GT:
3125            CFG_DEBUG(4) g_print("ALPHA_CHECK: [op_cond_exc_gt] (cmple + beq) Exc: %s\n",
3126                                 (char *)ins->inst_p1);
3127
3128            EMIT_COND_EXC_BRANCH(beq, alpha_at, ins->inst_p1);
3129            break;
3130
3131          case OP_COND_EXC_GT_UN:
3132            CFG_DEBUG(4) g_print("ALPHA_CHECK: [op_cond_exc_gt_un] (cmpule + beq) Exc: %s\n",
3133                                 (char *)ins->inst_p1);
3134
3135            EMIT_COND_EXC_BRANCH(beq, alpha_at, ins->inst_p1);
3136            break;
3137
3138          case OP_COND_EXC_LT:
3139            CFG_DEBUG(4) g_print("ALPHA_CHECK: [op_cond_exc_lt] (cmplt + bne) Exc: %s\n",
3140                                 (char *)ins->inst_p1);
3141
3142            EMIT_COND_EXC_BRANCH(bne, alpha_at, ins->inst_p1);
3143            break;
3144
3145          case OP_COND_EXC_LT_UN:
3146            CFG_DEBUG(4) g_print("ALPHA_CHECK: [op_cond_exc_lt_un] (cmpult + bne) Exc: %s\n",
3147                                 (char *)ins->inst_p1);
3148
3149            EMIT_COND_EXC_BRANCH(bne, alpha_at, ins->inst_p1);
3150            break;
3151
3152
3153          case OP_COND_EXC_LE_UN:
3154            CFG_DEBUG(4) g_print("ALPHA_CHECK: [op_cond_exc_le_un] (cmpule + bne) Exc: %s\n",
3155                                 (char *)ins->inst_p1);
3156            EMIT_COND_EXC_BRANCH(bne, alpha_at, ins->inst_p1);
3157            break;
3158
3159          case OP_COND_EXC_NE_UN:
3160            CFG_DEBUG(4) g_print("ALPHA_CHECK: [op_cond_exc_ne_un] (cmpeq + beq) Exc: %s\n",
3161                                 (char *)ins->inst_p1);
3162            EMIT_COND_EXC_BRANCH(beq, alpha_at, ins->inst_p1);
3163            break;
3164
3165          case OP_COND_EXC_EQ:
3166            CFG_DEBUG(4) g_print("ALPHA_CHECK: [op_cond_exc_eq] (cmpeq + bne) Exc: %s\n",
3167                                 (char *)ins->inst_p1);
3168            EMIT_COND_EXC_BRANCH(bne, alpha_at, ins->inst_p1);
3169            break;
3170
3171          case OP_COND_EXC_IOV:
3172          case OP_COND_EXC_OV:
3173            EMIT_COND_EXC_BRANCH(bne, alpha_at, "OverflowException");
3174            break;
3175
3176          case OP_COND_EXC_IC:
3177          case OP_COND_EXC_C:
3178            EMIT_COND_EXC_BRANCH(bne, alpha_pv, "OverflowException");
3179            break;
3180
3181          case CEE_CONV_OVF_U4:
3182            // Convert unsigned 32 bit value to 64 bit reg
3183            // Check overflow
3184            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_ovf_u4] sreg=%d, dreg=%d\n",
3185                                 ins->sreg1, ins->dreg);
3186            alpha_cmplt_(code, ins->sreg1, 0, alpha_at);
3187            EMIT_COND_EXC_BRANCH(bne, alpha_at, "OverflowException");
3188            alpha_mov1(code, ins->sreg1, ins->dreg);
3189            break;
3190
3191          case CEE_CONV_OVF_I4_UN:
3192            // Convert unsigned 32 bit value to 64 bit reg
3193            // Check overflow
3194            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_ovf_i4_un] sreg=%d, dreg=%d\n",
3195                                 ins->sreg1, ins->dreg);
3196            alpha_zap_(code, ins->sreg1, 0x0F, alpha_at);
3197
3198            EMIT_COND_EXC_BRANCH(bne, alpha_at, "OverflowException");
3199            alpha_mov1(code, ins->sreg1, ins->dreg);
3200            break;
3201
3202          case CEE_CONV_I1:
3203            // Move I1 (byte) to dreg(64 bits) and sign extend it
3204            // Read about sextb
3205            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_i1] sreg=%d, dreg=%d\n",
3206                   ins->sreg1, ins->dreg);
3207            if (bwx_supported)
3208              alpha_sextb(code, ins->sreg1, ins->dreg);
3209            else
3210              {
3211                alpha_sll_(code, ins->sreg1, 24, alpha_at);
3212                alpha_addl(code, alpha_at, alpha_zero, ins->dreg);
3213                alpha_sra_(code, ins->dreg, 24, ins->dreg);
3214              }
3215            break;
3216
3217          case CEE_CONV_I2:
3218            // Move I2 (word) to dreg(64 bits) and sign extend it
3219            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_i2] sreg=%d, dreg=%d\n",
3220                   ins->sreg1, ins->dreg);
3221            if (bwx_supported)
3222              alpha_sextw(code, ins->sreg1, ins->dreg);
3223            else
3224              {
3225                alpha_sll_(code, ins->sreg1, 16, alpha_at);
3226                alpha_addl(code, alpha_at, alpha_zero, ins->dreg);
3227                alpha_sra_(code, ins->dreg, 16, ins->dreg);
3228              }
3229            break;
3230            
3231          case CEE_CONV_I4:
3232            // Move I4 (long) to dreg(64 bits) and sign extend it
3233            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_i4] sreg=%d, dreg=%d\n",
3234                   ins->sreg1, ins->dreg);
3235            alpha_addl(code, ins->sreg1, alpha_zero, ins->dreg);
3236            break;
3237
3238          case CEE_CONV_I8:
3239          case CEE_CONV_I:
3240            // Convert I/I8 (64 bit) to dreg (64 bit) and sign extend it
3241            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_i8/conv_i] sreg=%d, dreg=%d\n",
3242                   ins->sreg1, ins->dreg);
3243            //alpha_addl(code, ins->sreg1, alpha_zero, ins->dreg);
3244            alpha_mov1(code, ins->sreg1, ins->dreg);
3245            break;
3246            
3247          case CEE_CONV_U1:
3248            // Move U1 (byte) to dreg(64 bits) don't sign extend it
3249            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_u1] sreg=%d, dreg=%d\n",
3250                   ins->sreg1, ins->dreg);
3251            alpha_extbl_(code, ins->sreg1, 0, ins->dreg);
3252            break;
3253            
3254          case CEE_CONV_U2:
3255            // Move U2 (word) to dreg(64 bits) don't sign extend it
3256            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_u2] sreg=%d, dreg=%d\n",
3257                   ins->sreg1, ins->dreg);
3258            alpha_extwl_(code, ins->sreg1, 0, ins->dreg);
3259            break;
3260            
3261          case CEE_CONV_U4:
3262            // Move U4 (long) to dreg(64 bits) don't sign extend it
3263            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_u4] sreg=%d, dreg=%d\n",
3264                   ins->sreg1, ins->dreg);
3265            alpha_extll_(code, ins->sreg1, 0, ins->dreg);
3266            break;
3267            
3268          case CEE_CONV_U8:
3269          case CEE_CONV_U:
3270            // Move U4 (long) to dreg(64 bits) don't sign extend it
3271            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_u8/conv_u] sreg=%d, dreg=%d\n",
3272                   ins->sreg1, ins->dreg);
3273            alpha_extll_(code, ins->sreg1, 0, ins->dreg);
3274            break;
3275
3276          case OP_FCONV_TO_I4:
3277          case OP_FCONV_TO_I8:
3278            // Move float to 32 bit reg
3279            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fconv_to_i4/fconv_to_i8] sreg=%d, dreg=%d\n",
3280                                  ins->sreg1, ins->dreg);
3281            //alpha_ftoit(code, ins->sreg1, ins->dreg); - 21264/EV6
3282            alpha_cvttq_c(code, ins->sreg1, ins->sreg1);
3283            alpha_lda(code, alpha_sp, alpha_sp, -8);
3284            alpha_stt(code, ins->sreg1, alpha_sp, 0);
3285            alpha_ldq(code, ins->dreg, alpha_sp, 0);
3286            alpha_lda(code, alpha_sp, alpha_sp, 8);
3287            break;
3288
3289          case OP_FCONV_TO_I2:
3290            // Move float to 16 bit reg
3291            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fconv_to_i2] sreg=%d, dreg=%d\n",
3292                                 ins->sreg1, ins->dreg);
3293            //alpha_ftoit(code, ins->sreg1, ins->dreg); - 21264/EV6
3294            alpha_cvttq_c(code, ins->sreg1, ins->sreg1);
3295            alpha_lda(code, alpha_sp, alpha_sp, -8);
3296            alpha_stt(code, ins->sreg1, alpha_sp, 0);
3297            alpha_ldq(code, ins->dreg, alpha_sp, 0);
3298            alpha_lda(code, alpha_sp, alpha_sp, 8);
3299            alpha_sll_(code, ins->dreg, 48, ins->dreg);
3300            alpha_sra_(code, ins->dreg, 48, ins->dreg);
3301            break;
3302
3303          case OP_FCONV_TO_U2:
3304            // Move float to 16 bit reg as unsigned 
3305            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fconv_to_u2] sreg=%d, dreg=%d\n",
3306                                 ins->sreg1, ins->dreg);
3307            //alpha_ftoit(code, ins->sreg1, ins->dreg); - 21264/EV6
3308            alpha_cvttq_c(code, ins->sreg1, ins->sreg1);
3309            alpha_lda(code, alpha_sp, alpha_sp, -8);
3310            alpha_stt(code, ins->sreg1, alpha_sp, 0);
3311            alpha_ldq(code, ins->dreg, alpha_sp, 0);
3312            alpha_lda(code, alpha_sp, alpha_sp, 8);
3313            alpha_zapnot_(code, ins->dreg, 3, ins->dreg);
3314            break;
3315
3316          case OP_FCONV_TO_U1:
3317            // Move float to 8 bit reg as unsigned
3318            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fconv_to_u1] sreg=%d, dreg=%d\n",
3319                                 ins->sreg1, ins->dreg);
3320            //alpha_ftoit(code, ins->sreg1, ins->dreg); - 21264/EV6
3321            alpha_cvttq_c(code, ins->sreg1, ins->sreg1);
3322            alpha_lda(code, alpha_sp, alpha_sp, -8);
3323            alpha_stt(code, ins->sreg1, alpha_sp, 0);
3324            alpha_ldq(code, ins->dreg, alpha_sp, 0);
3325            alpha_lda(code, alpha_sp, alpha_sp, 8);
3326            alpha_and_(code, ins->dreg, 0xff, ins->dreg);
3327            break;
3328
3329          case OP_FCONV_TO_I1:
3330            // Move float to 8 bit reg
3331            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fconv_to_i1] sreg=%d, dreg=%d\n",
3332                                 ins->sreg1, ins->dreg);
3333            //alpha_ftoit(code, ins->sreg1, ins->dreg); - 21264/EV6
3334            alpha_cvttq_c(code, ins->sreg1, ins->sreg1);
3335            alpha_lda(code, alpha_sp, alpha_sp, -8);
3336            alpha_stt(code, ins->sreg1, alpha_sp, 0);
3337            alpha_ldq(code, ins->dreg, alpha_sp, 0);
3338            alpha_lda(code, alpha_sp, alpha_sp, 8);
3339            alpha_sll_(code, ins->dreg, 56, ins->dreg);
3340            alpha_sra_(code, ins->dreg, 56, ins->dreg);
3341            break;
3342
3343          case CEE_CONV_R4:
3344          case OP_LCONV_TO_R4:
3345            // Move 32/64 bit int into float
3346            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_r4/lconv_r4] sreg=%d, dreg=%d\n",
3347                                  ins->sreg1, ins->dreg);
3348            alpha_lda(code, alpha_sp, alpha_sp, -8);
3349            alpha_stq(code, ins->sreg1, alpha_sp, 0);
3350            alpha_ldt(code, ins->dreg, alpha_sp, 0);
3351            alpha_lda(code, alpha_sp, alpha_sp, 8);
3352            alpha_cvtqs(code, ins->dreg, ins->dreg);
3353            alpha_trapb(code);
3354            break;
3355
3356          case CEE_CONV_R8:
3357          case OP_LCONV_TO_R8:
3358            // Move 32/64 bit int into double
3359            CFG_DEBUG(4) g_print("ALPHA_CHECK: [conv_r8/lconv_r8] sreg=%d, dreg=%d\n",
3360                                  ins->sreg1, ins->dreg);
3361            alpha_lda(code, alpha_sp, alpha_sp, -8);
3362            alpha_stq(code, ins->sreg1, alpha_sp, 0);
3363            alpha_ldt(code, ins->dreg, alpha_sp, 0);
3364            alpha_lda(code, alpha_sp, alpha_sp, 8);
3365            alpha_cvtqt(code, ins->dreg, ins->dreg);
3366            alpha_trapb(code);
3367            break;
3368
3369          case OP_FCONV_TO_R4:
3370            // Convert 64 bit float to 32 bit float (T -> S)
3371            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fconv_r4] sreg=%d, dreg=%d\n",
3372                                  ins->sreg1, ins->dreg);
3373            alpha_cvtts_su(code, ins->sreg1, ins->dreg);
3374            alpha_trapb(code);
3375            break;
3376
3377          case OP_LOCALLOC:
3378            // Allocate sreg1 bytes on stack, round bytes by 8,
3379            // modify SP, set dreg to end of current stack frame
3380            // top of stack is used for call params
3381            CFG_DEBUG(4) g_print("ALPHA_CHECK: [localloc] sreg=%d, dreg=%d\n",
3382                                 ins->sreg1, ins->dreg);
3383
3384            alpha_addq_(code, ins->sreg1, (MONO_ARCH_LOCALLOC_ALIGNMENT - 1), ins->sreg1);
3385            alpha_bic_(code, ins->sreg1, (MONO_ARCH_LOCALLOC_ALIGNMENT - 1), ins->sreg1);
3386            if (ins->flags & MONO_INST_INIT)
3387                alpha_mov1(code, ins->sreg1, ins->sreg2);
3388
3389            alpha_subq(code, alpha_sp, ins->sreg1, alpha_sp);
3390            if (cfg->arch.params_stack_size > 0)
3391            {
3392                alpha_lda(code, ins->dreg, alpha_zero,
3393                         (cfg->arch.params_stack_size));
3394                alpha_addq(code, alpha_sp, ins->dreg, ins->dreg);
3395            }
3396            else
3397                alpha_mov1(code, alpha_sp, ins->dreg);
3398
3399            if (ins->flags & MONO_INST_INIT)
3400            {
3401                 // TODO: Optimize it later
3402                 alpha_lda(code, ins->sreg2, ins->sreg2,
3403                         -(MONO_ARCH_LOCALLOC_ALIGNMENT));
3404                 alpha_blt(code, ins->sreg2, 3);
3405                 alpha_addq(code, ins->sreg2, ins->dreg, alpha_at);
3406                 alpha_stq(code, alpha_zero, alpha_at, 0);
3407                 alpha_br(code, alpha_zero, -5);
3408            }
3409
3410            break;
3411
3412          case OP_MOVE:
3413            CFG_DEBUG(4) g_print("ALPHA_CHECK: [move] sreg=%d, dreg=%d\n",
3414                   ins->sreg1, ins->dreg);
3415            alpha_mov1(code, ins->sreg1, ins->dreg);
3416            break;
3417            
3418          case OP_CGT_UN:
3419          case OP_ICGT_UN:
3420          case OP_ICGT:
3421          case OP_CGT:
3422            CFG_DEBUG(4) g_print("ALPHA_CHECK: [cgt/cgt_un/icgt_un/int_cgt] dreg=%d\n",
3423                   ins->dreg);
3424            alpha_clr(code, ins->dreg);
3425            alpha_cmoveq_(code, alpha_at, 1, ins->dreg);
3426            break;
3427
3428          case OP_ICLT:
3429          case OP_ICLT_UN:
3430          case OP_CLT:
3431          case OP_CLT_UN:
3432            CFG_DEBUG(4) g_print("ALPHA_CHECK: [int_clt/int_clt_un/clt/clt_un] dreg=%d\n",
3433                   ins->dreg);
3434            alpha_clr(code, ins->dreg);
3435            alpha_cmovne_(code, alpha_at, 1, ins->dreg);
3436            break;
3437
3438          case OP_ICEQ:
3439          case OP_CEQ:
3440            CFG_DEBUG(4) g_print("ALPHA_CHECK: [iceq/ceq] dreg=%d\n",
3441                   ins->dreg);
3442            alpha_clr(code, ins->dreg);
3443            alpha_cmovne_(code, alpha_at, 1, ins->dreg);
3444            break;
3445
3446          case OP_FCEQ:
3447            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fceq] dreg=%d\n",
3448                                 ins->dreg);
3449            alpha_clr(code, ins->dreg);
3450            alpha_fbeq(code, alpha_at, 1);
3451            alpha_lda(code, ins->dreg, alpha_zero, 1);
3452
3453            /*
3454            alpha_cvttq_c(code, alpha_at, alpha_at);
3455            alpha_lda(code, alpha_sp, alpha_sp, -8);
3456            alpha_stt(code, alpha_at, alpha_sp, 0);
3457            alpha_ldq(code, alpha_at, alpha_sp, 0);
3458            alpha_lda(code, alpha_sp, alpha_sp, 8);
3459
3460            alpha_cmovne_(code, alpha_at, 1, ins->dreg);
3461            */
3462            break;
3463
3464          case OP_FCGT:
3465            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fcgt] dreg=%d\n",
3466                                 ins->dreg);
3467            alpha_clr(code, ins->dreg);
3468            alpha_fbne(code, alpha_at, 1);
3469            alpha_lda(code, ins->dreg, alpha_zero, 1);
3470
3471            /*
3472            alpha_cvttq_c(code, alpha_at, alpha_at);
3473            alpha_lda(code, alpha_sp, alpha_sp, -8);
3474            alpha_stt(code, alpha_at, alpha_sp, 0);
3475            alpha_ldq(code, alpha_at, alpha_sp, 0);
3476            alpha_lda(code, alpha_sp, alpha_sp, 8);
3477
3478            alpha_cmoveq_(code, alpha_at, 1, ins->dreg);
3479            */
3480            break;
3481
3482
3483          case OP_FCLT:
3484            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fclt] dreg=%d\n",
3485                                 ins->dreg);
3486            alpha_clr(code, ins->dreg);
3487            alpha_fbeq(code, alpha_at, 1);
3488            alpha_lda(code, ins->dreg, alpha_zero, 1);
3489            break;
3490
3491          case OP_FCLT_UN:
3492            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fclt_un] dreg=%d\n",
3493                                 ins->dreg);
3494  
3495            alpha_clr(code, ins->dreg);
3496            alpha_fbne(code, (alpha_at+1), 1);
3497            alpha_fbeq(code, alpha_at, 1);
3498            alpha_lda(code, ins->dreg, alpha_zero, 1);
3499            break;
3500
3501
3502          case OP_IBNE_UN:
3503            CFG_DEBUG(4) g_print("ALPHA_CHECK: [ibne_un] [");
3504            EMIT_ALPHA_BRANCH(ins, alpha_at, bne);
3505            break;
3506
3507          case OP_FBNE_UN:
3508            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbne_un] [");
3509            alpha_fbeq(code, (alpha_at+1), 1);
3510            alpha_cpys(code, alpha_zero, alpha_zero, alpha_at);
3511            EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
3512            break;
3513
3514          case OP_FBGE_UN:
3515            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbge_un] [");
3516            alpha_fbeq(code, (alpha_at+1), 1);
3517            alpha_cpys(code, alpha_zero, alpha_zero, alpha_at);
3518            EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
3519            break;
3520
3521          case OP_FBGE:
3522            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbge] [");
3523            alpha_fbne(code, (alpha_at+1), 1);
3524            EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
3525            break;
3526
3527          case OP_FBLE_UN:
3528            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fble_un] [");
3529            alpha_fbeq(code, (alpha_at+1), 1);
3530            alpha_cpys(code, (alpha_at+1), (alpha_at+1), alpha_at);
3531            EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
3532            break;
3533
3534          case OP_FBLE:
3535            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fble] [");
3536            alpha_fbne(code, (alpha_at+1), 1);
3537            EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
3538            break;
3539
3540          case OP_FBLT_UN:
3541            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fblt_un] [");
3542            alpha_fbeq(code, (alpha_at+1), 1);
3543            alpha_cpys(code, (alpha_at+1), (alpha_at+1), alpha_at);
3544            EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
3545            break;
3546
3547          case OP_FBLT:
3548            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fblt] [");
3549            alpha_fbne(code, (alpha_at+1), 1);
3550            EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
3551            break;
3552
3553          case OP_FBGT_UN:
3554            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbgt_un] [");
3555            alpha_fbeq(code, (alpha_at+1), 1);
3556            alpha_cpys(code, alpha_zero, alpha_zero, alpha_at);
3557            EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
3558            break;
3559
3560          case OP_FBGT:
3561            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbgt] [");
3562            alpha_fbne(code, (alpha_at+1), 1);
3563            EMIT_ALPHA_BRANCH(ins, alpha_at, fbeq);
3564            break;
3565
3566          case OP_IBEQ:
3567            CFG_DEBUG(4) g_print("ALPHA_CHECK: [ibeq] [");
3568            EMIT_ALPHA_BRANCH(ins, alpha_at, beq);
3569            break;
3570
3571          case OP_FBEQ:
3572            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fbeq] [");
3573            EMIT_ALPHA_BRANCH(ins, alpha_at, fbne);
3574            break;
3575            
3576          case CEE_BEQ:
3577            CFG_DEBUG(4) g_print("ALPHA_CHECK: [beq] [");
3578            EMIT_ALPHA_BRANCH(ins, alpha_at, beq);
3579            break;
3580            
3581          case CEE_BNE_UN:
3582            CFG_DEBUG(4) g_print("ALPHA_CHECK: [bne_un] [");
3583            EMIT_ALPHA_BRANCH(ins, alpha_at, bne);
3584            break;
3585            
3586          case OP_LABEL:
3587            CFG_DEBUG(4) g_print("ALPHA_CHECK: [label]\n");
3588            ins->inst_c0 = (char *)code - (char *)cfg->native_code;
3589            break;
3590            
3591          case OP_BR:
3592            if (ins->flags & MONO_INST_BRLABEL)
3593              {
3594                if (ins->inst_i0->inst_c0)
3595                  {
3596                    CFG_DEBUG(4) g_print("inst_c0: %0lX, data: %p]\n",
3597                           ins->inst_i0->inst_c0,
3598                           cfg->native_code + ins->inst_i0->inst_c0);
3599                    alpha_br(code, alpha_zero, 0);
3600                  }
3601                else
3602                  {
3603                    CFG_DEBUG(4) g_print("add patch info: MONO_PATCH_INFO_LABEL offset: %0X, inst_i0: %p]\n",
3604                           offset, ins->inst_i0);
3605                    mono_add_patch_info (cfg, offset,
3606                                         MONO_PATCH_INFO_LABEL, ins->inst_i0);
3607                    
3608                    alpha_br(code, alpha_zero, 0);
3609                  }
3610              }
3611            else
3612              {
3613                if (ins->inst_target_bb->native_offset)
3614                  {
3615                    // Somehow native offset is offset from
3616                    // start of the code. So convert it to
3617                    // offset branch
3618                    long br_offset = (char *)cfg->native_code +
3619                      ins->inst_target_bb->native_offset - 4 - (char *)code;
3620                    
3621                    CFG_DEBUG(4) g_print("jump to: native_offset: %0X, address %p]\n",
3622                           ins->inst_target_bb->native_offset,
3623                           cfg->native_code +
3624                           ins->inst_target_bb->native_offset);
3625                    alpha_br(code, alpha_zero, br_offset/4);
3626                  }
3627                else
3628                  {
3629                    CFG_DEBUG(4) g_print("add patch info: MONO_PATCH_INFO_BB offset: %0X, target_bb: %p]\n",
3630                           offset, ins->inst_target_bb);
3631                    
3632                    mono_add_patch_info (cfg, offset,
3633                                         MONO_PATCH_INFO_BB,
3634                                         ins->inst_target_bb);
3635                    alpha_br(code, alpha_zero, 0);
3636                  }
3637              }
3638            
3639            break;
3640
3641          case OP_BR_REG:
3642            CFG_DEBUG(4) g_print("ALPHA_CHECK: [br_reg] sreg1=%d\n",
3643                   ins->sreg1);
3644
3645            alpha_jmp(code, alpha_zero, ins->sreg1, 0);
3646            break;
3647            
3648          case OP_FCALL:
3649          case OP_LCALL:
3650          case OP_VCALL:
3651          case OP_VOIDCALL:
3652          case OP_CALL:
3653            CFG_DEBUG(4) g_print("ALPHA_CHECK: [fcall/lcall/vcall/voidcall/call] Target: [");
3654            call = (MonoCallInst*)ins;
3655            
3656            if (ins->flags & MONO_INST_HAS_METHOD)
3657              {
3658                CFG_DEBUG(4) g_print("MONO_PATCH_INFO_METHOD] %p\n", call->method);
3659                code = emit_call (cfg, code,
3660                                  MONO_PATCH_INFO_METHOD, call->method);
3661              }
3662            else
3663              {
3664                CFG_DEBUG(4) g_print("MONO_PATCH_INFO_ABS] %p\n", call->fptr);
3665                code = emit_call (cfg, code,
3666                                  MONO_PATCH_INFO_ABS, call->fptr);
3667              }
3668
3669            //code = emit_move_return_value (cfg, ins, code);
3670
3671            break;
3672            
3673          case OP_FCALL_REG:
3674          case OP_LCALL_REG:
3675          case OP_VCALL_REG:
3676          case OP_VOIDCALL_REG:
3677          case OP_CALL_REG:
3678            {
3679              int offset;
3680
3681              CFG_DEBUG(4) g_print("ALPHA_CHECK: [fcall_reg/lcall_reg/vcall_reg/voidcall_reg/call_reg]: TargetReg: %d\n", ins->sreg1);
3682              call = (MonoCallInst*)ins;
3683            
3684              alpha_mov1(code, ins->sreg1, alpha_pv);
3685
3686              alpha_jsr(code, alpha_ra, alpha_pv, 0);
3687
3688              offset = (char *)code - (char *)cfg->native_code;
3689
3690              // Restore GP
3691              ALPHA_LOAD_GP(offset)
3692              alpha_ldah(code, alpha_gp, alpha_ra, 0);
3693              alpha_lda(code, alpha_gp, alpha_gp, 0);
3694            }
3695            break;
3696
3697          case OP_FCALL_MEMBASE:
3698          case OP_CALL_MEMBASE:
3699          case OP_LCALL_MEMBASE:
3700          case OP_VCALL_MEMBASE:
3701            {
3702              int offset;
3703
3704              CFG_DEBUG(4) g_print("ALPHA_CHECK: [(lvf)call_membase] basereg=%d, offset=%0lx\n",
3705                     ins->inst_basereg, ins->inst_offset);
3706              call = (MonoCallInst*)ins;
3707
3708              alpha_ldq(code, alpha_pv, ins->inst_basereg, ins->inst_offset);
3709              alpha_jsr(code, alpha_ra, alpha_pv, 0);
3710
3711              offset = (char *)code - (char *)cfg->native_code;
3712            
3713              // Restore GP
3714              ALPHA_LOAD_GP(offset)
3715              alpha_ldah(code, alpha_gp, alpha_ra, 0);
3716              alpha_lda(code, alpha_gp, alpha_gp, 0);
3717            }
3718            break;
3719
3720          case OP_VOIDCALL_MEMBASE:
3721            {
3722              int offset;
3723
3724              CFG_DEBUG(4) g_print("ALPHA_CHECK: [voidcall_membase] basereg=%d, offset=%0lx\n",
3725                     ins->inst_basereg, ins->inst_offset);
3726              call = (MonoCallInst*)ins;
3727
3728              alpha_ldq(code, alpha_pv, ins->inst_basereg, ins->inst_offset);
3729              alpha_jsr(code, alpha_ra, alpha_pv, 0);
3730
3731              offset = (char *)code - (char *)cfg->native_code;
3732
3733              // Restore GP
3734              ALPHA_LOAD_GP(offset)
3735              alpha_ldah(code, alpha_gp, alpha_ra, 0);
3736              alpha_lda(code, alpha_gp, alpha_gp, 0);
3737            }
3738            break;
3739
3740          case OP_START_HANDLER:
3741            {
3742              // TODO - find out when we called by call_handler or resume_context
3743              // of by call_filter. There should be difference. For now just
3744              // handle - call_handler
3745
3746              CFG_DEBUG(4) g_print("ALPHA_CHECK: [start_handler] basereg=%d, offset=%0lx\n",
3747                 ins->inst_left->inst_basereg, ins->inst_left->inst_offset);
3748
3749              alpha_stq(code, alpha_ra, ins->inst_left->inst_basereg, 
3750                         ins->inst_left->inst_offset);
3751            }
3752            break;
3753
3754          case OP_ENDFINALLY:
3755            {
3756              // Keep in sync with start_handler
3757              CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfinally] basereg=%d, offset=%0lx\n",
3758                 ins->inst_left->inst_basereg, ins->inst_left->inst_offset);
3759
3760              alpha_ldq(code, alpha_ra, ins->inst_left->inst_basereg,
3761                         ins->inst_left->inst_offset);
3762
3763              alpha_ret(code, alpha_ra, 1);
3764
3765            }
3766            break;
3767          case OP_ENDFILTER:
3768            {
3769              // Keep in sync with start_handler
3770              CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfilter] sreg1=%d, basereg=%d, offset=%0lx\n",
3771                 ins->sreg1, ins->inst_left->inst_basereg, ins->inst_left->inst_offset);
3772
3773              alpha_ldq(code, alpha_ra, ins->inst_left->inst_basereg,
3774                         ins->inst_left->inst_offset);
3775
3776              if (ins->sreg1 != -1 && ins->sreg1 != alpha_r0)
3777                 alpha_mov1(code, ins->sreg1, alpha_r0);
3778
3779              alpha_ret(code, alpha_ra, 1);
3780            }
3781            break;
3782          
3783         case OP_CALL_HANDLER:
3784            {
3785              int offset;
3786
3787              offset = (char *)code - (char *)cfg->native_code;
3788
3789              CFG_DEBUG(4) g_print("ALPHA_CHECK: [call_handler] add patch info: MONO_PATCH_INFO_BB offset: %0X, target_bb: %p]\n",
3790                                   offset, ins->inst_target_bb);
3791
3792              mono_add_patch_info (cfg, offset,
3793                                   MONO_PATCH_INFO_BB,
3794                                   ins->inst_target_bb);
3795              alpha_bsr(code, alpha_ra, 0);
3796            }
3797            break;
3798
3799          case OP_THROW:
3800            CFG_DEBUG(4) g_print("ALPHA_CHECK: [throw] sreg1=%0x\n",
3801                                 ins->sreg1);
3802            alpha_mov1(code, ins->sreg1, alpha_a0);
3803            code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
3804                              (gpointer)"mono_arch_throw_exception");
3805            break;
3806
3807          case OP_RETHROW:
3808            CFG_DEBUG(4) g_print("ALPHA_CHECK: [rethrow] sreg1=%0x\n",
3809                                 ins->sreg1);
3810            alpha_mov1(code, ins->sreg1, alpha_a0);
3811            code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
3812                              (gpointer)"mono_arch_rethrow_exception");
3813            break;
3814
3815          case OP_JMP:
3816            {
3817              /*
3818               * Note: this 'frame destruction' logic is useful for tail calls,
3819               too. Keep in sync with the code in emit_epilog.
3820               */
3821              int offset;
3822              AlphaGotData ge_data;
3823
3824              CFG_DEBUG(4) g_print("ALPHA_CHECK: [jmp] %p\n", ins->inst_p0);
3825
3826              /* FIXME: no tracing support... */
3827              if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
3828                code = mono_arch_instrument_epilog (cfg,
3829                                    mono_profiler_method_leave, code, FALSE);
3830              g_assert (!cfg->method->save_lmf);
3831
3832              alpha_mov1( code, alpha_fp, alpha_sp );
3833
3834              code = emit_load_volatile_arguments (cfg, code);
3835
3836              offset = cfg->arch.params_stack_size;
3837
3838              alpha_ldq( code, alpha_ra, alpha_sp, (offset + 0) );
3839              alpha_ldq( code, alpha_fp, alpha_sp, (offset + 8) );
3840              alpha_lda( code, alpha_sp, alpha_sp, cfg->arch.stack_size );
3841
3842              ge_data.data.p = ins->inst_p0;
3843              add_got_entry(cfg, GT_PTR, ge_data,
3844                            (char *)code - (char *)cfg->native_code,
3845                            MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0);
3846              alpha_ldq( code, alpha_pv, alpha_gp, 0);
3847
3848              alpha_jsr( code, alpha_zero, alpha_pv, 0);
3849            }
3850            break;
3851
3852          case OP_AOTCONST:
3853            mono_add_patch_info (cfg, offset,
3854                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3855            break;
3856
3857          case OP_MEMORY_BARRIER:
3858            CFG_DEBUG(4) g_print("ALPHA_CHECK: [mb]\n");
3859            alpha_mb(code);
3860            break;
3861           
3862          case OP_CKFINITE:
3863            // Float register contains a value which we need to check
3864            {
3865                 double  ni = -1.0 / 0.0;
3866                 double  pi = 1.0 / 0.0;
3867                 AlphaGotData    ge_data;
3868
3869                 CFG_DEBUG(4) g_print("ALPHA_TODO: [chfinite] sreg1=%d\n", ins->sreg1);
3870                 alpha_cmptun_su(code, ins->sreg1, ins->sreg1, alpha_at);
3871                 alpha_trapb(code);
3872                 EMIT_COND_EXC_BRANCH(fbne, alpha_at, "ArithmeticException");
3873
3874                 // Negative infinity
3875                 ge_data.data.d = ni;
3876                 add_got_entry(cfg, GT_DOUBLE, ge_data,
3877                            (char *)code - (char *)cfg->native_code,
3878                            MONO_PATCH_INFO_NONE, 0);
3879                 alpha_ldt(code, alpha_at, alpha_gp, 0);
3880
3881                 alpha_cmpteq_su(code, ins->sreg1, alpha_at, alpha_at);
3882                 alpha_trapb(code);
3883
3884                 EMIT_COND_EXC_BRANCH(fbne, alpha_at, "ArithmeticException");
3885
3886                 // Positive infinity
3887                 ge_data.data.d = pi;
3888                 add_got_entry(cfg, GT_DOUBLE, ge_data,
3889                            (char *)code - (char *)cfg->native_code,
3890                            MONO_PATCH_INFO_NONE, 0);
3891                 alpha_ldt(code, alpha_at, alpha_gp, 0);
3892
3893                 alpha_cmpteq_su(code, ins->sreg1, alpha_at, alpha_at);
3894                 alpha_trapb(code);
3895
3896                 EMIT_COND_EXC_BRANCH(fbne, alpha_at, "ArithmeticException");
3897            }
3898            break;
3899          case OP_FDIV:
3900            CFG_DEBUG(4) g_print("ALPHA_TODO: [fdiv] dest=%d, sreg1=%d, sreg2=%d\n",
3901                 ins->dreg, ins->sreg1, ins->sreg2);
3902            alpha_divt_su(code, ins->sreg1, ins->sreg2, ins->dreg);
3903            alpha_trapb(code);
3904
3905            break;
3906          default:
3907            g_warning ("unknown opcode %s in %s()\n",
3908                       mono_inst_name (ins->opcode), __FUNCTION__);
3909            alpha_nop(code);
3910            //            g_assert_not_reached ();
3911            
3912          }
3913        
3914        if ( (((char *)code) -
3915              ((char *)cfg->native_code) -
3916              offset) > max_len)
3917          {
3918            g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
3919                       mono_inst_name (ins->opcode), max_len,
3920                       ((char *)code) - ((char *)cfg->native_code) - offset );
3921            //g_assert_not_reached ();
3922          }
3923        
3924        cpos += max_len;
3925        
3926        last_offset = offset;
3927      }
3928    
3929    cfg->code_len = ((char *)code) - ((char *)cfg->native_code);
3930 }
3931
3932 /*========================= End of Function ========================*/
3933
3934
3935
3936
3937 /*------------------------------------------------------------------*/
3938 /*                                                                  */
3939 /* Name         - mono_arch_cpu_optimizazions                       */
3940 /*                                                                  */
3941 /* Function     - Returns the optimizations supported on this CPU   */
3942 /*                                                                  */
3943 /*------------------------------------------------------------------*/
3944
3945 guint32
3946 mono_arch_cpu_optimizazions (guint32 *exclude_mask)
3947 {
3948    guint32 opts = 0;
3949
3950    if (getenv("MONO_ALPHA_DEBUG"))
3951         mini_alpha_verbose_level = 1;
3952    
3953    ALPHA_DEBUG("mono_arch_cpu_optimizazions");
3954    
3955    /*----------------------------------------------------------*/
3956    /* no alpha-specific optimizations yet                       */
3957    /*----------------------------------------------------------*/
3958    *exclude_mask = MONO_OPT_LINEARS;
3959    //      *exclude_mask = MONO_OPT_INLINE|MONO_OPT_INLINE;
3960
3961    return opts;
3962 }
3963 /*========================= End of Function ========================*/
3964
3965 /*------------------------------------------------------------------*/
3966 /*                                                                  */
3967 /* Name         -  mono_arch_flush_icache                           */
3968 /*                                                                  */
3969 /* Function     -  Flush the CPU icache.                            */
3970 /*                                                                  */
3971 /*------------------------------------------------------------------*/
3972
3973 void
3974 mono_arch_flush_icache (guint8 *code, gint size)
3975 {
3976   //ALPHA_DEBUG("mono_arch_flush_icache");
3977    
3978    /* flush instruction cache to see trampoline code */
3979    asm volatile("imb":::"memory");
3980 }
3981
3982 /*========================= End of Function ========================*/
3983
3984 /*------------------------------------------------------------------*/
3985 /*                                                                  */
3986 /* Name         - mono_arch_regname                                 */
3987 /*                                                                  */
3988 /* Function     - Returns the name of the register specified by     */
3989 /*                the input parameter.                              */
3990 /*                                                                  */
3991 /*------------------------------------------------------------------*/
3992
3993 const char*
3994 mono_arch_regname (int reg) {
3995   static const char * rnames[] = {
3996     "alpha_r0", "alpha_r1", "alpha_r2", "alpha_r3", "alpha_r4",
3997     "alpha_r5", "alpha_r6", "alpha_r7", "alpha_r8", "alpha_r9",
3998     "alpha_r10", "alpha_r11", "alpha_r12", "alpha_r13", "alpha_r14",
3999     "alpha_r15", "alpha_r16", "alpha_r17", "alpha_r18", "alpha_r19",
4000     "alpha_r20", "alpha_r21", "alpha_r22", "alpha_r23", "alpha_r24",
4001     "alpha_r25", "alpha_r26", "alpha_r27", "alpha_r28", "alpha_r29",
4002     "alpha_r30", "alpha_r31"
4003   };
4004    
4005   if (reg >= 0 && reg < 32)
4006     return rnames [reg];
4007    else
4008      return "unknown";
4009 }
4010 /*========================= End of Function ========================*/
4011
4012 /*------------------------------------------------------------------*/
4013 /*                                                                  */
4014 /* Name         - mono_arch_fregname                                */
4015 /*                                                                  */
4016 /* Function     - Returns the name of the register specified by     */
4017 /*                the input parameter.                              */
4018 /*                                                                  */
4019 /*------------------------------------------------------------------*/
4020
4021 const char*
4022 mono_arch_fregname (int reg) {
4023   static const char * rnames[] = {
4024     "alpha_f0", "alpha_f1", "alpha_f2", "alpha_f3", "alpha_f4",
4025     "alpha_f5", "alpha_f6", "alpha_f7", "alpha_f8", "alpha_f9",
4026     "alpha_f10", "alpha_f11", "alpha_f12", "alpha_f13", "alpha_f14",
4027     "alpha_f15", "alpha_f16", "alpha_f17", "alpha_f18", "alpha_f19",
4028     "alpha_f20", "alpha_f21", "alpha_f22", "alpha_f23", "alpha_f24",
4029     "alpha_f25", "alpha_f26", "alpha_f27", "alpha_f28", "alpha_f29",
4030     "alpha_f30", "alpha_f31"
4031   };
4032    
4033   if (reg >= 0 && reg < 32)
4034     return rnames [reg];
4035   else
4036     return "unknown";
4037 }
4038
4039 /*========================= End of Function ========================*/
4040
4041 /*------------------------------------------------------------------*/
4042 /*                                                                  */
4043 /* Name         - mono_arch_patch_code                              */
4044 /*                                                                  */
4045 /* Function     - Process the patch data created during the         */
4046 /*                instruction build process. This resolves jumps,   */
4047 /*                calls, variables etc.                             */
4048 /*                                                                  */
4049 /*------------------------------------------------------------------*/
4050
4051 void
4052 mono_arch_patch_code (MonoMethod *method, MonoDomain *domain,
4053                       guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
4054 {
4055   MonoJumpInfo *patch_info;
4056   gboolean compile_aot = !run_cctors;
4057
4058   ALPHA_DEBUG("mono_arch_patch_code");
4059    
4060   for (patch_info = ji; patch_info; patch_info = patch_info->next) 
4061     {   
4062       unsigned char *ip = patch_info->ip.i + code;
4063       const unsigned char *target;
4064                 
4065       target = mono_resolve_patch_target (method, domain,
4066                                           code, patch_info, run_cctors);
4067                 
4068       if (compile_aot) 
4069         {
4070           switch (patch_info->type) 
4071             {
4072                                   
4073             case MONO_PATCH_INFO_BB:
4074             case MONO_PATCH_INFO_LABEL:
4075               break;
4076             default:
4077               /* No need to patch these */
4078               continue;
4079             }
4080         }
4081                 
4082       switch (patch_info->type) 
4083         {        
4084         case MONO_PATCH_INFO_NONE:
4085           continue;
4086
4087         case MONO_PATCH_INFO_GOT_OFFSET:
4088           {
4089             unsigned int *ip2 = (unsigned int *)ip;
4090             unsigned int inst = *ip2;
4091             unsigned int off = patch_info->data.offset & 0xFFFFFFFF;
4092
4093             g_assert(!(off & 0xFFFF8000));
4094
4095             inst |= off;
4096
4097             *ip2 = inst;
4098           }
4099           continue;
4100
4101         case MONO_PATCH_INFO_CLASS_INIT: 
4102           {               
4103             /* Might already been changed to a nop */
4104             unsigned int* ip2 = (unsigned int *)ip;
4105            unsigned long t_addr = (unsigned long)target;
4106  
4107             if (*ip2 != (t_addr & 0xFFFFFFFF) ||
4108                 *(ip2+1) != ((t_addr>>32) & 0xFFFFFFFF))
4109                         NOT_IMPLEMENTED;
4110             //  amd64_call_code (ip2, 0);
4111             break;
4112           }
4113                          
4114           //    case MONO_PATCH_INFO_METHOD_REL:
4115         case MONO_PATCH_INFO_R8:
4116         case MONO_PATCH_INFO_R4:
4117           g_assert_not_reached ();
4118           continue;
4119         case MONO_PATCH_INFO_BB:
4120           break;
4121
4122         case MONO_PATCH_INFO_METHOD:
4123         case MONO_PATCH_INFO_METHODCONST:
4124         case MONO_PATCH_INFO_INTERNAL_METHOD:
4125         case MONO_PATCH_INFO_METHOD_JUMP:
4126           {
4127             volatile unsigned int *p = (unsigned int *)ip;
4128             unsigned long t_addr;
4129
4130             t_addr = *(p+1);
4131             t_addr <<= 32;
4132             t_addr |= *(p);
4133
4134             ALPHA_PRINT
4135             g_debug("ALPHA_PATCH: MONO_PATCH_INFO_METHOD(CONST) calc target: %p, stored target: %0lX",
4136                    target, t_addr);
4137             if (target != ((void *)t_addr))
4138               {
4139                 t_addr = (unsigned long)target;
4140                 *p = (unsigned int)(t_addr & 0xFFFFFFFF);
4141                 *(p+1) = (unsigned int)((t_addr >> 32) & 0xFFFFFFFF);
4142               }
4143           }
4144           continue;
4145
4146         case MONO_PATCH_INFO_ABS:
4147           {
4148             volatile unsigned int *p = (unsigned int *)ip;
4149             unsigned long t_addr;
4150
4151             t_addr = *(p+1);
4152             t_addr <<= 32;
4153             t_addr += *(p);
4154
4155             ALPHA_PRINT g_debug("ALPHA_PATCH: MONO_PATCH_INFO_ABS calc target: %p, stored target: %0lX",
4156                    target, t_addr);
4157
4158           }
4159           continue;
4160         case MONO_PATCH_INFO_SWITCH:
4161           {
4162             unsigned int *pcode = (unsigned int *)ip;
4163             unsigned long t_addr;
4164
4165             t_addr = (unsigned long)target;
4166
4167             if (((unsigned long)ip) % 8)
4168               {
4169                 alpha_nop(pcode);
4170                 ip += 4;
4171               }
4172             
4173             //alpha_ldq(pcode, alpha_at, alpha_gp, (ip - code + 8));
4174             alpha_nop(pcode);        // TODO optimize later
4175             alpha_bsr(pcode, alpha_at, 2);
4176
4177             *pcode = (unsigned int)(t_addr & 0xFFFFFFFF);
4178             pcode++;
4179             *pcode = (unsigned int)((t_addr >> 32) & 0xFFFFFFFF);
4180             pcode++;
4181
4182             alpha_ldq(pcode, alpha_at, alpha_at, 0);
4183
4184           }
4185           continue;
4186
4187         default:
4188           break;
4189         }
4190       
4191       {
4192         volatile unsigned int *p = (unsigned int *)ip;
4193         unsigned int alpha_ins = *p;
4194         unsigned int opcode;
4195         long br_offset;
4196                          
4197         opcode = (alpha_ins >> AXP_OP_SHIFT) & AXP_OFF6_MASK;
4198                          
4199         if (opcode >= 0x30 && opcode <= 0x3f)
4200           {
4201             // This is branch with offset instruction
4202             br_offset = (target - ip - 4);
4203                                   
4204             g_assert(!(br_offset & 3));
4205                                   
4206             alpha_ins |= (br_offset/4) & AXP_OFF21_MASK;
4207                                   
4208             *p = alpha_ins;
4209           }
4210       }
4211     }
4212 }
4213
4214 /*========================= End of Function ========================*/
4215 /*------------------------------------------------------------------*/
4216 /*                                                                  */
4217 /* Name         - mono_arch_emit_this_vret_args                     */
4218 /*                                                                  */
4219 /* Function     -                                                   */
4220 /*                                                                  */
4221 /*------------------------------------------------------------------*/
4222
4223 void
4224 mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst,
4225         int this_reg, int this_type, int vt_reg)
4226 {
4227   MonoCallInst *call = (MonoCallInst*)inst;
4228   CallInfo * cinfo = get_call_info (cfg->generic_sharing_context, inst->signature, FALSE);
4229
4230   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_emit_this_vret_args");
4231
4232   if (vt_reg != -1)
4233     {
4234       MonoInst *vtarg;
4235
4236       if (cinfo->ret.storage == ArgValuetypeInReg)
4237         {
4238           /*
4239            * The valuetype is in RAX:RDX after the call, need to be copied to
4240            * the stack. Push the address here, so the call instruction can
4241            * access it.
4242            */
4243           //MONO_INST_NEW (cfg, vtarg, OP_X86_PUSH);
4244           //vtarg->sreg1 = vt_reg;
4245           //mono_bblock_add_inst (cfg->cbb, vtarg);
4246
4247           /* Align stack */
4248           //MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_E
4249           //                       SP, 8);
4250         }
4251       else
4252         {
4253           MONO_INST_NEW (cfg, vtarg, OP_MOVE);
4254           vtarg->sreg1 = vt_reg;
4255           vtarg->dreg = mono_regstate_next_int (cfg->rs);
4256           mono_bblock_add_inst (cfg->cbb, vtarg);
4257
4258           mono_call_inst_add_outarg_reg (cfg, call, vtarg->dreg,
4259                                          cinfo->ret.reg, FALSE);
4260         }
4261     }
4262
4263   /* add the this argument */
4264   if (this_reg != -1)
4265     {
4266       MonoInst *this;
4267       MONO_INST_NEW (cfg, this, OP_MOVE);
4268       this->type = this_type;
4269       this->sreg1 = this_reg;
4270       this->dreg = mono_regstate_next_int (cfg->rs);
4271       mono_bblock_add_inst (cfg->cbb, this);
4272
4273       mono_call_inst_add_outarg_reg (cfg, call, this->dreg,
4274                                      cinfo->args [0].reg, FALSE);
4275     }
4276
4277   g_free (cinfo);
4278 }
4279
4280 /*========================= End of Function ========================*/
4281
4282 /*------------------------------------------------------------------*/
4283 /*                                                                  */
4284 /* Name         - mono_arch_is_inst_imm                             */
4285 /*                                                                  */
4286 /* Function     - Determine if operand qualifies as an immediate    */
4287 /*                value. For Alpha this is a value 0 - 255          */
4288 /*                                                                  */
4289 /* Returns      - True|False - is [not] immediate value.            */
4290 /*                                                                  */
4291 /*------------------------------------------------------------------*/
4292
4293 gboolean
4294 mono_arch_is_inst_imm (gint64 imm)
4295 {
4296 //   ALPHA_DEBUG("mono_arch_is_inst_imm");
4297         
4298    return (imm & ~(0x0FFL)) ? 0 : 1;
4299 }
4300
4301 /*------------------------------------------------------------------*/
4302 /*                                                                  */
4303 /* Name         - mono_arch_setup_jit_tls_data                      */
4304 /*                                                                  */
4305 /* Function     - Setup the JIT's Thread Level Specific Data.       */
4306 /*                                                                  */
4307 /*------------------------------------------------------------------*/
4308
4309 void
4310 mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
4311 {
4312    ALPHA_DEBUG("mono_arch_setup_jit_tls_data");
4313    
4314    if (!tls_offset_inited) {
4315           tls_offset_inited = TRUE;
4316    }
4317    
4318    if (!lmf_addr_key_inited) {
4319           lmf_addr_key_inited = TRUE;
4320           pthread_key_create (&lmf_addr_key, NULL);
4321    }
4322
4323    pthread_setspecific (lmf_addr_key, &tls->lmf);
4324 }
4325
4326 /*------------------------------------------------------------------*/
4327 /*                                                                  */
4328 /* Name         - mono_arch_cpu_init                                */
4329 /*                                                                  */
4330 /* Function     - Perform CPU specific initialization to execute    */
4331 /*                managed code.                                     */
4332 /*                                                                  */
4333 /*------------------------------------------------------------------*/
4334
4335 void
4336 mono_arch_cpu_init (void)
4337 {
4338   unsigned long amask, implver;
4339   register long v0 __asm__("$0") = -1;
4340  
4341   ALPHA_DEBUG("mono_arch_cpu_init");
4342
4343   __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
4344   amask = ~v0;
4345   __asm__ (".long 0x47e03d80" : "=r"(v0));
4346   implver = v0;
4347
4348   if (amask & 1)
4349     bwx_supported = 1;
4350
4351   //printf("amask: %x, implver: %x", amask, implver);
4352 }
4353
4354 /*
4355  * Initialize architecture specific code.
4356  */
4357 void
4358 mono_arch_init (void)
4359 {
4360 }
4361
4362 /*
4363  * Cleanup architecture specific code.
4364  */
4365 void
4366 mono_arch_cleanup (void)
4367 {
4368 }
4369
4370 /*
4371  * get_call_info:
4372  *
4373  * Obtain information about a call according to the calling convention.
4374  *
4375  * For x86 ELF, see the "System V Application Binary Interface Intel386
4376  * Architecture Processor Supplment, Fourth Edition" document for more
4377  * information.
4378  * For x86 win32, see ???.
4379  */
4380 static CallInfo*
4381 get_call_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke)
4382 {
4383    guint32 i, gr, fr, *pgr, *pfr;
4384    MonoType *ret_type;
4385    int n = sig->hasthis + sig->param_count;
4386    guint32 stack_size = 0;
4387    CallInfo *cinfo;
4388    
4389    cinfo = g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
4390    
4391    gr = 0;
4392    fr = 0;
4393    
4394    if (is_pinvoke)
4395         pgr = pfr = &gr;
4396    else
4397    {
4398         pgr = &gr;
4399         pfr = &fr;
4400    }
4401
4402    /* return value */
4403    {
4404      ret_type = mono_type_get_underlying_type (sig->ret);
4405      switch (ret_type->type) {
4406      case MONO_TYPE_BOOLEAN:
4407      case MONO_TYPE_I1:
4408      case MONO_TYPE_U1:
4409      case MONO_TYPE_I2:
4410      case MONO_TYPE_U2:
4411      case MONO_TYPE_CHAR:
4412      case MONO_TYPE_I4:
4413      case MONO_TYPE_U4:
4414      case MONO_TYPE_I:
4415      case MONO_TYPE_U:
4416      case MONO_TYPE_PTR:
4417      case MONO_TYPE_FNPTR:
4418      case MONO_TYPE_CLASS:
4419      case MONO_TYPE_OBJECT:
4420      case MONO_TYPE_SZARRAY:
4421      case MONO_TYPE_ARRAY:
4422      case MONO_TYPE_STRING:
4423        cinfo->ret.storage = ArgInIReg;
4424        cinfo->ret.reg = alpha_r0;
4425        break;
4426      case MONO_TYPE_U8:
4427      case MONO_TYPE_I8:
4428        cinfo->ret.storage = ArgInIReg;
4429        cinfo->ret.reg = alpha_r0;
4430        break;
4431      case MONO_TYPE_R4:
4432        cinfo->ret.storage = ArgInFloatReg;
4433        cinfo->ret.reg = alpha_f0;
4434        break;
4435      case MONO_TYPE_R8:
4436        cinfo->ret.storage = ArgInDoubleReg;
4437        cinfo->ret.reg = alpha_f0;
4438        break;
4439      case MONO_TYPE_GENERICINST:
4440        if (!mono_type_generic_inst_is_valuetype (sig->ret))
4441          {
4442            cinfo->ret.storage = ArgInIReg;
4443            cinfo->ret.reg = alpha_r0;
4444            break;
4445          }
4446        /* Fall through */
4447      case MONO_TYPE_VALUETYPE:
4448        {
4449          guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
4450                         
4451          add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE,
4452                         &tmp_gr, &tmp_fr, &tmp_stacksize);
4453          
4454          if (cinfo->ret.storage == ArgOnStack)
4455            /* The caller passes the address where the value
4456               is stored */
4457            add_general (pgr, &stack_size, &cinfo->ret);
4458          break;
4459        }
4460      case MONO_TYPE_TYPEDBYREF:
4461        /* Same as a valuetype with size 24 */
4462        add_general (pgr, &stack_size, &cinfo->ret);
4463        ;
4464        break;
4465      case MONO_TYPE_VOID:
4466        break;
4467      default:
4468        g_error ("Can't handle as return value 0x%x", sig->ret->type);
4469      }
4470    }
4471    
4472    /* this */
4473    if (sig->hasthis)
4474      add_general (pgr, &stack_size, cinfo->args + 0);
4475    
4476    if (!sig->pinvoke &&
4477            (sig->call_convention == MONO_CALL_VARARG) && (n == 0))
4478      {
4479        gr = PARAM_REGS;
4480        fr = FLOAT_PARAM_REGS;
4481                 
4482        /* Emit the signature cookie just before the implicit arguments
4483         */
4484        add_general (pgr, &stack_size, &cinfo->sig_cookie);
4485      }
4486    
4487    for (i = 0; i < sig->param_count; ++i)
4488      {
4489        ArgInfo *ainfo = &cinfo->args [sig->hasthis + i];
4490        MonoType *ptype;
4491        
4492        if (!sig->pinvoke &&
4493            (sig->call_convention == MONO_CALL_VARARG) &&
4494            (i == sig->sentinelpos))
4495          {
4496            /* We allways pass the sig cookie on the stack for simpl
4497               icity */
4498            /*
4499             * Prevent implicit arguments + the sig cookie from being passed
4500             * in registers.
4501             */
4502            gr = PARAM_REGS;
4503            fr = FLOAT_PARAM_REGS;
4504                          
4505            /* Emit the signature cookie just before the implicit arguments */
4506            add_general (pgr, &stack_size, &cinfo->sig_cookie);
4507          }
4508                 
4509        if (sig->params [i]->byref) {
4510          add_general (pgr, &stack_size, ainfo);
4511          continue;
4512        }
4513        
4514        ptype = mono_type_get_underlying_type (sig->params [i]);
4515        
4516        switch (ptype->type) {
4517        case MONO_TYPE_BOOLEAN:
4518        case MONO_TYPE_I1:
4519        case MONO_TYPE_U1:
4520          add_general (pgr, &stack_size, ainfo);
4521          break;
4522        case MONO_TYPE_I2:
4523        case MONO_TYPE_U2:
4524        case MONO_TYPE_CHAR:
4525          add_general (pgr, &stack_size, ainfo);
4526          break;
4527        case MONO_TYPE_I4:
4528        case MONO_TYPE_U4:
4529          add_general (pgr, &stack_size, ainfo);
4530          break;
4531        case MONO_TYPE_I:
4532        case MONO_TYPE_U:
4533        case MONO_TYPE_PTR:
4534        case MONO_TYPE_FNPTR:
4535        case MONO_TYPE_CLASS:
4536        case MONO_TYPE_OBJECT:
4537        case MONO_TYPE_STRING:
4538        case MONO_TYPE_SZARRAY:
4539        case MONO_TYPE_ARRAY:
4540          add_general (pgr, &stack_size, ainfo);
4541          break;
4542        case MONO_TYPE_GENERICINST:
4543          if (!mono_type_generic_inst_is_valuetype (sig->params [i]))
4544            {
4545              add_general (pgr, &stack_size, ainfo);
4546              break;
4547            }
4548          /* Fall through */
4549        case MONO_TYPE_VALUETYPE:
4550          /* FIXME: */
4551          /* We allways pass valuetypes on the stack */
4552          add_valuetype (gsctx, sig, ainfo, sig->params [i],
4553                         FALSE, pgr, pfr, &stack_size);
4554          break;
4555        case MONO_TYPE_TYPEDBYREF:
4556          stack_size += sizeof (MonoTypedRef);
4557          ainfo->storage = ArgOnStack;
4558          break;
4559        case MONO_TYPE_U8:
4560        case MONO_TYPE_I8:
4561          add_general (pgr, &stack_size, ainfo);
4562          break;
4563        case MONO_TYPE_R4:
4564          add_float (pfr, &stack_size, ainfo, FALSE);
4565          break;
4566        case MONO_TYPE_R8:
4567          add_float (pfr, &stack_size, ainfo, TRUE);
4568          break;
4569        default:
4570          g_assert_not_reached ();
4571        }
4572      }
4573    
4574    if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) &&
4575        (n > 0) && (sig->sentinelpos == sig->param_count))
4576      {
4577        gr = PARAM_REGS;
4578        fr = FLOAT_PARAM_REGS;
4579                 
4580        /* Emit the signature cookie just before the implicit arguments
4581         */
4582        add_general (pgr, &stack_size, &cinfo->sig_cookie);
4583      }
4584    
4585    cinfo->stack_usage = stack_size;
4586    cinfo->reg_usage = gr;
4587    cinfo->freg_usage = fr;
4588    
4589    return cinfo;
4590 }
4591
4592 static const char *CvtMonoType(MonoTypeEnum t)
4593 {
4594   switch(t)
4595     {
4596     case MONO_TYPE_END:
4597       return "MONO_TYPE_END";
4598     case MONO_TYPE_VOID:
4599       return "MONO_TYPE_VOID";
4600     case MONO_TYPE_BOOLEAN:
4601       return "MONO_TYPE_BOOLEAN";
4602     case MONO_TYPE_CHAR:
4603       return "MONO_TYPE_CHAR";
4604     case MONO_TYPE_I1:
4605       return "MONO_TYPE_I1";
4606     case MONO_TYPE_U1:
4607       return "MONO_TYPE_U1";
4608     case MONO_TYPE_I2:
4609       return "MONO_TYPE_I2";
4610     case MONO_TYPE_U2:
4611       return "MONO_TYPE_U2";
4612     case MONO_TYPE_I4:
4613       return "MONO_TYPE_I4";
4614     case MONO_TYPE_U4:
4615       return "MONO_TYPE_U4";
4616     case MONO_TYPE_I8:
4617       return "MONO_TYPE_I8";
4618     case MONO_TYPE_U8:
4619       return "MONO_TYPE_U8";
4620     case MONO_TYPE_R4:
4621       return "MONO_TYPE_R4";
4622     case MONO_TYPE_R8:
4623       return "MONO_TYPE_R8";
4624     case MONO_TYPE_STRING:
4625       return "MONO_TYPE_STRING";
4626     case MONO_TYPE_PTR:
4627       return "MONO_TYPE_PTR";
4628     case MONO_TYPE_BYREF:
4629       return "MONO_TYPE_BYREF";
4630     case MONO_TYPE_VALUETYPE:
4631       return "MONO_TYPE_VALUETYPE";
4632     case MONO_TYPE_CLASS:
4633       return "MONO_TYPE_CLASS";
4634     case MONO_TYPE_VAR:
4635       return "MONO_TYPE_VAR";
4636     case MONO_TYPE_ARRAY:
4637       return "MONO_TYPE_ARRAY";
4638     case MONO_TYPE_GENERICINST:
4639       return "MONO_TYPE_GENERICINST";
4640     case MONO_TYPE_TYPEDBYREF:
4641       return "MONO_TYPE_TYPEDBYREF";
4642     case MONO_TYPE_I:
4643       return "MONO_TYPE_I";
4644     case MONO_TYPE_U:
4645       return "MONO_TYPE_U";
4646     case MONO_TYPE_FNPTR:
4647       return "MONO_TYPE_FNPTR";
4648     case MONO_TYPE_OBJECT:
4649       return "MONO_TYPE_OBJECT";
4650     case MONO_TYPE_SZARRAY:
4651       return "MONO_TYPE_SZARRAY";
4652     case MONO_TYPE_MVAR:
4653       return "MONO_TYPE_MVAR";
4654     case MONO_TYPE_CMOD_REQD:
4655       return "MONO_TYPE_CMOD_REQD";
4656     case MONO_TYPE_CMOD_OPT:
4657       return "MONO_TYPE_CMOD_OPT";
4658     case MONO_TYPE_INTERNAL:
4659       return "MONO_TYPE_INTERNAL";
4660     case MONO_TYPE_MODIFIER:
4661       return "MONO_TYPE_MODIFIER";
4662     case MONO_TYPE_SENTINEL:
4663       return "MONO_TYPE_SENTINEL";
4664     case MONO_TYPE_PINNED:
4665       return "MONO_TYPE_PINNED";
4666     default:
4667       ;
4668     }
4669   return "unknown";
4670 }
4671
4672
4673 /*------------------------------------------------------------------*/
4674 /*                                                                  */
4675 /* Name         - mono_arch_call_opcode                             */
4676 /*                                                                  */
4677 /* Function     - Take the arguments and generate the arch-specific */
4678 /*                instructions to properly call the function. This  */
4679 /*                includes pushing, moving argments to the correct  */
4680 /*                etc.                                              */
4681 /*
4682  * This method is called during converting method to IR
4683  * We need to generate IR ints to follow calling convention
4684  *  cfg - points to currently compiled unit
4685  *  bb - ???
4686  *  call - points to structure that describes what we are going to
4687  *         call (at least number of parameters required for the call)
4688  *
4689  * 
4690  * On return we need to pass back modified call structure
4691  */
4692 /*------------------------------------------------------------------*/
4693
4694 MonoCallInst*
4695 mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb,
4696                        MonoCallInst *call, int is_virtual)
4697 {
4698    MonoInst *arg, *in;
4699    MonoMethodSignature *sig;
4700    int i, n;
4701    CallInfo *cinfo;
4702    int sentinelpos;
4703    
4704    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_call_opcode");
4705    
4706    sig = call->signature;
4707    n = sig->param_count + sig->hasthis;
4708
4709    // Collect info about method we age going to call
4710    cinfo = get_call_info (cfg->generic_sharing_context, sig, sig->pinvoke);
4711
4712    CFG_DEBUG(3) g_print("ALPHA: Will call %s method with %d(%d) params. RetType: %s(0x%X)\n",
4713                         sig->pinvoke ? "PInvoke" : "Managed",
4714                         sig->param_count, sig->hasthis,
4715                         CvtMonoType(sig->ret->type), sig->ret->type);
4716   
4717    if (cinfo->stack_usage > cfg->arch.params_stack_size)
4718         cfg->arch.params_stack_size = cinfo->stack_usage;
4719  
4720    if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG))
4721          sentinelpos = sig->sentinelpos + (is_virtual ? 1 : 0);
4722     
4723    for (i = 0; i < n; ++i)
4724      {
4725        ArgInfo *ainfo = cinfo->args + i;
4726                 
4727        /* Emit the signature cookie just before the implicit arguments
4728         */
4729        if (!sig->pinvoke &&
4730            (sig->call_convention == MONO_CALL_VARARG) &&
4731            (i == sentinelpos))
4732          {
4733            MonoMethodSignature *tmp_sig;
4734            MonoInst *sig_arg;
4735                          
4736            /* FIXME: Add support for signature tokens to AOT */
4737            cfg->disable_aot = TRUE;
4738            MONO_INST_NEW (cfg, arg, OP_OUTARG);
4739                          
4740            /*
4741             * mono_ArgIterator_Setup assumes the signature cookie is
4742             * passed first and all the arguments which were before it are
4743             * passed on the stack after the signature. So compensate by
4744             * passing a different signature.
4745             */
4746            tmp_sig = mono_metadata_signature_dup (call->signature);
4747            tmp_sig->param_count -= call->signature->sentinelpos;
4748            tmp_sig->sentinelpos = 0;
4749            memcpy (tmp_sig->params,
4750                    call->signature->params + call->signature->sentinelpos,
4751                    tmp_sig->param_count * sizeof (MonoType*));
4752            
4753            MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
4754            sig_arg->inst_p0 = tmp_sig;
4755            
4756            MONO_INST_NEW (cfg, arg, OP_OUTARG);
4757            arg->inst_left = sig_arg;
4758            arg->type = STACK_PTR;
4759            MONO_INST_LIST_ADD (&arg->node, &call->out_args);
4760          }
4761                 
4762        if (is_virtual && i == 0) {
4763          /* the argument will be attached to the call instrucion
4764           */
4765          in = call->args [i];
4766        } else {
4767          MonoType *arg_type;
4768
4769          MONO_INST_NEW (cfg, arg, OP_OUTARG);
4770          in = call->args [i];
4771          arg->cil_code = in->cil_code;
4772          arg->inst_left = in;
4773          arg->type = in->type;
4774          MONO_INST_LIST_ADD (&arg->node, &call->out_args);
4775
4776          CFG_DEBUG(3) g_print("ALPHA: Param[%d] - ", i);
4777
4778          if (sig->hasthis && (i == 0))
4779            arg_type = &mono_defaults.object_class->byval_arg;
4780          else
4781            arg_type = sig->params [i - sig->hasthis];
4782          
4783          if ((i >= sig->hasthis) &&
4784              (MONO_TYPE_ISSTRUCT(arg_type)))
4785            {
4786              guint align;
4787              guint32 size;
4788              
4789              if (arg_type->type == MONO_TYPE_TYPEDBYREF) {
4790                size = sizeof (MonoTypedRef);
4791                align = sizeof (gpointer);
4792              }
4793              else
4794                if (sig->pinvoke)
4795                  size = mono_type_native_stack_size (&in->klass->byval_arg,
4796                                                      &align);
4797                else
4798                  size = mini_type_stack_size (cfg->generic_sharing_context, &in->klass->byval_arg, &align);
4799
4800              if (ainfo->storage == ArgAggregate)
4801                {
4802                  MonoInst *vtaddr, *load, *load2, *offset_ins, *set_reg;
4803                  int slot, j;
4804
4805                  CFG_DEBUG(3) g_print("aggregate value type, size:%d\n", size);
4806
4807                  vtaddr = mono_compile_create_var (cfg,
4808                               &mono_defaults.int_class->byval_arg, OP_LOCAL);
4809
4810                  /*
4811                   * Part of the structure is passed in registers.
4812                   */
4813                  for (j = 0; j < ainfo->nregs; ++j)
4814                    {
4815                      int offset, load_op, dest_reg, arg_storage;
4816
4817                      slot = ainfo->reg + j;
4818                      load_op = CEE_LDIND_I;
4819                      offset = j * 8;
4820                      dest_reg = ainfo->reg + j;
4821                      arg_storage = ArgInIReg;
4822                      
4823                      MONO_INST_NEW (cfg, load, CEE_LDIND_I);
4824                      load->ssa_op = MONO_SSA_LOAD;
4825                      load->inst_i0 = (cfg)->varinfo [vtaddr->inst_c0];
4826
4827                      NEW_ICONST (cfg, offset_ins, offset);
4828                      MONO_INST_NEW (cfg, load2, CEE_ADD);
4829                      load2->inst_left = load;
4830                      load2->inst_right = offset_ins;
4831
4832                      MONO_INST_NEW (cfg, load, load_op);
4833                      load->inst_left = load2;
4834
4835                      if (j == 0)
4836                        set_reg = arg;
4837                      else
4838                        MONO_INST_NEW (cfg, set_reg, OP_OUTARG_REG);
4839
4840                      add_outarg_reg (cfg, call, set_reg, arg_storage,
4841                                      dest_reg, load);
4842                      if (&set_reg->node != call->out_args.next)
4843                        {
4844                          MONO_INST_LIST_ADD (&set_reg->node, &call->out_args);
4845                      }
4846                    }
4847
4848                  /*
4849                   * Part of the structure is passed on the stack.
4850                   */
4851                  for (j = ainfo->nregs; j < ainfo->nslots; ++j)
4852                    {
4853                      MonoInst *outarg;
4854
4855                      slot = ainfo->reg + j;
4856
4857                      MONO_INST_NEW (cfg, load, CEE_LDIND_I);
4858                      load->ssa_op = MONO_SSA_LOAD;
4859                      load->inst_i0 = (cfg)->varinfo [vtaddr->inst_c0];
4860
4861                      NEW_ICONST (cfg, offset_ins, (j * sizeof (gpointer)));
4862                      MONO_INST_NEW (cfg, load2, CEE_ADD);
4863                      load2->inst_left = load;
4864                      load2->inst_right = offset_ins;
4865
4866                      MONO_INST_NEW (cfg, load, CEE_LDIND_I);
4867                      load->inst_left = load2;
4868
4869                      if (j == 0)
4870                        outarg = arg;
4871                      else
4872                        MONO_INST_NEW (cfg, outarg, OP_OUTARG);
4873                      
4874                      outarg->inst_left = load;
4875                      //outarg->inst_imm = 16 + ainfo->offset + (slot - 8) * 8;
4876                      outarg->dreg = ainfo->offset + (slot - 22) * 8;
4877
4878                      if (&outarg->node != call->out_args.next)
4879                        {
4880                          MONO_INST_LIST_ADD (&outarg->node, &call->out_args);
4881                        }
4882                    }
4883                 
4884                  /* Trees can't be shared so make a copy*/
4885                  MONO_INST_NEW (cfg, arg, CEE_STIND_I);
4886                  arg->cil_code = in->cil_code;
4887                  arg->ssa_op = MONO_SSA_STORE;
4888                  arg->inst_left = vtaddr;
4889                  arg->inst_right = in;
4890                  arg->type = in->type;
4891                  MONO_INST_LIST_ADD (&arg->node, &call->out_args);
4892                }
4893              else
4894                {
4895                  MonoInst *stack_addr;
4896
4897                  CFG_DEBUG(3) g_print("value type, size:%d\n", size);
4898
4899                  MONO_INST_NEW (cfg, stack_addr, OP_REGOFFSET);
4900                  stack_addr->inst_basereg = alpha_sp;
4901                  //stack_addr->inst_offset = -(cinfo->stack_usage - ainfo->offset);
4902                  stack_addr->inst_offset = ainfo->offset;
4903                  //stack_addr->inst_offset = 16 + ainfo->offset;
4904                  stack_addr->inst_imm = size;
4905
4906                  arg->opcode = OP_OUTARG_VT;
4907                  arg->inst_right = stack_addr;
4908                }
4909
4910              /*
4911                arg->opcode = OP_OUTARG_VT;
4912                arg->klass = in->klass;
4913                arg->backend.is_pinvoke = sig->pinvoke;
4914                arg->inst_imm = size; */
4915            }
4916          else
4917            {
4918              CFG_DEBUG(3) g_print("simple\n");
4919
4920              switch (ainfo->storage)
4921                {
4922                case ArgInIReg:
4923                  add_outarg_reg (cfg, call, arg, ainfo->storage, 
4924                                  ainfo->reg, in);
4925                  break;
4926                case ArgOnStack:
4927                  arg->opcode = OP_OUTARG;
4928                  //arg->dreg = -((n - i) * 8);
4929                  arg->dreg = ainfo->offset;
4930                  //arg->inst_left->inst_imm = (n - i - 1) * 8;
4931
4932                  if (!sig->params[i-sig->hasthis]->byref) {
4933                    if (sig->params[i-sig->hasthis]->type == MONO_TYPE_R4)
4934                      arg->opcode = OP_OUTARG_R4;
4935                    else
4936                      if (sig->params[i-sig->hasthis]->type == MONO_TYPE_R8)
4937                        arg->opcode = OP_OUTARG_R8;
4938                  }
4939                  break;
4940                 case ArgInFloatReg:
4941                 case ArgInDoubleReg:
4942                   add_outarg_reg (cfg, call, arg, ainfo->storage, ainfo->reg, in);
4943                 break;
4944                default:
4945                  g_assert_not_reached ();
4946                }
4947            }
4948        }
4949      }
4950
4951    if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret))
4952      {
4953        if (cinfo->ret.storage == ArgValuetypeInReg) {
4954          MonoInst *zero_inst;
4955          /*
4956           * After the call, the struct is in registers, but needs to be saved
4957           to the memory pointed
4958           * to by vt_arg in this_vret_args. This means that vt_ar
4959           g needs to be saved somewhere
4960           * before calling the function. So we add a dummy instru
4961           ction to represent pushing the
4962           * struct return address to the stack. The return addres
4963           s will be saved to this stack slot
4964           * by the code emitted in this_vret_args.
4965           */
4966          MONO_INST_NEW (cfg, arg, OP_OUTARG);
4967          MONO_INST_NEW (cfg, zero_inst, OP_ICONST);
4968          zero_inst->inst_p0 = 0;
4969          arg->inst_left = zero_inst;
4970          arg->type = STACK_PTR;
4971          MONO_INST_LIST_ADD (&arg->node, &call->out_args);
4972        }
4973        else
4974          /* if the function returns a struct, the called method a
4975             lready does a ret $0x4 */
4976          if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret))
4977            ; //cinfo->stack_usage -= 4;
4978      }
4979    
4980    // stack_usage shows how much stack we would need to do the call
4981    // (for example for params that we pass on stack
4982    call->stack_usage = cinfo->stack_usage;
4983
4984    // Save all used regs to do the call in compile unit structure
4985    cfg->used_int_regs |= call->used_iregs;
4986    
4987    g_free (cinfo);
4988    
4989    return call;
4990 }
4991
4992 /*========================= End of Function ========================*/
4993
4994 /*------------------------------------------------------------------*/
4995 /*                                                                  */
4996 /* Name         - mono_arch_register_lowlevel_calls                 */
4997 /*                                                                  */
4998 /* Function     - Register routines to help with --trace operation. */
4999 /*                                                                  */
5000 /*------------------------------------------------------------------*/
5001
5002 void
5003 mono_arch_register_lowlevel_calls (void)
5004 {
5005    ALPHA_DEBUG("mono_arch_register_lowlevel_calls");
5006    
5007    mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr",
5008                                                         NULL, TRUE);
5009 }
5010
5011 /*========================= End of Function ========================*/
5012
5013 /*------------------------------------------------------------------*/
5014 /*                                                                  */
5015 /* Name         - mono_arch_global_int_regs                         */
5016 /*                                                                  */
5017 /* Function     - Return a list of usable integer registers.        */
5018 /*                                                                  */
5019 /*------------------------------------------------------------------*/
5020
5021 GList *
5022 mono_arch_get_global_int_regs (MonoCompile *cfg)
5023 {
5024    GList *regs = NULL;
5025    
5026    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_get_global_int_regs");
5027    
5028 //   regs = g_list_prepend (regs, (gpointer)alpha_r9);
5029 //   regs = g_list_prepend (regs, (gpointer)alpha_r10);
5030 //   regs = g_list_prepend (regs, (gpointer)alpha_r11);
5031    regs = g_list_prepend (regs, (gpointer)alpha_r12);
5032    regs = g_list_prepend (regs, (gpointer)alpha_r13);
5033    regs = g_list_prepend (regs, (gpointer)alpha_r14);
5034
5035    return regs;
5036 }
5037
5038 /*========================= End of Function ========================*/
5039
5040 /*------------------------------------------------------------------*/
5041 /*                                                                  */
5042 /* Name         - mono_arch_get_allocatable_int_vars                */
5043 /*                                                                  */
5044 /* Function     -                                                   */
5045 /*                                                                  */
5046 /*------------------------------------------------------------------*/
5047
5048 GList *
5049 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
5050 {
5051    GList *vars = NULL;
5052    int i;
5053    MonoMethodSignature *sig;
5054    MonoMethodHeader *header;
5055    CallInfo *cinfo;
5056
5057    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_get_allocatable_int_vars");
5058
5059    header = mono_method_get_header (cfg->method);
5060
5061    sig = mono_method_signature (cfg->method);
5062
5063    cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
5064
5065    for (i = 0; i < sig->param_count + sig->hasthis; ++i)
5066      {
5067        MonoInst *ins = cfg->args [i];
5068
5069        ArgInfo *ainfo = &cinfo->args [i];
5070
5071        if (ins->flags &
5072            (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT))
5073          continue;
5074
5075        // if (ainfo->storage == ArgInIReg) {
5076        //        /* The input registers are non-volatile */
5077        // ins->opcode = OP_REGVAR;
5078        //ins->dreg = 32 + ainfo->reg;
5079        //   }
5080      }
5081    
5082    for (i = 0; i < cfg->num_varinfo; i++)
5083      {
5084        MonoInst *ins = cfg->varinfo [i];
5085        MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
5086
5087        /* unused vars */
5088        if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
5089          continue;
5090
5091        if ((ins->flags &
5092             (MONO_INST_IS_DEAD|MONO_INST_VOLATILE|MONO_INST_INDIRECT)) ||
5093            (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
5094          continue;
5095
5096        if (mono_is_regsize_var (ins->inst_vtype))
5097          {
5098            g_assert (MONO_VARINFO (cfg, i)->reg == -1);
5099            g_assert (i == vmv->idx);
5100            vars = g_list_prepend (vars, vmv);
5101          }
5102      }
5103    
5104    vars = mono_varlist_sort (cfg, vars, 0);
5105
5106    return vars;
5107 }
5108
5109 /*========================= End of Function ========================*/
5110
5111 /*------------------------------------------------------------------*/
5112 /*                                                                  */
5113 /* Name         - mono_arch_get_domain_intrinsic                    */
5114 /*                                                                  */
5115 /* Function     -                                                   */
5116 /*                                                                  */
5117 /* Returns      -                                                   */
5118 /*                                                                  */
5119 /*------------------------------------------------------------------*/
5120
5121 MonoInst *
5122 mono_arch_get_domain_intrinsic (MonoCompile* cfg)
5123 {
5124    MonoInst *ins;
5125    
5126    if (appdomain_tls_offset == -1)
5127          return NULL;
5128    
5129    MONO_INST_NEW (cfg, ins, OP_TLS_GET);
5130    ins->inst_offset = appdomain_tls_offset;
5131    return (ins);
5132 }
5133
5134 /*========================= End of Function ========================*/
5135
5136 /*------------------------------------------------------------------*/
5137 /*                                                                  */
5138 /* Name         - mono_arch_get_thread_intrinsic                    */
5139 /*                                                                  */
5140 /* Function     -                                                   */
5141 /*                                                                  */
5142 /* Returns      -                                                   */
5143 /*                                                                  */
5144 /*------------------------------------------------------------------*/
5145
5146 MonoInst *
5147 mono_arch_get_thread_intrinsic (MonoCompile* cfg)
5148 {
5149    MonoInst *ins;
5150    
5151    if (thread_tls_offset == -1)
5152          return NULL;
5153    
5154    MONO_INST_NEW (cfg, ins, OP_TLS_GET);
5155    ins->inst_offset = thread_tls_offset;
5156    return (ins);
5157 }
5158
5159 /*========================= End of Function ========================*/
5160
5161 /*------------------------------------------------------------------*/
5162 /*                                                                  */
5163 /* Name         - mono_arch_get_inst_for_method                   */
5164 /*                                                                  */
5165 /* Function     - Check for opcodes we can handle directly in       */
5166 /*                hardware.                                         */
5167 /*                                                                  */
5168 /*------------------------------------------------------------------*/
5169
5170 MonoInst*
5171 mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod,
5172                                MonoMethodSignature *fsig, MonoInst **args)
5173 {
5174    MonoInst *ins = NULL;
5175    
5176    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_get_inst_for_method");
5177    
5178    CFG_DEBUG(3) g_print("mono_arch_get_inst_for_method: %s\n", cmethod->name);
5179    
5180    return ins;
5181 }
5182
5183 /*========================= End of Function ========================*/
5184
5185 /*------------------------------------------------------------------*/
5186 /*                                                                  */
5187 /* Name         - mono_arch_create_class_init_trampoline            */
5188 /*                                                                  */
5189 /* Function     - Creates a trampoline function to run a type init- */
5190 /*                ializer. If the trampoline is called, it calls    */
5191 /*                mono_runtime_class_init with the given vtable,    */
5192 /*                then patches the caller code so it does not get   */
5193 /*                called any more.                                  */
5194 /*                                                                  */
5195 /* Parameter    - vtable - The type to initialize                   */
5196 /*                                                                  */
5197 /* Returns      - A pointer to the newly created code               */
5198 /*                                                                  */
5199 /*------------------------------------------------------------------*/
5200
5201 gpointer
5202 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
5203 {
5204    ALPHA_DEBUG("mono_arch_create_class_init_trampoline");
5205    
5206    NOT_IMPLEMENTED;
5207    
5208    return 0;
5209 }
5210
5211 /*------------------------------------------------------------------*/
5212 /*                                                                  */
5213 /* Name         - mono_arch_instrument_prolog                       */
5214 /*                                                                  */
5215 /* Function     - Create an "instrumented" prolog.                  */
5216 /*                                                                  */
5217 /*------------------------------------------------------------------*/
5218
5219 void*
5220 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
5221                              gboolean enable_arguments)
5222 {
5223   unsigned int *code = p;
5224   int offset;
5225
5226   CallInfo *cinfo = NULL;
5227   MonoMethodSignature *sig;
5228   MonoInst *inst;
5229   int i, n, stack_area = 0;
5230   AlphaGotData ge_data;
5231
5232   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_instrument_prolog");
5233
5234   /* Keep this in sync with mono_arch_get_argument_info */
5235   if (enable_arguments)
5236     {
5237       /* Allocate a new area on the stack and save arguments there */
5238       sig = mono_method_signature (cfg->method);
5239
5240       cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
5241
5242       n = sig->param_count + sig->hasthis;
5243
5244       stack_area = ALIGN_TO (n * 8, 8);
5245
5246       // Correct stack by calculated value
5247       if (stack_area)
5248         alpha_lda(code, alpha_sp, alpha_sp, -stack_area);
5249       
5250       for (i = 0; i < n; ++i)
5251         {
5252           inst = cfg->args [i];
5253
5254           if (inst->opcode == OP_REGVAR)
5255             {
5256               switch(cinfo->args[i].storage)
5257                 {
5258                 case ArgInDoubleReg:
5259                   alpha_stt(code, inst->dreg, alpha_sp, (i*8));
5260                   break;
5261                 case ArgInFloatReg:
5262                   alpha_sts(code, inst->dreg, alpha_sp, (i*8));
5263                   break;
5264                 default:
5265                   alpha_stq(code, inst->dreg, alpha_sp, (i*8));
5266                 }
5267             }
5268           else
5269             {
5270               alpha_ldq(code, alpha_at, inst->inst_basereg, inst->inst_offset);
5271               alpha_stq(code, alpha_at, alpha_sp, (i*8));
5272             }
5273         }
5274     }
5275   
5276   offset = (char *)code - (char *)cfg->native_code;
5277
5278   ge_data.data.p = cfg->method;
5279
5280   add_got_entry(cfg, GT_PTR, ge_data,
5281                 (char *)code - (char *)cfg->native_code, 
5282                 MONO_PATCH_INFO_METHODCONST, cfg->method);
5283   alpha_ldq(code, alpha_a0, alpha_gp, 0);
5284
5285   alpha_mov1(code, alpha_sp, alpha_a1);
5286
5287   code = emit_call(cfg, code, MONO_PATCH_INFO_ABS, (gpointer)func);
5288
5289   if (enable_arguments)
5290     {
5291       // Correct stack back by calculated value
5292       if (stack_area)
5293         alpha_lda(code, alpha_sp, alpha_sp, stack_area);
5294       
5295       g_free(cinfo);
5296     }
5297
5298   return code;
5299 }
5300
5301 /*========================= End of Function ========================*/
5302
5303 enum {
5304   SAVE_NONE,
5305   SAVE_STRUCT,
5306   SAVE_R0,
5307   SAVE_EAX_EDX,
5308   SAVE_XMM
5309 };
5310
5311 /*------------------------------------------------------------------*/
5312 /*                                                                  */
5313 /* Name         - mono_arch_instrument_epilog                       */
5314 /*                                                                  */
5315 /* Function     - Create an epilog that will handle the returned    */
5316 /*                values used in instrumentation.                   */
5317 /*                                                                  */
5318 /*------------------------------------------------------------------*/
5319
5320 void*
5321 mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p,
5322         gboolean enable_arguments)
5323 {
5324   unsigned int *code = p;
5325   int save_mode = SAVE_NONE;
5326   int offset;
5327   MonoMethod *method = cfg->method;
5328   AlphaGotData ge_data;
5329   int rtype = mono_type_get_underlying_type (mono_method_signature (method)->ret)->type;
5330
5331   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_instrument_epilog");
5332    
5333    switch (rtype)
5334      {
5335      case MONO_TYPE_VOID:
5336        /* special case string .ctor icall */
5337        if (strcmp (".ctor", method->name) &&
5338            method->klass == mono_defaults.string_class)
5339          save_mode = SAVE_R0;
5340        else
5341          save_mode = SAVE_NONE;
5342        break;
5343      case MONO_TYPE_I8:
5344      case MONO_TYPE_U8:
5345        save_mode = SAVE_R0;
5346        break;
5347      case MONO_TYPE_R4:
5348      case MONO_TYPE_R8:
5349        save_mode = SAVE_XMM;
5350        break;
5351      case MONO_TYPE_VALUETYPE:
5352        save_mode = SAVE_STRUCT;
5353        break;
5354      default:
5355        save_mode = SAVE_R0;
5356        break;
5357      }
5358
5359    /* Save the result and copy it into the proper argument register */
5360    switch (save_mode)
5361      {
5362      case SAVE_R0:
5363        alpha_lda(code, alpha_sp, alpha_sp, -8);
5364        alpha_stq(code, alpha_r0, alpha_sp, 0);
5365        
5366        if (enable_arguments)
5367          alpha_mov1(code, alpha_r0, alpha_a1);
5368
5369        break;
5370      case SAVE_STRUCT:
5371        /* FIXME: */
5372        if (enable_arguments)
5373          alpha_lda(code, alpha_a1, alpha_zero, 0);
5374
5375        break;
5376      case SAVE_XMM:
5377        //amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8);
5378        //amd64_movsd_membase_reg (code, AMD64_RSP, 0, AMD64_XMM0);
5379        /* Align stack */
5380        //amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8);
5381        /*
5382         * The result is already in the proper argument register so no copying
5383         * needed.
5384         */
5385        break;
5386      case SAVE_NONE:
5387        break;
5388      default:
5389        g_assert_not_reached ();
5390      }
5391
5392   offset = (char *)code - (char *)cfg->native_code;
5393
5394   ge_data.data.p = cfg->method;
5395
5396   add_got_entry(cfg, GT_PTR, ge_data,
5397                 (char *)code - (char *)cfg->native_code,
5398                 MONO_PATCH_INFO_METHODCONST, cfg->method);
5399   
5400   alpha_ldq(code, alpha_a0, alpha_gp, 0);
5401
5402   code = emit_call(cfg, code, MONO_PATCH_INFO_ABS, (gpointer)func);
5403    
5404   /* Restore result */
5405   switch (save_mode) 
5406      {
5407      case SAVE_R0:
5408        alpha_ldq(code, alpha_r0, alpha_sp, 0);
5409        alpha_lda(code, alpha_sp, alpha_sp, 8);
5410        break;
5411      case SAVE_STRUCT:
5412        /* FIXME: */
5413        break;
5414      case SAVE_XMM:
5415        //amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 8);
5416        //amd64_movsd_reg_membase (code, AMD64_XMM0, AMD64_RSP, 0);
5417        //amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 8);
5418        break;
5419      case SAVE_NONE:
5420        break;
5421      default:
5422        g_assert_not_reached ();
5423      }
5424    
5425    return code;
5426 }
5427
5428 /*========================= End of Function ========================*/
5429
5430 /*------------------------------------------------------------------*/
5431 /*                                                                  */
5432 /* Name         - mono_arch_allocate_vars                           */
5433 /*                                                                  */
5434 /* Function     - Set var information according to the calling      */
5435 /*                convention for Alpha. The local var stuff should  */
5436 /*                most likely be split in another method.           */
5437 /*                                                                  */
5438 /* Parameter    - @m - Compile unit.                                */
5439 /*
5440  * This method is called right before working with BBs. Conversion to
5441  * IR was done and some analises what registers would be used.
5442  * Collect info about registers we used - if we want to use a register
5443  * we need to allocate space for it and save on the stack in method
5444  * prolog.
5445  * 
5446  * Alpha calling convertion:
5447  * FP -> Stack top <- SP
5448  * 0:    Stack params to call others
5449  *
5450  *       RA               <- arch.params_stack_size
5451  *       old FP
5452  * 
5453  *       [LMF info]       <- arch.lmf_offset
5454  * .
5455  *       [possible return values allocated on stack]
5456  *
5457  * .     [locals]
5458  * .
5459  * .     caller saved regs <- arch.reg_save_area_offset
5460  * .     a0                <- arch.args_save_area_offset
5461  * .     a1
5462  * .     a2
5463  * .     a3
5464  * .     a4
5465  * .     a5
5466  * ------------------------
5467  * .     a6 - passed args on stack
5468  * .
5469  */
5470 /*------------------------------------------------------------------*/
5471
5472 void
5473 mono_arch_allocate_vars (MonoCompile *cfg)
5474 {
5475    MonoMethodSignature *sig;
5476    MonoMethodHeader *header;
5477    MonoInst *inst;
5478    int i, offset = 0, a_off = 0;
5479    guint32 locals_stack_size, locals_stack_align = 0;
5480    gint32 *offsets;
5481    CallInfo *cinfo;
5482    
5483    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_allocate_vars");
5484    
5485    header = mono_method_get_header (cfg->method);
5486    
5487    sig = mono_method_signature (cfg->method);
5488    
5489    cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
5490    
5491    /* if (cfg->arch.omit_fp) {
5492       cfg->flags |= MONO_CFG_HAS_SPILLUP;
5493       cfg->frame_reg = AMD64_RSP;
5494       offset = 0;
5495       }
5496       else */
5497    {
5498      /* Locals are allocated forwards from FP. After
5499       * RA (offset 0), FP (offset 8) and ret value, locals, A0-A5
5500       * (starting from offset 16).
5501       * FIXME: Check there Arg6...Argn are supposed to be
5502       */
5503      cfg->frame_reg = alpha_fp;
5504      //     offset = MONO_ALPHA_VARS_OFFSET;
5505    }
5506
5507    CFG_DEBUG(3) g_print ("ALPHA: Size for call params is %d(%x)\n",
5508                          cfg->arch.params_stack_size, cfg->arch.params_stack_size);
5509    offset += cfg->arch.params_stack_size;
5510
5511    offset += 16;    // Size to save RA & FP
5512
5513    if (cfg->method->save_lmf)
5514      {
5515        /* Reserve stack space for saving LMF + argument regs */
5516        guint32 size = sizeof (MonoLMF);
5517
5518        //if (lmf_tls_offset == -1)
5519        //        /* Need to save argument regs too */
5520        //        size += (AMD64_NREG * 8) + (8 * 8);
5521
5522        cfg->arch.lmf_offset = offset;
5523        offset += size;
5524
5525        CFG_DEBUG(3) g_print ("ALPHA: Method %s needs LMF. Offset: %x, Size: %x\n",
5526                              cfg->method->name, cfg->arch.lmf_offset, size);
5527      }
5528    
5529    if (sig->ret->type != MONO_TYPE_VOID)
5530      {
5531        switch (cinfo->ret.storage)
5532          {
5533          case ArgInIReg:
5534          case ArgInFloatReg:
5535          case ArgInDoubleReg:
5536            if ((MONO_TYPE_ISSTRUCT (sig->ret) &&
5537                 !mono_class_from_mono_type (sig->ret)->enumtype) ||
5538                (sig->ret->type == MONO_TYPE_TYPEDBYREF))
5539              {
5540                /* The register is volatile */
5541                cfg->ret->opcode = OP_REGOFFSET;
5542                cfg->ret->inst_basereg = cfg->frame_reg;
5543
5544                /*if (cfg->arch.omit_fp) {
5545                  cfg->ret->inst_offset = offset;
5546                  offset += 8;
5547                  } else */
5548                {
5549                  cfg->ret->inst_offset = offset;
5550                  CFG_DEBUG(3) g_print ("ALPHA: Return offset is %x\n", offset);
5551                  offset += 8;
5552                }
5553              }
5554            else
5555              {
5556                cfg->ret->opcode = OP_REGVAR;
5557                cfg->ret->inst_c0 = cinfo->ret.reg;
5558              }
5559            break;
5560          case ArgValuetypeInReg:
5561            /* Allocate a local to hold the result, the epilog will
5562               copy it to the correct place */
5563            // g_assert (!cfg->arch.omit_fp);
5564            offset += 16;
5565            cfg->ret->opcode = OP_REGOFFSET;
5566            cfg->ret->inst_basereg = cfg->frame_reg;
5567            cfg->ret->inst_offset = offset;
5568            break;
5569          default:
5570            g_assert_not_reached ();
5571          }
5572        cfg->ret->dreg = cfg->ret->inst_c0;
5573      }
5574    
5575    /* Allocate locals */
5576    offsets = mono_allocate_stack_slots_full (cfg,
5577                                              /*cfg->arch.omit_fp ? FALSE:*/ TRUE, 
5578                                              &locals_stack_size,
5579                                              &locals_stack_align);
5580    
5581    //g_assert((locals_stack_size % 8) == 0);
5582    if (locals_stack_size % 8)
5583      {
5584        locals_stack_size += 8 - (locals_stack_size % 8);
5585      }
5586
5587    /*   if (locals_stack_align)
5588      {
5589        offset += (locals_stack_align - 1);
5590        offset &= ~(locals_stack_align - 1);
5591      }
5592    */
5593
5594    cfg->arch.localloc_offset = offset;
5595    
5596    CFG_DEBUG(3) g_print ("ALPHA: Locals start offset is %d(%x)\n", offset, offset);
5597    CFG_DEBUG(3) g_print ("ALPHA: Locals size is %d(%x)\n",
5598                           locals_stack_size, locals_stack_size);
5599
5600    for (i = cfg->locals_start; i < cfg->num_varinfo; i++)
5601      {
5602        if (offsets [i] != -1) {
5603          MonoInst *inst = cfg->varinfo [i];
5604          inst->opcode = OP_REGOFFSET;
5605          inst->inst_basereg = cfg->frame_reg;
5606          //if (cfg->arch.omit_fp)
5607          //        inst->inst_offset = (offset + offsets [i]);
5608          //else
5609          inst->inst_offset = (offset + (locals_stack_size - offsets [i]));
5610
5611          CFG_DEBUG(3) g_print ("ALPHA: allocated local %d to ", i);
5612          CFG_DEBUG(3) mono_print_tree_nl (inst);
5613        }
5614      }
5615    
5616    // TODO check how offsets[i] are calculated
5617    // it seems they are points to the end on data. Like 8, but it actually - 0
5618
5619    offset += locals_stack_size; //+8;
5620    
5621    if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG)) {
5622      //                g_assert (!cfg->arch.omit_fp);
5623      g_assert (cinfo->sig_cookie.storage == ArgOnStack);
5624      cfg->sig_cookie = cinfo->sig_cookie.offset + ARGS_OFFSET;
5625    }
5626
5627    // Save offset for caller saved regs
5628    cfg->arch.reg_save_area_offset = offset;
5629
5630    CFG_DEBUG(3) g_print ("ALPHA: reg_save_area_offset at %d(%x)\n", offset, offset);
5631    
5632    // Reserve space for caller saved registers 
5633    for (i = 0; i < MONO_MAX_IREGS; ++i)
5634      if ((ALPHA_IS_CALLEE_SAVED_REG (i)) &&
5635          (cfg->used_int_regs & (1 << i)))
5636        {
5637          offset += sizeof (gpointer);
5638        }
5639
5640    // Save offset to args regs
5641    cfg->arch.args_save_area_offset = offset;
5642
5643    CFG_DEBUG(3) g_print ("ALPHA: args_save_area_offset at %d(%x)\n", offset, offset);
5644
5645    for (i = 0; i < sig->param_count + sig->hasthis; ++i)
5646      {
5647        ArgInfo *ainfo = &cinfo->args [i];
5648
5649        switch(ainfo->storage)
5650          {
5651          case ArgInIReg:
5652          case ArgInFloatReg:
5653          case ArgInDoubleReg:
5654            offset += sizeof (gpointer);
5655            break;
5656          case ArgAggregate:
5657            offset += ainfo->nregs * sizeof (gpointer);
5658            break;
5659          default:
5660            ;
5661          }
5662      }
5663
5664    CFG_DEBUG(3) g_print ("ALPHA: Stack size is %d(%x)\n",
5665                           offset, offset);
5666    
5667    // Reserve space for method params
5668    for (i = 0; i < sig->param_count + sig->hasthis; ++i)
5669      {
5670        inst = cfg->args [i];
5671
5672        if (inst->opcode != OP_REGVAR)
5673          {
5674            ArgInfo *ainfo = &cinfo->args [i];
5675            gboolean inreg = TRUE;
5676            MonoType *arg_type;
5677                  
5678            if (sig->hasthis && (i == 0))
5679              arg_type = &mono_defaults.object_class->byval_arg;
5680            else
5681              arg_type = sig->params [i - sig->hasthis];
5682                  
5683            /* FIXME: Allocate volatile arguments to registers */
5684            if (inst->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))
5685              inreg = FALSE;
5686                  
5687            /*
5688             * Under AMD64, all registers used to pass arguments to functions
5689             * are volatile across calls. For Alpha too.
5690             * FIXME: Optimize this.
5691             */
5692                  
5693            // Let's 
5694            if (inreg && (ainfo->storage == ArgInIReg)
5695                //&& cfg->used_int_regs & (1 << ainfo->reg)
5696                )
5697              inreg = FALSE;
5698                  
5699            if (//(ainfo->storage == ArgInIReg) ||
5700                (ainfo->storage == ArgInFloatReg) ||
5701                (ainfo->storage == ArgInDoubleReg) ||
5702                (ainfo->storage == ArgValuetypeInReg))
5703              inreg = FALSE;
5704                  
5705            inst->opcode = OP_REGOFFSET;
5706                  
5707            switch (ainfo->storage)
5708              {
5709              case ArgInIReg:
5710              case ArgInFloatReg:
5711              case ArgInDoubleReg:
5712                inst->opcode = OP_REGVAR;
5713                inst->dreg = ainfo->reg;
5714                break;
5715              case ArgOnStack:
5716                // g_assert (!cfg->arch.omit_fp);
5717                inst->opcode = OP_REGOFFSET;
5718                inst->inst_basereg = cfg->frame_reg;
5719                
5720                // "offset" here will point to the end of
5721                // array of saved ret,locals, args
5722                // Ideally it would point to "a7"
5723                inst->inst_offset = ainfo->offset + offset;
5724                break;
5725              case ArgValuetypeInReg:
5726                break;
5727              case ArgAggregate:
5728                inreg = FALSE;
5729                break;
5730
5731              default:
5732                NOT_IMPLEMENTED;
5733              }
5734
5735            if (!inreg && (ainfo->storage != ArgOnStack))
5736              {
5737                inst->opcode = OP_REGOFFSET;
5738                inst->inst_basereg = cfg->frame_reg;
5739                
5740                /* These arguments are saved to the stack in the prolog */
5741                /*if (cfg->arch.omit_fp) {
5742                  inst->inst_offset = offset;
5743                  offset += (ainfo->storage == ArgValuetypeInReg) ?
5744                  2 * sizeof (gpointer) : sizeof (gpointer);
5745                  } else */
5746                {
5747                  // offset += (ainfo->storage == ArgValuetypeInReg) ?
5748                  // 2 * sizeof (gpointer) : sizeof (gpointer);
5749
5750                  inst->inst_offset = cfg->arch.args_save_area_offset + a_off;
5751                  switch(ainfo->storage)
5752                    {
5753                    case ArgAggregate:
5754                      a_off += ainfo->nslots * 8;
5755                      break;
5756                    default:
5757                      a_off += sizeof (gpointer);
5758                    }
5759                 //   (/*(ainfo->reg - 16)*/ i * 8);
5760                }
5761              }
5762          }
5763     }
5764    
5765    cfg->stack_offset = offset;
5766    
5767    g_free (cinfo);
5768 }
5769
5770 /*========================= End of Function ========================*/
5771
5772 /*------------------------------------------------------------------*/
5773 /*                                                                  */
5774 /* Name         - mono_arch_print_tree                              */
5775 /*                                                                  */
5776 /* Function     - Print platform-specific opcode details.           */
5777 /*                                                                  */
5778 /* Returns      - 1 - opcode details have been printed              */
5779 /*                0 - opcode details have not been printed          */
5780 /*                                                                  */
5781 /*------------------------------------------------------------------*/
5782
5783 gboolean
5784 mono_arch_print_tree (MonoInst *tree, int arity)
5785 {
5786    gboolean done;
5787    
5788    ALPHA_DEBUG("mono_arch_print_tree");
5789    
5790    switch (tree->opcode) {
5791         default:
5792           done = 0;
5793    }
5794    return (done);
5795 }
5796
5797 /*========================= End of Function ========================*/
5798
5799 /*
5800 **
5801 ** mono_arch_get_vcall_slot_addr
5802 **  is called by mono_magic_trampoline to determine that the JIT compiled
5803 **  method is called via vtable slot. We need to analyze call sequence
5804 **  and determine that. In case it is true - we need to return address
5805 **  of vtable slot.
5806 **
5807 ** code - points to the next instruction after call
5808 ** reg - points to saved regs before the call (this is done
5809 **        by mono_magic_trampoline function
5810 */
5811
5812 gpointer*
5813 mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs)
5814 {
5815   unsigned int *pc = (unsigned int *)code;
5816   guint32 reg, disp;
5817   int     start_index = -2;
5818
5819   ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_vcall_slot_addr] code: %p regs: %p",
5820           pc, regs);
5821
5822   // Check if we have parameters on stack
5823   if ((pc[-2] & 0xFFFF0000) == 0x23DE0000)     // lda     sp,-n(sp)
5824     start_index = -3;
5825
5826   // Check for (call_membase):
5827   // -4: mov     v0,a0        - load this ???
5828   // -3: ldq     v0,0(v0)     - load vtable 
5829   // -2: ldq     t12,64(v0)   - load method (object->vtable->vtable[method->slot])
5830   if ((pc[start_index-1] & 0xFC00FFFF) == 0xA4000000 &&
5831       (pc[start_index] & 0xFFFF0000) == 0xA7600000
5832       )
5833     {
5834       disp = pc[start_index] & 0xFFFF;
5835       reg = (pc[start_index-1] >> AXP_REG1_SHIFT) & AXP_REG_MASK;
5836       //reg = 0; // For now
5837
5838       ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_vcall_slot_addr callvirt] call_membase");
5839
5840       return (gpointer)(((guint64)(regs [reg])) + disp);
5841     }
5842
5843   // Check for interface call
5844   // -5: mov     v0,a0
5845   // -4: ldq     v0,0(v0)
5846   // -3: ldq     v0,-n(v0)
5847   // -2: ldq     t12,0(v0)
5848   if ((pc[start_index-2] & 0xFC00FFFF) == 0xA4000000 &&
5849       (pc[start_index-1] & 0xFFFF0000) == 0xA4000000 &&
5850       (pc[start_index] & 0xFFFF0000) == 0xA7600000
5851       )
5852     {
5853       disp = pc[start_index] & 0xFFFF;;
5854       reg = 0; // For now
5855
5856       ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_vcall_slot_addr interf callvir] call_membase");
5857
5858       return (gpointer)(((guint64)(regs [reg])) + disp);
5859     }
5860
5861   return 0;
5862 }
5863
5864
5865 guint32
5866 mono_arch_get_patch_offset (guint8 *code)
5867 {
5868   return 3;
5869 }