* Removed all Id tags.
[cacao.git] / src / vm / jit / powerpc64 / linux / md-abi.c
index e2f7b70b0d4c645e044187e64d5127feb40f7b40..4349b45bddd594e987069e01f7c565be59c50bf9 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc64/linux/md-abi.c - functions for PowerPC64 Linux ABI
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Roland Lezuo
-
-   Changes: 
-
-   $Id: md-abi.c 5115 2006-07-12 14:55:04Z twisti $
-
 */
 
 
 #include "config.h"
+
+#include <assert.h>
+
 #include "vm/types.h"
 
 #include "vm/jit/powerpc64/linux/md-abi.h"
 
-#include "vm/descriptor.h"
 #include "vm/global.h"
+
 #include "vm/jit/abi.h"
 
+#include "vmcore/descriptor.h"
 
-#define _ALIGN(a)    do { if ((a) & 1) (a)++; } while (0)
+
+#define CACAO_ALIGN(a)    do { if ((a) & 1) (a)++; } while (0)
 
 
 /* register descripton array **************************************************/
 
 s4 nregdescint[] = {
-        /* zero,      sp,     TOC,   a0/v0,   a0/v1,      a2,      a3,      a4,   */
-        REG_RES, REG_RES, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+       /* zero,      sp,     TOC,   a0/v0,   a1/v1,      a2,      a3,      a4,   */
+       REG_RES, REG_RES, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+
+       /*   a5,      a6,      a7,   itmp1,   itmp2, NO(SYS),      pv,      s0,   */
+       REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_RES, REG_SAV,
+
+       /*itmp3,      t0,      t1,      t2,      t3,      t4,      t5,      t6,   */
+       REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
 
-        /*   a5,      a6,      a7,   itmp1,   itmp2, NO(SYS),      pv,      s0,   */
-        REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
+       /*   s1,      s2,      s3,      s4,      s5,      s6,      s7,      s8,   */
+       REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
 
-        /*itmp3,      t0,      t1,      t2,      t3,      t4,      t5,      t6,   */
-        REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+       REG_END
+};
 
