* Removed all Id tags.
[cacao.git] / src / vm / jit / mips / codegen.h
index 0048981cd6b21d77a34c8dfaf04608efa81fb007..12a88b412fe7e2adee0848fee2afaf62043ebe8c 100644 (file)
@@ -1,9 +1,9 @@
-/* vm/jit/mips/codegen.h - code generation macros and definitions for mips
+/* src/vm/jit/mips/codegen.h - code generation macros and definitions for MIPS
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Andreas Krall
-
-   $Id: codegen.h 2297 2005-04-13 12:50:07Z christian $
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 */
 
 #ifndef _CODEGEN_H
 #define _CODEGEN_H
 
-#include "vm/jit/mips/types.h"
-
-/* Macro for stack.c to set Argument Stackslots */
-
-/* SET_ARG_STACKSLOTS ***************************************************
-Macro for stack.c to set Argument Stackslots
-
-Sets the first call_argcount stackslots of curstack to varkind ARGVAR, if
-they to not have the SAVEDVAR flag set. According to the calling
-conventions these stackslots are assigned argument registers or memory
-locations
-
---- in
-i,call_argcount:  Number of arguments for this method
-call_intargshift: Amount of shifted argument registers in case of native
-                  method invokation or 0.
-curstack:         instack of the method invokation
-
---- uses
-i, copy
-
---- out
-copy:             Points to first stackslot after the parameters
-rd->argintreguse: max. number of used integer argument register so far
-rd->argfltreguse: max. number of used float argument register so far
-rd->ifmemuse:     max. number of stackslots used for spilling parameters
-                  so far
-************************************************************************/
-/* Todo ****************************************************************
-Change createnativestub in codegen.c to not destroy all not used argument
-registers in case of parametershift and change ICMD_xRETURN in codege.c
-Then delete #define DONT_USE_ARGREGS and delete the corresponding #ifdef
-part in reg.inc
-************************************************************************/
-#define SET_ARG_STACKSLOTS {                                                                                   \
-               s4 stacksize;     /* Stackoffset for spilled arg */                             \
-        s4 iarg = 0;                                                                                                   \
-        s4 farg = 0;                                                                                                   \
-                                                                                                                                               \
-               stacksize = (i < rd->intreg_argnum)? 0 : (i - rd->intreg_argnum); \
-               if (rd->ifmemuse < stacksize)                                                                   \
-                       rd->ifmemuse = stacksize;                                                                       \
-                                                                                                                                               \
-               copy = curstack;                                                                                                \
-               for (;i > 0; i--) {                                                                                             \
-                       if (IS_FLT_DBL_TYPE(copy->type)) {                                                      \
-                               if (farg == 0) farg = i;                                                                \
-                       } else {                                                                                                        \
-                               if (iarg == 0) iarg = i;                                                                \
-                       }                                                                                                                       \
-                       copy = copy->prev;                                                                                      \
-               }                                                                                                                               \
-               if (rd->argintreguse < iarg)                                    \
-                       rd->argintreguse = iarg;                                                                        \
-               if (rd->argfltreguse < farg)                                    \
-                       rd->argfltreguse = farg;                                                                        \
-                                                                                                                                               \
-               i = call_argcount;                                                                                              \
-               copy = curstack;                                                                                                \
-               while (--i >= 0) {                                                                                              \
-                       if (!(copy->flags & SAVEDVAR)) {                                                        \
-                               copy->varnum = i;                                                                               \
-                               copy->varkind = ARGVAR;                                                                 \
-                               if (IS_FLT_DBL_TYPE(copy->type)) {                                              \
-                                       if (i < rd->fltreg_argnum) {                                            \
-                                               copy->flags = 0;                                                                \
-                                               copy->regoff = rd->argfltregs[i];                               \
-                                       } else {                                                                                        \
-                                               copy->flags = INMEMORY;                                                 \
-                                               copy->regoff = --stacksize;                                             \
-                                       }                                                                                                       \
-                               } else { /* int arg */                                                                  \
-                                       if (i < rd->intreg_argnum) {                                            \
-                                               copy->flags = 0;                                                                \
-                                               copy->regoff = rd->argintregs[i];                               \
-                                       } else {                                                                                        \
-                                               copy->flags = INMEMORY;                                                 \
-                                               copy->regoff = --stacksize;                                             \
-                                       }                                                                                                       \
-                               }                                                                                                               \
-                       }                                                                                                                       \
-                       copy = copy->prev;                                                                                      \
-               }                                                                                                                               \
-       }
-
-
-/* additional functions and macros to generate code ***************************/
-
-/* #define BlockPtrOfPC(pc)        block+block_index[pc] */
-#define BlockPtrOfPC(pc)  ((basicblock *) iptr->target)
+#include "config.h"
+#include "vm/types.h"
 
+#include "vm/jit/jit.h"
 
-#ifdef STATISTICS
-#define COUNT_SPILLS count_spills++
-#else
-#define COUNT_SPILLS
-#endif
-
-
-/* gen_nullptr_check(objreg) */
-
-#define gen_nullptr_check(objreg) \
-    if (checknull) { \
-        M_BEQZ((objreg), 0); \
-        codegen_addxnullrefs(cd, mcodeptr); \
-        M_NOP; \
-    }
-
-#define gen_bound_check \
-    if (checkbounds) { \
-        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
-        M_CMPULT(s2, REG_ITMP3, REG_ITMP3); \
-        M_BEQZ(REG_ITMP3, 0); \
-        codegen_addxboundrefs(cd, mcodeptr, s2); \
-        M_NOP; \
-    }
 
+/* additional functions and macros to generate code ***************************/
 
 /* MCODECHECK(icnt) */
 
 #define MCODECHECK(icnt) \
-       if ((mcodeptr + (icnt)) > cd->mcodeend) \
-        mcodeptr = codegen_increase(cd, (u1 *) mcodeptr)
+    do { \
+        if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
 
 
 #define ALIGNCODENOP \
-    if ((int) ((long) mcodeptr & 7)) { \
+    if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
         M_NOP; \
     }
 
+#define M_INTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_MOV(a, b); \
+    } while (0)
+
+#if SIZEOF_VOID_P == 8
+
+#define M_LNGMOVE(a,b)    M_INTMOVE(a,b)
+
+#else /* SIZEOF_VOID_P == 8 */
+
+#define M_LNGMOVE(a,b) \
+    do { \
+        if (GET_LOW_REG(b) == GET_HIGH_REG(a)) { \
+            assert(GET_HIGH_REG(b) == GET_LOW_REG(a)); \
+            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
+            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
+        } else { \
+            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
+            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
+        } \
+    } while (0)
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+#define M_FLTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_FMOV(a, b); \
+    } while (0)
+
+#define M_DBLMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_DMOV(a, b); \
+    } while (0)
+
+#define ICONST(r,c)                     emit_iconst(cd, (r), (c))
+#define LCONST(r,c)                     emit_lconst(cd, (r), (c))
+
+
+/* branch defines *************************************************************/
+
+#define BRANCH_NOPS \
+    do { \
+        if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+        } \
+        else { \
+            M_NOP; \
+            M_NOP; \
+        } \
+    } while (0)
+
+
+/* patcher defines ************************************************************/
+
+#define PATCHER_CALL_INSTRUCTIONS    1     /* number of instructions          */
+#define PATCHER_CALL_SIZE            1 * 4 /* size in bytes of a patcher call */
+
+#define PATCHER_NOPS \
+    do { \
+        M_NOP; \
+    } while (0)
 
