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