-        /*   s1,      s2,      s3,      s4,      s5,      s6,      s7,      s8,   */
-        REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+const char *abi_registers_integer_name[] = {
+       "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+       "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
+       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+       "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+};
 
-        REG_END
+const s4 abi_registers_integer_argument[] = {
+       3,  /* a0 */
+       4,  /* a1 */
+       5,  /* a2 */
+       6,  /* a3 */
+       7,  /* a4 */
+       8,  /* a5 */
+       9,  /* a6 */
+       10, /* a7 */
 };
 
-char *regs[] = {
-        "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
-        "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
-        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
-        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+const s4 abi_registers_integer_saved[] = {
+       15, /* s0 */
+       24, /* s1 */
+       25, /* s2 */
+       26, /* s3 */
+       27, /* s4 */
+       28, /* s5 */
+       29, /* s6 */
+       30, /* s7 */
+       31, /* s8 */
+};
+
+const s4 abi_registers_integer_temporary[] = {
+       17, /* t0 */
+       18, /* t1 */
+       19, /* t2 */
+       20, /* t3 */
+       21, /* t4 */
+       22, /* t5 */
+       23, /* t6 */
 };
 
 
 s4 nregdescfloat[] = {
-        /*ftmp3,  fa0/v0,     fa1,     fa2,     fa3,     fa4,     fa5,     fa6,   */
-        REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+       /*ftmp3,  fa0/v0,     fa1,     fa2,     fa3,     fa4,     fa5,     fa6,   */
+       REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+
+       /*  fa7,     fa8,     fa9,    fa10,    fa11,    fa12,   ftmp1,   ftmp2,   */
+       REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES,
+
+       /*  fs0,     fs1,     fs2,     fs3,     fs4,     fs5,     fs6,     fs7    */
+       REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
 
-        /*  fa7,     ft0,     ft1,     ft2,     ft3,     ft4,     fs0,     fs1,   */
-        REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_SAV, REG_SAV,
+       /*  fs8,     fs9,    fs10,    fs11,    fs12,    fs13,    fs14,    fs15    */
+       REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
 
-        /*ftmp1,   ftmp2,     ft5,     ft6,     ft7,     ft8,     ft9,    ft10,   */
-        REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+       REG_END
+};
+
+const s4 abi_registers_float_argument[] = {
+       1,  /* fa0  */
+       2,  /* fa1  */
+       3,  /* fa2  */
+       4,  /* fa3  */
+       5,  /* fa4  */
+       6,  /* fa5  */
+       7,  /* fa6  */
+       8,  /* fa7  */
+       9,  /* fa8  */
+       10, /* fa9  */
+       11, /* fa10 */
+       12, /* fa11 */
+       13, /* fa12 */
+};
 
-        /*  fs2,     fs3,     fs4,     fs5,     fs6,     fs7,     fs8,     fs9    */
-        REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+const s4 abi_registers_float_saved[] = {
+       16, /* fs0  */
+       17, /* fs1  */
+       18, /* fs2  */
+       19, /* fs3  */
+       20, /* fs4  */
+       21, /* fs5  */
+       22, /* fs6  */
+       23, /* fs7  */
+       24, /* fs8  */
+       25, /* fs9  */
+       26, /* fs10 */
+       27, /* fs11 */
+       28, /* fs12 */
+       29, /* fs13 */
+       30, /* fs14 */
+       31, /* fs15 */
+};
 
-        REG_END
+const s4 abi_registers_float_temporary[] = {
+       -1,
 };
 
+
 /* md_param_alloc **************************************************************
 
    Allocate Arguments to Stackslots according the Calling Conventions
@@ -111,13 +181,17 @@ void md_param_alloc(methoddesc *md)
        s4         i;
        s4         iarg;
        s4         farg;
-       s4         stacksize;
+       s4         arg;
+       s4         stacksize, stackcount;
+
 
        /* set default values */
 
-       iarg = 0;
-       farg = 0;
-       stacksize = LA_WORD_SIZE;
+       iarg       = 0;
+       farg       = 0;
+       arg        = 0;
+       stacksize  = LA_SIZE_IN_POINTERS;
+       stackcount = 0;
 
        /* get params field of methoddesc */
 
@@ -125,75 +199,76 @@ void md_param_alloc(methoddesc *md)
 
        for (i = 0; i < md->paramcount; i++, pd++) {
                switch (md->paramtypes[i].type) {
+               case TYPE_LNG:
                case TYPE_INT:
                case TYPE_ADR:
                        if (iarg < INT_ARG_CNT) {
                                pd->inmemory = false;
-                               pd->regoff = iarg;
+                               pd->index = iarg;
+                               pd->regoff   = abi_registers_integer_argument[iarg];
                                iarg++;
-                       } else {
-                               pd->inmemory = true;
-                               pd->regoff = stacksize;
-                               stacksize++;
                        }
-                       break;
-               case TYPE_LNG:
-                       if (iarg < INT_ARG_CNT - 1) {
-                               _ALIGN(iarg);
-                               pd->inmemory = false;
-                                                            /* rd->arg[int|flt]regs index !! */
-                               pd->regoff = PACK_REGS(iarg + 1, iarg); 
-                               iarg += 2;
-                       } else {
-                               _ALIGN(stacksize);
+                       else {
                                pd->inmemory = true;
-                               pd->regoff = stacksize;
-                               iarg = INT_ARG_CNT;
-                               stacksize += 2;
+                               pd->index = stacksize + stackcount;
+                               pd->regoff   = (stacksize + stackcount) * 8;
                        }
                        break;
                case TYPE_FLT:
-                       if (farg < FLT_ARG_CNT) {
-                               pd->inmemory = false;
-                               pd->regoff = farg;
-                               farg++;
-                       } else {
-                               pd->inmemory = true;
-                               pd->regoff = stacksize;
-                               stacksize++;
-                       }
-                       break;
                case TYPE_DBL:
                        if (farg < FLT_ARG_CNT) {
                                pd->inmemory = false;
-                               pd->regoff = farg;
+                               pd->index = farg;
+                               pd->regoff   = abi_registers_float_argument[farg];
                                farg++;
-                       } else {
-                               _ALIGN(stacksize);
+                               if (arg < INT_ARG_CNT) {
+                                       iarg++;         /* yes, that is true, floating arguments take int register slots away */
+                               }
+                       }
+                       else {
                                pd->inmemory = true;
-                               pd->regoff = stacksize;
-                               stacksize += 2;
+                               pd->index = stacksize + stackcount;
+                               pd->regoff   = (stacksize + stackcount) * 8;
                        }
                        break;
+               default:
+                       assert(0);
                }
+               arg++;
+               stackcount++;
        }
 
-       /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */
+       /* Since R3, F1 (==A0, A0) are used for passing return values, this */
        /* argument register usage has to be regarded, too                        */
        if (IS_INT_LNG_TYPE(md->returntype.type)) {
-               if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1))
-                       iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1;
-       } else {
-               if (IS_FLT_DBL_TYPE(md->returntype.type))
-                       if (farg < 1)
-                               farg = 1;
+               if (iarg < 1)
+                       iarg = 1;
+       }
+       else if (IS_FLT_DBL_TYPE(md->returntype.type)) {
+               if (farg < 1)
+                       farg = 1;
        }
 
-       /* fill register and stack usage */
+       /* fill register and stack usage, parameter areas is at least PA_SIZE_IN_POINTERS */
 
        md->argintreguse = iarg;
        md->argfltreguse = farg;
-       md->memuse = stacksize;
+       md->memuse = stacksize + (stackcount<PA_SIZE_IN_POINTERS? PA_SIZE_IN_POINTERS: stackcount);     
+}
+
+
+/* md_param_alloc_native *******************************************************
+
+   Pre-allocate arguments according the native ABI.
+
+*******************************************************************************/
+
+void md_param_alloc_native(methoddesc *md)
+{
+       /* On PowerPC64 we use the same ABI for JIT method calls as for
+          native method calls. */
+
+       md_param_alloc(md);
 }
 
 
@@ -204,17 +279,13 @@ void md_param_alloc(methoddesc *md)
    for float/double)
 
    --- in
-   m:                       Methodinfo of current method
-   return_type:             Return Type of the Method (TYPE_INT.. TYPE_ADR)
-                            TYPE_VOID is not allowed!
+   jd:                      jitdata of the current method
    stackslot:               Java Stackslot to contain the Return Value
 
    --- out
    if precoloring was possible:
-   stackslot->varkind       =ARGVAR
-            ->varnum        =-1
-               ->flags         =0
-               ->regoff        =[REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT]
+   VAR(stackslot->varnum)->flags     = PREALLOC
+   VAR(stackslot->varnum)->vv.regoff = [REG_RESULT, REG_FRESULT]
    rd->arg[flt|int]reguse   set to a value according the register usage
 
 *******************************************************************************/
@@ -238,34 +309,24 @@ void md_return_alloc(jitdata *jd, stackptr stackslot)
           their argument register -> so leafmethods with paramcount > 0
           could already use R3 == a00! */
 
-       if (!code->isleafmethod || (md->paramcount == 0)) {
+       if (!jd->isleafmethod || (md->paramcount == 0)) {
                /* Only precolor the stackslot, if it is not a SAVEDVAR <->
                   has not to survive method invokations. */
 
                if (!(stackslot->flags & SAVEDVAR)) {
-                       stackslot->varkind = ARGVAR;
-                       stackslot->varnum = -1;
-                       stackslot->flags = 0;
-
-                       if (IS_INT_LNG_TYPE(md->returntype.type)) {
-                               if (!IS_2_WORD_TYPE(md->returntype.type)) {
-                                       if (rd->argintreguse < 1)
-                                               rd->argintreguse = 1;
 
-                                       stackslot->regoff = REG_RESULT;
+                       VAR(stackslot->varnum)->flags = PREALLOC;
 
-                               } else {
-                                       if (rd->argintreguse < 2)
-                                               rd->argintreguse = 2;
-
-       /*                                      stackslot->regoff = PACK_REGS(REG_RESULT2, REG_RESULT); // FIXME */
-                               }
+                       if (IS_INT_LNG_TYPE(md->returntype.type)) {
+                               if (rd->argintreguse < 1)
+                                       rd->argintreguse = 1;
 
+                               VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
                        } else { /* float/double */
                                if (rd->argfltreguse < 1)
                                        rd->argfltreguse = 1;
 
-                               stackslot->regoff = REG_FRESULT;
+                               VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
                        }
                }
        }