+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
+
+#if 0
+# define LOG(args) printf args
+#else
+# define LOG(args)
+#endif
+
+
+/* function prototypes for this file ******************************************/
+
+static void simplereg_allocate_interfaces(jitdata *jd);
+static void simplereg_allocate_locals(jitdata *jd);
+static void simplereg_allocate_temporaries(jitdata *jd);
+
+
+/* size of a stackslot used by the internal ABI */
+
+#if defined(HAS_4BYTE_STACKSLOT)
+# define SIZE_OF_STACKSLOT 4
+#else
+# define SIZE_OF_STACKSLOT 8
+#endif
+
+
+/* total number of registers */
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+#define TOTAL_REG_CNT (INT_REG_CNT + FLT_REG_CNT + ADR_REG_CNT)
+#else
+#define TOTAL_REG_CNT (INT_REG_CNT + FLT_REG_CNT)
+#endif
+
+
+/* macros for handling register stacks ****************************************/
+
+#define AVAIL_FRONT(cnt, limit) ((cnt) < (limit))
+#define AVAIL_BACK(cnt) ((cnt) > 0)
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define AVAIL_FRONT_INT(cnt, limit) ((cnt) < (limit) - intregsneeded)
+#define AVAIL_BACK_INT(cnt) ((cnt) > intregsneeded)
+#else
+#define AVAIL_FRONT_INT(cnt, limit) AVAIL_FRONT(cnt, limit)
+#define AVAIL_BACK_INT(cnt) AVAIL_BACK(cnt)
+#endif
+
+#define POP_FRONT(stk, cnt, reg) do { reg = stk[cnt++]; } while (0)
+#define POP_BACK(stk, cnt, reg) do { reg = stk[--cnt]; } while (0)
+#define PUSH_FRONT(stk, cnt, reg) do { stk[--cnt] = (reg); } while (0)
+#define PUSH_BACK(stk, cnt, reg) do { stk[cnt++] = (reg); } while (0)
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define POP_FRONT_INT(stk, cnt, reg) \
+ do { \
+ if (intregsneeded) { \
+ reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
+ cnt += 2; \
+ } \
+ else \
+ POP_FRONT(stk, cnt, reg); \
+ } while (0)
+#else
+#define POP_FRONT_INT(stk, cnt, reg) POP_FRONT(stk, cnt, reg)
+#endif
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define POP_BACK_INT(stk, cnt, reg) \
+ do { \
+ if (intregsneeded) { \
+ cnt -= 2; \
+ reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
+ } \
+ else \
+ POP_BACK(stk, cnt, reg); \
+ } while (0)
+#else
+#define POP_BACK_INT(stk, cnt, reg) POP_BACK(stk, cnt, reg)
+#endif
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define PUSH_BACK_INT(stk, cnt, reg) \
+ do { \
+ if (intregsneeded) { \
+ stk[cnt] = GET_LOW_REG(reg); \
+ stk[cnt + 1] = GET_HIGH_REG(reg); \
+ cnt += 2; \
+ } \
+ else \
+ PUSH_BACK(stk, cnt, reg); \
+ } while (0)
+#else
+#define PUSH_BACK_INT(stk, cnt, reg) PUSH_BACK(stk, cnt, reg)
+#endif
+
+#define AVAIL_ARG_FLT AVAIL_FRONT(rd->argfltreguse, FLT_ARG_CNT)
+#define AVAIL_TMP_FLT AVAIL_BACK(rd->tmpfltreguse)
+#define AVAIL_SAV_FLT AVAIL_BACK(rd->savfltreguse)
+
+#define AVAIL_ARG_ADR AVAIL_FRONT(rd->argadrreguse, ADR_ARG_CNT)
+#define AVAIL_TMP_ADR AVAIL_BACK(rd->tmpadrreguse)
+#define AVAIL_SAV_ADR AVAIL_BACK(rd->savadrreguse)
+
+#define AVAIL_ARG_INT AVAIL_FRONT_INT(rd->argintreguse, INT_ARG_CNT)
+#define AVAIL_TMP_INT AVAIL_BACK_INT(rd->tmpintreguse)
+#define AVAIL_SAV_INT AVAIL_BACK_INT(rd->savintreguse)
+
+#define AVAIL_FREE_ARG_FLT AVAIL_BACK(rd->freeargflttop)
+#define AVAIL_FREE_TMP_FLT AVAIL_BACK(rd->freetmpflttop)
+#define AVAIL_FREE_SAV_FLT AVAIL_BACK(rd->freesavflttop)
+
+#define AVAIL_FREE_ARG_ADR AVAIL_BACK(rd->freeargadrtop)
+#define AVAIL_FREE_TMP_ADR AVAIL_BACK(rd->freetmpadrtop)
+#define AVAIL_FREE_SAV_ADR AVAIL_BACK(rd->freesavadrtop)
+
+#define AVAIL_FREE_ARG_INT AVAIL_BACK_INT(rd->freearginttop)
+#define AVAIL_FREE_TMP_INT AVAIL_BACK_INT(rd->freetmpinttop)
+#define AVAIL_FREE_SAV_INT AVAIL_BACK_INT(rd->freesavinttop)
+
+#define TAKE_ARG_FLT(r) POP_FRONT(abi_registers_float_argument, rd->argfltreguse, r)
+#define TAKE_TMP_FLT(r) POP_BACK(rd->tmpfltregs, rd->tmpfltreguse, r)
+#define TAKE_SAV_FLT(r) POP_BACK(rd->savfltregs, rd->savfltreguse, r)
+
+#define TAKE_ARG_ADR(r) POP_FRONT(rd->argadrregs, rd->argadrreguse, r)
+#define TAKE_TMP_ADR(r) POP_BACK(rd->tmpadrregs, rd->tmpadrreguse, r)
+#define TAKE_SAV_ADR(r) POP_BACK(rd->savadrregs, rd->savadrreguse, r)
+
+#define TAKE_ARG_INT(r) POP_FRONT_INT(abi_registers_integer_argument, rd->argintreguse, r)
+#define TAKE_TMP_INT(r) POP_BACK_INT(rd->tmpintregs, rd->tmpintreguse, r)
+#define TAKE_SAV_INT(r) POP_BACK_INT(rd->savintregs, rd->savintreguse, r)
+
+#define TAKE_FREE_ARG_FLT(r) POP_BACK(rd->freeargfltregs, rd->freeargflttop, r)
+#define TAKE_FREE_TMP_FLT(r) POP_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
+#define TAKE_FREE_SAV_FLT(r) POP_BACK(rd->freesavfltregs, rd->freesavflttop, r)
+
+#define TAKE_FREE_ARG_ADR(r) POP_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
+#define TAKE_FREE_TMP_ADR(r) POP_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
+#define TAKE_FREE_SAV_ADR(r) POP_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
+
+#define TAKE_FREE_ARG_INT(r) POP_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
+#define TAKE_FREE_TMP_INT(r) POP_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
+#define TAKE_FREE_SAV_INT(r) POP_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
+
+#define PUSH_FREE_ARG_FLT(r) PUSH_BACK(rd->freeargfltregs, rd->freeargflttop, r)
+#define PUSH_FREE_TMP_FLT(r) PUSH_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
+#define PUSH_FREE_SAV_FLT(r) PUSH_BACK(rd->freesavfltregs, rd->freesavflttop, r)
+
+#define PUSH_FREE_ARG_ADR(r) PUSH_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
+#define PUSH_FREE_TMP_ADR(r) PUSH_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
+#define PUSH_FREE_SAV_ADR(r) PUSH_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
+
+#define PUSH_FREE_ARG_INT(r) PUSH_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
+#define PUSH_FREE_TMP_INT(r) PUSH_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
+#define PUSH_FREE_SAV_INT(r) PUSH_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
+
+
+/* macros for allocating memory slots ****************************************/
+
+#define NEW_MEM_SLOT(r) \
+ do { \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
+ rd->memuse += memneeded + 1; \
+ } while (0)
+
+#define NEW_MEM_SLOT_ALIGNED(r) \
+ do { \
+ if ( (memneeded) && (rd->memuse & 1)) \
+ rd->memuse++; \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
+ rd->memuse += memneeded + 1; \
+ } while (0)
+
+#define NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r) \
+ do { \
+ if ( (memneeded) && (rd->memuse & 1)) { \
+ PUSH_BACK(rd->freemem, rd->freememtop, rd->memuse); \
+ rd->memuse++; \
+ } \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
+ rd->memuse += memneeded + 1; \
+ } while (0)
+
+#if defined(ALIGN_LONGS_IN_MEMORY)
+#define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT_ALIGNED(r)
+#else
+#define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT(r)
+#endif
+
+#if defined(ALIGN_DOUBLES_IN_MEMORY)
+#define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT_ALIGNED(r)
+#else
+#define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT(r)
+#endif
+
+#if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
+#define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r)
+#else
+#define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT(r)
+#endif
+
+
+/* macros for creating/freeing temporary variables ***************************/
+
+#define NEW_TEMP_REG(index) \
+ if ( ((index) >= jd->localcount) \
+ && (!(VAR(index)->flags & (INOUT | PREALLOC))) ) \
+ simplereg_new_temp(jd, (index))