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