Added some missing vim modelines.
[cacao.git] / src / vm / jit / x86_64 / md-abi.c
index f0ef4b841e4b2c700d355146d0d5bd41db9a5366..c250388c777afa2eebdcb49910bd9c3a65576630 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/x86_64/md-abi.c - functions for x86_64 Linux ABI
 
-   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, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    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.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+*/
 
-   Authors: Christian Thalinger
 
-   Changes:
+#include "config.h"
+#include "vm/types.h"
 
-   $Id: md-abi.c 2588 2005-06-08 10:58:04Z twisti $
+#include "vm/jit/x86_64/md-abi.h"
 
-*/
+#include "vm/descriptor.hpp"
+#include "vm/global.h"
 
+#include "vm/jit/abi.h"
+#include "vm/jit/jit.hpp" /* for REG_* (maybe can be removed) */
+#include "vm/jit/stack.h"
 
-#include "vm/jit/x86_64/types.h"
-#include "vm/jit/x86_64/md-abi.h"
 
-#include "vm/descriptor.h"
-#include "vm/global.h"
+/* register descripton array **************************************************/
+
+s4 nregdescint[] = {
+    REG_RET, REG_ARG, REG_ARG, REG_TMP, REG_RES, REG_SAV, REG_ARG, REG_ARG,
+    REG_ARG, REG_ARG, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+    REG_END
+};
+
+const char *abi_registers_integer_name[] = {
+       "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+       "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15"
+};
+
+const s4 abi_registers_integer_argument[] = {
+       7,  /* a0 */
+       6,  /* a1 */
+       2,  /* a2 */
+       1,  /* a3 */
+       8,  /* a4 */
+       9,  /* a5 */
+};
+
+const s4 abi_registers_integer_saved[] = {
+       5,  /* s0 */
+       12, /* s1 */
+       13, /* s2 */
+       14, /* s3 */
+       15, /* s4 */
+};
+
+const s4 abi_registers_integer_temporary[] = {
+       3,  /* t0 */
+};
+
+
+/* float registers *************************************************************
+
+   xmm0,   xmm1,   xmm2,   xmm3,   xmm4,   xmm5,   xmm6,   xmm7,
+   (fa0)   (fa1)   (fa2)   (fa3)   (fa4)   (fa5)   (fa6)   (fa7)
+
+   xmm8,   xmm9,   xmm10,  xmm11,  xmm12,  xmm13,  xmm14,  xmm15
+   (ftmp1) (ftmp2) (ftmp3) (ft0)   (ft1)   (ft2)   (ft3)   (ft4)
+
+*******************************************************************************/
+
+s4 nregdescfloat[] = {
+    REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+    REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+    REG_END
+};
+
+
+const s4 abi_registers_float_argument[] = {
+       0,  /* fa0 */
+       1,  /* fa1 */
+       2,  /* fa2 */
+       3,  /* fa3 */
+       4,  /* fa4 */
+       5,  /* fa5 */
+       6,  /* fa6 */
+       7,  /* fa7 */
+};
+
+const s4 abi_registers_float_saved[] = {
+       -1,
+};
+
+const s4 abi_registers_float_temporary[] = {
+       11, /* ft0 */
+       12, /* ft1 */
+       13, /* ft2 */
+       14, /* ft3 */
+       15, /* ft4 */
+};
 
 
 /* md_param_alloc **************************************************************
@@ -56,8 +128,8 @@ void md_param_alloc(methoddesc *md)
 
        /* set default values */
 
-       iarg = 0;
-       farg = 0;
+       iarg      = 0;
+       farg      = 0;
        stacksize = 0;
 
        /* get params field of methoddesc */
@@ -71,39 +143,128 @@ void md_param_alloc(methoddesc *md)
                case TYPE_LNG:
                        if (iarg < INT_ARG_CNT) {
                                pd->inmemory = false;
-                               pd->regoff = iarg;
-
-                       } else {
-                               pd->inmemory = true;
-                               pd->regoff = stacksize;
-                       }
-                       if (iarg < INT_ARG_CNT)
+                               pd->index    = iarg;
+                               pd->regoff   = abi_registers_integer_argument[iarg];
                                iarg++;
