1
0
Fork 0
forked from fte/fteqw

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];
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];

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);

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
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

View file

@ -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];

View file

@ -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);

View file

@ -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)

View file

@ -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: