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