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