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