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