* Removed all Id tags.
[cacao.git] / src / vm / jit / arm / md-abi.c
index eb547663f2028d0d29f9a865f5e813179cd8f8f4..8ba32c8ad90c2bb7a0866ac2d68d9a9b3ddd101d 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/arm/md-abi.c - functions for arm 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: Michael Starzinger
-
-   Changes: Christian Thalinger
-
-   $Id: md-abi.c 6548 2006-10-01 22:18:38Z edwin $
-
 */
 
 
 
 #include "vm/jit/arm/md-abi.h"
 
-#include "vm/descriptor.h"
 #include "vm/global.h"
+
 #include "vm/jit/abi.h"
 
+#include "vmcore/descriptor.h"
+
 
 /* register descripton array **************************************************/
 
@@ -51,6 +45,32 @@ s4 nregdescint[] = {
        REG_END
 };
 
+const char *abi_registers_integer_name[] = {
+       "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4",
+       "v5", "t3", "t1", "t2", "ip", "sp", "lr", "pc",
+};
+
+const s4 abi_registers_integer_argument[] = {
+       0,  /* a0 */
+       1,  /* a1 */
+       2,  /* a2 */
+       3,  /* a3 */
+       REG_SPLIT,
+};
+
+const s4 abi_registers_integer_saved[] = {
+       4,  /* s0 */
+       5,  /* s1 */
+       6,  /* s2 */
+       7,  /* s3 */
+       8,  /* s4 */
+};
+
+const s4 abi_registers_integer_temporary[] = {
+       -1,
+};
+
+
 #if defined(ENABLE_SOFTFLOAT)
 s4 nregdescfloat[] = {
        REG_RES, REG_RES, REG_RES, REG_RES,
@@ -66,6 +86,27 @@ s4 nregdescfloat[] = {
 };
 #endif /* defined(ENABLE_SOFTFLOAT) */
 
+const s4 abi_registers_float_argument[] = {
+       -1,
+};
+
+const s4 abi_registers_float_saved[] = {
+       -1,
+};
+
+const s4 abi_registers_float_temporary[] = {
+#if defined(ENABLE_SOFTFLOAT)
+       -1,
+#else
+       0,  /* ft0 */
+       1,  /* ft1 */
+       2,  /* ft2 */
+       3,  /* ft3 */
+       4,  /* ft4 */
+       5,  /* ft5 */
+#endif
+};
+
 
 /* md_param_alloc **************************************************************
 
@@ -92,10 +133,12 @@ void md_param_alloc(methoddesc *md)
        s4         stacksize;
 
        /* set default values */
-       reguse = 0;
+
+       reguse    = 0;
        stacksize = 0;
 
        /* get params field of methoddesc */
+
        pd = md->params;
 
        for (i = 0; i < md->paramcount; i++, pd++) {
@@ -105,41 +148,163 @@ void md_param_alloc(methoddesc *md)
                case TYPE_FLT:
                        if (reguse < INT_ARG_CNT) {
                                pd->inmemory = false;
-                               pd->regoff = reguse;
+                               pd->index    = reguse;
+                               pd->regoff   = abi_registers_integer_argument[reguse];
                                reguse++;
                        }
                        else {
                                pd->inmemory = true;
-                               pd->regoff = stacksize;
+                               pd->index    = stacksize;
+                               pd->regoff   = stacksize * 8;
                                stacksize++;
                        }
                        break;
 
                case TYPE_LNG:
                case TYPE_DBL:
-                       if (reguse+1 < INT_ARG_CNT) {
+                       /* interally we use the EABI */
+
+                       ALIGN_2(reguse);
+
+                       if (reguse < INT_ARG_CNT) {
                                pd->inmemory = false;
 #if defined(__ARMEL__)
-                               pd->regoff = PACK_REGS(reguse, reguse+1);
+                               pd->index    = PACK_REGS(reguse, reguse + 1);
+                               pd->regoff   =
+                                       PACK_REGS(abi_registers_integer_argument[reguse],
+                                                         abi_registers_integer_argument[reguse + 1]);
 #else
-                               pd->regoff = PACK_REGS(reguse+1, reguse);
+                               pd->index    = PACK_REGS(reguse + 1, reguse);
+                               pd->regoff   =
+                                       PACK_REGS(abi_registers_integer_argument[reguse + 1],
+                                                         abi_registers_integer_argument[reguse]);
 #endif
                                reguse += 2;
                        }
-                       else if (reguse < INT_ARG_CNT) {
+                       else {
+
+                               /*ALIGN_2(stacksize);*/
+
+                               pd->inmemory  = true;
+                               pd->index     = stacksize;
+                               pd->regoff    = stacksize * 8;
+                               /*stacksize    += 2;*/
+                               stacksize++;
+                       }
+                       break;
+               }
+       }
+
+       /* Since R0/R1 (==A0/A1) are used for passing return values, this
+          argument register usage has to be regarded, too. */
+
+       if (md->returntype.type != TYPE_VOID) {
+               if (!IS_2_WORD_TYPE(md->returntype.type)) {
+                       if (reguse < 1)
+                               reguse = 1;
+               }
+               else {
+                       if (reguse < 2)
+                               reguse = 2;
+               }
+       }
+
+       /* fill register and stack usage */
+
+       md->argintreguse = reguse;
+       md->argfltreguse = 0;
+       md->memuse       = stacksize;
+}
+
+
+/* md_param_alloc_native *******************************************************
+
+   Pre-allocate arguments according the native ABI.
+
+*******************************************************************************/
+
+void md_param_alloc_native(methoddesc *md)
+{
+       paramdesc *pd;
+       s4         i;
+       s4         reguse;
+       s4         stacksize;
+
+       /* set default values */
+
+       reguse    = 0;
+       stacksize = 0;
+
+       /* get params field of methoddesc */
+
+       pd = md->params;
+
+       for (i = 0; i < md->paramcount; i++, pd++) {
+               switch (md->paramtypes[i].type) {
+               case TYPE_INT:
+               case TYPE_ADR:
+               case TYPE_FLT:
+                       if (reguse < INT_ARG_CNT) {
+                               pd->inmemory = false;
+                               pd->index    = -1;
+                               pd->regoff   = abi_registers_integer_argument[reguse];
+                               reguse++;
+                       }
+                       else {
+                               pd->inmemory = true;
+                               pd->index    = -1;
+                               pd->regoff   = stacksize * 4;
+                               stacksize++;
+                       }
+                       break;
+
+               case TYPE_LNG:
+               case TYPE_DBL:
+                       if (reguse < (INT_ARG_CNT - 1)) {
+#if defined(__ARM_EABI__)
+                               ALIGN_2(reguse);
+#endif
                                pd->inmemory = false;
 #if defined(__ARMEL__)
-                               pd->regoff = PACK_REGS(reguse, INT_ARG_CNT);
+                               pd->index    = -1;
+                               pd->regoff   =
+                                       PACK_REGS(abi_registers_integer_argument[reguse],
+                                                         abi_registers_integer_argument[reguse + 1]);
 #else
-                               pd->regoff = PACK_REGS(INT_ARG_CNT, reguse);
+                               pd->index    = -1;
+                               pd->regoff   =
+                                       PACK_REGS(abi_registers_integer_argument[reguse + 1],
+                                                         abi_registers_integer_argument[reguse]);
 #endif
+                               reguse += 2;
+                       }
+#if !defined(__ARM_EABI__)
+                       else if (reguse < INT_ARG_CNT) {
+                               pd->inmemory = false;
+# if defined(__ARMEL__)
+                               pd->index    = -1;
+                               pd->regoff   =
+                                       PACK_REGS(abi_registers_integer_argument[reguse],
+                                                         abi_registers_integer_argument[INT_ARG_CNT]);
+# else
+                               pd->index    = -1;
+                               pd->regoff   =
+                                       PACK_REGS(abi_registers_integer_argument[INT_ARG_CNT],
+                                                         abi_registers_integer_argument[reguse]);
+# endif
                                reguse++;
                                stacksize++;
                        }
+#endif
                        else {
-                               pd->inmemory = true;
-                               pd->regoff = stacksize;
-                               stacksize += 2;
+#if defined(__ARM_EABI__)
+                               ALIGN_2(stacksize);
+#endif
+                               pd->inmemory  = true;
+                               pd->index     = -1;
+                               pd->regoff    = stacksize * 4;
+                               reguse        = INT_ARG_CNT;
+                               stacksize    += 2;
                        }
                        break;
                }