-                       else
+                       }
+                       else {
+                               pd->inmemory = true;
+                               pd->index    = stacksize;
+                               pd->regoff   = stacksize * 8;
                                stacksize++;
+                       }
                        break;
+
                case TYPE_FLT:
                case TYPE_DBL:
                        if (farg < FLT_ARG_CNT) {
                                pd->inmemory = false;
-                               pd->regoff = farg;
-                       } else {
-                               pd->inmemory = true;
-                               pd->regoff = stacksize;
-                       }
-                       if (farg < FLT_ARG_CNT)
+                               pd->index    = farg;
+                               pd->regoff   = abi_registers_float_argument[farg];
                                farg++;
-                       else
+                       }
+                       else {
+                               pd->inmemory = true;
+                               pd->index    = stacksize;
+                               pd->regoff   = stacksize * 8;
                                stacksize++;
+                       }
                        break;
                }
        }
 
+       /* Since XMM0 (==A0) is used for passing return values, this
+          argument register usage has to be regarded, too. */
+
+       if (IS_FLT_DBL_TYPE(md->returntype.type))
+               if (farg < 1)
+                       farg = 1;
+
        /* fill register and stack usage */
 
        md->argintreguse = iarg;
        md->argfltreguse = farg;
-       md->memuse = stacksize;
+       md->memuse       = stacksize;
+}
+
+
+/* md_param_alloc_native *******************************************************
+
+   Pre-allocate arguments according the native ABI.
+
+*******************************************************************************/
+
+void md_param_alloc_native(methoddesc *md)
+{
+       /* On x86_64 we use the same ABI for JIT method calls as for
+          native method calls. */
+
+       md_param_alloc(md);
+}
+
+
+/* md_return_alloc *************************************************************
+
+   Precolor the Java Stackelement containing the Return Value. Only
+   for float/ double types straight forward possible, since INT_LNG
+   types use "reserved" registers Float/Double values use a00 as
+   return register.
+
+   --- in
+   jd:                      jitdata of the current method
+   stackslot:               Java Stackslot to contain the Return Value
+
+   --- out
+   if precoloring was possible:
+   VAR(stackslot->varnum)->flags     = PREALLOC
+                                    ->vv.regoff = [REG_RESULT|REG_FRESULT]
+   rd->arg[flt|int]reguse   set to a value according the register usage
+
+   NOTE: Do not pass a LOCALVAR in stackslot->varnum.
+
+*******************************************************************************/
+
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
+{
+       methodinfo   *m;
+       codeinfo     *code;
+       registerdata *rd;
+       methoddesc   *md;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       rd   = jd->rd;
+
+       md = m->parseddesc;
+
+       /* precoloring only straightforward possible with flt/dbl types
+          For Address/Integer/Long REG_RESULT == rax == REG_ITMP1 and so
+          could be destroyed if the return value Stack Slot "lives too
+          long" */
+
+       if (IS_FLT_DBL_TYPE(md->returntype.type)) {
+               /* In Leafmethods Local Vars holding parameters are precolored
+                  to their argument register -> so leafmethods with
+                  paramcount > 0 could already use a00! */
+
+               if (!code_is_leafmethod(code) || (md->paramcount == 0)) {
+                       /* Only precolor the stackslot, if it is not a SAVEDVAR
+                          <-> has not to survive method invokations */
+
+                       if (!(stackslot->flags & SAVEDVAR)) {
+
+                               VAR(stackslot->varnum)->flags = PREALLOC;
+
+                           /* float/double */
+                               if (rd->argfltreguse < 1)
+                                       rd->argfltreguse = 1;
+
+                               VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
+                       }
+               }
+       }
 }
 
 
@@ -118,4 +279,5 @@ void md_param_alloc(methoddesc *md)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */