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
This commit is contained in:
Spoike 2011-07-08 18:59:48 +00:00
parent 94debdcaf3
commit f6856f7d2d
10 changed files with 469 additions and 301 deletions

View file

@ -101,16 +101,16 @@ reeval:
OPC->_vector[2] = OPB->_float / OPA->_vector[2]; OPC->_vector[2] = OPB->_float / OPA->_vector[2];
break; break;
case OP_BITAND: case OP_BITAND_F:
OPC->_float = (float)((int)OPA->_float & (int)OPB->_float); OPC->_float = (float)((int)OPA->_float & (int)OPB->_float);
break; break;
case OP_BITOR: case OP_BITOR_F:
OPC->_float = (float)((int)OPA->_float | (int)OPB->_float); OPC->_float = (float)((int)OPA->_float | (int)OPB->_float);
break; break;
case OP_GE: case OP_GE_F:
OPC->_float = (float)(OPA->_float >= OPB->_float); OPC->_float = (float)(OPA->_float >= OPB->_float);
break; break;
case OP_GE_I: case OP_GE_I:
@ -123,7 +123,7 @@ reeval:
OPC->_float = (float)(OPA->_float >= OPB->_int); OPC->_float = (float)(OPA->_float >= OPB->_int);
break; break;
case OP_LE: case OP_LE_F:
OPC->_float = (float)(OPA->_float <= OPB->_float); OPC->_float = (float)(OPA->_float <= OPB->_float);
break; break;
case OP_LE_I: case OP_LE_I:
@ -136,7 +136,7 @@ reeval:
OPC->_float = (float)(OPA->_float <= OPB->_int); OPC->_float = (float)(OPA->_float <= OPB->_int);
break; break;
case OP_GT: case OP_GT_F:
OPC->_float = (float)(OPA->_float > OPB->_float); OPC->_float = (float)(OPA->_float > OPB->_float);
break; break;
case OP_GT_I: case OP_GT_I:
@ -149,7 +149,7 @@ reeval:
OPC->_float = (float)(OPA->_float > OPB->_int); OPC->_float = (float)(OPA->_float > OPB->_int);
break; break;
case OP_LT: case OP_LT_F:
OPC->_float = (float)(OPA->_float < OPB->_float); OPC->_float = (float)(OPA->_float < OPB->_float);
break; break;
case OP_LT_I: case OP_LT_I:
@ -162,10 +162,10 @@ reeval:
OPC->_float = (float)(OPA->_float < OPB->_int); OPC->_float = (float)(OPA->_float < OPB->_int);
break; break;
case OP_AND: case OP_AND_F:
OPC->_float = (float)(OPA->_float && OPB->_float); OPC->_float = (float)(OPA->_float && OPB->_float);
break; break;
case OP_OR: case OP_OR_F:
OPC->_float = (float)(OPA->_float || OPB->_float); OPC->_float = (float)(OPA->_float || OPB->_float);
break; break;
@ -511,7 +511,7 @@ reeval:
st += (sofs)st->b - 1; // offset the s++ st += (sofs)st->b - 1; // offset the s++
break; break;
case OP_IFNOT: case OP_IFNOT_I:
RUNAWAYCHECK(); RUNAWAYCHECK();
if (!OPA->_int) if (!OPA->_int)
st += (sofs)st->b - 1; // offset the s++ st += (sofs)st->b - 1; // offset the s++
@ -529,7 +529,7 @@ reeval:
st += (sofs)st->b - 1; // offset the s++ st += (sofs)st->b - 1; // offset the s++
break; break;
case OP_IF: case OP_IF_I:
RUNAWAYCHECK(); RUNAWAYCHECK();
if (OPA->_int) if (OPA->_int)
st += (sofs)st->b - 1; // offset the s++ st += (sofs)st->b - 1; // offset the s++
@ -741,7 +741,7 @@ if (pr_typecurrent != 0)
break; break;
//array/structure reading/riting. //array/structure reading/writing.
case OP_GLOBALADDRESS: case OP_GLOBALADDRESS:
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
break; 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); PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
} }
t = (eval_t *)&pr_globals[(uofs)st->a t = (eval_t *)&pr_globals[(uofs)st->a + i*3];
+((int)OPB->_float)*3];
OPC->_vector[0] = t->_vector[0]; OPC->_vector[0] = t->_vector[0];
OPC->_vector[1] = t->_vector[1]; OPC->_vector[1] = t->_vector[1];
OPC->_vector[2] = t->_vector[2]; OPC->_vector[2] = t->_vector[2];

View file

@ -111,11 +111,6 @@ void PR_Configure (progfuncs_t *progfuncs, int addressable_size, int max_progs)
unsigned int i; unsigned int i;
edictrun_t *e; edictrun_t *e;
// int a;
#ifdef QCJIT
prinst->usejit = true;
#endif
max_fields_size=0; max_fields_size=0;
fields_size = 0; fields_size = 0;
progfuncs->stringtable = 0; progfuncs->stringtable = 0;

View file

