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:
parent
94debdcaf3
commit
f6856f7d2d
10 changed files with 469 additions and 301 deletions
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue