First set of licensing changes
[mono.git] / mono / arch / mips / mips-codegen.h
index 8cc0cd0bcef7f273db04baaa97c3c7206315d163..c579c88a9b3a990a26afc0edaeac0c2da8693417 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2004 Novell, Inc
  * Author: Paolo Molaro (lupus@ximian.com)
  *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 /* registers */
@@ -16,6 +17,7 @@ enum {
        mips_a1,
        mips_a2,
        mips_a3,
+#if _MIPS_SIM == _ABIO32
        mips_t0, /* 8 temporaries */
        mips_t1,
        mips_t2,
@@ -24,6 +26,16 @@ enum {
        mips_t5,
        mips_t6,
        mips_t7,
+#elif _MIPS_SIM == _ABIN32
+       mips_a4, /* 4 more argument registers */
+       mips_a5,
+       mips_a6,
+       mips_a7,
+       mips_t0, /* 4 temporaries */
+       mips_t1,
+       mips_t2,
+       mips_t3,
+#endif
        mips_s0, /* 16 calle saved */
        mips_s1,
        mips_s2,
@@ -33,7 +45,7 @@ enum {
        mips_s6,
        mips_s7,
        mips_t8, /* 24 temps */
-       mips_t9,
+       mips_t9, /* 25 temp / pic call-through register */
        mips_k0, /* 26 kernel-reserved */
        mips_k1,
        mips_gp, /* 28 */
@@ -45,29 +57,39 @@ enum {
 /* we treat the register file as containing just doubles... */
 enum {
        mips_f0, /* return regs */
+       mips_f1,
        mips_f2,
+       mips_f3,
        mips_f4, /* temps */
+       mips_f5,
        mips_f6,
+       mips_f7,
        mips_f8,
+       mips_f9,
        mips_f10,
+       mips_f11,
        mips_f12, /* first arg */
+       mips_f13,
        mips_f14, /* second arg */
+       mips_f15,
        mips_f16, /* temps */
+       mips_f17,
        mips_f18,
+       mips_f19,
        mips_f20, /* callee saved */
+       mips_f21,
        mips_f22,
+       mips_f23,
        mips_f24,
+       mips_f25,
        mips_f26,
+       mips_f27,
        mips_f28,
-       mips_f30
+       mips_f29,
+       mips_f30,
+       mips_f31
 };
 
-#define mips_emit32(c,x) do { *((unsigned int *) c) = x; ((unsigned int *)c)++;} while (0)
-#define mips_format_i(code,op,rs,rt,imm) mips_emit32 ((code), (((op)<<26)|((rs)<<21)|((rt)<<16)|(imm)))
-#define mips_format_j(code,op,imm) mips_emit32 ((code), (((op)<<26)|(imm)))
-#define mips_format_r(code,op,rs,rt,rd,sa,func) mips_emit32 ((code), (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(func)))
-#define mips_format_divmul(code,op,src1,src2,fun) mips_emit32 ((code), (((op)<<26)|((src1)<<21)|((src2)<<16)|(fun)))
-
 /* prefetch hints */
 enum {
        MIPS_FOR_LOAD,
@@ -118,18 +140,89 @@ enum {
        MIPS_FPU_CAUSES_OFFSET = 12
 };
 
-/* fpu condition values */
+/* fpu condition values - see manual entry for C.cond.fmt instructions */
 enum {
-       MIPS_FPU_FALSE, /* TRUE */
-       MIPS_FPU_UNORDERED, /* ORDERED */
-       MIPS_FPU_EQ, /* NOT_EQUAL */
-       MIPS_FPU_UNORD_EQ, /* ORDERED or NEQ */
-       MIPS_FPU_ORD_LT, /* UNORDERED or GE */
-       MIPS_FPU_UNORD_LT, /* ORDERED or GE */
-       MIPS_FPU_ORD_LE, /* UNORDERED or GT */
-       MIPS_FPU_UNORD_LE /* OREDERED or GT */
+       MIPS_FPU_F,
+       MIPS_FPU_UN,
+       MIPS_FPU_EQ,
+       MIPS_FPU_UEQ,
+       MIPS_FPU_OLT,
+       MIPS_FPU_ULT,
+       MIPS_FPU_OLE,
+       MIPS_FPU_ULE,
+       MIPS_FPU_SF,
+       MIPS_FPU_NGLE,
+       MIPS_FPU_SEQ,
+       MIPS_FPU_NGL,
+       MIPS_FPU_LT,
+       MIPS_FPU_NGE,
+       MIPS_FPU_LE,
+       MIPS_FPU_NGT
 };
 
+#if SIZEOF_REGISTER == 4
+
+#define MIPS_SW                mips_sw
+#define MIPS_LW                mips_lw
+#define MIPS_ADDU      mips_addu
+#define MIPS_ADDIU     mips_addiu
+#define MIPS_SWC1      mips_swc1
+#define MIPS_LWC1      mips_lwc1
+#define MIPS_MOVE      mips_move
+
+#elif SIZEOF_REGISTER == 8
+
+#define MIPS_SW                mips_sd
+#define MIPS_LW                mips_ld
+#define MIPS_ADDU      mips_daddu
+#define MIPS_ADDIU     mips_daddiu
+#define MIPS_SWC1      mips_sdc1
+#define MIPS_LWC1      mips_ldc1
+#define MIPS_MOVE      mips_dmove
+
+#else
+#error Unknown SIZEOF_REGISTER
+#endif
+
+#define mips_emit32(c,x) do {                          \
+               *((guint32 *) (void *)(c)) = x;                         \
+               (c) = (typeof(c))(((guint32 *)(void *)(c)) + 1);        \
+       } while (0)
+
+#define mips_format_i(code,op,rs,rt,imm) mips_emit32 ((code), (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff)))
+#define mips_format_j(code,op,imm) mips_emit32 ((code), (((op)<<26)|((imm)&0x03ffffff)))
+#define mips_format_r(code,op,rs,rt,rd,sa,func) mips_emit32 ((code), (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(func)))
+#define mips_format_divmul(code,op,src1,src2,fun) mips_emit32 ((code), (((op)<<26)|((src1)<<21)|((src2)<<16)|(fun)))
+
+#define mips_is_imm16(val) ((gint)(gshort)(gint)(val) == (gint)(val))
+
+/* Load always using lui/addiu pair (for later patching) */
+#define mips_load(c,D,v) do {  \
+               if (((guint32)(v)) & (1 << 15)) {                                                               \
+                       mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16)+1);         \
+               }                                                                                                                               \
+               else {                                                                                                                  \
+                       mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16));           \
+               }                                                                                                                               \
+               mips_addiu ((c), (D), (D), ((guint32)(v)) & 0xffff);                    \
+       } while (0)
+
+/* load constant - no patch-up */
+#define mips_load_const(c,D,v) do {    \
+               if (!mips_is_imm16 ((v)))       {       \
+                       if (((guint32)(v)) & (1 << 15)) {               \
+                               mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16)+1); \
+                       } \
+                       else {                  \
+                               mips_lui ((c), (D), mips_zero, (((guint32)(v))>>16)); \
+                       }                                               \
+                       if (((guint32)(v)) & 0xffff) \
+                               mips_addiu ((c), (D), (D), ((guint32)(v)) & 0xffff); \
+               }                                                       \
+               else                                                    \
+                       mips_addiu ((c), (D), mips_zero, ((guint32)(v)) & 0xffff); \
+       } while (0)
+
 /* arithmetric ops */
 #define mips_add(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,32)
 #define mips_addi(c,dest,src1,imm) mips_format_i(c,8,src1,dest,imm)
