From 22ee80835eb2c1e7f9fba67d3e5fcbc6c6d71583 Mon Sep 17 00:00:00 2001 From: christian Date: Wed, 8 Jun 2005 14:41:35 +0000 Subject: [PATCH] Moved abi stuff to machine depended files --- src/vm/jit/i386/Makefile.am | 5 +- src/vm/jit/i386/arch.h | 49 +--- src/vm/jit/i386/codegen.c | 457 ++++++++++++++++++++---------------- src/vm/jit/i386/codegen.h | 62 +---- src/vm/jit/i386/emitfuncs.c | 3 +- src/vm/jit/i386/md-abi.c | 89 +++++++ src/vm/jit/i386/md-abi.h | 101 ++++++++ src/vm/jit/i386/md-abi.inc | 80 +++++++ 8 files changed, 532 insertions(+), 314 deletions(-) create mode 100644 src/vm/jit/i386/md-abi.c create mode 100644 src/vm/jit/i386/md-abi.h create mode 100644 src/vm/jit/i386/md-abi.inc diff --git a/src/vm/jit/i386/Makefile.am b/src/vm/jit/i386/Makefile.am index cff7e4085..5b0f60193 100644 --- a/src/vm/jit/i386/Makefile.am +++ b/src/vm/jit/i386/Makefile.am @@ -28,7 +28,7 @@ ## ## Changes: ## -## $Id: Makefile.am 2341 2005-04-22 13:33:39Z twisti $ +## $Id: Makefile.am 2605 2005-06-08 14:41:35Z christian $ ## Process this file with automake to produce Makefile.in @@ -41,6 +41,7 @@ CLEANFILES = offsets.h noinst_HEADERS = \ arch.h \ machine-instr.h \ + md-abi.h \ types.h noinst_LTLIBRARIES = libarch.la @@ -59,6 +60,8 @@ libarch_la_SOURCES = \ emitfuncs.c \ emitfuncs.h \ i386-dis.c \ + md-abi.inc \ + md-abi.c \ patcher.c \ symcat.h diff --git a/src/vm/jit/i386/arch.h b/src/vm/jit/i386/arch.h index b58140f5e..322dc436c 100644 --- a/src/vm/jit/i386/arch.h +++ b/src/vm/jit/i386/arch.h @@ -28,7 +28,7 @@ Changes: - $Id: arch.h 2477 2005-05-13 14:04:16Z twisti $ + $Id: arch.h 2605 2005-06-08 14:41:35Z christian $ */ @@ -48,50 +48,6 @@ #define ESI 6 #define EDI 7 - -/* preallocated registers *****************************************************/ - -/* integer registers */ - -#define REG_RESULT EAX /* to deliver method results */ -#define REG_RESULT2 EDX /* to deliver long method results */ - -#define REG_ITMP1 EAX /* temporary register */ -#define REG_ITMP2 ECX /* temporary register */ -#define REG_ITMP3 EDX /* temporary register */ - -#define REG_NULL -1 /* used for reg_of_var where d is not needed */ - -#define REG_ITMP1_XPTR EAX /* exception pointer = temporary register 1 */ -#define REG_ITMP2_XPC ECX /* exception pc = temporary register 2 */ - -#define REG_SP ESP /* stack pointer */ - -/* floating point registers */ - -#define REG_FRESULT 0 /* to deliver floating point method results */ -#define REG_FTMP1 6 /* temporary floating point register */ -#define REG_FTMP2 7 /* temporary floating point register */ -#define REG_FTMP3 7 /* temporary floating point register */ - - -#define INT_REG_CNT 8 /* number of integer registers */ -#define INT_SAV_CNT 3 /* number of integer callee saved registers */ -#define INT_ARG_CNT 0 /* number of integer argument registers */ -#define INT_TMP_CNT 1 /* number of integer temporary registers */ -#define INT_RES_CNT 3 /* numebr of integer reserved registers */ - -#define FLT_REG_CNT 8 /* number of float registers */ -#define FLT_SAV_CNT 0 /* number of float callee saved registers */ -#define FLT_ARG_CNT 0 /* number of float argument registers */ -#define FLT_TMP_CNT 0 /* number of float temporary registers */ -#define FLT_RES_CNT 8 /* numebr of float reserved registers */ - -#define TRACE_ARGS_NUM 8 - -#define REG_RES_CNT 3 /* number of reserved registers */ - - /* define architecture features ***********************************************/ #define POINTERSIZE 4 @@ -132,9 +88,6 @@ #define HAS_4BYTE_STACKSLOT /* define SUPPORT_COMBINE_INTEGER_REGISTERS */ -/* #define CONSECUTIVE_INTEGER_ARGS */ -/* #define CONSECUTIVE_FLOAT_ARGS */ - #endif /* _ARCH_H */ diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index c804d979c..195722686 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -29,7 +29,7 @@ Changes: Joseph Wenninger - $Id: codegen.c 2481 2005-05-17 09:05:33Z twisti $ + $Id: codegen.c 2605 2005-06-08 14:41:35Z christian $ */ @@ -44,6 +44,10 @@ #endif #include "config.h" + +#include "vm/jit/i386/md-abi.h" +#include "vm/jit/i386/md-abi.inc" + #include "cacao/cacao.h" #include "native/jni.h" #include "native/native.h" @@ -64,33 +68,6 @@ #include "vm/jit/i386/types.h" #include "vm/jit/i386/asmoffsets.h" - -/* register descripton - array ************************************************/ - -/* #define REG_RES 0 reserved register for OS or code generator */ -/* #define REG_RET 1 return value register */ -/* #define REG_EXC 2 exception value register (only old jit) */ -/* #define REG_SAV 3 (callee) saved register */ -/* #define REG_TMP 4 scratch temporary register (caller saved) */ -/* #define REG_ARG 5 argument register (caller saved) */ - -/* #define REG_END -1 last entry in tables */ - -static int nregdescint[] = { - REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV, - REG_END -}; - - -static int nregdescfloat[] = { - /* rounding problems with callee saved registers */ -/* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */ -/* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */ - REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, - REG_END -}; - - /******************************************************************************* include independent code generation stuff -- include after register @@ -249,11 +226,14 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd) s4 parentargs_base; u2 currentline; s4 fpu_st_offset = 0; + methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ + builtintable_entry *bte; + methoddesc *md; exceptiontable *ex; { - s4 i, p, pa, t, l; + s4 i, p, t, l; s4 savedregs_num = 0; s4 stack_off = 0; @@ -344,87 +324,114 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd) /* take arguments out of register or stack frame */ + md = m->parseddesc; + stack_off = 0; - for (p = 0, l = 0; p < m->paramcount; p++) { - t = m->paramtypes[p]; + for (p = 0, l = 0; p < md->paramcount; p++) { + t = md->paramtypes[p].type; var = &(rd->locals[l][t]); l++; if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */ l++; - if (var->type >= 0) { - if (IS_INT_LNG_TYPE(t)) { /* integer args */ - if (p < rd->intreg_argnum) { /* register arguments */ - log_text("integer register argument"); - assert(0); - if (!(var->flags & INMEMORY)) { /* reg arg -> register */ - /* M_INTMOVE (argintregs[p], r); */ - - } else { /* reg arg -> spilled */ - /* M_LST (argintregs[p], REG_SP, 8 * r); */ - } - } else { /* stack arguments */ - /* pa = p - rd->intreg_argnum; */ - if (!(var->flags & INMEMORY)) { /* stack arg -> register */ - i386_mov_membase_reg(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4, var->regoff); /* + 4 for return address */ - } else { /* stack arg -> spilled */ - if (!IS_2_WORD_TYPE(t)) { - /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4, REG_ITMP1) */; /* + 4 for return address */ -/* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4); */ - var->regoff = parentargs_base + stack_off + 1; + if (var->type < 0) + continue; + s1 = md->params[p].regoff; + if (IS_INT_LNG_TYPE(t)) { /* integer args */ + if (!md->params[p].inmemory) { /* register arguments */ + log_text("integer register argument"); + assert(0); + if (!(var->flags & INMEMORY)) { /* reg arg -> register */ + /* rd->argintregs[md->params[p].regoff -> var->regoff */ + } else { /* reg arg -> spilled */ + /* rd->argintregs[md->params[p].regoff -> var->regoff * 4 */ + } + } else { /* stack arguments */ + if (!(var->flags & INMEMORY)) { /* stack arg -> register */ + i386_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (parentargs_base + s1) * 4 + 4, var->regoff); + /* + 4 for return address */ + } else { /* stack arg -> spilled */ + if (!IS_2_WORD_TYPE(t)) { +#if 0 + i386_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (parentargs_base + s1) * 4 + 4, + REG_ITMP1); + i386_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4); +#else + /* reuse Stackslotand avoid copying */ + var->regoff = parentargs_base + s1 + 1; +#endif - } else { - /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4, REG_ITMP1); */ /* + 4 for return address */ -/* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4); */ - /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4 + 4, REG_ITMP1); *//* + 4 for return address */ -/* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4); */ - var->regoff = parentargs_base + stack_off + 1; - } + } else { +#if 0 + i386_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (parentargs_base + s1) * 4 + 4, + REG_ITMP1); + i386_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4); + i386_mov_membase_reg( /* + 4 for return address */ + cd, REG_SP, (parentargs_base + s1) * 4 + 4 + 4, + REG_ITMP1); + i386_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4 + 4); +#else + /* reuse Stackslotand avoid copying */ + var->regoff = parentargs_base + s1 + 1; +#endif } } + } - } else { /* floating args */ - if (p < rd->fltreg_argnum) { /* register arguments */ - log_text("There are no float argument registers!"); - assert(0); - - if (!(var->flags & INMEMORY)) { /* reg arg -> register */ - } else { /* reg arg -> spilled */ - } + } else { /* floating args */ + if (!md->params[p].inmemory) { /* register arguments */ + log_text("There are no float argument registers!"); + assert(0); + if (!(var->flags & INMEMORY)) { /* reg arg -> register */ + /* rd->argfltregs[md->params[p].regoff -> var->regoff */ + } else { /* reg arg -> spilled */ + /* rd->argfltregs[md->params[p].regoff -> var->regoff * 4 */ + } - } else { /* stack arguments */ - /* pa = p - rd->fltreg_argnum; */ - if (!(var->flags & INMEMORY)) { /* stack-arg -> register */ - if (t == TYPE_FLT) { - i386_flds_membase(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4); - fpu_st_offset++; - i386_fstp_reg(cd, var->regoff + fpu_st_offset); - fpu_st_offset--; + } else { /* stack arguments */ + if (!(var->flags & INMEMORY)) { /* stack-arg -> register */ + if (t == TYPE_FLT) { + i386_flds_membase( + cd, REG_SP, (parentargs_base + s1) * 4 + 4); + fpu_st_offset++; + i386_fstp_reg(cd, var->regoff + fpu_st_offset); + fpu_st_offset--; - } else { - i386_fldl_membase(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4); - fpu_st_offset++; - i386_fstp_reg(cd, var->regoff + fpu_st_offset); - fpu_st_offset--; - } - - } else { /* stack-arg -> spilled */ -/* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */ -/* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */ - if (t == TYPE_FLT) { -/* i386_flds_membase(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4); */ -/* i386_fstps_membase(cd, REG_SP, var->regoff * 4); */ - var->regoff = parentargs_base + stack_off + 1; + } else { + i386_fldl_membase( + cd, REG_SP, (parentargs_base + s1) * 4 + 4); + fpu_st_offset++; + i386_fstp_reg(cd, var->regoff + fpu_st_offset); + fpu_st_offset--; + } - } else { -/* i386_fldl_membase(cd, REG_SP, (parentargs_base + stack_off) * 4 + 4); */ -/* i386_fstpl_membase(cd, REG_SP, var->regoff * 4); */ - var->regoff = parentargs_base + stack_off + 1; - } + } else { /* stack-arg -> spilled */ +#if 0 + i386_mov_membase_reg( + cd, REG_SP, (parentargs_base + s1) * 4 + 4, REG_ITMP1); + i386_mov_reg_membase( + cd, REG_ITMP1, REG_SP, var->regoff * 4); + if (t == TYPE_FLT) { + i386_flds_membase( + cd, REG_SP, (parentargs_base + s1) * 4 + 4); + i386_fstps_membase(cd, REG_SP, var->regoff * 4); + } else { + i386_fldl_membase( + cd, REG_SP, (parentargs_base + s1) * 4 + 4); + i386_fstpl_membase(cd, REG_SP, var->regoff * 4); } +#else + /* reuse Stackslotand avoid copying */ + var->regoff = parentargs_base + s1 + 1; +#endif } } } - stack_off += (IS_2_WORD_TYPE(t)) ? 2 : 1; } /* end for */ /* call monitorenter function */ @@ -467,8 +474,8 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd) for (p = 0; p < INT_TMP_CNT; p++) M_IST(rd->tmpintregs[p], REG_SP, TRACE_ARGS_NUM * 8 + 4 + p * 4); - for (p = 0, l=0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) { - t = m->paramtypes[p]; + for (p = 0, l = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) { + t = md->paramtypes[p].type; if (IS_INT_LNG_TYPE(t)) { if (IS_2_WORD_TYPE(t)) { @@ -477,18 +484,18 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd) i386_mov_membase_reg(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + (parentargs_base + stack_off) * 4 + 4 + 4, REG_ITMP1); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4); -/* } else if (t == TYPE_ADR) { */ - } else { + } else if (t == TYPE_ADR) { +/* } else { */ i386_mov_membase_reg(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + (parentargs_base + stack_off) * 4 + 4, REG_ITMP1); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8); i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4); -/* } else { */ -/* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */ -/* i386_cltd(cd); */ -/* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */ -/* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */ + } else { + i386_mov_membase_reg(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + (parentargs_base + stack_off) * 4 + 4, EAX); + i386_cltd(cd); + i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); + i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); } } else { @@ -508,7 +515,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd) /* fill up the remaining arguments */ i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); - for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) { + for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) { i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4); } @@ -4327,125 +4334,94 @@ nowperformreturn: } break; - - case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */ - /* op1 = return type, val.a = function pointer*/ + case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ + /* op1 = arg count val.a = builtintable entry */ /* REG_RES Register usage: see icmd_uses_reg_res.inc */ /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/ - s3 = 3; - goto gen_method; - - case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */ - /* op1 = return type, val.a = function pointer*/ - /* REG_RES Register usage: see icmd_uses_reg_res.inc */ - /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/ - s3 = 2; - goto gen_method; - - case ICMD_BUILTIN1: /* ..., arg1 ==> ... */ - /* op1 = return type, val.a = function pointer*/ - /* REG_RES Register usage: see icmd_uses_reg_res.inc */ - /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/ - s3 = 1; + bte = (builtintable_entry *) iptr->val.a; + md = bte->md; goto gen_method; case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */ /* op1 = arg count, val.a = method pointer */ - /* REG_RES Register usage: see icmd_uses_reg_res.inc */ - /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/ case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */ - /* op1 = arg count, val.a = method pointer */ + case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ + case ICMD_INVOKEINTERFACE: /* REG_RES Register usage: see icmd_uses_reg_res.inc */ /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/ - case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */ - /* op1 = arg count, val.a = method pointer */ - /* REG_RES Register usage: see icmd_uses_reg_res.inc */ - /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/ + lm = iptr->val.a; - case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */ - /* op1 = arg count, val.a = method pointer */ - /* REG_RES Register usage: see icmd_uses_reg_res.inc */ - /* EAX: S|YES ECX: YES EDX: YES OUTPUT: EAX*/ + if (lm) + md = lm->parseddesc; + else { + unresolved_method *um = iptr->target; + md = um->methodref->parseddesc.md; + } +gen_method: s3 = iptr->op1; -gen_method: { - methodinfo *lm; - s4 stack_off = 0; - s4 arg_num; - stackptr src_save; - MCODECHECK((s3 << 1) + 64); /* copy arguments to registers or stack location */ - arg_num=s3; - src_save = src; - for (; --s3 >= 0; src = src->prev) - stack_off += IS_2_WORD_TYPE(src->type) ? 2 : 1; - - s3 = arg_num; - src = src_save; - - for (; --s3 >= 0; src = src->prev) { - stack_off -= IS_2_WORD_TYPE(src->type) ? 2 : 1; + for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) { if (src->varkind == ARGVAR) continue; - if (IS_INT_LNG_TYPE(src->type)) { - if (s3 < rd->intreg_argnum) { + if (!md->params[s3].inmemory) { log_text("No integer argument registers available!"); assert(0); - } else { if (!IS_2_WORD_TYPE(src->type)) { if (src->flags & INMEMORY) { - i386_mov_membase_reg(cd, REG_SP, src->regoff * 4, REG_ITMP1); - i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stack_off * 4); + i386_mov_membase_reg( + cd, REG_SP, src->regoff * 4, REG_ITMP1); + i386_mov_reg_membase( + cd, REG_ITMP1, REG_SP, + md->params[s3].regoff * 4); } else { - i386_mov_reg_membase(cd, src->regoff, REG_SP, stack_off * 4); + i386_mov_reg_membase( + cd, src->regoff, REG_SP, + md->params[s3].regoff * 4); } } else { if (src->flags & INMEMORY) { - M_LNGMEMMOVE(src->regoff, stack_off); - + M_LNGMEMMOVE( + src->regoff, md->params[s3].regoff * 4); } else { log_text("copy arguments: longs have to be in memory"); assert(0); } } } - } else { - if (s3 < rd->fltreg_argnum) { + if (!md->params[s3].inmemory) { log_text("No float argument registers available!"); assert(0); - } else { var_to_reg_flt(d, src, REG_FTMP1); if (src->type == TYPE_FLT) { - i386_fstps_membase(cd, REG_SP, stack_off * 4); + i386_fstps_membase( + cd, REG_SP, md->params[s3].regoff * 4); } else { - i386_fstpl_membase(cd, REG_SP, stack_off * 4); + i386_fstpl_membase( + cd, REG_SP, md->params[s3].regoff * 4); } } } } /* end of for */ - lm = iptr->val.a; switch (iptr->opc) { - case ICMD_BUILTIN3: - case ICMD_BUILTIN2: - case ICMD_BUILTIN1: - d = iptr->op1; + case ICMD_BUILTIN: + d = md->returntype.type; if (iptr->target) { - codegen_addpatchref(cd, cd->mcodeptr, - (functionptr) lm, iptr->target); + codegen_addpatchref(cd, cd->mcodeptr, bte->fp, iptr->target); if (showdisassemble) { M_NOP; M_NOP; M_NOP; M_NOP; M_NOP; @@ -4454,7 +4430,7 @@ gen_method: { a = 0; } else { - a = (ptrint) lm; + a = (ptrint) bte->fp; } i386_mov_imm_reg(cd, a, REG_ITMP1); @@ -4482,7 +4458,7 @@ gen_method: { } a = 0; - d = um->methodref->parseddesc.md->returntype.type; + d = md->returntype.type; } else { a = (ptrint) lm->stubroutine; @@ -4508,12 +4484,12 @@ gen_method: { } s1 = 0; - d = um->methodref->parseddesc.md->returntype.type; + d = md->returntype.type; } else { s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex; - d = lm->parseddesc->returntype.type; + d = md->returntype.type; } i386_mov_membase_reg(cd, REG_ITMP1, @@ -4539,7 +4515,7 @@ gen_method: { s1 = 0; s2 = 0; - d = um->methodref->parseddesc.md->returntype.type; + d = md->returntype.type; } else { s1 = OFFSET(vftbl_t, interfacetable[0]) - @@ -4547,7 +4523,7 @@ gen_method: { s2 = sizeof(methodptr) * (lm - lm->class->methods); - d = lm->parseddesc->returntype.type; + d = md->returntype.type; } i386_mov_membase_reg(cd, REG_ITMP1, @@ -4567,9 +4543,11 @@ gen_method: { if (IS_INT_LNG_TYPE(iptr->dst->type)) { if (IS_2_WORD_TYPE(iptr->dst->type)) { if (iptr->dst->flags & INMEMORY) { - i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4); - i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 4 + 4); - + i386_mov_reg_membase( + cd, REG_RESULT, REG_SP, iptr->dst->regoff * 4); + i386_mov_reg_membase( + cd, REG_RESULT2, REG_SP, + iptr->dst->regoff * 4 + 4); } else { log_text("RETURN: longs have to be in memory"); assert(0); @@ -4590,7 +4568,6 @@ gen_method: { store_reg_to_var_flt(iptr->dst, d); } } - } break; @@ -5700,9 +5677,16 @@ u1 *createnativestub(functionptr f, methodinfo *m) codegendata *cd; registerdata *rd; t_inlining_globals *id; + methoddesc *md; + methoddesc *nmd; + s4 nativeparams; + s4 i, j; /* count variables */ + s4 t; + s4 s1, s2; s4 dumpsize; - s4 i; +#if 0 u1 *tptr; +#endif s4 stackframesize; s4 stackframeoffset; bool require_clinit_call; @@ -5711,9 +5695,14 @@ u1 *createnativestub(functionptr f, methodinfo *m) u1 *jmpInstrPos; s4 *jmpInstrPatchPos; + /* set some variables */ + + nativeparams = (m->flags & ACC_STATIC) ? 2 : 1; + /* initial 4 bytes is space for jni env, + 4 byte thread pointer + 4 byte */ /* previous pointer + method info + 4 offset native */ - stackframesize = 4 + 16; + /* already handled by nmd->memuse */ + stackframesize = /* 4 + */ 16; stackframeoffset = 4; /* mark start of dump memory area */ @@ -5731,7 +5720,27 @@ u1 *createnativestub(functionptr f, methodinfo *m) inlining_setup(m, id); reg_setup(m, rd, id); - method_descriptor2types(m); /* set paramcount and paramtypes */ + /* create new method descriptor with additional native parameters */ + + md = m->parseddesc; + + nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) + + md->paramcount * sizeof(typedesc) + + nativeparams * sizeof(typedesc)); + + nmd->paramcount = md->paramcount + nativeparams; + + nmd->params = DMNEW(paramdesc, nmd->paramcount); + + nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */ + + if (m->flags & ACC_STATIC) + nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */ + + MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc, + md->paramcount); + + md_param_alloc(nmd); require_clinit_call = (m->flags & ACC_STATIC) && !m->class->initialized; @@ -5772,7 +5781,8 @@ u1 *createnativestub(functionptr f, methodinfo *m) /* if function is static, check for initialized */ if (m->flags & ACC_STATIC) { - stackframesize += 4; + /* already handled by nmd->memuse */ +/* stackframesize += 4; */ stackframeoffset += 4; /* if class isn't yet initialized, do it */ @@ -5791,23 +5801,27 @@ u1 *createnativestub(functionptr f, methodinfo *m) i386_alu_imm_reg(cd, ALU_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP); - for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) { - t = m->paramtypes[p]; + for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) { + t = md->paramtypes[p].type; if (IS_INT_LNG_TYPE(t)) { if (IS_2_WORD_TYPE(t)) { - i386_mov_membase_reg(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, REG_ITMP1); - i386_mov_membase_reg(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off + 4, REG_ITMP2); + i386_mov_membase_reg(cd, REG_SP, + 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, REG_ITMP1); + i386_mov_membase_reg(cd, REG_SP, + 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off + 4, REG_ITMP2); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8); i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4); } else if (t == TYPE_ADR) { - i386_mov_membase_reg(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, REG_ITMP1); + i386_mov_membase_reg(cd, REG_SP, + 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, REG_ITMP1); i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8); i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4); } else { - i386_mov_membase_reg(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, EAX); + i386_mov_membase_reg(cd, REG_SP, + 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off, EAX); i386_cltd(cd); i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); @@ -5815,13 +5829,15 @@ u1 *createnativestub(functionptr f, methodinfo *m) } else { if (!IS_2_WORD_TYPE(t)) { - i386_flds_membase(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off); + i386_flds_membase(cd, REG_SP, + 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off); i386_fstps_membase(cd, REG_SP, p * 8); i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP2, REG_ITMP2); i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4); } else { - i386_fldl_membase(cd, REG_SP, 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off); + i386_fldl_membase(cd, REG_SP, + 4 + TRACE_ARGS_NUM * 8 + 4 + stack_off); i386_fstpl_membase(cd, REG_SP, p * 8); } } @@ -5829,7 +5845,7 @@ u1 *createnativestub(functionptr f, methodinfo *m) } i386_alu_reg_reg(cd, ALU_XOR, REG_ITMP1, REG_ITMP1); - for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) { + for (p = md->paramcount; p < TRACE_ARGS_NUM; p++) { i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8); i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4); } @@ -5854,10 +5870,14 @@ u1 *createnativestub(functionptr f, methodinfo *m) i386_ffree_reg(cd, 7); /* calculate stackframe size for native function */ - tptr = m->paramtypes; - for (i = 0; i < m->paramcount; i++) { +#if 0 + tptr = md->paramtypes; + for (i = 0; i < md->paramcount; i++) { stackframesize += IS_2_WORD_TYPE(*tptr++) ? 8 : 4; } +#else + stackframesize += nmd->memuse * 4; +#endif /* align Stackframe to 8 Byte */ /* if ((stackframesize + 1) & 1) */ @@ -5869,9 +5889,11 @@ u1 *createnativestub(functionptr f, methodinfo *m) i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8); i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1); i386_call_reg(cd, REG_ITMP1); - i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-12); /*save thread specific pointer*/ + /*save thread specific pointer*/ + i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-12); i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); - i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-16); /*save previous value of memory adress pointed to by thread specific pointer*/ + /*save previous value of memory adress pointed to by thread specific pointer*/ + i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-16); i386_mov_reg_reg(cd, REG_SP,REG_ITMP2); i386_alu_imm_reg(cd, ALU_ADD,stackframesize-16,REG_ITMP2); i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0); @@ -5922,26 +5944,55 @@ u1 *createnativestub(functionptr f, methodinfo *m) /* RESOLVE NATIVE METHOD -- END*/ /* copy arguments into new stackframe */ - +#if 0 { s4 stack_off = 0; tptr = m->paramtypes; for (i = 0; i < m->paramcount; i++) { if (IS_2_WORD_TYPE(*tptr++)) { - i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + stack_off, REG_ITMP1); - i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + stack_off + 4, REG_ITMP2); - i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset + stack_off); - i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + stack_off + 4); + i386_mov_membase_reg( + cd, REG_SP, stackframesize + (1 * 4) + stack_off, + REG_ITMP1); + i386_mov_membase_reg( + cd, REG_SP, stackframesize + (1 * 4) + stack_off + 4, + REG_ITMP2); + i386_mov_reg_membase( + cd, REG_ITMP1, REG_SP, stackframeoffset + stack_off); + i386_mov_reg_membase( + cd, REG_ITMP2, REG_SP, stackframeoffset + stack_off + 4); stack_off += 8; } else { - i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + stack_off, REG_ITMP1); - i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset + stack_off); + i386_mov_membase_reg( + cd, REG_SP, stackframesize + (1 * 4) + stack_off, + REG_ITMP1); + i386_mov_reg_membase( + cd, REG_ITMP1, REG_SP, stackframeoffset + stack_off); stack_off += 4; } } } +#endif + /* copy arguments into new stackframe */ + for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) { + t = md->paramtypes[i].type; + + if (!md->params[i].inmemory) { + /* no integer argument registers */ + } else { /* float/double in memory can be copied like int/longs */ + s1 = md->params[i].regoff * 4 + stackframesize + (1 * 4); + s2 = nmd->params[j].regoff * 4; + + i386_mov_membase_reg(cd, REG_SP, s1, REG_ITMP1); + i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s2); + if (IS_2_WORD_TYPE(t)) { + i386_mov_membase_reg(cd, REG_SP, s1 + 4, REG_ITMP1); + i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s2 + 4); + } + } + } + /* if function is static, put class into second argument */ diff --git a/src/vm/jit/i386/codegen.h b/src/vm/jit/i386/codegen.h index e98472db4..60c5c7694 100644 --- a/src/vm/jit/i386/codegen.h +++ b/src/vm/jit/i386/codegen.h @@ -29,7 +29,7 @@ Changes: - $Id: codegen.h 2496 2005-05-23 08:06:06Z twisti $ + $Id: codegen.h 2605 2005-06-08 14:41:35Z christian $ */ @@ -44,66 +44,6 @@ #define LSRA_USES_REG_RES #endif -/* 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: Number of arguments for this method -curstack: instack of the method invokation - ---- uses -i, copy - ---- out -copy: Points to first stackslot after the parameters -rd->ifmemuse: max. number of stackslots used for spilling parameters - so far -************************************************************************/ -#if defined(HAS_4BYTE_STACKSLOT) -#define SET_ARG_STACKSLOTS { \ - s4 stacksize = 0; \ - copy = curstack; \ - while (--i >= 0) { \ - stacksize+=IS_2_WORD_TYPE(copy->type)?2:1; \ - copy = copy->prev; \ - } \ - i=call_argcount; \ - copy=curstack; \ - if (stacksize > rd->ifmemuse) \ - rd->ifmemuse = stacksize; \ - while (--i >= 0) { \ - stacksize -= IS_2_WORD_TYPE(copy->type)?2:1; \ - if (!(copy->flags & SAVEDVAR)) { \ - copy->varkind = ARGVAR; \ - copy->varnum = i; \ - copy->flags |= INMEMORY; \ - copy->regoff = stacksize; \ - } \ - copy = copy->prev; \ - } \ - } -#else -#define SET_ARG_STACKSLOTS { \ - copy = curstack; \ - if (i > rd->ifmemuse) \ - rd->ifmemuse = i; \ - while (--i >= 0) { \ - if (!(copy->flags & SAVEDVAR)) { \ - copy->varkind = ARGVAR; \ - copy->varnum = i; \ - copy->flags |= INMEMORY; \ - copy->regoff = i; \ - } \ - copy = copy->prev; \ - } \ - } -#endif /* defined(HAS_4BYTE_STACKSLOTS) */ - /* additional functions and macros to generate code ***************************/ #define BlockPtrOfPC(pc) ((basicblock *) iptr->target) diff --git a/src/vm/jit/i386/emitfuncs.c b/src/vm/jit/i386/emitfuncs.c index e344d8ce7..22c072da1 100644 --- a/src/vm/jit/i386/emitfuncs.c +++ b/src/vm/jit/i386/emitfuncs.c @@ -26,12 +26,13 @@ Authors: Christian Thalinger - $Id: emitfuncs.c 2466 2005-05-13 09:04:04Z twisti $ + $Id: emitfuncs.c 2605 2005-06-08 14:41:35Z christian $ */ #include "vm/statistics.h" #include "vm/jit/jit.h" +#include "vm/jit/i386/md-abi.h" #include "vm/jit/i386/emitfuncs.h" #include "vm/jit/i386/codegen.h" #include "vm/jit/i386/types.h" diff --git a/src/vm/jit/i386/md-abi.c b/src/vm/jit/i386/md-abi.c new file mode 100644 index 000000000..38595dc0f --- /dev/null +++ b/src/vm/jit/i386/md-abi.c @@ -0,0 +1,89 @@ +/* src/vm/jit/i386/md-abi.c - functions for i386 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 + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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: Christian Thalinger + + Changes: + + $Id: md-abi.c 2605 2005-06-08 14:41:35Z christian $ + +*/ + + +#include "vm/jit/i386/types.h" +#include "vm/jit/i386/md-abi.h" + +#include "vm/descriptor.h" +#include "vm/global.h" + + +/* md_param_alloc ************************************************************** + +Allocate Arguments to Stackslots according the Calling Conventions + +--- in +md->paramcount: Number of arguments for this method +md->paramtypes[].type: Argument types + +--- out +md->params[].inmemory: Argument spilled on stack +md->params[].regoff: Stack offset or rd->arg[int|flt]regs index +md->memuse: Stackslots needed for argument spilling +md->argintreguse: max number of integer arguments used +md->argfltreguse: max number of float arguments used + +*******************************************************************************/ +void md_param_alloc(methoddesc *md) +{ + paramdesc *pd; + s4 stacksize; + int i; + + pd = md->params; + stacksize = 0; + + for (i = 0; i < md->paramcount; i++, pd++) { + pd->inmemory = true; + pd->regoff = stacksize; + stacksize += IS_2_WORD_TYPE(md->paramtypes[i].type) ? 2 : 1; + } + md->memuse = stacksize; + md->argintreguse = 0; + md->argfltreguse = 0; +} + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/src/vm/jit/i386/md-abi.h b/src/vm/jit/i386/md-abi.h new file mode 100644 index 000000000..af1ad69d4 --- /dev/null +++ b/src/vm/jit/i386/md-abi.h @@ -0,0 +1,101 @@ +/* src/vm/jit/i386/md-abi.h - defines for i386 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 + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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: Christian Thalinger + + Changes: + + $Id: md-abi.h 2605 2005-06-08 14:41:35Z christian $ + +*/ + + +#ifndef _MD_ABI_H +#define _MD_ABI_H + +#include "vm/descriptor.h" + +/* preallocated registers *****************************************************/ + +/* integer registers */ + +#define REG_RESULT EAX /* to deliver method results */ +#define REG_RESULT2 EDX /* to deliver long method results */ + +#define REG_ITMP1 EAX /* temporary register */ +#define REG_ITMP2 ECX /* temporary register */ +#define REG_ITMP3 EDX /* temporary register */ + +#define REG_NULL -1 /* used for reg_of_var where d is not needed */ + +#define REG_ITMP1_XPTR EAX /* exception pointer = temporary register 1 */ +#define REG_ITMP2_XPC ECX /* exception pc = temporary register 2 */ + +#define REG_SP ESP /* stack pointer */ + +/* floating point registers */ + +#define REG_FRESULT 0 /* to deliver floating point method results */ +#define REG_FTMP1 6 /* temporary floating point register */ +#define REG_FTMP2 7 /* temporary floating point register */ +#define REG_FTMP3 7 /* temporary floating point register */ + + +#define INT_REG_CNT 8 /* number of integer registers */ +#define INT_SAV_CNT 3 /* number of integer callee saved registers */ +#define INT_ARG_CNT 0 /* number of integer argument registers */ +#define INT_TMP_CNT 1 /* number of integer temporary registers */ +#define INT_RES_CNT 3 /* numebr of integer reserved registers */ + +#define FLT_REG_CNT 8 /* number of float registers */ +#define FLT_SAV_CNT 0 /* number of float callee saved registers */ +#define FLT_ARG_CNT 0 /* number of float argument registers */ +#define FLT_TMP_CNT 0 /* number of float temporary registers */ +#define FLT_RES_CNT 8 /* numebr of float reserved registers */ + +#define TRACE_ARGS_NUM 8 + +#define REG_RES_CNT 3 /* number of reserved registers */ + +/* function prototypes ********************************************************/ + +void md_param_alloc(methoddesc *md); + +#endif /* _MD_ABI_H */ + + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/src/vm/jit/i386/md-abi.inc b/src/vm/jit/i386/md-abi.inc new file mode 100644 index 000000000..94efad47d --- /dev/null +++ b/src/vm/jit/i386/md-abi.inc @@ -0,0 +1,80 @@ +/* src/vm/jit/i386/md-abi.inc - stuff for i386 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 + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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: Christian Thalinger + + Changes: + + $Id: md-abi.inc 2605 2005-06-08 14:41:35Z christian $ + +*/ + + +#ifndef _MD_ABI_INC +#define _MD_ABI_INC + +#include "vm/jit/jit.h" + +/* register descripton - array ************************************************/ + +/* #define REG_RES 0 reserved register for OS or code generator */ +/* #define REG_RET 1 return value register */ +/* #define REG_EXC 2 exception value register (only old jit) */ +/* #define REG_SAV 3 (callee) saved register */ +/* #define REG_TMP 4 scratch temporary register (caller saved) */ +/* #define REG_ARG 5 argument register (caller saved) */ + +/* #define REG_END -1 last entry in tables */ + +static int nregdescint[] = { + REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV, + REG_END +}; + + +static int nregdescfloat[] = { + /* rounding problems with callee saved registers */ + /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */ + /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */ + REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, + REG_END +}; + +#endif /* _MD_ABI_INC */ + + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ -- 2.25.1