@ -31,7 +31,7 @@ typedef int QCC_string_t;
#define RESERVED_OFS 28 #define RESERVED_OFS 28
enum { enum qcop_e {
OP_DONE, //0 OP_DONE, //0
OP_MUL_F, OP_MUL_F,
OP_MUL_V, OP_MUL_V,
@ -55,10 +55,10 @@ enum {
OP_NE_E, OP_NE_E,
OP_NE_FNC, OP_NE_FNC,
OP_LE, //20 OP_LE_F, //20
OP_GE, OP_GE_F,
OP_LT, OP_LT_F,
OP_GT, OP_GT_F,
OP_LOAD_F, OP_LOAD_F,
OP_LOAD_V, OP_LOAD_V,
@ -89,8 +89,8 @@ enum {
OP_NOT_S, OP_NOT_S,
OP_NOT_ENT, OP_NOT_ENT,
OP_NOT_FNC, OP_NOT_FNC,
OP_IF, OP_IF_I,
OP_IFNOT, //50 OP_IFNOT_I, //50
OP_CALL0, //careful... hexen2 and q1 have different calling conventions OP_CALL0, //careful... hexen2 and q1 have different calling conventions
OP_CALL1, //remap hexen2 calls to OP_CALL2H OP_CALL1, //remap hexen2 calls to OP_CALL2H
OP_CALL2, OP_CALL2,
@ -102,11 +102,11 @@ enum {
OP_CALL8, OP_CALL8,
OP_STATE, //60 OP_STATE, //60
OP_GOTO, OP_GOTO,
OP_AND, OP_AND_F,
OP_OR, OP_OR_F,
OP_BITAND, OP_BITAND_F,
OP_BITOR, OP_BITOR_F,
//these following ones are Hexen 2 constants. //these following ones are Hexen 2 constants.
@ -184,10 +184,10 @@ enum {
OP_ADD_I, OP_ADD_I,
OP_ADD_FI, OP_ADD_FI,
OP_ADD_IF, //110 OP_ADD_IF,
OP_SUB_I, OP_SUB_I,
OP_SUB_FI, OP_SUB_FI, //120
OP_SUB_IF, OP_SUB_IF,
OP_CONV_ITOF, OP_CONV_ITOF,
@ -196,10 +196,10 @@ enum {
OP_CP_FTOI, OP_CP_FTOI,
OP_LOAD_I, OP_LOAD_I,
OP_STOREP_I, OP_STOREP_I,
OP_STOREP_IF, //120 OP_STOREP_IF,
OP_STOREP_FI, OP_STOREP_FI,
OP_BITAND_I, OP_BITAND_I, //130
OP_BITOR_I, OP_BITOR_I,
OP_MUL_I, OP_MUL_I,
@ -210,11 +210,11 @@ enum {
OP_IFNOT_S, OP_IFNOT_S,
OP_IF_S, OP_IF_S,
OP_NOT_I, //130 OP_NOT_I,
OP_DIV_VF, OP_DIV_VF,
OP_XOR_I, OP_XOR_I, //140
OP_RSHIFT_I, OP_RSHIFT_I,
OP_LSHIFT_I, OP_LSHIFT_I,
@ -224,9 +224,9 @@ enum {
OP_LOADA_F, OP_LOADA_F,
OP_LOADA_V, OP_LOADA_V,
OP_LOADA_S, OP_LOADA_S,
OP_LOADA_ENT, //140 OP_LOADA_ENT,
OP_LOADA_FLD, OP_LOADA_FLD,
OP_LOADA_FNC, OP_LOADA_FNC, //150
OP_LOADA_I, OP_LOADA_I,
OP_STORE_P, //152... erm.. wait... OP_STORE_P, //152... erm.. wait...
@ -236,9 +236,9 @@ enum {
OP_LOADP_V, OP_LOADP_V,
OP_LOADP_S, OP_LOADP_S,
OP_LOADP_ENT, OP_LOADP_ENT,
OP_LOADP_FLD, //150 OP_LOADP_FLD,
OP_LOADP_FNC, OP_LOADP_FNC,
OP_LOADP_I, OP_LOADP_I, //160
OP_LE_I, OP_LE_I,
OP_GE_I, OP_GE_I,
@ -248,10 +248,10 @@ enum {
OP_LE_IF, OP_LE_IF,
OP_GE_IF, OP_GE_IF,
OP_LT_IF, OP_LT_IF,
OP_GT_IF, //160 OP_GT_IF,
OP_LE_FI, OP_LE_FI,
OP_GE_FI, OP_GE_FI, //170
OP_LT_FI, OP_LT_FI,
OP_GT_FI, OP_GT_FI,
@ -263,12 +263,12 @@ enum {
OP_ADD_SF, //(char*)c = (char*)a + (float)b OP_ADD_SF, //(char*)c = (char*)a + (float)b
OP_SUB_S, //(float)c = (char*)a - (char*)b OP_SUB_S, //(float)c = (char*)a - (char*)b
OP_STOREP_C,//(float)c = *(char*)b = (float)a 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_IF,
OP_MUL_FI, OP_MUL_FI, //180
OP_MUL_VI, OP_MUL_VI,
OP_MUL_IV, OP_MUL_IV,
OP_DIV_IF, OP_DIV_IF,
@ -276,9 +276,9 @@ enum {
OP_BITAND_IF, OP_BITAND_IF,
OP_BITOR_IF, OP_BITOR_IF,
OP_BITAND_FI, OP_BITAND_FI,
OP_BITOR_FI, //180 OP_BITOR_FI,
OP_AND_I, OP_AND_I,
OP_OR_I, OP_OR_I, //190
OP_AND_IF, OP_AND_IF,
OP_OR_IF, OP_OR_IF,
OP_AND_FI, OP_AND_FI,
@ -288,9 +288,9 @@ enum {
//erm... FTEQCC doesn't make use of these... These are for DP. //erm... FTEQCC doesn't make use of these... These are for DP.
OP_GSTOREP_I, OP_GSTOREP_I,
OP_GSTOREP_F, //190 OP_GSTOREP_F,
OP_GSTOREP_ENT, OP_GSTOREP_ENT,
OP_GSTOREP_FLD, // integers OP_GSTOREP_FLD, // integers //200
OP_GSTOREP_S, OP_GSTOREP_S,
OP_GSTOREP_FNC, // pointers OP_GSTOREP_FNC, // pointers
OP_GSTOREP_V, OP_GSTOREP_V,
@ -298,9 +298,9 @@ enum {
OP_GLOAD_I, OP_GLOAD_I,
OP_GLOAD_F, OP_GLOAD_F,
OP_GLOAD_FLD, OP_GLOAD_FLD,
OP_GLOAD_ENT, //200 OP_GLOAD_ENT,
OP_GLOAD_S, OP_GLOAD_S,
OP_GLOAD_FNC, OP_GLOAD_FNC, //210
OP_BOUNDCHECK, OP_BOUNDCHECK,
//back to ones that we do use. //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. These ops are emulated out, always, and are only present in the compiler.
*/ */
OP_BITSET_I, OP_BITSET_I, //220
OP_BITSETP_I, OP_BITSETP_I,
OP_MULSTORE_I, OP_MULSTORE_I,
@ -332,7 +332,7 @@ enum {
OP_ADDSTOREP_I, OP_ADDSTOREP_I,
OP_SUBSTOREP_I, OP_SUBSTOREP_I,
OP_MULSTORE_IF, OP_MULSTORE_IF, //230
OP_MULSTOREP_IF, OP_MULSTOREP_IF,
OP_DIVSTORE_IF, OP_DIVSTORE_IF,
OP_DIVSTOREP_IF, OP_DIVSTOREP_IF,
@ -343,14 +343,14 @@ enum {
OP_MULSTORE_FI, OP_MULSTORE_FI,
OP_MULSTOREP_FI, OP_MULSTOREP_FI,
OP_DIVSTORE_FI, OP_DIVSTORE_FI, //240
OP_DIVSTOREP_FI, OP_DIVSTOREP_FI,
OP_ADDSTORE_FI, OP_ADDSTORE_FI,
OP_ADDSTOREP_FI, OP_ADDSTOREP_FI,
OP_SUBSTORE_FI, OP_SUBSTORE_FI,
OP_SUBSTOREP_FI, OP_SUBSTOREP_FI,
OP_NUMOPS OP_NUMOPS //246
}; };
#define MAX_PARMS 8 #define MAX_PARMS 8

View file

@ -859,9 +859,9 @@ void PR_ExecuteCode (progfuncs_t *progfuncs, int s)
prinst->continuestatement = -1; prinst->continuestatement = -1;
#ifdef QCJIT #ifdef QCJIT
if (prinst->usejit) if (prinst->jit)
{ {
PR_EnterJIT(progfuncs, s); PR_EnterJIT(progfuncs, prinst->jit, s);
return; return;
} }
#endif #endif

View file

@ -94,8 +94,7 @@ progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_
progfuncs->numprogs = a+1; progfuncs->numprogs = a+1;
#ifdef QCJIT #ifdef QCJIT
if (prinst->usejit) prinst->jit = PR_GenerateJit(progfuncs);
prinst->usejit = PR_GenerateJit(progfuncs);
#endif #endif
if (oldtype>=0) if (oldtype>=0)
PR_SwitchProgs(progfuncs, oldtype); PR_SwitchProgs(progfuncs, oldtype);

View file

@ -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 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 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 eax - tmp
ebx - prinst->edicttable ebx - prinst->edicttable
ecx - tmp ecx - tmp
edx - tmp edx - tmp
esi - esi - debug opcode number
edi - tmp (because its preserved by subfunctions edi - tmp (because its preserved by subfunctions
ebp - ebp -
to use gas to provide binary opcodes: to use gas to provide binary opcodes:
vim -N blob.s && as blob.s && objdump.exe -d a.out 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 #define PROGSUSED
@ -29,56 +44,59 @@ optimisations:
static float ta, tb, nullfloat=0; static float ta, tb, nullfloat=0;
unsigned int *statementjumps; //[MAX_STATEMENTS*2] struct jitstate
unsigned char **statementoffsets; //[MAX_STATEMENTS] {
unsigned int numjumps; unsigned int *statementjumps; //[MAX_STATEMENTS*3]
unsigned char *code; unsigned char **statementoffsets; //[MAX_STATEMENTS]
unsigned int codesize; unsigned int numjumps;
unsigned int jitstatements; 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; jit->code[jit->codesize++] = (value>> 0)&0xff;
code[codesize++] = (value>> 8)&0xff; jit->code[jit->codesize++] = (value>> 8)&0xff;
code[codesize++] = (value>>16)&0xff; jit->code[jit->codesize++] = (value>>16)&0xff;
code[codesize++] = (value>>24)&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; union {float f; unsigned int i;} u;
u.f = value; 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; jit->code[jit->codesize++] = (value>> 0)&0xff;
code[codesize++] = (value>> 8)&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; union {void *f; unsigned int i;} u;
u.f = func; u.f = func;
u.i -= (unsigned int)&code[codesize+bias]; u.i -= (unsigned int)&jit->code[jit->codesize+bias];
Emit4Byte(u.i); Emit4Byte(jit, u.i);
} }
void Emit4ByteJump(int statementnum, int offset) static void Emit4ByteJump(struct jitstate *jit, int statementnum, int offset)
{ {
statementjumps[numjumps++] = codesize; jit->statementjumps[jit->numjumps++] = jit->codesize;
statementjumps[numjumps++] = statementnum; jit->statementjumps[jit->numjumps++] = statementnum;
statementjumps[numjumps++] = offset; jit->statementjumps[jit->numjumps++] = offset;
//the offset is filled in later //the offset is filled in later
codesize += 4; jit->codesize += 4;
} }
enum 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 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 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 STOREF(f, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);EmitFloat(f);
#define STOREI(f, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);EmitFloat(f); #define STOREI(i, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);Emit4Byte(i);
#define SETREGI(val,reg) EmitByte(0xbe);EmitByte(val);EmitByte(val>>8);EmitByte(val>>16);EmitByte(val>>24); #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) if (cond == OP_GOTO)
EmitByte(0xeb); //jmp EmitByte(jit, 0xeb); //jmp
else if (cond == OP_LE) else if (cond == OP_LE_F)
EmitByte(0x7e); //jle EmitByte(jit, 0x76); //jbe
else if (cond == OP_GE) else if (cond == OP_GE_F)
EmitByte(0x7d); //jge EmitByte(jit, 0x73); //jae
else if (cond == OP_LT) else if (cond == OP_LT_F)
EmitByte(0x7c); //jl EmitByte(jit, 0x72); //jb
else if (cond == OP_GT) else if (cond == OP_GT_F)
EmitByte(0x7f); //jg 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) 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) 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) #if defined(DEBUG) && defined(_WIN32)
else else
{ {
@ -128,11 +151,11 @@ void *LocalJmp(int cond)
} }
#endif #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; int offs;
unsigned char *a = jmp; unsigned char *a = jmp;
@ -149,7 +172,7 @@ void LocalJmpLoc(void *jmp, void *loc)
a[-1] = offs; a[-1] = offs;
} }
void FixupJumps(void) static void FixupJumps(struct jitstate *jit)
{ {
unsigned int j; unsigned int j;
unsigned char *codesrc; unsigned char *codesrc;
@ -158,15 +181,15 @@ void FixupJumps(void)
unsigned int v; unsigned int v;
for (j = 0; j < numjumps;) for (j = 0; j < jit->numjumps;)
{ {
v = statementjumps[j++]; v = jit->statementjumps[j++];
codesrc = &code[v]; codesrc = &jit->code[v];
v = statementjumps[j++]; v = jit->statementjumps[j++];
codedst = statementoffsets[v]; 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 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; codesrc[0] = (offset>> 0)&0xff;
@ -179,8 +202,27 @@ void FixupJumps(void)
int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs); int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs);
int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum); 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 *j0, *l0;
void *j1, *l1; void *j1, *l1;
void *j2, *l2; void *j2, *l2;
@ -190,44 +232,48 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
int *glob = (int*)current_progstate->globals; int *glob = (int*)current_progstate->globals;
if (current_progstate->numbuiltins) 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); jit->numjumps = 0;
statementoffsets = malloc(numstatements*4); jit->codesize = 0;
code = malloc(numstatements*500);
numjumps = 0;
codesize = 0;
for (i = 0; i < numstatements; i++) for (i = 0; i < numstatements; i++)
{ {
statementoffsets[i] = &code[codesize]; jit->statementoffsets[i] = &jit->code[jit->codesize];
/*DEBUG*/
SETREGI(op[i].op, REG_ESI); SETREGI(op[i].op, REG_ESI);
switch(op[i].op) switch(op[i].op)
{ {
//jumps //jumps
case OP_IF: case OP_IF_I:
//integer compare //integer compare
//if a, goto b //if a, goto b
//cmpl $0,glob[A] //cmpl $0,glob[A]
EmitByte(0x83);EmitByte(0x3d);EmitAdr(glob + op[i].a);EmitByte(0x0); 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); EmitByte(0x0f);EmitByte(0x85);Emit4ByteJump(i + (signed short)op[i].b, -4);
break; break;
case OP_IFNOT: case OP_IFNOT_I:
//integer compare //integer compare
//if !a, goto b //if !a, goto b
//cmpl $0,glob[A] //cmpl $0,glob[A]
EmitByte(0x83);EmitByte(0x3d);EmitAdr(glob + op[i].a);EmitByte(0x0); 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); EmitByte(0x0f);EmitByte(0x84);Emit4ByteJump(i + (signed short)op[i].b, -4);
break; break;
@ -276,7 +322,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
// je returntoc // je returntoc
j1 = LocalJmp(OP_EQ_E); j1 = LocalJmp(OP_EQ_E);
// mov statementoffsets[%eax*4],%eax // 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 // jmp *eax
EmitByte(0xff);EmitByte(0xe0); EmitByte(0xff);EmitByte(0xe0);
// returntoc: // returntoc:
@ -299,9 +345,9 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
case OP_CALL8: case OP_CALL8:
//save the state in place the rest of the engine can cope with //save the state in place the rest of the engine can cope with
//movl $i, pr_xstatement //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 //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 //figure out who we're calling, and what that involves
//%eax = glob[A] //%eax = glob[A]
@ -358,8 +404,9 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
//cmp $0,%edx //cmp $0,%edx
EmitByte(0x83);EmitByte(0xfa);EmitByte(0x00); EmitByte(0x83);EmitByte(0xfa);EmitByte(0x00);
//jl isabuiltin //jl isabuiltin
j1 = LocalJmp(OP_LE); j1 = LocalJmp(OP_LT_I);
{ {
/* call the function*/
//push %ecx //push %ecx
EmitByte(0x51); EmitByte(0x51);
//push %eax //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) //eax is now the next statement number (first of the new function, usually equal to ecx, but not always)
//jmp statementoffsets[%eax*4] //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: //isabuiltin:
l1 = LocalLoc(); l1 = LocalLoc();
LocalJmpLoc(j1,l1); LocalJmpLoc(j1,l1);
@ -403,7 +451,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
EmitByte(0xc7);EmitByte(0x05);EmitAdr(&prinst->continuestatement);Emit4Byte((unsigned int)-1); EmitByte(0xc7);EmitByte(0x05);EmitAdr(&prinst->continuestatement);Emit4Byte((unsigned int)-1);
//jmp statementoffsets[%eax*4] //jmp statementoffsets[%eax*4]
EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(statementoffsets); EmitByte(0xff);EmitByte(0x24);EmitByte(0x85);EmitAdr(jit->statementoffsets);
} }
//donebuiltincall: //donebuiltincall:
l1 = LocalLoc(); l1 = LocalLoc();
@ -444,10 +492,10 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
break; break;
case OP_NOT_F: case OP_NOT_F:
//flds glob[A]
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a);
//fldz //fldz
EmitByte(0xd9);EmitByte(0xee); EmitByte(0xd9);EmitByte(0xee);
//fcomps glob[A]
EmitByte(0xd8); EmitByte(0x1d); EmitAdr(glob + op[i].a);
//fnstsw %ax //fnstsw %ax
EmitByte(0xdf);EmitByte(0xe0); EmitByte(0xdf);EmitByte(0xe0);
//testb 0x40,%ah //testb 0x40,%ah
@ -455,13 +503,13 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
j1 = LocalJmp(OP_NE_F); j1 = LocalJmp(OP_NE_F);
{ {
STOREF(1.0f, glob + op[i].c); STOREF(0.0f, glob + op[i].c);
j2 = LocalJmp(OP_GOTO); j2 = LocalJmp(OP_GOTO);
} }
{ {
//noteq: //noteq:
l1 = LocalLoc(); l1 = LocalLoc();
STOREF(0.0f, glob + op[i].c); STOREF(1.0f, glob + op[i].c);
} }
//end: //end:
l2 = LocalLoc(); l2 = LocalLoc();
@ -508,18 +556,18 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
EmitByte(0x8b);EmitByte(0x50);EmitByte((int)&((edictrun_t*)NULL)->fields); EmitByte(0x8b);EmitByte(0x50);EmitByte((int)&((edictrun_t*)NULL)->fields);
//edx is now the field array for that ent //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); EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(progfuncs->fieldadjust*4);
STOREREG(REG_EAX, glob + op[i].c) STOREREG(REG_EAX, glob + op[i].c)
if (op[i].op == OP_LOAD_V) 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); EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(4+progfuncs->fieldadjust*4);
STOREREG(REG_EAX, glob + op[i].c+1) 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); EmitByte(0x8b); EmitByte(0x84); EmitByte(0x8a); Emit4Byte(8+progfuncs->fieldadjust*4);
STOREREG(REG_EAX, glob + op[i].c+2) 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); EmitByte(0x3b); EmitByte(0x04); EmitByte(0x25); EmitAdr(glob + op[i].b);
j1 = LocalJmp(op[i].op); j1 = LocalJmp(op[i].op);
{ {
STOREF(1.0f, glob + op[i].c); STOREF(0.0f, glob + op[i].c);
j2 = LocalJmp(OP_GOTO); j2 = LocalJmp(OP_GOTO);
} }
{ {
l1 = LocalLoc(); l1 = LocalLoc();
STOREF(0.0f, glob + op[i].c); STOREF(1.0f, glob + op[i].c);
} }
l2 = LocalLoc(); l2 = LocalLoc();
LocalJmpLoc(j1,l1); LocalJmpLoc(j1,l1);
@ -617,47 +665,45 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
LocalJmpLoc(j2,l2); LocalJmpLoc(j2,l2);
break; break;
case OP_BITOR: //floats... case OP_BITOR_F: //floats...
//flds glob[A] //flds glob[A]
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a); EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a);
//flds glob[B] //flds glob[B]
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b); EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b);
//fistp tb //fistp tb
EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&tb); EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&tb);
//fistp ta //fistp ta
EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&ta); EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta);
LOADREG(&ta, REG_EAX) LOADREG(&ta, REG_EAX)
//or tb,%eax //or %eax,tb
EmitByte(0x09); EmitByte(0x05);EmitAdr(&tb); EmitByte(0x09); EmitByte(0x05);EmitAdr(&tb);
STOREREG(REG_EAX, &tb)
//fild tb //fild tb
EmitByte(0xdf); EmitByte(0x05);EmitAdr(&tb); EmitByte(0xdb); EmitByte(0x05);EmitAdr(&tb);
//fstps glob[C] //fstps glob[C]
EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c); EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c);
break; break;
case OP_BITAND: case OP_BITAND_F:
//flds glob[A] //flds glob[A]
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a); EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].a);
//flds glob[B] //flds glob[B]
EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b); EmitByte(0xd9); EmitByte(0x05);EmitAdr(glob + op[i].b);
//fistp tb //fistp tb
EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&tb); EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&tb);
//fistp ta //fistp ta
EmitByte(0xdf); EmitByte(0x1d);EmitAdr(&ta); EmitByte(0xdb); EmitByte(0x1d);EmitAdr(&ta);
/*two args are now at ta and tb*/ /*two args are now at ta and tb*/
LOADREG(&ta, REG_EAX) LOADREG(&ta, REG_EAX)
//and tb,%eax //and tb,%eax
EmitByte(0x21); EmitByte(0x05);EmitAdr(&tb); 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*/ /*we just wrote the int value to tb, convert that to a float and store it at c*/
//fild tb //fild tb
EmitByte(0xdf); EmitByte(0x05);EmitAdr(&tb); EmitByte(0xdb); EmitByte(0x05);EmitAdr(&tb);
//fstps glob[C] //fstps glob[C]
EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c); EmitByte(0xd9); EmitByte(0x1d);EmitAdr(glob + op[i].c);
break; break;
case OP_AND: case OP_AND_F:
//test floats properly, so we don't get confused with -0.0 //test floats properly, so we don't get confused with -0.0
//flds glob[A] //flds glob[A]
@ -668,7 +714,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
EmitByte(0xdf); EmitByte(0xe0); EmitByte(0xdf); EmitByte(0xe0);
//test $0x40,%ah //test $0x40,%ah
EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40); EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40);
//je onefalse //jz onefalse
EmitByte(0x75); EmitByte(0x1f); EmitByte(0x75); EmitByte(0x1f);
//flds glob[B] //flds glob[B]
@ -679,7 +725,7 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
EmitByte(0xdf); EmitByte(0xe0); EmitByte(0xdf); EmitByte(0xe0);
//test $0x40,%ah //test $0x40,%ah
EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40); EmitByte(0xf6); EmitByte(0xc4);EmitByte(0x40);
//jne onefalse //jnz onefalse
EmitByte(0x75); EmitByte(0x0c); EmitByte(0x75); EmitByte(0x0c);
//mov float0,glob[C] //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); EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f);
//done: //done:
break; break;
case OP_OR: case OP_OR_F:
//test floats properly, so we don't get confused with -0.0 //test floats properly, so we don't get confused with -0.0
//flds glob[A] //flds glob[A]
@ -731,7 +777,6 @@ pbool PR_GenerateJit(progfuncs_t *progfuncs)
case OP_EQ_S: case OP_EQ_S:
case OP_NE_S: case OP_NE_S:
{ {
void *j0b, *j1b, *j1c;
//put a in ecx //put a in ecx
LOADREG(glob + op[i].a, REG_ECX); LOADREG(glob + op[i].a, REG_ECX);
//put b in edi //put b in edi
@ -940,14 +985,14 @@ LOADREG(glob + op[i].b, REG_EDI);
case OP_EQ_F: case OP_EQ_F:
case OP_NE_F: case OP_NE_F:
case OP_LE: case OP_LE_F:
case OP_GE: case OP_GE_F:
case OP_LT: case OP_LT_F:
case OP_GT: case OP_GT_F:
//flds glob[A] //flds glob[A]
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a);
//flds glob[B]
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].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 //fcomip %st(1),%st
EmitByte(0xdf);EmitByte(0xe9); EmitByte(0xdf);EmitByte(0xe9);
//fstp %st(0) (aka: pop) //fstp %st(0) (aka: pop)
@ -988,21 +1033,21 @@ LOADREG(glob + op[i].b, REG_EDI);
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + f); EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + f);
//flds glob[V0] //flds glob[V0]
EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+0); EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+0);
//fmul st(1) //fmul st(1)
EmitByte(0xd8);EmitByte(0xc9); EmitByte(0xd8);EmitByte(0xc9);
//fstps glob[C] //fstps glob[C]
EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+0); EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+0);
//flds glob[V0] //flds glob[V0]
EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+1); EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+1);
//fmul st(1) //fmul st(1)
EmitByte(0xd8);EmitByte(0xc9); EmitByte(0xd8);EmitByte(0xc9);
//fstps glob[C] //fstps glob[C]
EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+1); EmitByte(0xd9);EmitByte(0x1d);EmitAdr(glob + op[i].c+1);
//flds glob[V0] //flds glob[V0]
EmitByte(0xd8);EmitByte(0x0d);EmitAdr(glob + v+2); EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + v+2);
//fmul st(1) //fmul st(1)
EmitByte(0xd8);EmitByte(0xc9); EmitByte(0xd8);EmitByte(0xc9);
//fstps glob[C] //fstps glob[C]
@ -1045,8 +1090,17 @@ LOADREG(glob + op[i].b, REG_EDI);
//done: //done:
break; 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_NE_V:
case OP_EQ_V: case OP_EQ_V:
{
void *f0, *f1, *f2, *floc;
//compare v[0]
//flds glob[A] //flds glob[A]
EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+0); EmitByte(0xd9);EmitByte(0x05);EmitAdr(glob + op[i].a+0);
//flds glob[B] //flds glob[B]
@ -1056,43 +1110,151 @@ LOADREG(glob + op[i].b, REG_EDI);
//fstp %st(0) (aka: pop) //fstp %st(0) (aka: pop)
EmitByte(0xdd);EmitByte(0xd8); EmitByte(0xdd);EmitByte(0xd8);
//jncc _true /*if the condition is true, don't fail*/
if (op[i].op == OP_NE_V) j1 = LocalJmp(op[i].op);
EmitByte(0x74); //je {
else STOREF(0.0f, glob + op[i].c);
EmitByte(0x75); //jne f0 = LocalJmp(OP_GOTO);
EmitByte(0x0c); }
//_false0: l1 = LocalLoc();
//mov 0.0f,c LocalJmpLoc(j1,l1);
EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(1.0f);
//jmp done
EmitByte(0xeb); EmitByte(0x0a);
//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: /*if the condition is true, don't fail*/
//mov 1.0f,c j1 = LocalJmp(op[i].op);
EmitByte(0xc7); EmitByte(0x05); EmitAdr(glob + op[i].c); EmitFloat(0.0f); {
//_done: 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; break;
case OP_NOT_V: /*other extended opcodes*/
EmitByte(0xcd);EmitByte(op[i].op); case OP_BITOR_I:
printf("QCJIT: instruction %i is not implemented\n", op[i].op); 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; break;
#endif
default: 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(jit->statementjumps); //[MAX_STATEMENTS]
free(statementoffsets); //[MAX_STATEMENTS] free(jit->statementoffsets); //[MAX_STATEMENTS]
free(code); free(jit->code);
statementoffsets = NULL; free(jit);
return false; return NULL;
} }
} }
FixupJumps(); FixupJumps(jit);
#ifdef _WIN32 #ifdef _WIN32
{ {
@ -1100,22 +1262,32 @@ LOADREG(glob + op[i].b, REG_EDI);
//this memory is on the heap. //this memory is on the heap.
//this means that we must maintain read/write protection, or libc will crash us //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 #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__ #ifdef __GNUC__
//call, it clobbers pretty much everything. //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) #elif defined(_MSC_VER)
void *entry = statementoffsets[statement+1]; void *entry = jit->statementoffsets[statement+1];
void *edicttable = prinst->edicttable; void *edicttable = prinst->edicttable;
__asm { __asm {
pushad pushad

View file

@ -344,7 +344,7 @@ void PR_SetBuiltins(int type);
typedef struct prinst_s { typedef struct prinst_s {
#ifdef QCJIT #ifdef QCJIT
pbool usejit; struct jitstate *jit;
#endif #endif
char **tempstrings; char **tempstrings;
int maxtempstrings; int maxtempstrings;
@ -478,8 +478,9 @@ char *PR_GlobalStringNoContents (progfuncs_t *progfuncs, int ofs);
pbool CompileFile(progfuncs_t *progfuncs, char *filename); pbool CompileFile(progfuncs_t *progfuncs, char *filename);
pbool PR_GenerateJit(progfuncs_t *progfuncs); struct jitstate;
void PR_EnterJIT(progfuncs_t *progfuncs, int statement); struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs);
void PR_EnterJIT(progfuncs_t *progfuncs, struct jitstate *jitstate, int statement);
char *QCC_COM_Parse (char *data); char *QCC_COM_Parse (char *data);
extern char qcc_token[1024]; extern char qcc_token[1024];

View file

@ -661,12 +661,12 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
&pr_opcodes[OP_DIV_I], &pr_opcodes[OP_DIV_I],
&pr_opcodes[OP_DIV_VF], &pr_opcodes[OP_DIV_VF],
&pr_opcodes[OP_BITAND], &pr_opcodes[OP_BITAND_F],
&pr_opcodes[OP_BITAND_I], &pr_opcodes[OP_BITAND_I],
&pr_opcodes[OP_BITAND_IF], &pr_opcodes[OP_BITAND_IF],
&pr_opcodes[OP_BITAND_FI], &pr_opcodes[OP_BITAND_FI],
&pr_opcodes[OP_BITOR], &pr_opcodes[OP_BITOR_F],
&pr_opcodes[OP_BITOR_I], &pr_opcodes[OP_BITOR_I],
&pr_opcodes[OP_BITOR_IF], &pr_opcodes[OP_BITOR_IF],
&pr_opcodes[OP_BITOR_FI], &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_IF],
&pr_opcodes[OP_NE_FI], &pr_opcodes[OP_NE_FI],
&pr_opcodes[OP_LE], &pr_opcodes[OP_LE_F],
&pr_opcodes[OP_LE_I], &pr_opcodes[OP_LE_I],
&pr_opcodes[OP_LE_IF], &pr_opcodes[OP_LE_IF],
&pr_opcodes[OP_LE_FI], &pr_opcodes[OP_LE_FI],
&pr_opcodes[OP_GE], &pr_opcodes[OP_GE_F],
&pr_opcodes[OP_GE_I], &pr_opcodes[OP_GE_I],
&pr_opcodes[OP_GE_IF], &pr_opcodes[OP_GE_IF],
&pr_opcodes[OP_GE_FI], &pr_opcodes[OP_GE_FI],
&pr_opcodes[OP_LT], &pr_opcodes[OP_LT_F],
&pr_opcodes[OP_LT_I], &pr_opcodes[OP_LT_I],
&pr_opcodes[OP_LT_IF], &pr_opcodes[OP_LT_IF],
&pr_opcodes[OP_LT_FI], &pr_opcodes[OP_LT_FI],
&pr_opcodes[OP_GT], &pr_opcodes[OP_GT_F],
&pr_opcodes[OP_GT_I], &pr_opcodes[OP_GT_I],
&pr_opcodes[OP_GT_IF], &pr_opcodes[OP_GT_IF],
&pr_opcodes[OP_GT_FI], &pr_opcodes[OP_GT_FI],
@ -805,11 +805,11 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
NULL NULL
}, { //7 }, { //7
&pr_opcodes[OP_AND], &pr_opcodes[OP_AND_F],
&pr_opcodes[OP_AND_I], &pr_opcodes[OP_AND_I],
&pr_opcodes[OP_AND_IF], &pr_opcodes[OP_AND_IF],
&pr_opcodes[OP_AND_FI], &pr_opcodes[OP_AND_FI],
&pr_opcodes[OP_OR], &pr_opcodes[OP_OR_F],
&pr_opcodes[OP_OR_I], &pr_opcodes[OP_OR_I],
&pr_opcodes[OP_OR_IF], &pr_opcodes[OP_OR_IF],
&pr_opcodes[OP_OR_FI], &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 //both are constants
switch (op - pr_opcodes) //improve some of the maths. switch (op - pr_opcodes) //improve some of the maths.
{ {
case OP_BITOR: case OP_BITOR_F:
optres_constantarithmatic++; optres_constantarithmatic++;
return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) | (int)G_FLOAT(var_b->ofs))); 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++; optres_constantarithmatic++;
return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs))); return QCC_MakeFloatDef((float)((int)G_FLOAT(var_a->ofs) & (int)G_FLOAT(var_b->ofs)));
case OP_MUL_F: 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++; optres_constantarithmatic++;
return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs)); return QCC_MakeIntDef(G_INT(var_a->ofs) - G_INT(var_b->ofs));
case OP_AND: case OP_AND_F:
optres_constantarithmatic++; optres_constantarithmatic++;
return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs)); return QCC_MakeIntDef(G_INT(var_a->ofs) && G_INT(var_b->ofs));
case OP_OR: case OP_OR_F:
optres_constantarithmatic++; optres_constantarithmatic++;
return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs)); return QCC_MakeIntDef(G_INT(var_a->ofs) || G_INT(var_b->ofs));
case OP_MUL_V: //mul_f is actually a dot-product 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 //a is const, b is not
switch (op - pr_opcodes) switch (op - pr_opcodes)
{ {
case OP_BITOR: case OP_BITOR_F:
case OP_OR: case OP_OR_F:
case OP_ADD_F: case OP_ADD_F:
if (G_FLOAT(var_a->ofs) == 0) 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; return var_b;
} }
break; break;
case OP_BITAND: case OP_BITAND_F:
case OP_AND: case OP_AND_F:
if (G_FLOAT(var_a->ofs) != 0) if (G_FLOAT(var_a->ofs) != 0)
{ {
optres_constantarithmatic++; 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 //b is const, a is not
switch (op - pr_opcodes) switch (op - pr_opcodes)
{ {
case OP_BITOR: case OP_BITOR_F:
case OP_OR: case OP_OR_F:
case OP_SUB_F: case OP_SUB_F:
case OP_ADD_F: case OP_ADD_F:
if (G_FLOAT(var_b->ofs) == 0) 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; break;
//no bitand_f, I don't trust the casts //no bitand_f, I don't trust the casts
case OP_AND: case OP_AND_F:
if (G_FLOAT(var_b->ofs) != 0) if (G_FLOAT(var_b->ofs) != 0)
{ {
optres_constantarithmatic++; 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) switch (op - pr_opcodes)
{ {
case OP_AND: case OP_AND_F:
if (var_a->ofs == var_b->ofs) if (var_a->ofs == var_b->ofs)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same"); QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same");
if (var_a->constant || var_b->constant) if (var_a->constant || var_b->constant)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant"); QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
break; break;
case OP_OR: case OP_OR_F:
if (var_a->ofs == var_b->ofs) if (var_a->ofs == var_b->ofs)
QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameters for || are the same"); QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameters for || are the same");
if (var_a->constant || var_b->constant) 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_E:
case OP_NE_FNC: case OP_NE_FNC:
case OP_LE: case OP_LE_F:
case OP_GE: case OP_GE_F:
case OP_LT: case OP_LT_F:
case OP_GT: case OP_GT_F:
if ((var_a->constant && var_b->constant && !var_a->temp && !var_b->temp) || var_a->ofs == var_b->ofs) 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"); QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
break; 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_IFNOT_S:
case OP_IF_F: case OP_IF_F:
case OP_IFNOT_F: case OP_IFNOT_F:
case OP_IF: case OP_IF_I:
case OP_IFNOT: case OP_IFNOT_I:
// if (var_a->type->type == ev_function && !var_a->temp) // if (var_a->type->type == ev_function && !var_a->temp)
// QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant"); // QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Result of comparison is constant");
if (var_a->constant && !var_a->temp) 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) if (numstatements)
{ //optimise based on last statement. { //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)) 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) if (statements[numstatements-1].op == OP_NOT_F)
op = &pr_opcodes[OP_IF_F]; op = &pr_opcodes[OP_IF_F];
else else
op = &pr_opcodes[OP_IF]; op = &pr_opcodes[OP_IF_I];
numstatements--; numstatements--;
QCC_FreeTemp(var_a); QCC_FreeTemp(var_a);
memcpy(&nvara, var_a, sizeof(nvara)); 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++; numstatements++;
QCC_FreeTemp(var_a); QCC_FreeTemp(var_a);
op = &pr_opcodes[OP_IF]; op = &pr_opcodes[OP_IF_I];
break; break;
case OP_IFNOT_S: 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++; numstatements++;
QCC_FreeTemp(var_a); QCC_FreeTemp(var_a);
op = &pr_opcodes[OP_IFNOT]; op = &pr_opcodes[OP_IFNOT_I];
break; break;
case OP_IF_F: 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++; numstatements++;
QCC_FreeTemp(var_a); QCC_FreeTemp(var_a);
op = &pr_opcodes[OP_IF]; op = &pr_opcodes[OP_IF_I];
break; break;
case OP_IFNOT_F: 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++; numstatements++;
QCC_FreeTemp(var_a); QCC_FreeTemp(var_a);
op = &pr_opcodes[OP_IFNOT]; op = &pr_opcodes[OP_IFNOT_I];
break; break;
case OP_ADDSTORE_F: 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; var_c = var_a;
break; break;
case OP_BITSET: case OP_BITSET:
op = &pr_opcodes[OP_BITOR]; op = &pr_opcodes[OP_BITOR_F];
var_c = var_b; var_c = var_b;
var_b = var_a; var_b = var_a;
var_a = var_c; 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); QCC_UnFreeTemp(var_b);
numstatements--; 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); QCC_FreeTemp(var_c);
statement = &statements[numstatements]; statement = &statements[numstatements];
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; statement->op = OP_DIV_F;
break; break;
case OP_BITSETP: case OP_BITSETP:
statement->op = OP_BITOR; statement->op = OP_BITOR_F;
break; break;
case OP_BITSETP_I: case OP_BITSETP_I:
statement->op = OP_BITOR_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: case OP_BITCLRP:
//float pointer float //float pointer float
temp = QCC_GetTemp(type_float); temp = QCC_GetTemp(type_float);
statement->op = OP_BITAND; statement->op = OP_BITAND_F;
statement->a = var_c ? var_c->ofs : 0; statement->a = var_c ? var_c->ofs : 0;
statement->b = var_a ? var_a->ofs : 0; statement->b = var_a ? var_a->ofs : 0;
statement->c = temp->ofs; 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)) if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{ {
t = QCC_PR_Statement(&pr_opcodes[OP_GT], d, e, NULL); t = QCC_PR_Statement(&pr_opcodes[OP_GT_F], d, e, NULL);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT], t, 0, &st)); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_IFNOT_I], t, 0, &st));
st->b = 3; st->b = 3;
t = QCC_PR_Statement(&pr_opcodes[OP_SUB_F], d, e, NULL); 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)) if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{ {
t = QCC_GetTemp(type_float); t = QCC_GetTemp(type_float);
QCC_PR_SimpleStatement(OP_GT, d->ofs+2, e->ofs+2, t->ofs, false); QCC_PR_SimpleStatement(OP_GT_F, d->ofs+2, e->ofs+2, t->ofs, false);
QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, 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_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); 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)) if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{ {
t = QCC_GetTemp(type_float); t = QCC_GetTemp(type_float);
QCC_PR_SimpleStatement(OP_GT, d->ofs+1, e->ofs+1, t->ofs, false); QCC_PR_SimpleStatement(OP_GT_F, d->ofs+1, e->ofs+1, t->ofs, false);
QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, 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_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); 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)) if ((!d->constant || !e->constant) && G_FLOAT(d->ofs) >= G_FLOAT(d->ofs))
{ {
t = QCC_GetTemp(type_float); t = QCC_GetTemp(type_float);
QCC_PR_SimpleStatement(OP_GT, d->ofs, e->ofs, t->ofs, false); QCC_PR_SimpleStatement(OP_GT_F, d->ofs, e->ofs, t->ofs, false);
QCC_PR_SimpleStatement(OP_IFNOT, t->ofs, 3, 0, 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_SUB_F, d->ofs, e->ofs, t->ofs, false);
QCC_PR_SimpleStatement(OP_MUL_F, OFS_RETURN, t->ofs, OFS_RETURN, 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 ("?")) if (QCC_PR_CheckToken ("?"))
{ {
QCC_dstatement32_t *fromj, *elsej; 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); e = QCC_PR_Expression(TOP_PRIORITY, 0);
e2 = QCC_GetTemp(e->type); 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)); 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++; optres_logicops++;
st = &statements[numstatements]; st = &statements[numstatements];
if (*op->name == '&') //statement 3 because we don't want to optimise this into if from not ifnot 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 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); 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 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)); QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
else 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_Expect (")"); //after the line number is noted..
QCC_PR_ParseStatement (); QCC_PR_ParseStatement ();
@ -5718,7 +5718,7 @@ void QCC_PR_ParseStatement (void)
numtemp = 0; numtemp = 0;
if (e) 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 else
patch1 = NULL; patch1 = NULL;
if (!QCC_PR_CheckToken(";")) 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]))) 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)); QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, NULL, &patch2));
else 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; 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]))) 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)); QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, 0, &patch1));
else 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 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]))) 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)); QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1));
else 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 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) if (e->type->type == ev_float)
{ {
e2 = QCC_PR_Statement (&pr_opcodes[OP_GE], e, pr_casesdef[i], NULL); e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_F], e, pr_casesdef[i], NULL);
e3 = QCC_PR_Statement (&pr_opcodes[OP_LE], e, pr_casesdef2[i], NULL); e3 = QCC_PR_Statement (&pr_opcodes[OP_LE_F], e, pr_casesdef2[i], NULL);
e2 = QCC_PR_Statement (&pr_opcodes[OP_AND], e2, e3, NULL); e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_F], e2, e3, NULL);
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));
patch3->b = &statements[pr_cases[i]] - patch3; patch3->b = &statements[pr_cases[i]] - patch3;
} }
else if (e->type->type == ev_integer) else if (e->type->type == ev_integer)
{ {
e2 = QCC_PR_Statement (&pr_opcodes[OP_GE_I], e, pr_casesdef[i], NULL); 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); 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); e2 = QCC_PR_Statement (&pr_opcodes[OP_AND_I], e2, e3, NULL);
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));
patch3->b = &statements[pr_cases[i]] - patch3; patch3->b = &statements[pr_cases[i]] - patch3;
} }
else else
@ -6153,7 +6153,7 @@ void QCC_PR_ParseStatement (void)
e2 = NULL; e2 = NULL;
break; 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 else
{ {
@ -6162,7 +6162,7 @@ void QCC_PR_ParseStatement (void)
else if (e->type->type == ev_float) else if (e->type->type == ev_float)
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch3)); QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch3));
else 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; 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. //make sure the frame is within the bounds given.
ftemp = frame->temp; ftemp = frame->temp;
frame->temp = NULL; frame->temp = NULL;
t1 = QCC_PR_Statement(&pr_opcodes[OP_LT], frame, s1, NULL); t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
t2 = QCC_PR_Statement(&pr_opcodes[OP_GT], frame, def, NULL); t2 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
t1 = QCC_PR_Statement(&pr_opcodes[OP_OR], t1, t2, NULL); t1 = QCC_PR_Statement(&pr_opcodes[OP_OR_F], t1, t2, NULL);
QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 2, 0, false); QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs, 2, 0, false);
QCC_FreeTemp(t1); QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL)); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
QCC_PR_SimpleStatement(OP_GOTO, t1->ofs, 13, 0, false); QCC_PR_SimpleStatement(OP_GOTO, t1->ofs, 13, 0, false);
t1 = QCC_PR_Statement(&pr_opcodes[OP_GE], def, s1, NULL); t1 = QCC_PR_Statement(&pr_opcodes[OP_GE_F], def, s1, NULL);
QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs, 7, 0, false); 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_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); 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); t1 = QCC_PR_Statement(&pr_opcodes[OP_GT_F], frame, def, NULL);
QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false); QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
QCC_FreeTemp(t1); QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL)); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], s1, frame, NULL));
QCC_UnFreeTemp(frame); QCC_UnFreeTemp(frame);
@ -6480,8 +6480,8 @@ void QCC_PR_ParseState (void)
QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false); QCC_PR_SimpleStatement(OP_GOTO, 6, 0, 0, false);
//reverse animation. //reverse animation.
QCC_PR_SimpleStatement(OP_SUB_F, frame->ofs, QCC_MakeFloatDef(1)->ofs, frame->ofs, false); 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); t1 = QCC_PR_Statement(&pr_opcodes[OP_LT_F], frame, s1, NULL);
QCC_PR_SimpleStatement(OP_IFNOT, t1->ofs,2, 0, false); QCC_PR_SimpleStatement(OP_IFNOT_I, t1->ofs,2, 0, false);
QCC_FreeTemp(t1); QCC_FreeTemp(t1);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL)); QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], def, frame, NULL));
QCC_UnFreeTemp(frame); 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; QCC_def_t *eq;
if (min == max || min+1 == max) 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_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; st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = array->ofs + min*array->type->size; 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) 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_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 else
st = NULL; st = NULL;
@ -7510,9 +7510,9 @@ void QCC_PR_ArrayRecurseDivideUsingVectors(QCC_def_t *array, QCC_def_t *index, i
QCC_def_t *eq; QCC_def_t *eq;
if (min == max || min+1 == max) 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_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; st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = array->ofs + min*3; 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) 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_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 else
st = NULL; st = NULL;
@ -7561,7 +7561,7 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array)
locals_end = numpr_globals; locals_end = numpr_globals;
df->locals = locals_end - df->parm_start; 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_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 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) 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 //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. //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); div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 1, false);
intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", 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! 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, eq, 0, &st)); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2; st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, &st); QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatDef(0), 0, &st);
div3->references++; 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_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_STORE_F, index, &def_parms[0], NULL, false);
QCC_PR_Statement3(pr_opcodes+OP_CALL1, vectortrick, NULL, 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_PR_Statement3(pr_opcodes+OP_SUB_F, index, div3, index, false);
QCC_FreeTemp(div3); QCC_FreeTemp(div3);
eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(0+0.5f), NULL); 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, eq, 0, &st)); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2; st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 0; st->a = ret->ofs + 0;
eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(1+0.5f), NULL); 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, eq, 0, &st)); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2; st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 1; st->a = ret->ofs + 1;
eq = QCC_PR_Statement(pr_opcodes+OP_LT, index, QCC_MakeFloatDef(2+0.5), NULL); 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, eq, 0, &st)); QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
st->b = 2; st->b = 2;
QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st); QCC_PR_Statement(pr_opcodes+OP_RETURN, 0, 0, &st);
st->a = ret->ofs + 2; st->a = ret->ofs + 2;
@ -7685,7 +7685,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
} }
else 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); 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); eq = QCC_PR_Statement(pr_opcodes+OP_EQ_F, index, QCC_MakeFloatDef((float)min), NULL);
QCC_UnFreeTemp(index); 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; st->b = 3;
if (array->type->size == 3) if (array->type->size == 3)
QCC_PR_Statement(pr_opcodes+OP_STORE_V, value, array, &st); 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) 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_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 else
st = NULL; st = NULL;
@ -7774,7 +7774,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
{ {
QCC_dstatement_t *st; 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. //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 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; 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_ArraySetRecurseDivide(def, index, value, 0, def->arraysize);
QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL); QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);

View file

@ -1712,6 +1712,7 @@ int QCC_PR_FinishCompilation (void)
// if (!f || (!f->code && !f->builtin) ) // if (!f || (!f->code && !f->builtin) )
if (d->initialized==0) if (d->initialized==0)
{ {
s_file = d->s_file;
if (!strncmp(d->name, "ArrayGet*", 9)) if (!strncmp(d->name, "ArrayGet*", 9))
{ {
QCC_PR_EmitArrayGetFunction(d, d->name+9); QCC_PR_EmitArrayGetFunction(d, d->name+9);
@ -1733,6 +1734,7 @@ int QCC_PR_FinishCompilation (void)
bodylessfuncs = true; bodylessfuncs = true;
errors = true; errors = true;
} }
s_file = NULL;
// errors = true; // errors = true;
} }
else if (d->initialized==2) else if (d->initialized==2)

View file

@ -329,7 +329,7 @@ int WriteStatement(progfuncs_t *progfuncs, progstate_t *progs, int stnum, int fi
st = &((dstatement16_t*)progs->statements)[stnum]; st = &((dstatement16_t*)progs->statements)[stnum];
switch(st->op) switch(st->op)
{ {
case OP_IFNOT: case OP_IFNOT_I:
count = (signed short)st->b; count = (signed short)st->b;
writes(file, "if ("); writes(file, "if (");
WriteStatementProducingOfs(progfuncs, progs, stnum, firstpossible, st->a); 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"); writes(file, "}\r\n");
} }
break; break;
case OP_IF: case OP_IF_I:
longjmp(decompilestatementfailure, 1); longjmp(decompilestatementfailure, 1);
break; break;
case OP_GOTO: case OP_GOTO: