mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 13:31:07 +00:00
- Added some code for generating VM code from FxExpressions. This is completely untested, since
it isn't even used anywhere yet. In retrospect, I probably should have targeted an intermediate representation and done codegen with that instead, since that would be something I can reuse. SVN r1908 (scripting)
This commit is contained in:
parent
e9db2c83a5
commit
3001708d16
8 changed files with 1430 additions and 30 deletions
|
@ -42,12 +42,14 @@
|
||||||
|
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
|
|
||||||
|
|
||||||
#define CHECKRESOLVED() if (isresolved) return this; isresolved=true;
|
#define CHECKRESOLVED() if (isresolved) return this; isresolved=true;
|
||||||
#define SAFE_DELETE(p) if (p!=NULL) { delete p; p=NULL; }
|
#define SAFE_DELETE(p) if (p!=NULL) { delete p; p=NULL; }
|
||||||
#define RESOLVE(p,c) if (p!=NULL) p = p->Resolve(c)
|
#define RESOLVE(p,c) if (p!=NULL) p = p->Resolve(c)
|
||||||
#define ABORT(p) if (!(p)) { delete this; return NULL; }
|
#define ABORT(p) if (!(p)) { delete this; return NULL; }
|
||||||
#define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p)
|
#define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p)
|
||||||
|
|
||||||
|
class VMFunctionBuilder;
|
||||||
extern PSymbolTable GlobalSymbols;
|
extern PSymbolTable GlobalSymbols;
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -142,6 +144,15 @@ struct ExpVal
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExpEmit
|
||||||
|
{
|
||||||
|
ExpEmit() : RegNum(0), RegType(REGT_NIL) {}
|
||||||
|
ExpEmit(int reg, int type) : RegNum(reg), RegType(type) {}
|
||||||
|
ExpEmit(int reg, int type, bool konst) : RegNum(reg), RegType(type), Konst(konst) {}
|
||||||
|
ExpEmit(VMFunctionBuilder *build, int type);
|
||||||
|
|
||||||
|
BYTE RegNum, RegType, Konst;
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -166,12 +177,25 @@ public:
|
||||||
virtual bool isConstant() const;
|
virtual bool isConstant() const;
|
||||||
virtual void RequestAddress();
|
virtual void RequestAddress();
|
||||||
|
|
||||||
|
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
|
||||||
FScriptPosition ScriptPosition;
|
FScriptPosition ScriptPosition;
|
||||||
FExpressionType ValueType;
|
FExpressionType ValueType;
|
||||||
|
|
||||||
bool isresolved;
|
bool isresolved;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FxParameter : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression *Operand;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FxParameter(FxExpression*);
|
||||||
|
~FxParameter();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxIdentifier
|
// FxIdentifier
|
||||||
|
@ -310,6 +334,21 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
|
class FxFloatCast : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression *basex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FxFloatCast(FxExpression *x);
|
||||||
|
~FxFloatCast();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,6 +366,7 @@ public:
|
||||||
FxPlusSign(FxExpression*);
|
FxPlusSign(FxExpression*);
|
||||||
~FxPlusSign();
|
~FxPlusSign();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -344,6 +384,7 @@ public:
|
||||||
~FxMinusSign();
|
~FxMinusSign();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -361,6 +402,7 @@ public:
|
||||||
~FxUnaryNotBitwise();
|
~FxUnaryNotBitwise();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -378,6 +420,7 @@ public:
|
||||||
~FxUnaryNotBoolean();
|
~FxUnaryNotBoolean();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -396,6 +439,7 @@ public:
|
||||||
FxBinary(int, FxExpression*, FxExpression*);
|
FxBinary(int, FxExpression*, FxExpression*);
|
||||||
~FxBinary();
|
~FxBinary();
|
||||||
bool ResolveLR(FCompileContext& ctx, bool castnumeric);
|
bool ResolveLR(FCompileContext& ctx, bool castnumeric);
|
||||||
|
void Promote();
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -411,6 +455,7 @@ public:
|
||||||
FxAddSub(int, FxExpression*, FxExpression*);
|
FxAddSub(int, FxExpression*, FxExpression*);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -426,6 +471,7 @@ public:
|
||||||
FxMulDiv(int, FxExpression*, FxExpression*);
|
FxMulDiv(int, FxExpression*, FxExpression*);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -441,6 +487,7 @@ public:
|
||||||
FxCompareRel(int, FxExpression*, FxExpression*);
|
FxCompareRel(int, FxExpression*, FxExpression*);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -456,6 +503,7 @@ public:
|
||||||
FxCompareEq(int, FxExpression*, FxExpression*);
|
FxCompareEq(int, FxExpression*, FxExpression*);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -471,6 +519,7 @@ public:
|
||||||
FxBinaryInt(int, FxExpression*, FxExpression*);
|
FxBinaryInt(int, FxExpression*, FxExpression*);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -491,6 +540,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -511,6 +561,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -530,6 +581,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -551,6 +603,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -564,6 +617,7 @@ class FxFRandom : public FxRandom
|
||||||
public:
|
public:
|
||||||
FxFRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos);
|
FxFRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -584,6 +638,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -623,6 +678,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
void RequestAddress();
|
void RequestAddress();
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -637,6 +693,7 @@ public:
|
||||||
FxSelf(const FScriptPosition&);
|
FxSelf(const FScriptPosition&);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -657,6 +714,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
//void RequestAddress();
|
//void RequestAddress();
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -700,6 +758,7 @@ public:
|
||||||
~FxActionSpecialCall();
|
~FxActionSpecialCall();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -719,6 +778,7 @@ public:
|
||||||
~FxGlobalFunctionCall();
|
~FxGlobalFunctionCall();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -739,6 +799,7 @@ public:
|
||||||
~FxClassTypeCast();
|
~FxClassTypeCast();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -775,6 +836,7 @@ public:
|
||||||
FxMultiNameState(const char *statestring, const FScriptPosition &pos);
|
FxMultiNameState(const char *statestring, const FScriptPosition &pos);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpVal EvalExpression (AActor *self);
|
ExpVal EvalExpression (AActor *self);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -107,6 +107,7 @@ enum
|
||||||
ATAG_AREGISTER, // pointer to an address register
|
ATAG_AREGISTER, // pointer to an address register
|
||||||
|
|
||||||
ATAG_STATE, // pointer to FState
|
ATAG_STATE, // pointer to FState
|
||||||
|
ATAG_RNG, // pointer to FRandom
|
||||||
};
|
};
|
||||||
|
|
||||||
class VMFunction : public DObject
|
class VMFunction : public DObject
|
||||||
|
|
|
@ -61,10 +61,10 @@ VMScriptFunction *VMFunctionBuilder::MakeFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign required register space.
|
// Assign required register space.
|
||||||
func->NumRegD = IntRegisters.MostUsed;
|
func->NumRegD = Registers[REGT_INT].MostUsed;
|
||||||
func->NumRegF = FloatRegisters.MostUsed;
|
func->NumRegF = Registers[REGT_FLOAT].MostUsed;
|
||||||
func->NumRegA = AddressRegisters.MostUsed;
|
func->NumRegA = Registers[REGT_POINTER].MostUsed;
|
||||||
func->NumRegS = StringRegisters.MostUsed;
|
func->NumRegS = Registers[REGT_STRING].MostUsed;
|
||||||
func->MaxParam = MaxParam;
|
func->MaxParam = MaxParam;
|
||||||
|
|
||||||
// Technically, there's no reason why we can't end the function with
|
// Technically, there's no reason why we can't end the function with
|
||||||
|
@ -274,7 +274,7 @@ VMFunctionBuilder::RegAvailability::RegAvailability()
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// VMFunctionBuilder :: RegAvailibity :: GetReg
|
// VMFunctionBuilder :: RegAvailibity :: Get
|
||||||
//
|
//
|
||||||
// Gets one or more unused registers. If getting multiple registers, they
|
// Gets one or more unused registers. If getting multiple registers, they
|
||||||
// will all be consecutive. Returns -1 if there were not enough consecutive
|
// will all be consecutive. Returns -1 if there were not enough consecutive
|
||||||
|
@ -286,7 +286,7 @@ VMFunctionBuilder::RegAvailability::RegAvailability()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int VMFunctionBuilder::RegAvailability::GetReg(int count)
|
int VMFunctionBuilder::RegAvailability::Get(int count)
|
||||||
{
|
{
|
||||||
VM_UWORD mask;
|
VM_UWORD mask;
|
||||||
int i, firstbit;
|
int i, firstbit;
|
||||||
|
@ -368,13 +368,13 @@ int VMFunctionBuilder::RegAvailability::GetReg(int count)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// VMFunctionBuilder :: RegAvailibity :: ReturnReg
|
// VMFunctionBuilder :: RegAvailibity :: Return
|
||||||
//
|
//
|
||||||
// Marks a range of registers as free again.
|
// Marks a range of registers as free again.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void VMFunctionBuilder::RegAvailability::ReturnReg(int reg, int count)
|
void VMFunctionBuilder::RegAvailability::Return(int reg, int count)
|
||||||
{
|
{
|
||||||
assert(count >= 1 && count <= 32);
|
assert(count >= 1 && count <= 32);
|
||||||
assert(reg >= 0 && reg + count <= 256);
|
assert(reg >= 0 && reg + count <= 256);
|
||||||
|
@ -406,8 +406,108 @@ void VMFunctionBuilder::RegAvailability::ReturnReg(int reg, int count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMFunctionBuilder::RegAvailability::Dump()
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// VMFunctionBuilder :: Emit
|
||||||
|
//
|
||||||
|
// Just dumbly output an instruction. Returns instruction position, not
|
||||||
|
// byte position. (Because all instructions are exactly four bytes long.)
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc)
|
||||||
{
|
{
|
||||||
Printf("%032B %032B %032B %032B\n%032B %032B %032B %032B\n",
|
assert(opcode >= 0 && opcode < NUM_OPS);
|
||||||
Used[0], Used[1], Used[2], Used[3], Used[4], Used[5], Used[6], Used[7]);
|
assert(opa >= 0 && opa <= 255);
|
||||||
|
assert(opb >= 0 && opb <= 255);
|
||||||
|
assert(opc >= 0 && opc <= 255);
|
||||||
|
size_t loc = Code.Reserve(4);
|
||||||
|
VM_UBYTE *code = &Code[loc];
|
||||||
|
code[0] = opcode;
|
||||||
|
code[1] = opa;
|
||||||
|
code[2] = opb;
|
||||||
|
code[3] = opc;
|
||||||
|
return loc / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VMFunctionBuilder::Emit(int opcode, int opa, VM_SHALF opbc)
|
||||||
|
{
|
||||||
|
assert(opcode >= 0 && opcode < NUM_OPS);
|
||||||
|
assert(opa >= 0 && opa <= 255);
|
||||||
|
assert(opbc >= -32768 && opbc <= 32767);
|
||||||
|
size_t loc = Code.Reserve(4);
|
||||||
|
VM_UBYTE *code = &Code[loc];
|
||||||
|
code[0] = opcode;
|
||||||
|
code[1] = opa;
|
||||||
|
*(VM_SHALF *)&code[2] = opbc;
|
||||||
|
return loc / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VMFunctionBuilder::Emit(int opcode, int opabc)
|
||||||
|
{
|
||||||
|
assert(opcode >= 0 && opcode < NUM_OPS);
|
||||||
|
assert(opabc >= -(1 << 23) && opabc <= (1 << 24) - 1);
|
||||||
|
size_t loc = Code.Reserve(4);
|
||||||
|
#ifdef __BIG_ENDIAN__
|
||||||
|
*(VM_UWORD *)&Code[loc] = (opabc & 0xFFFFFF) | (opcode << 24);
|
||||||
|
#else
|
||||||
|
*(VM_UWORD *)&Code[loc] = opcode | (opabc << 8);
|
||||||
|
#endif
|
||||||
|
return loc / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// VMFunctionBuilder :: EmitLoadInt
|
||||||
|
//
|
||||||
|
// Loads an integer constant into a register, using either an immediate
|
||||||
|
// value or a constant register, as appropriate.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
size_t VMFunctionBuilder::EmitLoadInt(int regnum, int value)
|
||||||
|
{
|
||||||
|
assert(regnum >= 0 && regnum < Registers[REGT_INT].MostUsed);
|
||||||
|
if (value >= -32768 && value <= 32767)
|
||||||
|
{
|
||||||
|
return Emit(OP_LI, regnum, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Emit(OP_LK, regnum, GetConstantInt(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// VMFunctionBuilder :: Backpatch
|
||||||
|
//
|
||||||
|
// Store a JMP instruction at <loc> that points at <target>.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void VMFunctionBuilder::Backpatch(size_t loc, size_t target)
|
||||||
|
{
|
||||||
|
assert(loc < Code.Size() / 4);
|
||||||
|
int offset = int(target - loc - 1);
|
||||||
|
assert(offset >= -(1 << 24) && offset <= (1 << 24) - 1);
|
||||||
|
#ifdef __BIG_ENDIAN__
|
||||||
|
*(VM_UWORD *)&Code[loc * 4] = (offset & 0xFFFFFF) | (OP_JMP << 24);
|
||||||
|
#else
|
||||||
|
*(VM_UWORD *)&Code[loc * 4] = OP_JMP | (offset << 8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// VMFunctionBuilder :: BackpatchToHere
|
||||||
|
//
|
||||||
|
// Store a JMP instruction at <loc> that points to the current code gen
|
||||||
|
// location.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void VMFunctionBuilder::BackpatchToHere(size_t loc)
|
||||||
|
{
|
||||||
|
Backpatch(loc, Code.Size() / 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,8 @@ public:
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RegAvailability();
|
RegAvailability();
|
||||||
int GetReg(int count); // Returns the first register in the range
|
int Get(int count); // Returns the first register in the range
|
||||||
void ReturnReg(int reg, int count);
|
void Return(int reg, int count);
|
||||||
void Dump();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
|
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
|
||||||
|
@ -35,6 +34,12 @@ public:
|
||||||
|
|
||||||
// Returns the address of the newly-emitted instruction.
|
// Returns the address of the newly-emitted instruction.
|
||||||
size_t Emit(int opcode, int opa, int opb, int opc);
|
size_t Emit(int opcode, int opa, int opb, int opc);
|
||||||
|
size_t Emit(int opcode, int opa, VM_SHALF opbc);
|
||||||
|
size_t Emit(int opcode, int opabc);
|
||||||
|
size_t EmitLoadInt(int regnum, int value);
|
||||||
|
|
||||||
|
void Backpatch(size_t addr, size_t target);
|
||||||
|
void BackpatchToHere(size_t addr);
|
||||||
|
|
||||||
// Write out complete constant tables.
|
// Write out complete constant tables.
|
||||||
void FillIntConstants(int *konst);
|
void FillIntConstants(int *konst);
|
||||||
|
@ -46,10 +51,10 @@ public:
|
||||||
void ParamChange(int delta);
|
void ParamChange(int delta);
|
||||||
|
|
||||||
// Track available registers.
|
// Track available registers.
|
||||||
RegAvailability IntRegisters;
|
RegAvailability Registers[4];
|
||||||
RegAvailability FloatRegisters;
|
|
||||||
RegAvailability AddressRegisters;
|
// Free a register.
|
||||||
RegAvailability StringRegisters;
|
void FreeReg(int regtype, int regnum);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct AddrKonst
|
struct AddrKonst
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#define JMPOFS(x) ((*(VM_SWORD *)(x) >> 6) & ~3)
|
#define JMPOFS(x) ((*(VM_SWORD *)(x) >> 6) & ~3)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define KC (konst[C])
|
#define KC (konstd[C])
|
||||||
#define RC (reg.i[C])
|
#define RC (reg.d[C])
|
||||||
|
|
||||||
#define PA (reg.a[A])
|
#define PA (reg.a[A])
|
||||||
#define PB (reg.a[B])
|
#define PB (reg.a[B])
|
||||||
|
@ -61,11 +61,12 @@ enum
|
||||||
X_READ_NIL,
|
X_READ_NIL,
|
||||||
X_WRITE_NIL,
|
X_WRITE_NIL,
|
||||||
X_TOO_MANY_TRIES,
|
X_TOO_MANY_TRIES,
|
||||||
|
X_ARRAY_OUT_OF_BOUNDS
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GETADDR(a,o,x) \
|
#define GETADDR(a,o,x) \
|
||||||
if (a == 0) { THROW(x); } \
|
if (a == NULL) { THROW(x); } \
|
||||||
ptr = (VM_SBYTE *)a + x \
|
ptr = (VM_SBYTE *)a + o
|
||||||
|
|
||||||
static const VM_UWORD ZapTable[16] =
|
static const VM_UWORD ZapTable[16] =
|
||||||
{
|
{
|
||||||
|
|
|
@ -586,6 +586,13 @@ begin:
|
||||||
assert(0);
|
assert(0);
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
|
||||||
|
OP(BOUND):
|
||||||
|
if (reg.d[a] >= BC)
|
||||||
|
{
|
||||||
|
THROW(X_ARRAY_OUT_OF_BOUNDS);
|
||||||
|
}
|
||||||
|
NEXTOP;
|
||||||
|
|
||||||
OP(CONCAT):
|
OP(CONCAT):
|
||||||
ASSERTS(a); ASSERTS(B); ASSERTS(C);
|
ASSERTS(a); ASSERTS(B); ASSERTS(C);
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,7 +73,7 @@ xx(DYNCAST_K, dyncast,RPRPKP),
|
||||||
xx(TEST, test, RII16), // if (dA != BC) then pc++
|
xx(TEST, test, RII16), // if (dA != BC) then pc++
|
||||||
xx(JMP, jmp, I24), // pc += ABC -- The ABC fields contain a signed 24-bit offset.
|
xx(JMP, jmp, I24), // pc += ABC -- The ABC fields contain a signed 24-bit offset.
|
||||||
xx(IJMP, ijmp, RII16), // pc += dA + BC -- BC is a signed offset. The target instruction must be a JMP.
|
xx(IJMP, ijmp, RII16), // pc += dA + BC -- BC is a signed offset. The target instruction must be a JMP.
|
||||||
xx(PARAM, param, __BCP), // push parameter encoded in BC for function call or result for return
|
xx(PARAM, param, __BCP), // push parameter encoded in BC for function call (B=regtype, C=regnum)
|
||||||
xx(CALL, call, RPI8I8), // Call function pkA with parameter count B and expected result count C
|
xx(CALL, call, RPI8I8), // Call function pkA with parameter count B and expected result count C
|
||||||
xx(CALL_K, call, KPI8I8),
|
xx(CALL_K, call, KPI8I8),
|
||||||
xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL)
|
xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL)
|
||||||
|
@ -87,6 +87,7 @@ xx(CATCH, catch, CATCH), // A == 0: continue search on next try
|
||||||
// A == 2: (pB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH
|
// A == 2: (pB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH
|
||||||
// A == 3: (pkB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH
|
// A == 3: (pkB == <type of exception thrown>) then pc++ ; next instruction must JMP to another CATCH
|
||||||
// for A > 0, exception is stored in pC
|
// for A > 0, exception is stored in pC
|
||||||
|
xx(BOUND, bound, RII16), // if rA >= BC, throw exception
|
||||||
|
|
||||||
// String instructions.
|
// String instructions.
|
||||||
xx(CONCAT, concat, RSRSRS), // sA = sB.. ... ..sC
|
xx(CONCAT, concat, RSRSRS), // sA = sB.. ... ..sC
|
||||||
|
@ -129,7 +130,7 @@ xx(MAX_RR, max, RIRIRI), // dA = max(dB,dkC)
|
||||||
xx(MAX_RK, max, RIRIKI),
|
xx(MAX_RK, max, RIRIKI),
|
||||||
xx(ABS, abs, RIRI), // dA = abs(dB)
|
xx(ABS, abs, RIRI), // dA = abs(dB)
|
||||||
xx(NEG, neg, RIRI), // dA = -dB
|
xx(NEG, neg, RIRI), // dA = -dB
|
||||||
xx(NOT, not, RIRI), // dA = !dB
|
xx(NOT, not, RIRI), // dA = ~dB
|
||||||
xx(SEXT, sext, RIRII8), // dA = dB, sign extended by shifting left then right by C
|
xx(SEXT, sext, RIRII8), // dA = dB, sign extended by shifting left then right by C
|
||||||
xx(ZAP_R, zap, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are one
|
xx(ZAP_R, zap, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are one
|
||||||
xx(ZAP_I, zap, RIRII8),
|
xx(ZAP_I, zap, RIRII8),
|
||||||
|
|
Loading…
Reference in a new issue