From f6856f7d2d71ca7e0b4d5022cb159ae8ed2f072c Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 8 Jul 2011 18:59:48 +0000 Subject: [PATCH] Changed internal opcode names to always specify variable type. The x86 jit appears to work properly after quick tests. Needs wider testing. Currently disabled still. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3857 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/execloop.h | 25 +- engine/qclib/initlib.c | 5 - engine/qclib/pr_comp.h | 72 +++--- engine/qclib/pr_exec.c | 4 +- engine/qclib/pr_multi.c | 3 +- engine/qclib/pr_x86.c | 454 +++++++++++++++++++++++++------------ engine/qclib/progsint.h | 7 +- engine/qclib/qcc_pr_comp.c | 194 ++++++++-------- engine/qclib/qccmain.c | 2 + engine/qclib/qcdecomp.c | 4 +- 10 files changed, 469 insertions(+), 301 deletions(-) diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index 5164c5dad..08d0ce9fd 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -101,16 +101,16 @@ reeval: OPC->_vector[2] = OPB->_float / OPA->_vector[2]; break; - case OP_BITAND: + case OP_BITAND_F: OPC->_float = (float)((int)OPA->_float & (int)OPB->_float); break; - case OP_BITOR: + case OP_BITOR_F: OPC->_float = (float)((int)OPA->_float | (int)OPB->_float); break; - case OP_GE: + case OP_GE_F: OPC->_float = (float)(OPA->_float >= OPB->_float); break; case OP_GE_I: @@ -123,7 +123,7 @@ reeval: OPC->_float = (float)(OPA->_float >= OPB->_int); break; - case OP_LE: + case OP_LE_F: OPC->_float = (float)(OPA->_float <= OPB->_float); break; case OP_LE_I: @@ -136,7 +136,7 @@ reeval: OPC->_float = (float)(OPA->_float <= OPB->_int); break; - case OP_GT: + case OP_GT_F: OPC->_float = (float)(OPA->_float > OPB->_float); break; case OP_GT_I: @@ -149,7 +149,7 @@ reeval: OPC->_float = (float)(OPA->_float > OPB->_int); break; - case OP_LT: + case OP_LT_F: OPC->_float = (float)(OPA->_float < OPB->_float); break; case OP_LT_I: @@ -162,10 +162,10 @@ reeval: OPC->_float = (float)(OPA->_float < OPB->_int); break; - case OP_AND: + case OP_AND_F: OPC->_float = (float)(OPA->_float && OPB->_float); break; - case OP_OR: + case OP_OR_F: OPC->_float = (float)(OPA->_float || OPB->_float); break; @@ -511,7 +511,7 @@ reeval: st += (sofs)st->b - 1; // offset the s++ break; - case OP_IFNOT: + case OP_IFNOT_I: RUNAWAYCHECK(); if (!OPA->_int) st += (sofs)st->b - 1; // offset the s++ @@ -529,7 +529,7 @@ reeval: st += (sofs)st->b - 1; // offset the s++ break; - case OP_IF: + case OP_IF_I: RUNAWAYCHECK(); if (OPA->_int) st += (sofs)st->b - 1; // offset the s++ @@ -741,7 +741,7 @@ if (pr_typecurrent != 0) break; - //array/structure reading/riting. + //array/structure reading/writing. case OP_GLOBALADDRESS: OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); break; @@ -824,8 +824,7 @@ if (pr_typecurrent != 0) { PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); } - t = (eval_t *)&pr_globals[(uofs)st->a - +((int)OPB->_float)*3]; + t = (eval_t *)&pr_globals[(uofs)st->a + i*3]; OPC->_vector[0] = t->_vector[0]; OPC->_vector[1] = t->_vector[1]; OPC->_vector[2] = t->_vector[2]; diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index eeb214e26..8ee0f99a2 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -111,11 +111,6 @@ void PR_Configure (progfuncs_t *progfuncs, int addressable_size, int max_progs) unsigned int i; edictrun_t *e; -// int a; -#ifdef QCJIT - prinst->usejit = true; -#endif - max_fields_size=0; fields_size = 0; progfuncs->stringtable = 0; diff --git a/engine/qclib/pr_comp.h b/engine/qclib/pr_comp.h index 463445d0d..d6c34a96e 100644 --- a/engine/qclib/pr_comp.h +++ b/engine/qclib/pr_comp.h @@ -31,7 +31,7 @@ typedef int QCC_string_t; #define RESERVED_OFS 28 -enum { +enum qcop_e { OP_DONE, //0 OP_MUL_F, OP_MUL_V, @@ -55,10 +55,10 @@ enum { OP_NE_E, OP_NE_FNC, - OP_LE, //20 - OP_GE, - OP_LT, - OP_GT, + OP_LE_F, //20 + OP_GE_F, + OP_LT_F, + OP_GT_F, OP_LOAD_F, OP_LOAD_V, @@ -89,8 +89,8 @@ enum { OP_NOT_S, OP_NOT_ENT, OP_NOT_FNC, - OP_IF, - OP_IFNOT, //50 + OP_IF_I, + OP_IFNOT_I, //50 OP_CALL0, //careful... hexen2 and q1 have different calling conventions OP_CALL1, //remap hexen2 calls to OP_CALL2H OP_CALL2, @@ -102,11 +102,11 @@ enum { OP_CALL8, OP_STATE, //60 OP_GOTO, - OP_AND, - OP_OR, + OP_AND_F, + OP_OR_F, - OP_BITAND, - OP_BITOR, + OP_BITAND_F, + OP_BITOR_F, //these following ones are Hexen 2 constants. @@ -184,10 +184,10 @@ enum { OP_ADD_I, OP_ADD_FI, - OP_ADD_IF, //110 + OP_ADD_IF, OP_SUB_I, - OP_SUB_FI, + OP_SUB_FI, //120 OP_SUB_IF, OP_CONV_ITOF, @@ -196,10 +196,10 @@ enum { OP_CP_FTOI, OP_LOAD_I, OP_STOREP_I, - OP_STOREP_IF, //120 + OP_STOREP_IF, OP_STOREP_FI, - OP_BITAND_I, + OP_BITAND_I, //130 OP_BITOR_I, OP_MUL_I, @@ -210,11 +210,11 @@ enum { OP_IFNOT_S, OP_IF_S, - OP_NOT_I, //130 + OP_NOT_I, OP_DIV_VF, - OP_XOR_I, + OP_XOR_I, //140 OP_RSHIFT_I, OP_LSHIFT_I, @@ -224,9 +224,9 @@ enum { OP_LOADA_F, OP_LOADA_V, OP_LOADA_S, - OP_LOADA_ENT, //140 - OP_LOADA_FLD, - OP_LOADA_FNC, + OP_LOADA_ENT, + OP_LOADA_FLD, + OP_LOADA_FNC, //150 OP_LOADA_I, OP_STORE_P, //152... erm.. wait... @@ -236,9 +236,9 @@ enum { OP_LOADP_V, OP_LOADP_S, OP_LOADP_ENT, - OP_LOADP_FLD, //150 + OP_LOADP_FLD, OP_LOADP_FNC, - OP_LOADP_I, + OP_LOADP_I, //160 OP_LE_I, OP_GE_I, @@ -248,10 +248,10 @@ enum { OP_LE_IF, OP_GE_IF, OP_LT_IF, - OP_GT_IF, //160 + OP_GT_IF, OP_LE_FI, - OP_GE_FI, + OP_GE_FI, //170 OP_LT_FI, OP_GT_FI, @@ -263,12 +263,12 @@ enum { OP_ADD_SF, //(char*)c = (char*)a + (float)b OP_SUB_S, //(float)c = (char*)a - (char*)b OP_STOREP_C,//(float)c = *(char*)b = (float)a - OP_LOADP_C, //(float)c = *(char*) //170 + OP_LOADP_C, //(float)c = *(char*) //------------------------------------- OP_MUL_IF, - OP_MUL_FI, + OP_MUL_FI, //180 OP_MUL_VI, OP_MUL_IV, OP_DIV_IF, @@ -276,9 +276,9 @@ enum { OP_BITAND_IF, OP_BITOR_IF, OP_BITAND_FI, - OP_BITOR_FI, //180 + OP_BITOR_FI, OP_AND_I, - OP_OR_I, + OP_OR_I, //190 OP_AND_IF, OP_OR_IF, OP_AND_FI, @@ -288,9 +288,9 @@ enum { //erm... FTEQCC doesn't make use of these... These are for DP. OP_GSTOREP_I, - OP_GSTOREP_F, //190 + OP_GSTOREP_F, OP_GSTOREP_ENT, - OP_GSTOREP_FLD, // integers + OP_GSTOREP_FLD, // integers //200 OP_GSTOREP_S, OP_GSTOREP_FNC, // pointers OP_GSTOREP_V, @@ -298,9 +298,9 @@ enum { OP_GLOAD_I, OP_GLOAD_F, OP_GLOAD_FLD, - OP_GLOAD_ENT, //200 + OP_GLOAD_ENT, OP_GLOAD_S, - OP_GLOAD_FNC, + OP_GLOAD_FNC, //210 OP_BOUNDCHECK, //back to ones that we do use. @@ -320,7 +320,7 @@ enum { These ops are emulated out, always, and are only present in the compiler. */ - OP_BITSET_I, + OP_BITSET_I, //220 OP_BITSETP_I, OP_MULSTORE_I, @@ -332,7 +332,7 @@ enum { OP_ADDSTOREP_I, OP_SUBSTOREP_I, - OP_MULSTORE_IF, + OP_MULSTORE_IF, //230 OP_MULSTOREP_IF, OP_DIVSTORE_IF, OP_DIVSTOREP_IF, @@ -343,14 +343,14 @@ enum { OP_MULSTORE_FI, OP_MULSTOREP_FI, - OP_DIVSTORE_FI, + OP_DIVSTORE_FI, //240 OP_DIVSTOREP_FI, OP_ADDSTORE_FI, OP_ADDSTOREP_FI, OP_SUBSTORE_FI, OP_SUBSTOREP_FI, - OP_NUMOPS + OP_NUMOPS //246 }; #define MAX_PARMS 8 diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index 3e2601034..979560393 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -859,9 +859,9 @@ void PR_ExecuteCode (progfuncs_t *progfuncs, int s) prinst->continuestatement = -1; #ifdef QCJIT - if (prinst->usejit) + if (prinst->jit) { - PR_EnterJIT(progfuncs, s); + PR_EnterJIT(progfuncs, prinst->jit, s); return; } #endif diff --git a/engine/qclib/pr_multi.c b/engine/qclib/pr_multi.c index cc49641b8..b66b8b5e7 100644 --- a/engine/qclib/pr_multi.c +++ b/engine/qclib/pr_multi.c @@ -94,8 +94,7 @@ progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_ progfuncs->numprogs = a+1; #ifdef QCJIT - if (prinst->usejit) - prinst->usejit = PR_GenerateJit(progfuncs); + prinst->jit = PR_GenerateJit(progfuncs); #endif if (oldtype>=0) PR_SwitchProgs(progfuncs, oldtype); diff --git a/engine/qclib/pr_x86.c b/engine/qclib/pr_x86.c index 7876b9adc..9f217b339 100644 --- a/engine/qclib/pr_x86.c +++ b/engine/qclib/pr_x86.c @@ -10,16 +10,31 @@ optimisations: instructions need to be chained. stuff that writes to C should be cacheable, etc. maybe we don't even need to do the write to C it should also be possible to fold in eq+ifnot, so none of this silly storeing of floats in equality tests + this means that we need to track which vars are cached and in what form: fpreg, ireg+floatasint, ireg+float. + certain qccx hacks can use fpu operations on ints, so do what the instruction says, rather than considering an add an add regardless of types. + + OP_AND_F, OP_OR_F etc will generally result in ints, and we should be able to keep them as ints if they combine with other ints. + + some instructions are jump sites. any cache must be flushed before the start of the instruction. + some variables are locals, and will only ever be written by a single instruction, then read by the following instruction. such temps do not need to be written, or are overwritten later in the function anyway. + such locals need to be calculated PER FUNCTION as (fte)qcc can overlap locals making multiple distinct locals on a single offset. + + store locals on a proper stack instead of the current absurd mechanism. + eax - tmp ebx - prinst->edicttable ecx - tmp edx - tmp - esi - + esi - debug opcode number edi - tmp (because its preserved by subfunctions ebp - to use gas to provide binary opcodes: vim -N blob.s && as blob.s && objdump.exe -d a.out + + + notable mods to test: + prydon gate, due to fpu mangling to carry values between maps */ #define PROGSUSED @@ -29,56 +44,59 @@ optimisations: static float ta, tb, nullfloat=0; -unsigned int *statementjumps; //[MAX_STATEMENTS*2] -unsigned char **statementoffsets; //[MAX_STATEMENTS] -unsigned int numjumps; -unsigned char *code; -unsigned int codesize; -unsigned int jitstatements; +struct jitstate +{ + unsigned int *statementjumps; //[MAX_STATEMENTS*3] + unsigned char **statementoffsets; //[MAX_STATEMENTS] + unsigned int numjumps; + unsigned char *code; + unsigned int codesize; + unsigned int jitstatements; +}; -void EmitByte(unsigned char byte) +static void EmitByte(struct jitstate *jit, unsigned char byte) { - code[codesize++] = byte; + jit->code[jit->codesize++] = byte; } -void Emit4Byte(unsigned int value) +static void Emit4Byte(struct jitstate *jit, unsigned int value) { - code[codesize++] = (value>> 0)&0xff; - code[codesize++] = (value>> 8)&0xff; - code[codesize++] = (value>>16)&0xff; - code[codesize++] = (value>>24)&0xff; + jit->code[jit->codesize++] = (value>> 0)&0xff; + jit->code[jit->codesize++] = (value>> 8)&0xff; + jit->code[jit->codesize++] = (value>>16)&0xff; + jit->code[jit->codesize++] = (value>>24)&0xff; } -void EmitAdr(void *value) +static void EmitAdr(struct jitstate *jit, void *value) { - Emit4Byte((unsigned int)value); + Emit4Byte(jit, (unsigned int)value); } -void EmitFloat(float value) +static void EmitFloat(struct jitstate *jit, float value) { union {float f; unsigned int i;} u; u.f = value; - Emit4Byte(u.i); + Emit4Byte(jit, u.i); } -void Emit2Byte(unsigned short value) +static void Emit2Byte(struct jitstate *jit, unsigned short value) { - code[codesize++] = (value>> 0)&0xff; - code[codesize++] = (value>> 8)&0xff; + jit->code[jit->codesize++] = (value>> 0)&0xff; + jit->code[jit->codesize++] = (value>> 8)&0xff; } -void EmitFOffset(void *func, int bias) +static void EmitFOffset(struct jitstate *jit, void *func, int bias) { union {void *f; unsigned int i;} u; u.f = func; - u.i -= (unsigned int)&code[codesize+bias]; - Emit4Byte(u.i); + u.i -= (unsigned int)&jit->code[jit->codesize+bias]; + Emit4Byte(jit, u.i); } -void Emit4ByteJump(int statementnum, int offset) +static void Emit4ByteJump(struct jitstate *jit, int statementnum, int offset) { - statementjumps[numjumps++] = codesize; - statementjumps[numjumps++] = statementnum; - statementjumps[numjumps++] = offset; + jit->statementjumps[jit->numjumps++] = jit->codesize; + jit->statementjumps[jit->numjumps++] = statementnum; + jit->statementjumps[jit->numjumps++] = offset; //the offset is filled in later - codesize += 4; + jit->codesize += 4; } enum @@ -97,29 +115,34 @@ enum #define LOADREG(addr, reg) if (reg == REG_EAX) {EmitByte(0xa1);} else {EmitByte(0x8b); EmitByte((reg<<3) | 0x05);} EmitAdr(addr); #define STOREREG(reg, addr) if (reg == REG_EAX) {EmitByte(0xa3);} else {EmitByte(0x89); EmitByte((reg<<3) | 0x05);} EmitAdr(addr); #define STOREF(f, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);EmitFloat(f); -#define STOREI(f, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);EmitFloat(f); -#define SETREGI(val,reg) EmitByte(0xbe);EmitByte(val);EmitByte(val>>8);EmitByte(val>>16);EmitByte(val>>24); +#define STOREI(i, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);Emit4Byte(i); +#define SETREGI(val,reg) EmitByte(0xbe);Emit4Byte(val); -void *LocalLoc(void) +static void *LocalLoc(struct jitstate *jit) { - return &code[codesize]; + return &jit->code[jit->codesize]; } -void *LocalJmp(int cond) +static void *LocalJmp(struct jitstate *jit, int cond) { + /*floating point ops don't set the sign flag, thus we use the 'above/below' instructions instead of 'greater/less' instructions*/ if (cond == OP_GOTO) - EmitByte(0xeb); //jmp - else if (cond == OP_LE) - EmitByte(0x7e); //jle - else if (cond == OP_GE) - EmitByte(0x7d); //jge - else if (cond == OP_LT) - EmitByte(0x7c); //jl - else if (cond == OP_GT) - EmitByte(0x7f); //jg + EmitByte(jit, 0xeb); //jmp + else if (cond == OP_LE_F) + EmitByte(jit, 0x76); //jbe + else if (cond == OP_GE_F) + EmitByte(jit, 0x73); //jae + else if (cond == OP_LT_F) + EmitByte(jit, 0x72); //jb + else if (cond == OP_GT_F) + EmitByte(jit, 0x77); //ja + else if (cond == OP_LE_I) + EmitByte(jit, 0x7e); //jle + else if (cond == OP_LT_I) + EmitByte(jit, 0x7c); //jl else if ((cond >= OP_NE_F && cond <= OP_NE_FNC) || cond == OP_NE_I) - EmitByte(0x75); //jne + EmitByte(jit, 0x75); //jne else if ((cond >= OP_EQ_F && cond <= OP_EQ_FNC) || cond == OP_EQ_I) - EmitByte(0x74); //je + EmitByte(jit, 0x74); //je #if defined(DEBUG) && defined(_WIN32) else { @@ -128,11 +151,11 @@ void *LocalJmp(int cond) } #endif - EmitByte(0); + EmitByte(jit, 0); - return LocalLoc(); + return LocalLoc(jit); } -void LocalJmpLoc(void *jmp, void *loc) +static void LocalJmpLoc(void *jmp, void *loc) { int offs; unsigned char *a = jmp; @@ -149,7 +172,7 @@ void LocalJmpLoc(void *jmp, void *loc) a[-1] = offs; } -void FixupJumps(void) +static void FixupJumps(struct jitstate *jit) { unsigned int j; unsigned char *codesrc; @@ -158,15 +181,15 @@ void FixupJumps(void) unsigned int v; - for (j = 0; j < numjumps;) + for (j = 0; j < jit->numjumps;) { - v = statementjumps[j++]; - codesrc = &code[v]; + v = jit->statementjumps[j++]; + codesrc = &jit->code[v]; - v = statementjumps[j++]; - codedst = statementoffsets[v]; + v = jit->statementjumps[j++]; + codedst = jit->statementoffsets[v]; - v = statementjumps[j++]; + v = jit->statementjumps[j++]; offset = (int)(codedst - (codesrc-v)); //3rd term because the jump is relative to the instruction start, not the instruction's offset codesrc[0] = (offset>> 0)&0xff; @@ -179,8 +202,27 @@ void FixupJumps(void) int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs); int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum); -pbool PR_GenerateJit(progfuncs_t *progfuncs) +void PR_CloseJit(struct jitstate *jit) { + free(jit->statementjumps); + free(jit->statementoffsets); + free(jit->code); +} + +#define EmitByte(v) EmitByte(jit, v) +#define EmitAdr(v) EmitAdr(jit, v) +#define EmitFOffset(a,b) EmitFOffset(jit, a, b) +#define Emit4ByteJump(a,b) Emit4ByteJump(jit, a, b) +#define Emit4Byte(v) Emit4Byte(jit, v) +#define EmitFloat(v) EmitFloat(jit, v) +#define LocalJmp(v) LocalJmp(jit, v) +#define LocalLoc() LocalLoc(jit) + + +struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs) +{ + struct jitstate *jit; + void *j0, *l0; void *j1, *l1; void *j2, *l2; @@ -190,44 +232,48 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) int *glob = (int*)current_progstate->globals; if (current_progstate->numbuiltins) - return false; + return NULL; + jit = malloc(sizeof(*jit)); + jit->jitstatements = numstatements; - jitstatements = numstatements; + jit->statementjumps = malloc(numstatements*12); + jit->statementoffsets = malloc(numstatements*4); + jit->code = malloc(numstatements*500); + if (!jit->code) + return NULL; - statementjumps = malloc(numstatements*12); - statementoffsets = malloc(numstatements*4); - code = malloc(numstatements*500); - - numjumps = 0; - codesize = 0; + jit->numjumps = 0; + jit->codesize = 0; for (i = 0; i < numstatements; i++) { - statementoffsets[i] = &code[codesize]; + jit->statementoffsets[i] = &jit->code[jit->codesize]; + /*DEBUG*/ SETREGI(op[i].op, REG_ESI); + switch(op[i].op) { //jumps - case OP_IF: + case OP_IF_I: //integer compare //if a, goto b //cmpl $0,glob[A] EmitByte(0x83);EmitByte(0x3d);EmitAdr(glob + op[i].a);EmitByte(0x0); - //jnz B + //jne B EmitByte(0x0f);EmitByte(0x85);Emit4ByteJump(i + (signed short)op[i].b, -4); break; - case OP_IFNOT: + case OP_IFNOT_I: //integer compare //if !a, goto b //cmpl $0,glob[A] EmitByte(0x83);EmitByte(0x3d);EmitAdr(glob + op[i].a);EmitByte(0x0); - //jz B + //je B EmitByte(0x0f);EmitByte(0x84);Emit4ByteJump(i + (signed short)op[i].b, -4); break; @@ -276,7 +322,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) // je returntoc j1 = LocalJmp(OP_EQ_E); // mov statementoffsets[%eax*4],%eax - EmitByte(0x8b);EmitByte(0x04);EmitByte(0x85);EmitAdr(statementoffsets+1); + EmitByte(0x8b);EmitByte(0x04);EmitByte(0x85);EmitAdr(jit->statementoffsets+1); // jmp *eax EmitByte(0xff);EmitByte(0xe0); // returntoc: @@ -299,9 +345,9 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) case OP_CALL8: //save the state in place the rest of the engine can cope with //movl $i, pr_xstatement - EmitByte(0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i); + EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i); //movl $(op[i].op-OP_CALL0), pr_argc - EmitByte(0xc7);EmitByte(0x05);EmitAdr(&pr_argc);Emit4Byte(op[i].op-OP_CALL0); + EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_argc);Emit4Byte(op[i].op-OP_CALL0); //figure out who we're calling, and what that involves //%eax = glob[A] @@ -358,8 +404,9 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) //cmp $0,%edx EmitByte(0x83);EmitByte(0xfa);EmitByte(0x00); //jl isabuiltin - j1 = LocalJmp(OP_LE); + j1 = LocalJmp(OP_LT_I); { + /* call the function*/ //push %ecx EmitByte(0x51); //push %eax @@ -373,8 +420,9 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) //eax is now the next statement number (first of the new function, usually equal to ecx, but not always) //jmp statementoffsets[%eax*4] - EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(statementoffsets+1); + EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(jit->statementoffsets+1); } + /*its a builtin, figure out which, and call it*/ //isabuiltin: l1 = LocalLoc(); LocalJmpLoc(j1,l1); @@ -403,7 +451,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) EmitByte(0xc7);EmitByte(0x05);EmitAdr(&prinst->continuestatement);Emit4Byte((unsigned int)-1); //jmp statementoffsets[%eax*4] - EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(statementoffsets); + EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(jit->statementoffsets); } //donebuiltincall: l1 = LocalLoc(); @@ -444,10 +492,10 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) break; case OP_NOT_F: - //flds glob[A] - EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a); //fldz EmitByte(0xd9);EmitByte(0xee); + //fcomps glob[A] + EmitByte(0xd8); EmitByte(0x1d); EmitAdr(glob + op[i].a); //fnstsw %ax EmitByte(0xdf);EmitByte(0xe0); //testb 0x40,%ah @@ -455,13 +503,13 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) j1 = LocalJmp(OP_NE_F); { - STOREF(1.0f, glob + op[i].c); + STOREF(0.0f, glob + op[i].c); j2 = LocalJmp(OP_GOTO); } { //noteq: l1 = LocalLoc(); - STOREF(0.0f, glob + op[i].c); + STOREF(1.0f, glob + op[i].c); } //end: l2 = LocalLoc(); @@ -508,18 +556,18 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) EmitByte(0x8b);EmitByte(0x50);EmitByte((int)&((edictrun_t*)NULL)->fields); //edx is now the field array for that ent - //mov fieldajust(%edx,%ecx,4),%eax //offset = progfuncs->fieldadjust + //mov fieldajust(%edx,%ecx,4),%eax EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(progfuncs->fieldadjust*4); STOREREG(REG_EAX, glob + op[i].c) if (op[i].op == OP_LOAD_V) { - //mov fieldajust+4(%edx,%ecx,4),%eax //offset = progfuncs->fieldadjust + //mov fieldajust+4(%edx,%ecx,4),%eax EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(4+progfuncs->fieldadjust*4); STOREREG(REG_EAX, glob + op[i].c+1) - //mov fieldajust+8(%edx,%ecx,4),%eax //offset = progfuncs->fieldadjust + //mov fieldajust+8(%edx,%ecx,4),%eax EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(8+progfuncs->fieldadjust*4); STOREREG(REG_EAX, glob + op[i].c+2) } @@ -586,12 +634,12 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) EmitByte(0x3b); EmitByte(0x04); EmitByte(0x25); EmitAdr(glob + op[i].b); j1 = LocalJmp(op[i].op); { - STOREF(1.0f, glob + op[i].c); + STOREF(0.0f, glob + op[i].c); j2 = LocalJmp(OP_GOTO); } { l1 = LocalLoc(); - STOREF(0.0f, glob + op[i].c); + STOREF(1.0f, glob + op[i].c); } l2 = LocalLoc(); LocalJmpLoc(j1,l1); @@ -617,47 +665,45 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) LocalJmpLoc(j2,l2); break; - case OP_BITOR: //floats... + case OP_BITOR_F: //floats... //flds glob[A] EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a); //flds glob[B] EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b); //fistp tb - EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&tb); + EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&tb); //fistp ta - EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&ta); + EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta); LOADREG(&ta, REG_EAX) - //or tb,%eax + //or %eax,tb EmitByte(0x09); EmitByte(0x05);EmitAdr(&tb); - STOREREG(REG_EAX, &tb) //fild tb - EmitByte(0xdf); EmitByte(0x05);EmitAdr(&tb); + EmitByte(0xdb); EmitByte(0x05);EmitAdr(&tb); //fstps glob[C] EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c); break; - case OP_BITAND: + case OP_BITAND_F: //flds glob[A] EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a); //flds glob[B] EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b); //fistp tb - EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&tb); + EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&tb); //fistp ta - EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&ta); + EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta); /*two args are now at ta and tb*/ LOADREG(&ta, REG_EAX) //and tb,%eax EmitByte(0x21); EmitByte(0x05);EmitAdr(&tb); - STOREREG(REG_EAX, &tb) /*we just wrote the int value to tb, convert that to a float and store it at c*/ //fild tb - EmitByte(0xdf); EmitByte(0x05);EmitAdr(&tb); + EmitByte(0xdb); EmitByte(0x05);EmitAdr(&tb); //fstps glob[C] EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c); break; - case OP_AND: + case OP_AND_F: //test floats properly, so we don't get confused with -0.0 //flds glob[A] @@ -668,7 +714,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) EmitByte(0xdf); EmitByte(0xe0); //test $0x40,%ah EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40); - //je onefalse + //jz onefalse EmitByte(0x75); EmitByte(0x1f); //flds glob[B] @@ -679,7 +725,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) EmitByte(0xdf); EmitByte(0xe0); //test $0x40,%ah EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40); - //jne onefalse + //jnz onefalse EmitByte(0x75); EmitByte(0x0c); //mov float0,glob[C] @@ -692,7 +738,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f); //done: break; - case OP_OR: + case OP_OR_F: //test floats properly, so we don't get confused with -0.0 //flds glob[A] @@ -731,7 +777,6 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs) case OP_EQ_S: case OP_NE_S: { - void *j0b, *j1b, *j1c; //put a in ecx LOADREG(glob + op[i].a, REG_ECX); //put b in edi @@ -940,14 +985,14 @@ LOADREG(glob + op[i].b, REG_EDI); case OP_EQ_F: case OP_NE_F: - case OP_LE: - case OP_GE: - case OP_LT: - case OP_GT: + case OP_LE_F: + case OP_GE_F: + case OP_LT_F: + case OP_GT_F: //flds glob[A] - EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a); - //flds glob[B] EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].b); + //flds glob[B] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a); //fcomip %st(1),%st EmitByte(0xdf);EmitByte(0xe9); //fstp %st(0) (aka: pop) @@ -988,21 +1033,21 @@ LOADREG(glob + op[i].b, REG_EDI); EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + f); //flds glob[V0] - EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+0); + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+0); //fmul st(1) EmitByte(0xd8);EmitByte(0xc9); //fstps glob[C] EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+0); //flds glob[V0] - EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+1); + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+1); //fmul st(1) EmitByte(0xd8);EmitByte(0xc9); //fstps glob[C] EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+1); //flds glob[V0] - EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+2); + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+2); //fmul st(1) EmitByte(0xd8);EmitByte(0xc9); //fstps glob[C] @@ -1045,8 +1090,17 @@ LOADREG(glob + op[i].b, REG_EDI); //done: break; */ + + case OP_NOT_V: + EmitByte(0xcd);EmitByte(op[i].op); + printf("QCJIT: instruction %i is not implemented\n", op[i].op); + break; +#endif case OP_NE_V: case OP_EQ_V: + { + void *f0, *f1, *f2, *floc; +//compare v[0] //flds glob[A] EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+0); //flds glob[B] @@ -1056,43 +1110,151 @@ LOADREG(glob + op[i].b, REG_EDI); //fstp %st(0) (aka: pop) EmitByte(0xdd);EmitByte(0xd8); - //jncc _true - if (op[i].op == OP_NE_V) - EmitByte(0x74); //je - else - EmitByte(0x75); //jne - EmitByte(0x0c); -//_false0: - //mov 0.0f,c - EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(1.0f); - //jmp done - EmitByte(0xeb); EmitByte(0x0a); + /*if the condition is true, don't fail*/ + j1 = LocalJmp(op[i].op); + { + STOREF(0.0f, glob + op[i].c); + f0 = LocalJmp(OP_GOTO); + } + l1 = LocalLoc(); + LocalJmpLoc(j1,l1); +//compare v[1] + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+1); + //flds glob[B] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].b+1); + //fcomip %st(1),%st + EmitByte(0xdf);EmitByte(0xe9); + //fstp %st(0) (aka: pop) + EmitByte(0xdd);EmitByte(0xd8); -//_true: - //mov 1.0f,c - EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f); -//_done: + /*if the condition is true, don't fail*/ + j1 = LocalJmp(op[i].op); + { + STOREF(0.0f, glob + op[i].c); + f1 = LocalJmp(OP_GOTO); + } + l1 = LocalLoc(); + LocalJmpLoc(j1,l1); + +//compare v[2] + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+2); + //flds glob[B] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].b+2); + //fcomip %st(1),%st + EmitByte(0xdf);EmitByte(0xe9); + //fstp %st(0) (aka: pop) + EmitByte(0xdd);EmitByte(0xd8); + + /*if the condition is true, don't fail*/ + j1 = LocalJmp(op[i].op); + { + STOREF(0.0f, glob + op[i].c); + f2 = LocalJmp(OP_GOTO); + } + l1 = LocalLoc(); + LocalJmpLoc(j1,l1); + +//success! + STOREF(1.0f, glob + op[i].c); + + floc = LocalLoc(); + LocalJmpLoc(f0,floc); + LocalJmpLoc(f1,floc); + LocalJmpLoc(f2,floc); + break; + } + + /*fteqcc generates these from reading 'fast arrays', and are part of hexenc extras*/ + case OP_FETCH_GBL_F: + case OP_FETCH_GBL_S: + case OP_FETCH_GBL_E: + case OP_FETCH_GBL_FNC: + case OP_FETCH_GBL_V: + { + unsigned int max = ((unsigned int*)glob)[op[i].a-1]; + unsigned int base = op[i].a; + //flds glob[B] + EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b); + //fistp ta + EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta); + LOADREG(&ta, REG_EAX) + //FIXME: if eax >= $max, abort + + if (op[i].op == OP_FETCH_GBL_V) + { + /*scale the index by 3*/ + SETREGI(3, REG_EDX) + //mul %edx + EmitByte(0xf7); EmitByte(0xe2); + } + + //lookup global + //mov &glob[base](,%eax,4),%edx + EmitByte(0x8b);EmitByte(0x14);EmitByte(0x85);Emit4Byte((unsigned int)(glob + base+0)); + STOREREG(REG_EDX, glob + op[i].c+0) + if (op[i].op == OP_FETCH_GBL_V) + { + //mov &glob[base+1](,%eax,4),%edx + EmitByte(0x8b);EmitByte(0x14);EmitByte(0x85);Emit4Byte((unsigned int)(glob + base+1)); + STOREREG(REG_EDX, glob + op[i].c+1) + //mov &glob[base+2](,%eax,4),%edx + EmitByte(0x8b);EmitByte(0x14);EmitByte(0x85);Emit4Byte((unsigned int)(glob + base+2)); + STOREREG(REG_EDX, glob + op[i].c+2) + } + break; + } + + /*fteqcc generates these from writing 'fast arrays'*/ + case OP_GLOBALADDRESS: + LOADREG(glob + op[i].b, REG_EAX); + //lea &glob[A](, %eax, 4),%eax + EmitByte(0x8d);EmitByte(0x04);EmitByte(0x85);EmitAdr(glob + op[i].b+2); + STOREREG(REG_EAX, glob + op[i].c); + break; +// case OP_BOUNDCHECK: + //FIXME: assert b <= a < c + break; + case OP_CONV_FTOI: + //flds glob[A] + EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a); + //fistp glob[C] + EmitByte(0xdb); EmitByte(0x1d);EmitAdr(glob + op[i].c); + break; + case OP_MUL_I: + LOADREG(glob + op[i].a, REG_EAX); + //mull glob[C] (arg*eax => edx:eax) + EmitByte(0xfc); EmitByte(0x25);EmitAdr(glob + op[i].b); + STOREREG(REG_EAX, glob + op[i].c); break; - case OP_NOT_V: - EmitByte(0xcd);EmitByte(op[i].op); - printf("QCJIT: instruction %i is not implemented\n", op[i].op); + /*other extended opcodes*/ + case OP_BITOR_I: + LOADREG(glob + op[i].a, REG_EAX) + //or %eax,tb + EmitByte(0x0b); EmitByte(0x05);EmitAdr(glob + op[i].b); + STOREREG(REG_EAX, glob + op[i].c); break; -#endif + + default: - printf("QCJIT: Extended instruction set %i is not supported, not using jit.\n", op[i].op); + { + enum qcop_e e = op[i].op; + printf("QCJIT: Extended instruction set %i is not supported, not using jit.\n", e); + } - free(statementjumps); //[MAX_STATEMENTS] - free(statementoffsets); //[MAX_STATEMENTS] - free(code); - statementoffsets = NULL; - return false; + free(jit->statementjumps); //[MAX_STATEMENTS] + free(jit->statementoffsets); //[MAX_STATEMENTS] + free(jit->code); + free(jit); + return NULL; } } - FixupJumps(); + FixupJumps(jit); #ifdef _WIN32 { @@ -1100,22 +1262,32 @@ LOADREG(glob + op[i].b, REG_EDI); //this memory is on the heap. //this means that we must maintain read/write protection, or libc will crash us - VirtualProtect(code, codesize, PAGE_EXECUTE_READWRITE, &old); + VirtualProtect(jit->code, jit->codesize, PAGE_EXECUTE_READWRITE, &old); } #endif -// externs->WriteFile("jit.x86", code, codesize); +// externs->WriteFile("jit.x86", jit->code, jit->codesize); - return true; + return jit; } -void PR_EnterJIT(progfuncs_t *progfuncs, int statement) +float foo(float arg) +{ + float f; + if (!arg) + f = 1; + else + f = 0; + return f; +} + +void PR_EnterJIT(progfuncs_t *progfuncs, struct jitstate *jit, int statement) { #ifdef __GNUC__ //call, it clobbers pretty much everything. - asm("call *%0" :: "r"(statementoffsets[statement+1]),"b"(prinst->edicttable):"cc","memory","eax","ecx","edx"); + asm("call *%0" :: "r"(jit->statementoffsets[statement+1]),"b"(prinst->edicttable):"cc","memory","eax","ecx","edx"); #elif defined(_MSC_VER) - void *entry = statementoffsets[statement+1]; + void *entry = jit->statementoffsets[statement+1]; void *edicttable = prinst->edicttable; __asm { pushad diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 5e2687847..e0d5cd461 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -344,7 +344,7 @@ void PR_SetBuiltins(int type); typedef struct prinst_s { #ifdef QCJIT - pbool usejit; + struct jitstate *jit; #endif char **tempstrings; int maxtempstrings; @@ -478,8 +478,9 @@ char *PR_GlobalStringNoContents (progfuncs_t *progfuncs, int ofs); pbool CompileFile(progfuncs_t *progfuncs, char *filename); -pbool PR_GenerateJit(progfuncs_t *progfuncs); -void PR_EnterJIT(progfuncs_t *progfuncs, int statement); +struct jitstate; +struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs); +void PR_EnterJIT(progfuncs_t *progfuncs, struct jitstate *jitstate, int statement); char *QCC_COM_Parse (char *data); extern char qcc_token[1024]; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 6e04b89c6..f37ef7368 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -661,12 +661,12 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_DIV_I], &pr_opcodes[OP_DIV_VF], - &pr_opcodes[OP_BITAND], + &pr_opcodes[OP_BITAND_F], &pr_opcodes[OP_BITAND_I], &pr_opcodes[OP_BITAND_IF], &pr_opcodes[OP_BITAND_FI], - &pr_opcodes[OP_BITOR], + &pr_opcodes[OP_BITOR_F], &pr_opcodes[OP_BITOR_I], &pr_opcodes[OP_BITOR_IF], &pr_opcodes[OP_BITOR_FI], @@ -712,19 +712,19 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = &pr_opcodes[OP_NE_IF], &pr_opcodes[OP_NE_FI], - &pr_opcodes[OP_LE], + &pr_opcodes[OP_LE_F], &pr_opcodes[OP_LE_I], &pr_opcodes[OP_LE_IF], &pr_opcodes[OP_LE_FI], - &pr_opcodes[OP_GE], + &pr_opcodes[OP_GE_F], &pr_opcodes[OP_GE_I], &pr_opcodes[OP_GE_IF], &pr_opcodes[OP_GE_FI], - &pr_opcodes[OP_LT], + &pr_opcodes[OP_LT_F], &pr_opcodes[OP_LT_I], &pr_opcodes[OP_LT_IF], &pr_opcodes[OP_LT_FI], - &pr_opcodes[OP_GT], + &pr_opcodes[OP_GT_F], &pr_opcodes[OP_GT_I], &pr_opcodes[OP_GT_IF], &pr_opcodes[OP_GT_FI], @@ -805,11 +805,11 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = NULL }, { //7 - &pr_opcodes[OP_AND], + &pr_opcodes[OP_AND_F], &pr_opcodes[OP_AND_I], &pr_opcodes[OP_AND_IF], &pr_opcodes[OP_AND_FI], - &pr_opcodes[OP_OR], + &pr_opcodes[OP_OR_F], &pr_opcodes[OP_OR_I], &pr_opcodes[OP_OR_IF], &pr_opcodes[OP_OR_FI], @@ -1674,10 +1674,10 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //both are constants switch (op - pr_opcodes) //improve some of the maths. { - case OP_BITOR: + case OP_BITOR_F: optres_constantarithmatic++; return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs))); - case OP_BITAND: + case OP_BITAND_F: optres_constantarithmatic++; return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs))); case OP_MUL_F: @@ -1712,10 +1712,10 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var optres_constantarithmatic++; return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs)); - case OP_AND: + case OP_AND_F: optres_constantarithmatic++; return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs)); - case OP_OR: + case OP_OR_F: optres_constantarithmatic++; return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs)); case OP_MUL_V: //mul_f is actually a dot-product @@ -1750,8 +1750,8 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //a is const, b is not switch (op - pr_opcodes) { - case OP_BITOR: - case OP_OR: + case OP_BITOR_F: + case OP_OR_F: case OP_ADD_F: if (G_FLOAT(var_a->ofs) == 0) { @@ -1768,8 +1768,8 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var return var_b; } break; - case OP_BITAND: - case OP_AND: + case OP_BITAND_F: + case OP_AND_F: if (G_FLOAT(var_a->ofs) != 0) { optres_constantarithmatic++; @@ -1813,8 +1813,8 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //b is const, a is not switch (op - pr_opcodes) { - case OP_BITOR: - case OP_OR: + case OP_BITOR_F: + case OP_OR_F: case OP_SUB_F: case OP_ADD_F: if (G_FLOAT(var_b->ofs) == 0) @@ -1834,7 +1834,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var } break; //no bitand_f, I don't trust the casts - case OP_AND: + case OP_AND_F: if (G_FLOAT(var_b->ofs) != 0) { optres_constantarithmatic++; @@ -1884,13 +1884,13 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var switch (op - pr_opcodes) { - case OP_AND: + case OP_AND_F: if (var_a->ofs == var_b->ofs) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same"); if (var_a->constant || var_b->constant) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant"); break; - case OP_OR: + case OP_OR_F: if (var_a->ofs == var_b->ofs) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameters for || are the same"); if (var_a->constant || var_b->constant) @@ -1911,10 +1911,10 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var case OP_NE_E: case OP_NE_FNC: - case OP_LE: - case OP_GE: - case OP_LT: - case OP_GT: + case OP_LE_F: + case OP_GE_F: + case OP_LT_F: + case OP_GT_F: if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant"); break; @@ -1922,8 +1922,8 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var case OP_IFNOT_S: case OP_IF_F: case OP_IFNOT_F: - case OP_IF: - case OP_IFNOT: + case OP_IF_I: + case OP_IFNOT_I: // if (var_a->type->type == ev_function && !var_a->temp) // QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant"); if (var_a->constant && !var_a->temp) @@ -1935,7 +1935,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var if (numstatements) { //optimise based on last statement. - if (op - pr_opcodes == OP_IFNOT) + if (op - pr_opcodes == OP_IFNOT_I) { if (opt_shortenifnots && var_a && (statements[numstatements-1].op == OP_NOT_F || statements[numstatements-1].op == OP_NOT_FNC || statements[numstatements-1].op == OP_NOT_ENT)) { @@ -1945,7 +1945,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var if (statements[numstatements-1].op == OP_NOT_F) op = &pr_opcodes[OP_IF_F]; else - op = &pr_opcodes[OP_IF]; + op = &pr_opcodes[OP_IF_I]; numstatements--; QCC_FreeTemp(var_a); memcpy(&nvara, var_a, sizeof(nvara)); @@ -2040,7 +2040,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var numstatements++; QCC_FreeTemp(var_a); - op = &pr_opcodes[OP_IF]; + op = &pr_opcodes[OP_IF_I]; break; case OP_IFNOT_S: @@ -2051,7 +2051,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var numstatements++; QCC_FreeTemp(var_a); - op = &pr_opcodes[OP_IFNOT]; + op = &pr_opcodes[OP_IFNOT_I]; break; case OP_IF_F: @@ -2062,7 +2062,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var numstatements++; QCC_FreeTemp(var_a); - op = &pr_opcodes[OP_IF]; + op = &pr_opcodes[OP_IF_I]; break; case OP_IFNOT_F: @@ -2073,7 +2073,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var numstatements++; QCC_FreeTemp(var_a); - op = &pr_opcodes[OP_IFNOT]; + op = &pr_opcodes[OP_IFNOT_I]; break; case OP_ADDSTORE_F: @@ -2196,7 +2196,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_c = var_a; break; case OP_BITSET: - op = &pr_opcodes[OP_BITOR]; + op = &pr_opcodes[OP_BITOR_F]; var_c = var_b; var_b = var_a; var_a = var_c; @@ -2210,7 +2210,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var QCC_UnFreeTemp(var_b); numstatements--; - var_c = QCC_PR_Statement(&pr_opcodes[OP_BITAND], var_b, var_a, NULL); + var_c = QCC_PR_Statement(&pr_opcodes[OP_BITAND_F], var_b, var_a, NULL); QCC_FreeTemp(var_c); statement = &statements[numstatements]; numstatements++; @@ -2322,7 +2322,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var statement->op = OP_DIV_F; break; case OP_BITSETP: - statement->op = OP_BITOR; + statement->op = OP_BITOR_F; break; case OP_BITSETP_I: statement->op = OP_BITOR_I; @@ -2330,7 +2330,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var case OP_BITCLRP: //float pointer float temp = QCC_GetTemp(type_float); - statement->op = OP_BITAND; + statement->op = OP_BITAND_F; statement->a = var_c ? var_c->ofs : 0; statement->b = var_a ? var_a->ofs : 0; statement->c = temp->ofs; @@ -3134,8 +3134,8 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs)) { - t = QCC_PR_Statement(&pr_opcodes[OP_GT], d, e, NULL); - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], t, 0, &st)); + t = QCC_PR_Statement(&pr_opcodes[OP_GT_F], d, e, NULL); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], t, 0, &st)); st->b = 3; t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], d, e, NULL); @@ -3264,8 +3264,8 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs)) { t = QCC_GetTemp(type_float); - QCC_PR_SimpleStatement(OP_GT, d->ofs+2, e->ofs+2, t->ofs, false); - QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false); + QCC_PR_SimpleStatement(OP_GT_F, d->ofs+2, e->ofs+2, t->ofs, false); + QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false); QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+2, e->ofs+2, t->ofs, false); QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+2, false); @@ -3288,8 +3288,8 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs)) { t = QCC_GetTemp(type_float); - QCC_PR_SimpleStatement(OP_GT, d->ofs+1, e->ofs+1, t->ofs, false); - QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false); + QCC_PR_SimpleStatement(OP_GT_F, d->ofs+1, e->ofs+1, t->ofs, false); + QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false); QCC_PR_SimpleStatement(OP_SUB_F, d->ofs+1, e->ofs+1, t->ofs, false); QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN+1, false); @@ -3311,8 +3311,8 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs)) { t = QCC_GetTemp(type_float); - QCC_PR_SimpleStatement(OP_GT, d->ofs, e->ofs, t->ofs, false); - QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, false); + QCC_PR_SimpleStatement(OP_GT_F, d->ofs, e->ofs, t->ofs, false); + QCC_PR_SimpleStatement(OP_IFNOT_I, t->ofs, 3, 0, false); QCC_PR_SimpleStatement(OP_SUB_F, d->ofs, e->ofs, t->ofs, false); QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, false); @@ -5070,7 +5070,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) if (QCC_PR_CheckToken ("?")) { QCC_dstatement32_t *fromj, *elsej; - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], e, NULL, &fromj)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], e, NULL, &fromj)); e = QCC_PR_Expression(TOP_PRIORITY, 0); e2 = QCC_GetTemp(e->type); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[(e2->type->size>=3)?OP_STORE_V:OP_STORE_F], e, e2, NULL)); @@ -5181,9 +5181,9 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) optres_logicops++; st = &statements[numstatements]; if (*op->name == '&') //statement 3 because we don't want to optimise this into if from not ifnot - QCC_PR_Statement3(&pr_opcodes[OP_IFNOT], e, NULL, NULL, false); + QCC_PR_Statement3(&pr_opcodes[OP_IFNOT_I], e, NULL, NULL, false); else - QCC_PR_Statement3(&pr_opcodes[OP_IF], e, NULL, NULL, false); + QCC_PR_Statement3(&pr_opcodes[OP_IF_I], e, NULL, NULL, false); } e2 = QCC_PR_Expression (priority-1, exprflags); @@ -5634,7 +5634,7 @@ void QCC_PR_ParseStatement (void) else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) //special case, as negative 0 is also zero QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1)); else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1)); } QCC_PR_Expect (")"); //after the line number is noted.. QCC_PR_ParseStatement (); @@ -5718,7 +5718,7 @@ void QCC_PR_ParseStatement (void) numtemp = 0; if (e) - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], e, 0, &patch1)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], e, 0, &patch1)); else patch1 = NULL; if (!QCC_PR_CheckToken(";")) @@ -5785,7 +5785,7 @@ void QCC_PR_ParseStatement (void) else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, NULL, &patch2)); else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, NULL, &patch2)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &patch2)); patch2->b = patch1 - patch2; } @@ -5883,7 +5883,7 @@ void QCC_PR_ParseStatement (void) else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, 0, &patch1)); else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e, 0, &patch1)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, 0, &patch1)); } else { @@ -5895,7 +5895,7 @@ void QCC_PR_ParseStatement (void) else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1)); else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch1)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1)); } QCC_PR_Expect (")"); //close bracket is after we save the statement to mem (so debugger does not show the if statement as being on the line after @@ -6096,18 +6096,18 @@ void QCC_PR_ParseStatement (void) if (e->type->type == ev_float) { - e2 = QCC_PR_Statement (&pr_opcodes[OP_GE], e, pr_casesdef[i], NULL); - e3 = QCC_PR_Statement (&pr_opcodes[OP_LE], e, pr_casesdef2[i], NULL); - e2 = QCC_PR_Statement (&pr_opcodes[OP_AND], e2, e3, NULL); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3)); + e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_F], e, pr_casesdef[i], NULL); + e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_F], e, pr_casesdef2[i], NULL); + e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_F], e2, e3, NULL); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3)); patch3->b = &statements[pr_cases[i]] - patch3; } else if (e->type->type == ev_integer) { e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_I], e, pr_casesdef[i], NULL); e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_I], e, pr_casesdef2[i], NULL); - e2 = QCC_PR_Statement (&pr_opcodes[OP_AND], e2, e3, NULL); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3)); + e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_I], e2, e3, NULL); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3)); patch3->b = &statements[pr_cases[i]] - patch3; } else @@ -6153,7 +6153,7 @@ void QCC_PR_ParseStatement (void) e2 = NULL; break; } - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF], e2, 0, &patch3)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e2, 0, &patch3)); } else { @@ -6162,7 +6162,7 @@ void QCC_PR_ParseStatement (void) else if (e->type->type == ev_float) QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch3)); else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT], e, 0, &patch3)); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch3)); } patch3->b = &statements[pr_cases[i]] - patch3; } @@ -6457,20 +6457,20 @@ void QCC_PR_ParseState (void) //make sure the frame is within the bounds given. ftemp = frame->temp; frame->temp = NULL; - t1 = QCC_PR_Statement(&pr_opcodes[OP_LT], frame, s1, NULL); - t2 = QCC_PR_Statement(&pr_opcodes[OP_GT], frame, def, NULL); - t1 = QCC_PR_Statement(&pr_opcodes[OP_OR], t1, t2, NULL); - QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 2, 0, false); + t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL); + t2 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL); + t1 = QCC_PR_Statement(&pr_opcodes[OP_OR_F], t1, t2, NULL); + QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 2, 0, false); QCC_FreeTemp(t1); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL)); QCC_PR_SimpleStatement(OP_GOTO, t1->ofs, 13, 0, false); - t1 = QCC_PR_Statement(&pr_opcodes[OP_GE], def, s1, NULL); - QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 7, 0, false); + t1 = QCC_PR_Statement(&pr_opcodes[OP_GE_F], def, s1, NULL); + QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 7, 0, false); QCC_FreeTemp(t1); //this block is the 'it's in a forwards direction' QCC_PR_SimpleStatement(OP_ADD_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false); - t1 = QCC_PR_Statement(&pr_opcodes[OP_GT], frame, def, NULL); - QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false); + t1 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL); + QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false); QCC_FreeTemp(t1); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL)); QCC_UnFreeTemp(frame); @@ -6480,8 +6480,8 @@ void QCC_PR_ParseState (void) QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false); //reverse animation. QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false); - t1 = QCC_PR_Statement(&pr_opcodes[OP_LT], frame, s1, NULL); - QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false); + t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL); + QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false); QCC_FreeTemp(t1); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL)); QCC_UnFreeTemp(frame); @@ -7476,9 +7476,9 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi QCC_def_t *eq; if (min == max || min+1 == max) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(min+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL); QCC_UnFreeTemp(index); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); st->a = array->ofs + min*array->type->size; @@ -7489,9 +7489,9 @@ void QCC_PR_ArrayRecurseDivideRegular(QCC_def_t *array, QCC_def_t *index, int mi if (max-min>4) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(mid+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL); QCC_UnFreeTemp(index); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); } else st = NULL; @@ -7510,9 +7510,9 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i QCC_def_t *eq; if (min == max || min+1 == max) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(min+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(min+0.5f), NULL); QCC_UnFreeTemp(index); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); st->a = array->ofs + min*3; @@ -7523,9 +7523,9 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i if (max-min>4) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(mid+0.5f), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(mid+0.5f), NULL); QCC_UnFreeTemp(index); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); } else st = NULL; @@ -7561,7 +7561,7 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array) locals_end = numpr_globals; df->locals = locals_end - df->parm_start; QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), temp, false); - QCC_PR_Statement3(pr_opcodes+OP_BITAND, temp, temp, temp, false);//round down to int + QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, temp, temp, temp, false);//round down to int QCC_PR_ArrayRecurseDivideUsingVectors(array, temp, 0, (array->arraysize+2)/3); //round up @@ -7615,7 +7615,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) if (fasttrackpossible) { - QCC_PR_Statement(pr_opcodes+OP_IFNOT, fasttrackpossible, NULL, &st); + QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, fasttrackpossible, NULL, &st); //fetch_gbl takes: (float size, variant array[]), float index, variant pos //note that the array size is coded into the globals, one index before the array. @@ -7641,15 +7641,15 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 1, false); intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 1, false); - eq = QCC_PR_Statement(pr_opcodes+OP_GE, index, QCC_MakeFloatDef((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule! - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatDef((float)def->arraysize), NULL); //escape clause - should call some sort of error function instead.. that'd rule! + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, &st); div3->references++; - QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false); + QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false); QCC_PR_Statement3(pr_opcodes+OP_DIV_F, index, QCC_MakeFloatDef(3), div3, false); - QCC_PR_Statement3(pr_opcodes+OP_BITAND, div3, div3, intdiv3, false); + QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, div3, div3, intdiv3, false); QCC_PR_Statement3(pr_opcodes+OP_STORE_F, index, &def_parms[0], NULL, false); QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, NULL, false); @@ -7663,20 +7663,20 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) QCC_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false); QCC_FreeTemp(div3); - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(0+0.5f), NULL); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(0+0.5f), NULL); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); st->a = ret->ofs + 0; - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(1+0.5f), NULL); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(1+0.5f), NULL); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); st->a = ret->ofs + 1; - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(2+0.5), NULL); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef(2+0.5), NULL); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 2; QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); st->a = ret->ofs + 2; @@ -7685,7 +7685,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname) } else { - QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false); + QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false); QCC_PR_ArrayRecurseDivideRegular(def, index, 0, def->arraysize); } @@ -7710,7 +7710,7 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t { eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatDef((float)min), NULL); QCC_UnFreeTemp(index); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); st->b = 3; if (array->type->size == 3) QCC_PR_Statement(pr_opcodes+OP_STORE_V, value, array, &st); @@ -7725,9 +7725,9 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t if (max-min>4) { - eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef((float)mid), NULL); + eq = QCC_PR_Statement(pr_opcodes+OP_LT_F, index, QCC_MakeFloatDef((float)mid), NULL); QCC_UnFreeTemp(index); - QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT, eq, 0, &st)); + QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st)); } else st = NULL; @@ -7774,7 +7774,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) { QCC_dstatement_t *st; - QCC_PR_Statement(pr_opcodes+OP_IFNOT, fasttrackpossible, NULL, &st); + QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, fasttrackpossible, NULL, &st); //note that the array size is coded into the globals, one index before the array. QCC_PR_Statement3(&pr_opcodes[OP_CONV_FTOI], index, NULL, index, true); //address stuff is integer based, but standard qc (which this accelerates in supported engines) only supports floats @@ -7792,7 +7792,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) st->b = &statements[numstatements] - st; } - QCC_PR_Statement3(pr_opcodes+OP_BITAND, index, index, index, false); + QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false); QCC_PR_ArraySetRecurseDivide(def, index, value, 0, def->arraysize); QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index ebe1377c3..5fb287257 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -1712,6 +1712,7 @@ int QCC_PR_FinishCompilation (void) // if (!f || (!f->code && !f->builtin) ) if (d->initialized==0) { + s_file = d->s_file; if (!strncmp(d->name, "ArrayGet*", 9)) { QCC_PR_EmitArrayGetFunction(d, d->name+9); @@ -1733,6 +1734,7 @@ int QCC_PR_FinishCompilation (void) bodylessfuncs = true; errors = true; } + s_file = NULL; // errors = true; } else if (d->initialized==2) diff --git a/engine/qclib/qcdecomp.c b/engine/qclib/qcdecomp.c index a8d466e13..24fc433f6 100644 --- a/engine/qclib/qcdecomp.c +++ b/engine/qclib/qcdecomp.c @@ -329,7 +329,7 @@ int WriteStatement(progfuncs_t *progfuncs, progstate_t *progs, int stnum, int fi st = &((dstatement16_t*)progs->statements)[stnum]; switch(st->op) { - case OP_IFNOT: + case OP_IFNOT_I: count = (signed short)st->b; writes(file, "if ("); WriteStatementProducingOfs(progfuncs, progs, stnum, firstpossible, st->a); @@ -375,7 +375,7 @@ int WriteStatement(progfuncs_t *progfuncs, progstate_t *progs, int stnum, int fi writes(file, "}\r\n"); } break; - case OP_IF: + case OP_IF_I: longjmp(decompilestatementfailure, 1); break; case OP_GOTO: