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