/* _____ __ ___ __ ____ _ __ / ___/__ ___ _ ___ / |/ /__ ___ / /_____ __ __/ __/_______(_)__ / /_ / (_ / _ `/ ' \/ -_) /|_/ / _ \/ _ \/ '_/ -_) // /\ \/ __/ __/ / _ \/ __/ \___/\_,_/_/_/_/\__/_/ /_/\___/_//_/_/\_\\__/\_, /___/\__/_/ /_/ .__/\__/ /___/ /_/ See Copyright Notice in gmMachine.h */ #include "gmConfig.h" #include "gmByteCodeGen.h" gmByteCodeGen::gmByteCodeGen(void * a_context) { m_tos = 0; m_maxTos = 0; m_emitCallback = NULL; m_context = a_context; } void gmByteCodeGen::Reset(void * a_context) { gmStreamBufferDynamic::Reset(); m_tos = 0; m_maxTos = 0; m_emitCallback = NULL; m_context = a_context; } bool gmByteCodeGen::Emit(gmByteCode a_instruction) { if(m_emitCallback) m_emitCallback(Tell(), m_context); AdjustStack(a_instruction); *this << (gmuint32) a_instruction; return true; } bool gmByteCodeGen::Emit(gmByteCode a_instruction, gmuint32 a_operand32) { if(m_emitCallback) m_emitCallback(Tell(), m_context); AdjustStack(a_instruction); *this << (gmuint32) a_instruction; *this << a_operand32; return true; } bool gmByteCodeGen::EmitPtr(gmByteCode a_instruction, gmptr a_operand) { if(m_emitCallback) m_emitCallback(Tell(), m_context); AdjustStack(a_instruction); *this << ((gmuint32) a_instruction); *this << a_operand; return true; } unsigned int gmByteCodeGen::Skip(unsigned int p_n, unsigned char p_value) { unsigned int oldPos = Tell(); if(p_n) { char * fill = (char *) alloca(p_n); memset(fill, p_value, p_n); Write(fill, p_n); } return oldPos; } void gmByteCodeGen::AdjustStack(gmByteCode a_instruction) { switch(a_instruction) { case BC_NOP : break; case BC_LINE : break; case BC_GETDOT : m_tos += 0; break; case BC_SETDOT : m_tos -= 2; break; case BC_GETIND : --m_tos; break; case BC_SETIND : m_tos -= 3; break; case BC_BRA : break; case BC_BRZ : --m_tos; break; case BC_BRNZ : --m_tos; break; case BC_BRZK : break; case BC_BRNZK : break; case BC_CALL : break; case BC_RET : break; case BC_RETV : break; case BC_FOREACH : ++m_tos; break; case BC_POP : --m_tos; break; case BC_POP2 : m_tos -= 2; break; case BC_DUP : ++m_tos; break; case BC_DUP2 : m_tos += 2; break; case BC_SWAP : break; case BC_PUSHNULL : ++m_tos; break; case BC_PUSHINT : ++m_tos; break; case BC_PUSHINT0 : ++m_tos; break; case BC_PUSHINT1 : ++m_tos; break; case BC_PUSHFP : ++m_tos; break; case BC_PUSHSTR : ++m_tos; break; case BC_PUSHTBL : ++m_tos; break; case BC_PUSHFN : ++m_tos; break; case BC_PUSHTHIS : ++m_tos; break; case BC_GETLOCAL : ++m_tos; break; case BC_SETLOCAL : --m_tos; break; case BC_GETGLOBAL : ++m_tos; break; case BC_SETGLOBAL : --m_tos; break; case BC_GETTHIS : ++m_tos; break; case BC_SETTHIS : --m_tos; break; case BC_OP_ADD : --m_tos; break; case BC_OP_SUB : --m_tos; break; case BC_OP_MUL : --m_tos; break; case BC_OP_DIV : --m_tos; break; case BC_OP_REM : --m_tos; break; case BC_BIT_OR : --m_tos; break; case BC_BIT_XOR : --m_tos; break; case BC_BIT_AND : --m_tos; break; case BC_BIT_INV : --m_tos; break; case BC_BIT_SHL : --m_tos; break; case BC_BIT_SHR : --m_tos; break; case BC_OP_NEG : break; case BC_OP_POS : break; case BC_OP_NOT : break; case BC_OP_LT : --m_tos; break; case BC_OP_GT : --m_tos; break; case BC_OP_LTE : --m_tos; break; case BC_OP_GTE : --m_tos; break; case BC_OP_EQ : --m_tos; break; case BC_OP_NEQ : --m_tos; break; } if(m_tos > m_maxTos) m_maxTos = m_tos; }