-/* M_INTMOVE:
-     generates an integer-move from register a to b.
-     if a and b are the same int-register, no code will be generated.
-*/ 
-
-#define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
-
-
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
-
-#define M_FLTMOVE(a,b) if (a != b) { M_DMOV(a, b); }
-
-#define M_TFLTMOVE(t,a,b) \
-       {if(a!=b) \
-               if ((t)==TYPE_DBL) \
-                   {M_DMOV(a,b);} \
-               else {M_FMOV(a,b);} \
-       }
-
-#define M_TFLD(t,a,b,disp) \
-    if ((t)==TYPE_DBL) \
-         {M_DLD(a,b,disp);} \
-    else \
-         {M_FLD(a,b,disp);}
-
-#define M_TFST(t,a,b,disp) \
-    if ((t)==TYPE_DBL) \
-         {M_DST(a,b,disp);} \
-    else \
-         {M_FST(a,b,disp);}
-
-#define M_CCFLTMOVE(t1,t2,a,b) \
-       if ((t1)==(t2)) \
-         {M_TFLTMOVE(t1,a,b);} \
-       else \
-         if ((t1)==TYPE_DBL) \
-               {M_CVTDF(a,b);} \
-         else \
-               {M_CVTFD(a,b);}
-
-#define M_CCFLD(t1,t2,a,b,disp) \
-    if ((t1)==(t2)) \
-         {M_DLD(a,b,disp);} \
-       else { \
-         M_DLD(REG_FTMP1,b,disp); \
-         if ((t1)==TYPE_DBL) \
-           {M_CVTDF(REG_FTMP1,a);} \
-         else \
-           {M_CVTFD(REG_FTMP1,a);} \
-       }
-         
-#define M_CCFST(t1,t2,a,b,disp) \
-    if ((t1)==(t2)) \
-         {M_DST(a,b,disp);} \
-       else { \
-         if ((t1)==TYPE_DBL) \
-           {M_CVTDF(a,REG_FTMP1);} \
-         else \
-           {M_CVTFD(a,REG_FTMP1);} \
-         M_DST(REG_FTMP1,b,disp); \
-       }
-         
-
-/* var_to_reg_xxx:
-    this function generates code to fetch data from a pseudo-register
-    into a real register. 
-    If the pseudo-register has actually been assigned to a real 
-    register, no code will be emitted, since following operations
-    can use this register directly.
-    
-    v: pseudoregister to be fetched from
-    tempregnum: temporary register to be used if v is actually spilled to ram
-
-    return: the register number, where the operand can be found after 
-            fetching (this wil be either tempregnum or the register
-            number allready given to v)
-*/
 
-#define var_to_reg_int(regnr,v,tempnr) { \
-       if ((v)->flags & INMEMORY) { \
-               COUNT_SPILLS; \
-        M_LLD(tempnr, REG_SP, 8 * (v)->regoff); \
-        regnr = tempnr; \
-       } else regnr = (v)->regoff; \
-}
-
-
-#define var_to_reg_flt(regnr,v,tempnr) { \
-       if ((v)->flags & INMEMORY) { \
-               COUNT_SPILLS; \
-        M_DLD(tempnr, REG_SP, 8 * (v)->regoff); \
-        regnr = tempnr; \
-       } else regnr = (v)->regoff; \
-}
-
-
-/* store_reg_to_var_xxx:
-    This function generates the code to store the result of an operation
-    back into a spilled pseudo-variable.
-    If the pseudo-variable has not been spilled in the first place, this 
-    function will generate nothing.
-    
-    v ............ Pseudovariable
-    tempregnum ... Number of the temporary registers as returned by
-                   reg_of_var.
-*/     
-
-#define store_reg_to_var_int(sptr, tempregnum) {       \
-       if ((sptr)->flags & INMEMORY) {                    \
-               COUNT_SPILLS;                                  \
-               M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
-               }                                              \
-       }
-
-#define store_reg_to_var_flt(sptr, tempregnum) {       \
-       if ((sptr)->flags & INMEMORY) {                    \
-               COUNT_SPILLS;                                  \
-               M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
-               }                                              \
-       }
-
-
-#define M_COPY(from,to) \
-       d = reg_of_var(rd, to, REG_IFTMP); \
-       if ((from->regoff != to->regoff) || \
-           ((from->flags ^ to->flags) & INMEMORY)) { \
-               if (IS_FLT_DBL_TYPE(from->type)) { \
-                       var_to_reg_flt(s1, from, d); \
-                       M_TFLTMOVE(from->type, s1, d); \
-                       store_reg_to_var_flt(to, d); \
-               } else { \
-                       var_to_reg_int(s1, from, d); \
-                       M_INTMOVE(s1, d); \
-                       store_reg_to_var_int(to, d); \
-               } \
-       }
-
-
-#define ICONST(r,c) \
-    if ((c) >= -32768 && (c) <= 32767) { \
-        M_IADD_IMM(REG_ZERO, (c), (r)); \
-    } else if ((c) >= 0 && (c) <= 0xffff) { \
-        M_OR_IMM(REG_ZERO, (c), (r)); \
-    } else { \
-        a = dseg_adds4(cd, (c)); \
-        M_ILD((r), REG_PV, a); \
-    }
+/* stub defines ***************************************************************/
 
