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