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