-#define LCONST(r,c) \
-    if ((c) >= -32768 && (c) <= 32767) { \
-        M_LADD_IMM(REG_ZERO, (c), (r)); \
-    } else if ((c) >= 0 && (c) <= 0xffff) { \
-        M_OR_IMM(REG_ZERO, (c), (r)); \
-    } else { \
-        a = dseg_adds8(cd, (c)); \
-        M_LLD((r), REG_PV, a); \
-    }
+#define COMPILERSTUB_CODESIZE    4 * 4
 
 
 /* macros to create code ******************************************************/
@@ -340,14 +140,28 @@ part in reg.inc
 */
 
 
-#define M_ITYPE(op, rs, rt, imm)\
-  *(mcodeptr++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((imm)&0xffff))
+#define M_ITYPE(op,rs,rt,imm) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((imm) & 0xffff)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+#define M_ITYPE_GET_RS(x)               (((x) >> 21) & 0x1f  )
+#define M_ITYPE_GET_RT(x)               (((x) >> 16) & 0x1f  )
+#define M_ITYPE_GET_IMM(x)              ( (x)        & 0xffff)
 
-#define M_JTYPE(op, imm)\
-  *(mcodeptr++) = (((op)<<26)|((off)&0x3ffffff))
 
-#define M_RTYPE(op, rs, rt, rd, sa, fu)\
-  *(mcodeptr++) = (((op)<<26)|((rs)<<21)|((rt)<<16)|((rd)<<11)|((sa)<<6)|(fu))
+#define M_JTYPE(op,imm) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((op) << 26) | ((off) & 0x3ffffff)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+#define M_RTYPE(op,rs,rt,rd,sa,fu) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((sa) << 6) | (fu)); \
+        cd->mcodeptr += 4; \
+    } while (0)
 
 #define M_FP2(fu, fmt, fs, fd)       M_RTYPE(0x11, fmt,  0, fs, fd, fu)
 #define M_FP3(fu, fmt, fs, ft, fd)   M_RTYPE(0x11, fmt, ft, fs, fd, fu)
@@ -357,25 +171,245 @@ part in reg.inc
 #define FMT_I  20
 #define FMT_L  21
 
-/* macros for all used commands (see a MIPS-manual for description) ***********/ 
+
+/* macros for all used commands (see a MIPS-manual for description) ***********/
 
 /* load/store macros use the form OPERATION(source/dest, base, offset)        */
 
+#define M_LDA(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_AADD_IMM(b,lo,a); \
+        } else { \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD_IMM(REG_ITMP3, lo, REG_ITMP3); \
+            M_AADD(b, REG_ITMP3, a); \
+        } \
+    } while (0)
+
 #define M_BLDS(a,b,disp)        M_ITYPE(0x20,b,a,disp)          /*  8 load    */
 #define M_BLDU(a,b,disp)        M_ITYPE(0x24,b,a,disp)          /*  8 load    */
 #define M_SLDS(a,b,disp)        M_ITYPE(0x21,b,a,disp)          /* 16 load    */
 #define M_SLDU(a,b,disp)        M_ITYPE(0x25,b,a,disp)          /* 16 load    */
-#define M_ILD(a,b,disp)         M_ITYPE(0x23,b,a,disp)          /* 32 load    */
-#define M_LLD(a,b,disp)         M_ITYPE(0x37,b,a,disp)          /* 64 load    */
+
+#define M_ILD_INTERN(a,b,disp)  M_ITYPE(0x23,b,a,disp)          /* 32 load    */
+
+#define M_ILD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_ILD_INTERN(a,b,lo); \
+        } else { \
+            M_LUI(a,hi); \
+            M_AADD(b,a,a); \
+            M_ILD_INTERN(a,a,lo); \
+        } \
+    } while (0)
+
+#if SIZEOF_VOID_P == 8
+
+#define M_LLD_INTERN(a,b,disp)  M_ITYPE(0x37,b,a,disp)          /* 64 load    */
+
+#else /* SIZEOF_VOID_P == 8 */
+
+# if WORDS_BIGENDIAN == 1
+
+/* ATTENTION: b may be equal to GET_LOW_REG(a) (displacement overflow case ) */
+
+#define M_LLD_INTERN(a,b,disp) \
+    do { \
+        M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
+        M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
+    } while (0)
+
+/* this macro is specially for ICMD_GETFIELD since the base (source)
+   register may be one of the destination registers */
+
+#define M_LLD_GETFIELD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            if (GET_HIGH_REG(a) == (b)) { \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
+            } else { \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
+            } \
+        } else { \
+            M_LUI(GET_LOW_REG(a), hi); \
+            M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
+            M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
+        } \
+    } while (0)
+
+# else /* if WORDS_BIGENDIAN == 1 */
+
+/* ATTENTION: b may be equal to GET_LOW_REG(a) (displacement overflow case ) */
+
+#define M_LLD_INTERN(a,b,disp) \
+    do { \
+        M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+        M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
+    } while (0)
+
+/* this macro is specially for ICMD_GETFIELD since the base (source)
+   register may be one of the destination registers */
+
+#define M_LLD_GETFIELD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            if (GET_HIGH_REG(a) == (b)) { \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+            } else { \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
+            } \
+        } else { \
+            M_LUI(GET_LOW_REG(a), hi); \
+            M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
+            M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
+        } \
+    } while (0)
+
+# endif /* if WORDS_BIGENDIAN == 1 */
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+#define M_LLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_LLD_INTERN(a, b, lo); \
+        } else { \
+            M_LUI(GET_LOW_REG(a), hi); \
+            M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
+            M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
+        } \
+    } while (0)
+
 #define M_BST(a,b,disp)         M_ITYPE(0x28,b,a,disp)          /*  8 store   */
 #define M_SST(a,b,disp)         M_ITYPE(0x29,b,a,disp)          /* 16 store   */
-#define M_IST(a,b,disp)         M_ITYPE(0x2b,b,a,disp)          /* 32 store   */
-#define M_LST(a,b,disp)         M_ITYPE(0x3f,b,a,disp)          /* 64 store   */
 
-#define M_FLD(a,b,disp)         M_ITYPE(0x31,b,a,disp)          /* load flt   */
-#define M_DLD(a,b,disp)         M_ITYPE(0x35,b,a,disp)          /* load dbl   */
-#define M_FST(a,b,disp)         M_ITYPE(0x39,b,a,disp)          /* store flt  */
-#define M_DST(a,b,disp)         M_ITYPE(0x3d,b,a,disp)          /* store dbl  */
+#define M_IST_INTERN(a,b,disp)  M_ITYPE(0x2b,b,a,disp)          /* 32 store   */
+
+#define M_IST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_IST_INTERN(a,b,lo); \
+        } else { \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_IST_INTERN(a, REG_ITMP3, lo); \
+        } \
+    } while (0)
+
+#if SIZEOF_VOID_P == 8
+
+#define M_LST_INTERN(a,b,disp)  M_ITYPE(0x3f,b,a,disp)          /* 64 store   */
+
+#else /* SIZEOF_VOID_P == 8 */
+
+#if WORDS_BIGENDIAN == 1
+
+#define M_LST_INTERN(a,b,disp) \
+    do { \
+        M_IST_INTERN(GET_HIGH_REG(a), b, disp); \
+        M_IST_INTERN(GET_LOW_REG(a), b, disp + 4); \
+    } while (0)
+
+#else /* if WORDS_BIGENDIAN == 1 */
+
+#define M_LST_INTERN(a,b,disp) \
+    do { \
+        M_IST_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+        M_IST_INTERN(GET_LOW_REG(a), b, disp); \
+    } while (0)
+
+#endif /* if WORDS_BIGENDIAN == 1 */
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+#define M_LST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_LST_INTERN(a,b,lo); \
+        } else { \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_LST_INTERN(a, REG_ITMP3, lo); \
+        } \
+    } while (0)
+
+#define M_FLD_INTERN(a,b,disp)  M_ITYPE(0x31,b,a,disp)          /* load flt   */
+#define M_DLD_INTERN(a,b,disp)  M_ITYPE(0x35,b,a,disp)          /* load dbl   */
+
+#define M_FLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_FLD_INTERN(a,b,lo); \
+        } else { \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_FLD_INTERN(a, REG_ITMP3, lo); \
+        } \
+    } while (0)
+
+#define M_DLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_DLD_INTERN(a,b,lo); \
+        } else { \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_DLD_INTERN(a, REG_ITMP3, lo); \
+        } \
+    } while (0)
+
+#define M_FST_INTERN(a,b,disp)  M_ITYPE(0x39,b,a,disp)          /* store flt  */
+#define M_DST_INTERN(a,b,disp)  M_ITYPE(0x3d,b,a,disp)          /* store dbl  */
+
+#define M_FST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_FST_INTERN(a,b,lo); \
+        } else { \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_FST_INTERN(a, REG_ITMP3, lo); \
+        } \
+    } while (0)
+
+#define M_DST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_DST_INTERN(a,b,lo); \
+        } else { \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_DST_INTERN(a, REG_ITMP3, lo); \
+        } \
+    } while (0)
 
 #define M_BEQ(a,b,disp)         M_ITYPE(0x04,a,b,disp)          /* br a == b  */
 #define M_BNE(a,b,disp)         M_ITYPE(0x05,a,b,disp)          /* br a != b  */
@@ -386,6 +420,7 @@ part in reg.inc
 #define M_BGEZ(a,disp)          M_ITYPE(0x01,a,1,disp)          /* br a >= 0  */
 #define M_BGTZ(a,disp)          M_ITYPE(0x07,a,0,disp)          /* br a >  0  */
 
+#if 0
 #define M_BEQL(a,b,disp)        M_ITYPE(0x14,a,b,disp)          /* br a == b  */
 #define M_BNEL(a,b,disp)        M_ITYPE(0x15,a,b,disp)          /* br a != b  */
 #define M_BEQZL(a,disp)         M_ITYPE(0x14,a,0,disp)          /* br a == 0  */
@@ -394,6 +429,7 @@ part in reg.inc
 #define M_BNEZL(a,disp)         M_ITYPE(0x15,a,0,disp)          /* br a != 0  */
 #define M_BGEZL(a,disp)         M_ITYPE(0x01,a,3,disp)          /* br a >= 0  */
 #define M_BGTZL(a,disp)         M_ITYPE(0x17,a,0,disp)          /* br a >  0  */
+#endif
 
 #define M_BR(disp)              M_ITYPE(0x04,0,0,disp)          /* branch     */
 #define M_BRS(disp)             M_ITYPE(0x01,0,17,disp)         /* branch sbr */
@@ -433,6 +469,7 @@ part in reg.inc
 #define M_ISUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x23)         /* 32 sub     */
 #define M_LSUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x2f)         /* 64 sub     */
 #define M_IMUL(a,b)             M_ITYPE(0,a,b,0x18)             /* 32 mul     */
+#define M_IMULU(a,b)            M_ITYPE(0,a,b,0x19)             /* 32 mul     */
 #define M_LMUL(a,b)             M_ITYPE(0,a,b,0x1c)             /* 64 mul     */
 #define M_IDIV(a,b)             M_ITYPE(0,a,b,0x1a)             /* 32 div     */
 #define M_LDIV(a,b)             M_ITYPE(0,a,b,0x1e)             /* 64 div     */
@@ -442,8 +479,8 @@ part in reg.inc
 
 #define M_IADD_IMM(a,b,c)       M_ITYPE(0x09,a,c,b)             /* 32 add     */
 #define M_LADD_IMM(a,b,c)       M_ITYPE(0x19,a,c,b)             /* 64 add     */
-#define M_ISUB_IMM(a,b,c)       M_ITYPE(0x09,a,c,-(b))          /* 32 sub     */
-#define M_LSUB_IMM(a,b,c)       M_ITYPE(0x19,a,c,-(b))          /* 64 sub     */
+#define M_ISUB_IMM(a,b,c)       M_IADD_IMM(a,-(b),c)            /* 32 sub     */
+#define M_LSUB_IMM(a,b,c)       M_LADD_IMM(a,-(b),c)            /* 64 sub     */
 
 #define M_LUI(a,imm)            M_ITYPE(0x0f,0,a,imm)           /* a = imm<<16*/
 
@@ -464,8 +501,6 @@ part in reg.inc
 #define M_OR_IMM( a,b,c)        M_ITYPE(0x0d,a,c,b)             /* c = a |  b */
 #define M_XOR_IMM(a,b,c)        M_ITYPE(0x0e,a,c,b)             /* c = a ^  b */
 
-#define M_CZEXT(a,c)            M_AND_IMM(a,0xffff,c)           /* c = zext(a)*/
-
 #define M_ISLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x04)         /* c = a << b */
 #define M_ISRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x06)         /* c = a >>>b */
 #define M_ISRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x07)         /* c = a >> b */
@@ -538,6 +573,9 @@ part in reg.inc
 #define M_MOVID(i,d)            M_FP3(0,4,d,i,0)                /* d = i      */
 #define M_MOVLD(l,d)            M_FP3(0,5,d,l,0)                /* d = l      */
 
+#define M_MFC1(l,f)             M_FP3(0,0,f,l,0)
+#define M_MTC1(l,f)             M_FP3(0,4,f,l,0)
+
 #define M_DMFC1(l,f)            M_FP3(0,1,f,l,0)
 #define M_DMTC1(l,f)            M_FP3(0,5,f,l,0)
 
@@ -566,63 +604,38 @@ part in reg.inc
 #define M_CMOVF(a,b)                   M_RTYPE(0x00,a,0,b,0,1)
 #define M_CMOVT(a,b)                   M_RTYPE(0x00,a,1,b,0,1)
 
+
 /*
  * Load Address pseudo instruction:
  * -n32 addressing mode -> 32 bit addrs, -64 addressing mode -> 64 bit addrs
  */
-#if POINTERSIZE==8
+#if SIZEOF_VOID_P == 8
+
 #define POINTERSHIFT 3
+
+#define M_ALD_INTERN(a,b,disp)  M_LLD_INTERN(a,b,disp)
 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)
+#define M_AST_INTERN(a,b,disp)  M_LST_INTERN(a,b,disp)
 #define M_AST(a,b,disp)         M_LST(a,b,disp)
 #define M_AADD(a,b,c)           M_LADD(a,b,c)
+#define M_AADD_IMM(a,b,c)       M_LADD_IMM(a,b,c)
+#define M_ASUB_IMM(a,b,c)       M_LSUB_IMM(a,b,c)
 #define M_ASLL_IMM(a,b,c)       M_LSLL_IMM(a,b,c)
-#define M_LDA(a,b,disp)         M_LADD_IMM(b,disp,a)            /* a = b+disp */
-#else
+
+#else /* SIZEOF_VOID_P == 8 */
+
 #define POINTERSHIFT 2
+
+#define M_ALD_INTERN(a,b,disp)  M_ILD_INTERN(a,b,disp)
 #define M_ALD(a,b,disp)         M_ILD(a,b,disp)
+#define M_AST_INTERN(a,b,disp)  M_IST_INTERN(a,b,disp)
 #define M_AST(a,b,disp)         M_IST(a,b,disp)
 #define M_AADD(a,b,c)           M_IADD(a,b,c)
+#define M_AADD_IMM(a,b,c)       M_IADD_IMM(a,b,c)
+#define M_ASUB_IMM(a,b,c)       M_ISUB_IMM(a,b,c)
 #define M_ASLL_IMM(a,b,c)       M_ISLL_IMM(a,b,c)
-#define M_LDA(a,b,disp)         M_IADD_IMM(b,disp,a)            /* a = b+disp */
-#endif
-
-/* macros for special commands (see an Alpha-manual for description) **********/ 
-
-#if 0
-#define M_CMOVEQ(a,b,c)         M_OP3 (0x11,0x24, a,b,c,0)     /* a==0 ? c=b  */
-#define M_CMOVNE(a,b,c)         M_OP3 (0x11,0x26, a,b,c,0)     /* a!=0 ? c=b  */
-#define M_CMOVLT(a,b,c)         M_OP3 (0x11,0x44, a,b,c,0)     /* a< 0 ? c=b  */
-#define M_CMOVGE(a,b,c)         M_OP3 (0x11,0x46, a,b,c,0)     /* a>=0 ? c=b  */
-#define M_CMOVLE(a,b,c)         M_OP3 (0x11,0x64, a,b,c,0)     /* a<=0 ? c=b  */
-#define M_CMOVGT(a,b,c)         M_OP3 (0x11,0x66, a,b,c,0)     /* a> 0 ? c=b  */
-
-#define M_CMOVEQ_IMM(a,b,c)     M_OP3 (0x11,0x24, a,b,c,1)     /* a==0 ? c=b  */
-#define M_CMOVNE_IMM(a,b,c)     M_OP3 (0x11,0x26, a,b,c,1)     /* a!=0 ? c=b  */
-#define M_CMOVLT_IMM(a,b,c)     M_OP3 (0x11,0x44, a,b,c,1)     /* a< 0 ? c=b  */
-#define M_CMOVGE_IMM(a,b,c)     M_OP3 (0x11,0x46, a,b,c,1)     /* a>=0 ? c=b  */
-#define M_CMOVLE_IMM(a,b,c)     M_OP3 (0x11,0x64, a,b,c,1)     /* a<=0 ? c=b  */
-#define M_CMOVGT_IMM(a,b,c)     M_OP3 (0x11,0x66, a,b,c,1)     /* a> 0 ? c=b  */
-#endif
-
-/* function gen_resolvebranch **************************************************
-
-       backpatches a branch instruction; MIPS branch instructions are very
-       regular, so it is only necessary to overwrite some fixed bits in the
-       instruction.
-
-       parameters: ip ... pointer to instruction after branch (void*)
-                   so ... offset of instruction after branch  (s4)
-                   to ... offset of branch target             (s4)
-
-*******************************************************************************/
-
-#define gen_resolvebranch(ip,so,to) \
-    ((s4 *) (ip))[-1] |= ((s4) (to) - (so)) >> 2 & 0xffff
-
-
-/* function prototypes */
 
-void docacheflush(u1 *p, long bytelen);
+#endif /* SIZEOF_VOID_P == 8 */
 
 #endif /* _CODEGEN_H */