@@ -141,6 +234,7 @@ enum {
 #define mips_daddiu(c,dest,src1,imm) mips_format_i(c,25,src1,dest,imm)
 #define mips_dsub(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,46)
 #define mips_dsubu(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,47)
+#define mips_mul(c,dest,src1,src2) mips_format_r(c,28,src1,src2,dest,0,2)
 #define mips_sub(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,34)
 #define mips_subu(c,dest,src1,src2) mips_format_r(c,0,src1,src2,dest,0,35)
 
@@ -226,6 +320,7 @@ enum {
 #define mips_lwl(c,dest,base,offset) mips_format_i(c,34,base,dest,offset)
 #define mips_lwr(c,dest,base,offset) mips_format_i(c,38,base,dest,offset)
 #define mips_lwu(c,dest,base,offset) mips_format_i(c,39,base,dest,offset)
+
 #define mips_sb(c,src,base,offset) mips_format_i(c,40,base,src,offset)
 #define mips_sc(c,src,base,offset) mips_format_i(c,56,base,src,offset)
 #define mips_scd(c,src,base,offset) mips_format_i(c,60,base,src,offset)
@@ -238,8 +333,9 @@ enum {
 #define mips_swr(c,src,base,offset) mips_format_i(c,54,base,src,offset)
 
 /* misc and coprocessor ops */
-#define mips_move(c,dest,src) mips_add(c,dest,src,mips_zero)
-#define mips_nop(c) mips_sll(c,0,0,0)
+#define mips_move(c,dest,src) mips_addu(c,dest,src,mips_zero)
+#define mips_dmove(c,dest,src) mips_daddu(c,dest,src,mips_zero)
+#define mips_nop(c) mips_or(c,mips_at,mips_at,0)
 #define mips_break(c,code) mips_emit32(c, ((code)<<6)|13)
 #define mips_mfhi(c,dest) mips_format_r(c,0,0,0,dest,0,16)
 #define mips_mflo(c,dest) mips_format_r(c,0,0,0,dest,0,18)
@@ -323,10 +419,10 @@ enum {
 /* fp moves, loads */
 #define mips_fmovs(c,dest,src) mips_format_r(c,17,MIPS_FMT_SINGLE,0,src,dest,6)
 #define mips_fmovd(c,dest,src) mips_format_r(c,17,MIPS_FMT_DOUBLE,0,src,dest,6)
-#define mips_wmovfc1(c,dest,src) mips_format_r(c,17,0,dest,src,0,0)
-#define mips_wmovtc1(c,dest,src) mips_format_r(c,17,4,src,dest,0,0)
-#define mips_dmovfc1(c,dest,src) mips_format_r(c,17,1,0,dest,src,0,0)
-#define mips_dmovtc1(c,dest,src) mips_format_r(c,17,1,0,src,dest,0,0)
+#define mips_mfc1(c,dest,src) mips_format_r(c,17,0,dest,src,0,0)
+#define mips_mtc1(c,dest,src) mips_format_r(c,17,4,src,dest,0,0)
+#define mips_dmfc1(c,dest,src) mips_format_r(c,17,1,0,dest,src,0)
+#define mips_dmtc1(c,dest,src) mips_format_r(c,17,1,0,src,dest,0)
 #define mips_ldc1(c,dest,base,offset) mips_ldc(c,1,dest,base,offset)
 #define mips_ldxc1(c,dest,base,idx) mips_format_r(c,19,base,idx,0,dest,1)
 #define mips_lwc1(c,dest,base,offset) mips_lwc(c,1,dest,base,offset)