/*-
 * Copyright (c) 2004 - 2011 CTPP Team
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the CTPP Team nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *      CTPP2VM.cpp
 *
 * $CTPP$
 */

#include "CTPP2VM.hpp"

#include "CTPP2OutputCollector.hpp"
#include "CTPP2SyscallFactory.hpp"
#include "CTPP2VMMemoryCore.hpp"

#include "CTPP2VMDebugInfo.hpp"
#include "CTPP2VMOpcodes.h"
#include "CTPP2VMException.hpp"
#include "CTPP2VMStackException.hpp"
#include "CTPP2VMInstruction.hpp"

#include <string.h>

#ifdef _DEBUG
#include <stdio.h>
#endif

/*
    Foreground colors
       30    Black
       31    Red
       32    Green
       33    Yellow
       34    Blue
       35    Magenta
       36    Cyan
       37    White

    Background colors
       40    Black
       41    Red
       42    Green
       43    Yellow
       44    Blue
       45    Magenta
       46    Cyan
       47    White
*/
#define BRIGHT 1
#define RED    31
#define YELLOW 33
#define GREEN  32
#define BLUE   34
#define BG_BLACK 40


#ifndef WIN32 /* Windows console is not so funky */
#define HL_CODE(x) fprintf(stderr, "%c[%d;%d;%dm", 0x1B, BRIGHT, (x), BG_BLACK)
#define HL_RST  fprintf(stderr, "%c[%dm", 0x1B, 0)
#else
    #define HL_CODE(x)
    #define HL_RST
#endif

// Aliases for registers
#define AR oRegs[0]
#define BR oRegs[1]
#define CR oRegs[2]
#define DR oRegs[3]
#define ER oRegs[4]
#define FR oRegs[5]
#define GR oRegs[6]
#define HR oRegs[7]

namespace CTPP // C++ Template Engine
{

//
// Constructor
//
VM::VM(SyscallFactory  * pISyscallFactory,
       const UINT_32     iIMaxArgStackSize,
       const UINT_32     iIMaxCodeStackSize,
       const UINT_32     iIMaxSteps,
       const UINT_32     iIDebugLevel): pSyscallFactory(pISyscallFactory),
                                        iMaxArgStackSize(iIMaxArgStackSize),
                                        iMaxCodeStackSize(iIMaxCodeStackSize),
                                        iMaxSteps(iIMaxSteps),
                                        iDebugLevel(iIDebugLevel),
                                        iMaxCalls(0),
                                        iMaxUsedCalls(0),
                                        aCallTranslationMap(NULL),
                                        oVMArgStack(iMaxArgStackSize),
                                        oVMCodeStack(iMaxCodeStackSize)
{
	;;
}

//
// Initialize virtual machine
//
INT_32 VM::Init(const VMMemoryCore  * pMemoryCore,
                OutputCollector     * pOutputCollector,
                Logger              * pLogger)
{
	// Create syscalls translation map
	iMaxUsedCalls = pMemoryCore -> syscalls.GetRecordsNum();
	// Cache
	if (iMaxUsedCalls >= iMaxCalls)
	{
		delete [] aCallTranslationMap;
		aCallTranslationMap = new SyscallHandler *[iMaxUsedCalls];
		iMaxCalls = iMaxUsedCalls;
	}

	// Initialize program
	for (UINT_32 iCallNum = 0; iCallNum < iMaxUsedCalls; ++iCallNum)
	{
		// Ugh
		UINT_32 iCallNameLength = 0;
		// NULL-terminated string, iCallNameLength will not used
		CCHAR_P sCallName = pMemoryCore -> syscalls.GetData(iCallNum, iCallNameLength);

		// Get syscall
		SyscallHandler * pTMP = pSyscallFactory -> GetHandlerByName(sCallName);

		// If this syscall is not present in factory, throw exception
		if (pTMP == NULL)
		{
			UINT_32 iDataSize = 0;
			CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(pMemoryCore -> instructions[0].reserved).GetDescrId(), iDataSize);

			throw InvalidSyscall(sCallName, 0, pMemoryCore -> instructions[0].reserved, szTMP);
		}

		// All OK
		aCallTranslationMap[iCallNum] = pTMP;

		// Initialize syscall handler
		pTMP -> PreExecuteSetup(*pOutputCollector,
		                        DR,
		                        pMemoryCore -> syscalls,
		                        pMemoryCore -> static_data,
		                        pMemoryCore -> static_text,
		                        *pLogger);
	}

return 0;
}

//
// Run program
//
INT_32 VM::Run(const VMMemoryCore  * pMemoryCore,
               OutputCollector     * pOutputCollector,
               UINT_32             & iIP,
               CDT                 & oCDT,
               Logger              * pLogger)
{
	DR = oCDT;
	// Get code segment
	const VMInstruction * aCode = pMemoryCore -> instructions;
	const UINT_32 iCodeLength   = pMemoryCore -> code_size;
	UINT_32 iExecutedSteps      = 0;

	try
	{
		while (iIP < iCodeLength)
		{
			const UINT_32 iOpCode = aCode[iIP].instruction;
			const UINT_32 iOpCodeHi = SYSCALL_OPCODE_HI(iOpCode);
			const UINT_32 iOpCodeLo = SYSCALL_OPCODE_LO(iOpCode);
#ifdef _DEBUG
HL_CODE(BLUE);
fprintf(stderr, "CODE 0x%08X ARG 0x%08X RES 0x%016llX | ", iOpCode, aCode[iIP].argument, (long long)(aCode[iIP].reserved));
HL_RST;
#endif

			switch(iOpCodeHi)
			{
				// Instructions //////// 0x-1-X----
				case 0x01:
					{
						switch(iOpCodeLo)
						{
							// SYSCALL
							case SYSCALL_OPCODE_LO(SYSCALL):
								{
									const UINT_32 iCallNum    = (aCode[iIP].argument & 0xFFFF0000) >> 16;
									const UINT_32 iCallArgNum = (aCode[iIP].argument & 0x0000FFFF);
#ifdef _DEBUG
{
	UINT_32 iCallNameLength = 0;
	// NULL-terminated string, iCallNameLength not need to use
	CCHAR_P sCallName = pMemoryCore -> syscalls.GetData(iCallNum, iCallNameLength);
	HL_CODE(YELLOW);
	fprintf(stderr, "0x%08X SYSCALL   0x%08X %s(ARGS: %d)\n", iIP, iCallNum, sCallName, iCallArgNum);
	HL_RST;
}
#endif
									// Check call number
									if (iCallNum > iMaxUsedCalls)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw InvalidSyscall("*** CORRUPTED ***", iIP, aCode[iIP].reserved, szTMP);
									}

									CDT oResult(CDT::UNDEF);
									// Invoke handler
									if (aCallTranslationMap[iCallNum] -> Handler(oVMArgStack.GetStackFrame(), iCallArgNum, oResult, *pLogger) != 0)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw InvalidSyscall("*** Internal syscall error ***", iIP, aCode[iIP].reserved, szTMP);
									}

									// Clear stack
									oVMArgStack.ClearStack(iCallArgNum);

									// Store execution result into stack
									oVMArgStack.PushElement(oResult);

									++iIP;
								}
								break;

							// CALLNAME
							case SYSCALL_OPCODE_LO(CALLNAME):
								{
									// Get call name
									UINT_32 iDataSize = 0;
									CCHAR_P szCallName = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);

									UINT_32 iNewIP = UINT_32(pMemoryCore -> calls_table.Get(szCallName, iDataSize));
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X CALLNAME  `%s` -> %d\n", iIP, szCallName, iNewIP);
HL_RST;
#endif
									// Call exist?
									if (iNewIP == (UINT_32)-1)
									{
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw InvalidCall(iIP, aCode[iIP].reserved, szCallName, szTMP);
									}

									// New IP is correct?
									if (iNewIP >= iCodeLength)
									{
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
									}

									oVMCodeStack.PushAddress(iIP + 1);
									iIP = iNewIP;
								}
								break;

							// CALLIND
							case SYSCALL_OPCODE_LO(CALLIND):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X CALLIND   ", iIP);
#endif
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);

									// Call name
									STLW::string sCallName;

									// From register?
									if (iSrcReg <= ARG_SRC_HR)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
										sCallName = oRegs[iSrcReg].GetString();
									}
									// From Stack?
									else if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d] (`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										sCallName = oVMArgStack.GetTopElement(aCode[iIP].argument).GetString();
										STLW::vector<CDT> vArgs;
										vArgs.reserve(aCode[iIP].argument);
										for (UINT_32 iI = 0; iI < aCode[iIP].argument; ++iI)
										{
											vArgs.push_back(oVMArgStack.GetTopElement(iI));
										}
										oVMArgStack.ClearStack(aCode[iIP].argument + 1);
										for (STLW::vector<CDT>::reverse_iterator vIt = vArgs.rbegin(); vIt != vArgs.rend(); ++vIt)
										{
											oVMArgStack.PushElement(*vIt);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}

									// Call exist?
									if (sCallName.empty())
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw InvalidCall(iIP, aCode[iIP].reserved, "No name of call", szTMP);
									}

									// New IP
									const UINT_32 iNewIP = UINT_32(pMemoryCore -> calls_table.Get(sCallName.c_str(), sCallName.size()));

									// Call exist?
									if (iNewIP == (UINT_32)-1)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw InvalidCall(iIP, aCode[iIP].reserved, sCallName.c_str(), szTMP);
									}

									// New IP is correct?
									if (iNewIP >= iCodeLength)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
									}

									// Store return address
									oVMCodeStack.PushAddress(iIP + 1);
									iIP = iNewIP;
								}
								break;

							// CALL
							case SYSCALL_OPCODE_LO(CALL):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X CALL      0x%08X\n", iIP, aCode[iIP].argument);
#endif
									// Check execution limit
									if (iExecutedSteps >= iMaxSteps)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
									}

									const UINT_32 iNewIP = aCode[iIP].argument;
									// New IP is correct?
									if (iNewIP >= iCodeLength)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
									}

									oVMCodeStack.PushAddress(iIP + 1);
									iIP = iNewIP;
								}
								break;

							// RET
							case SYSCALL_OPCODE_LO(RET):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X RET       %d\n", iIP, aCode[iIP].argument);
HL_RST;
#endif
									// Check execution limit
									if (iExecutedSteps >= iMaxSteps)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
									}

									// Clear stack
									oVMArgStack.ClearStack(aCode[iIP].argument);
									// Return
									iIP = oVMCodeStack.PopAddress();
								}
								break;

							// JMP
							case SYSCALL_OPCODE_LO(JMP):
								{
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X JMP       0x%08X\n", iIP, aCode[iIP].argument);
HL_RST;
#endif
									// Check execution limit
									if (iExecutedSteps >= iMaxSteps)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
									}

									const UINT_32 iNewIP = aCode[iIP].argument;
									// New IP is correct?
									if (iNewIP >= iCodeLength)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
									}

									iIP = iNewIP;
								}
								break;

							// LOOP, cycle
							case SYSCALL_OPCODE_LO(LOOP):
								{
									// Check execution limit
									if (iExecutedSteps >= iMaxSteps)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
									}

									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									if (iDstReg <= ARG_DST_LASTREG && iSrcReg <= ARG_SRC_LASTREG)
									{
										CDT & oLoopReg = oRegs[iSrcReg];

#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X LOOP      0x%08X (%cR = %d, %cR = %d)\n", iIP, aCode[iIP].argument, CHAR_8(iSrcReg + 'A'), INT_32(oLoopReg.GetInt()), CHAR_8((iDstReg >> 8) + 'A'), INT_32(oRegs[iDstReg >> 8].GetInt()));
HL_RST;
#endif
										// Decrease number of iterations
										--oLoopReg;
										// End of cycle?
										if (oLoopReg <= 0) { ++iIP; }
										// New iteration
										else
										{
											const UINT_32 iNewIP = aCode[iIP].argument;
											// New IP is correct?
											if (iNewIP >= iCodeLength)
											{
												UINT_32 iDataSize = 0;
												CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
												throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
											}
											iIP = iNewIP;

											// Iteration counter
											++oRegs[iDstReg >> 8];
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// RCALL
							case SYSCALL_OPCODE_LO(RCALL):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X RCALL     0x%08X\n", iIP, aCode[iIP].argument);
#endif
									// Check execution limit
									if (iExecutedSteps >= iMaxSteps)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
									}

									const UINT_32 iNewIP = iIP + aCode[iIP].argument;
									// New IP is correct?
									if (iNewIP >= iCodeLength)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
									}

									oVMCodeStack.PushAddress(iIP + 1);
									iIP = iNewIP;
								}
								break;

							// RJMP
							case SYSCALL_OPCODE_LO(RJMP):
								{
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X RJMP      0x%08X\n", iIP, aCode[iIP].argument);
HL_RST;
#endif
									// Check execution limit
									if (iExecutedSteps >= iMaxSteps)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
									}

									const UINT_32 iNewIP = iIP + aCode[iIP].argument;
									// New IP is correct?
									if (iNewIP >= iCodeLength)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
									}

									iIP = iNewIP;
								}
								break;

							// Illegal Opcode?
							default:
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
							}
						}
					}
					break;

				// Stack operations //// 0x-2-X----
				case 0x02:
					{
						switch(iOpCodeLo)
						{
							// PUSH
							case SYSCALL_OPCODE_LO(PUSH):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X PUSH      ", iIP);
#endif
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);

									// From register to stack
									if (iSrcReg <= ARG_SRC_LASTREG)
									{
										oVMArgStack.PushElement(oRegs[iSrcReg]);
#ifdef _DEBUG
fprintf(stderr, "%cR\n", CHAR_8(iOpCode + 'A'));
HL_RST;
#endif
									}
									// From static text segment to stack
									else if (iSrcReg == ARG_SRC_STR)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
										oVMArgStack.PushElement(STLW::string(szTMP, iDataSize));
#ifdef _DEBUG
fprintf(stderr, "STRING POS: %d (VAL: `%s`)\n", aCode[iIP].argument, szTMP);
HL_RST;
#endif
									}
									// From static data segment to stack (integer value)
									else if (iSrcReg == ARG_SRC_INT)
									{
										oVMArgStack.PushElement(pMemoryCore -> static_data.GetInt(aCode[iIP].argument));
#ifdef _DEBUG
fprintf(stderr, "INT POS: %d (VAL: %d)\n", aCode[iIP].argument, INT_32(pMemoryCore -> static_data.GetInt(aCode[iIP].argument)));
HL_RST;
#endif
									}
									// From static data segment to stack (float value)
									else if (iSrcReg == ARG_SRC_FLOAT)
									{
										oVMArgStack.PushElement(pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
#ifdef _DEBUG
fprintf(stderr, "FLOAT POS: %d (VAL: %f)\n", aCode[iIP].argument, pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
HL_RST;
#endif
									}
									// From indirect ARRAY
									else if (iSrcReg == ARG_SRC_IND_VAL)
									{
										const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
										// Indirect operations works ONLY with registers AR - HR and LR
										if (iDstReg <= ARG_DST_LASTREG)
										{
											oVMArgStack.PushElement(oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument));
#ifdef _DEBUG
fprintf(stderr, "%cR[%d] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), aCode[iIP].argument, oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// From indirect HASH
									else if (iSrcReg == ARG_SRC_IND_STR)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);

										const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
										// Indirect operations works ONLY with registers AR - HR and LR
										if (iDstReg <= ARG_DST_LASTREG)
										{
											bool bCDTExist = false;
#ifdef _DEBUG
fprintf(stderr, "%cR[\"%s\"] ", CHAR_8((iDstReg >> 8) + 'A'), szTMP);
fprintf(stderr, "(`%s`)\n", oRegs[iDstReg >> 8].GetExistedCDT(STLW::string(szTMP, iDataSize), bCDTExist).GetString().c_str());
HL_RST;
#endif
											oVMArgStack.PushElement(oRegs[iDstReg >> 8].GetExistedCDT(STLW::string(szTMP, iDataSize), bCDTExist));

											// Found
											if (bCDTExist) { iFlags = FL_EQ; }
											// Not Found
											else           { iFlags = 0;     }
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// From stack to stack
									else if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](%s)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										oVMArgStack.PushElement(oVMArgStack.GetTopElement(aCode[iIP].argument));
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// POP
							case SYSCALL_OPCODE_LO(POP):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X POP       ", iIP);
#endif
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);

									// From register to stack
									if (iSrcReg <= ARG_SRC_LASTREG)
									{
										oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
										oVMArgStack.ClearStack(1);
#ifdef _DEBUG
fprintf(stderr, "%cR\n", CHAR_8(iOpCode + 'A'));
HL_RST;
#endif
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// PUSH13
							case SYSCALL_OPCODE_LO(PUSH13):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X PUSH13    \n", iIP);
#endif
									for (INT_32 iSrcReg = ARG_SRC_AR; iSrcReg <= ARG_SRC_DR; ++iSrcReg)
									{
										oVMArgStack.PushElement(oRegs[iSrcReg]);
									}
								}
								break;

							// POP13
							case SYSCALL_OPCODE_LO(POP13):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X POP13     \n", iIP);
#endif
									for (INT_32 iSrcReg = ARG_SRC_DR; iSrcReg >= ARG_SRC_AR; --iSrcReg)
									{
										oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
										oVMArgStack.ClearStack(1);
									}
								}
								break;

							// PUSH47
							case SYSCALL_OPCODE_LO(PUSH47):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X PUSH47    \n", iIP);
#endif

									for (INT_32 iSrcReg = ARG_SRC_ER; iSrcReg <= ARG_SRC_HR; ++iSrcReg)
									{
										oVMArgStack.PushElement(oRegs[iSrcReg]);
									}
								}
								break;

							// POP47
							case SYSCALL_OPCODE_LO(POP47):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X POP47     \n", iIP);
#endif

									for (INT_32 iSrcReg = ARG_SRC_HR; iSrcReg >= ARG_SRC_ER; --iSrcReg)
									{
										oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
										oVMArgStack.ClearStack(1);
									}
								}
								break;

							// PUSHA
							case SYSCALL_OPCODE_LO(PUSHA):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X PUSHA     \n", iIP);
#endif

									for (INT_32 iSrcReg = 0; iSrcReg <= ARG_SRC_LASTREG; ++iSrcReg)
									{
										oVMArgStack.PushElement(oRegs[iSrcReg]);
									}
								}
								break;

							// POPA
							case SYSCALL_OPCODE_LO(POPA):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X POPA      \n", iIP);
#endif

									for (INT_32 iSrcReg = ARG_SRC_LASTREG; iSrcReg >= 0; --iSrcReg)
									{
										oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
										oVMArgStack.ClearStack(1);
									}
								}
								break;

							// Illegal Opcode?
							default:
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
							}
						}
					}
					++iIP;
					break;

				// Arithmetic ops. ///// 0x-3-X----
				case 0x03:
					{
						const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
						const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);

						switch(iOpCodeLo)
						{
							// ADD, Add values
							case SYSCALL_OPCODE_LO(ADD):
								{
									CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X ADD       ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
HL_RST;
#endif
									oVMArgStack.GetTopElement(1) += oVMArgStack.GetTopElement(0);
									oVMArgStack.ClearStack(1);
								}
								break;

							// SUB, Substract values
							case SYSCALL_OPCODE_LO(SUB):
								{
									CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X SUB       ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
HL_RST;
#endif
									oVMArgStack.GetTopElement(1) -= oVMArgStack.GetTopElement(0);
									oVMArgStack.ClearStack(1);
								}
								break;

							// MUL, Multiplicate values
							case SYSCALL_OPCODE_LO(MUL):
								{
									CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MUL       ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
HL_RST;
#endif
									oVMArgStack.GetTopElement(1) *= oVMArgStack.GetTopElement(0);
									oVMArgStack.ClearStack(1);
								}
								break;

							// DIV, Divide values
							case SYSCALL_OPCODE_LO(DIV):
								{
									CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X DIV       ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
HL_RST;
#endif
									oVMArgStack.GetTopElement(1) /= oVMArgStack.GetTopElement(0);
									oVMArgStack.ClearStack(1);
								}
								break;

							// INC, Increment value
							case SYSCALL_OPCODE_LO(INC):
								{
									if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X INC       %cR (%d)\n", iIP, CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
HL_RST;
#endif
										++oRegs[iSrcReg];
									}
									else if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X INC       STACK[%d] (%d)\n", iIP, 0, INT_32(oVMArgStack.GetTopElement(0).GetInt()));
HL_RST;
#endif
										++oVMArgStack.GetTopElement(0);
									}
								}
								break;

							// DEC, Decrement value
							case SYSCALL_OPCODE_LO(DEC):
								{
									if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X DEC       %cR (%d)\n", iIP, CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
HL_RST;
#endif
										--oRegs[iSrcReg];
									}
									else if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X DEC       STACK[%d] (%d)\n", iIP, 0, INT_32(oVMArgStack.GetTopElement(0).GetInt()));
HL_RST;
#endif
										--oVMArgStack.GetTopElement(0);
									}
								}
								break;

							// IDIV, Integer division
							case SYSCALL_OPCODE_LO(IDIV):
								{
									CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X IDIV      ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
HL_RST;
#endif
									const INT_64 iFirst  = oVMArgStack.GetTopElement(1).GetInt();
									const INT_64 iSecond = oVMArgStack.GetTopElement(0).GetInt();

									if (iSecond == 0)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw ZeroDivision(iIP, aCode[iIP].reserved, szTMP);
									}

									oVMArgStack.GetTopElement(1) = iFirst / iSecond;
									oVMArgStack.ClearStack(1);
								}
								break;

							// MOD, Divide two numbers and returns only the remainder
							case SYSCALL_OPCODE_LO(MOD):
								{
									CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);

#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MOD       ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
HL_RST;
#endif
									const INT_64 iFirst  = oVMArgStack.GetTopElement(1).GetInt();
									const INT_64 iSecond = oVMArgStack.GetTopElement(0).GetInt();

									oVMArgStack.GetTopElement(1) = iFirst % iSecond;
									oVMArgStack.ClearStack(1);
								}
								break;

							// NEG, Negate
							case SYSCALL_OPCODE_LO(NEG):
								{

									if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X NEG       %cR (%d)\n", iIP, CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
HL_RST;
#endif
										CDT & oTMP = oRegs[iSrcReg];
										if (oTMP.GetType() <= CDT::REAL_VAL) { oTMP = 0 - oTMP; }
									}
									else if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X NEG       STACK[%d](%s)\n", iIP, aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										CDT & oTMP = oVMArgStack.GetTopElement(aCode[iIP].argument);
										if (oTMP.GetType() <= CDT::REAL_VAL) { oTMP = 0 - oTMP; }
									}
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// NOT, Logical negation
							case SYSCALL_OPCODE_LO(NOT):
								{
									if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "0x%08X NOT       STACK[%d](%c)\n", iIP, aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).Nonzero() ? 't':'f');
HL_RST;
#endif
										CDT & oTMP = oVMArgStack.GetTopElement(aCode[iIP].argument);

										if (oTMP.Nonzero()) { oTMP = CDT(CDT::UNDEF); }
										// Undefined
										else                { oTMP = 1;               }
									}
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "0x%08X NOT       %cR (`%s`)\n", iIP, CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
										// Defined
										if (oRegs[iSrcReg].Nonzero()) { oRegs[iSrcReg] = CDT(CDT::UNDEF); }
										// Undefined
										else                          { oRegs[iSrcReg] = 1;               }
									}
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// CONCAT, Concatenate strings
							case SYSCALL_OPCODE_LO(CONCAT):
								{
									CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X CONCAT    ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
HL_RST;
#endif
									oVMArgStack.GetTopElement(1).Append(oVMArgStack.GetTopElement(0));
									oVMArgStack.ClearStack(1);
								}
								break;

							// Illegal Opcode?
							default:
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
							}
						}
					}
					++iIP;
					break;

				// Register ops. /////// 0x-4------
				case 0x04:
					{
						switch(iOpCodeLo)
						{
							// MOV
							case SYSCALL_OPCODE_LO(MOV):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MOV       ", iIP);
#endif
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR, ", CHAR_8((iDstReg >> 8) + 'A'));
#endif
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
#ifdef _DEBUG
fprintf(stderr, "%cR == `%s`\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
											oRegs[iDstReg >> 8] = oRegs[iSrcReg];
										}
										// Register-to-stack
										else if (iSrcReg <= ARG_SRC_STACK)
										{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d] = `%s`\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
											oRegs[iDstReg >> 8] = oVMArgStack.GetTopElement(aCode[iIP].argument);
										}
										// Integer-to-register
										else if (iSrcReg == ARG_SRC_INT)
										{
#ifdef _DEBUG
fprintf(stderr, "INT POS: %d (VAL: %d)\n", aCode[iIP].argument, INT_32(pMemoryCore -> static_data.GetInt(aCode[iIP].argument)));
HL_RST;
#endif
											oRegs[iDstReg >> 8] = pMemoryCore -> static_data.GetInt(aCode[iIP].argument);
										}
										// Float-to-register
										else if (iSrcReg == ARG_SRC_FLOAT)
										{
#ifdef _DEBUG
fprintf(stderr, "FLOAT POS: %d (VAL: %f)\n", aCode[iIP].argument, pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
HL_RST;
#endif
											oRegs[iDstReg >> 8] = pMemoryCore -> static_data.GetFloat(aCode[iIP].argument);
										}
										// String-to-register
										else if (iSrcReg == ARG_SRC_STR)
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
#ifdef _DEBUG
fprintf(stderr, "STRING POS: %d (VAL: `%s`)\n", aCode[iIP].argument, szTMP);
HL_RST;
#endif
											oRegs[iDstReg >> 8] = STLW::string(szTMP, iDataSize);
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// MOVIINT, Move indirect ARRAY to register
							case SYSCALL_OPCODE_LO(MOVIINT):
								{
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MOVIINT   %cR, %cR[%d] (`%s`)", iIP, CHAR_8((iDstReg >> 8) + 'A'), CHAR_8(iSrcReg + 'A'), aCode[iIP].argument, oRegs[iDstReg >> 8].GetString().c_str());
HL_RST;
#endif

											oRegs[iDstReg >> 8] = oRegs[iSrcReg].GetCDT(aCode[iIP].argument);
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// MOVISTR, Move indirect HASH to register
							case SYSCALL_OPCODE_LO(MOVISTR):
								{
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);

											bool bCDTExist = false;
											oRegs[iDstReg >> 8] = oRegs[iSrcReg].GetExistedCDT(STLW::string(szTMP, iDataSize), bCDTExist);

											// Found
											if (bCDTExist) { iFlags = FL_EQ; }
											// Not Found
											else           { iFlags = FL_NE; }

#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MOVISTR   %cR, %cR[%s] (`%s`)\n", iIP, CHAR_8((iDstReg >> 8)  + 'A'), CHAR_8(iSrcReg + 'A'), szTMP, oRegs[iDstReg >> 8].GetString().c_str());
HL_RST;
#endif
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// IMOVINT, Move register to indirect ARRAY
							case SYSCALL_OPCODE_LO(IMOVINT):
								{
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
											oRegs[iDstReg >> 8][aCode[iIP].argument] = oRegs[iSrcReg];
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X IMOVINT   %cR[%d], %cR[%d] (`%s`)\n", iIP, CHAR_8((iDstReg >> 8)+ 'A'), aCode[iIP].argument, CHAR_8(iSrcReg + 'A'), aCode[iIP].argument, oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// IMOVSTR
							case SYSCALL_OPCODE_LO(IMOVSTR):
								{
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
											oRegs[iDstReg >> 8][STLW::string(szTMP, iDataSize)] = oRegs[iSrcReg];
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X IMOVSTR   %cR[%s], %cR (`%s`)\n", iIP, CHAR_8((iDstReg >> 8) + 'A'), szTMP, CHAR_8(iSrcReg + 'A'), oRegs[iDstReg >> 8][STLW::string(szTMP, iDataSize)].GetString().c_str());
HL_RST;
#endif
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// MOVSIZE, Get object size
							case SYSCALL_OPCODE_LO(MOVSIZE):
								{
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);

									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MOVSIZE   %cR, %cR.Size() (%d)\n", iIP, CHAR_8((iDstReg >> 8) + 'A'), CHAR_8(iSrcReg + 'A'), UINT_32(oRegs[iSrcReg].Size()));
HL_RST;
#endif
											const UINT_64 iSize = oRegs[iSrcReg].Size();
											oRegs[iDstReg >> 8] = iSize;

											if (iSize == 0) { iFlags = FL_EQ; }
											else            { iFlags = 0;     }
										}
										// Stack-to-register
										else if (iSrcReg <= ARG_SRC_STACK)
										{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MOVSIZE   %cR, STACK[%d] (%d)\n", iIP, CHAR_8((iDstReg >> 8) + 'A'), aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).Size());
HL_RST;
#endif
											const UINT_64 iSize = oVMArgStack.GetTopElement(aCode[iIP].argument).Size();
											oRegs[iDstReg >> 8] = iSize;

											if (iSize == 0) { iFlags = FL_EQ; }
											else            { iFlags = 0;     }
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// To stack
									else if (iDstReg <= ARG_DST_STACK)
									{
										// Register-to-stack
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X MOVSIZE   STACK[%d], %cR (%d)\n", iIP, aCode[iIP].argument, CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].Size());
HL_RST;
#endif
											const UINT_64 iSize = oRegs[iSrcReg].Size();
											oVMArgStack.GetTopElement(aCode[iIP].argument) = iSize;

											if (iSize == 0) { iFlags = FL_EQ; }
											else            { iFlags = 0;     }
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// MOVIREGI
							case SYSCALL_OPCODE_LO(MOVIREGI):
								{
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);

									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
											const UINT_32 iArgNum = aCode[iIP].argument;
											// Illegal Opcode?
											if (iArgNum > ARG_SRC_LASTREG)
											{
												UINT_32 iDataSize = 0;
												CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
												throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
											}
											// AR <- CR[BR]
											//oRegs[iDstReg >> 8] = oRegs[iSrcReg][oRegs[iArgNum].GetInt()];
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X MOVIREG   %cR, %cR[%cR] ", iIP, CHAR_8((iDstReg >> 8) + 'A'), CHAR_8(iSrcReg + 'A'), CHAR_8(iArgNum + 'A'));
#endif
                                            const INT_32 iIdx = oRegs[iArgNum].GetInt();
                                            CDT oItVal(CDT::HASH_VAL);
                                            if (iIdx == 0)
                                            {
                                                oItVal["__first__"] = 1;
                                            }
                                            else if (UINT_32(iIdx + 1) == oRegs[iSrcReg].Size())
                                            {
                                                oItVal["__last__"] = 1;
                                            }
                                            else
                                            {
                                                oItVal["__inner__"] = 1;
                                            }

                                            if ((iIdx + 1) % 2 == 1) { oItVal["__odd__"] = 1; }
                                            else                     { oItVal["__even__"] = 1; }

                                            if (oRegs[iSrcReg].GetType() == CDT::HASH_VAL)
                                            {
                                                CDT::Iterator it = oRegs[iSrcReg].Begin();
                                                for (INT_32 iI = 0; iI < iIdx; ++iI) { ++it; }
#ifdef _DEBUG
fprintf(stderr, "(`%s`): %s\n", it->first.c_str(), it->second.GetString().c_str());
HL_RST;
#endif
                                                oItVal["__value__"] = it->second;
                                                oItVal["__key__"] = it->first;
                                                oRegs[iDstReg >> 8] = oItVal;
                                            }
                                            else
                                            {
#ifdef _DEBUG
fprintf(stderr, "(%d): %s\n", iIdx, oRegs[iSrcReg][iIdx].GetString().c_str());
HL_RST;
#endif
                                                oItVal["__value__"] = oRegs[iSrcReg][iIdx];
                                                oItVal["__index__"] = iIdx;
                                                oRegs[iDstReg >> 8] = oItVal;
                                            }
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;
							// MOVIREGS
							case SYSCALL_OPCODE_LO(MOVIREGS):
								{
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);

									// To register
									if (iDstReg <= ARG_DST_LASTREG)
									{
										// Register-to-register
										if (iSrcReg <= ARG_SRC_LASTREG)
										{
											const UINT_32 iArgNum = aCode[iIP].argument;
											// Illegal Opcode?
											if (iArgNum > ARG_SRC_LASTREG)
											{
												UINT_32 iDataSize = 0;
												CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
												throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
											}
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X MOVIREGS   %cR, %cR{%cR} (%s): %s\n", iIP, CHAR_8((iDstReg >> 8) + 'A'), CHAR_8(iSrcReg + 'A'), CHAR_8(iArgNum + 'A'), oRegs[iArgNum].GetString().c_str(), oRegs[iSrcReg][oRegs[iArgNum].GetString()].GetString().c_str());
HL_RST;
#endif
											// AR <- CR[BR]
											oRegs[iDstReg >> 8] = oRegs[iSrcReg][oRegs[iArgNum].GetString()];
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;
							// Illegal Opcode?
							default:
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
							}
						}
					}
					++iIP;
					break;

				// Comparison ops. ///// 0x-5-X----
				case 0x05:
					{
						switch(iOpCodeLo)
						{
							// CMP
							case SYSCALL_OPCODE_LO(CMP):
								{
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									W_FLOAT dSrc    = 0.0;
									W_FLOAT dDst    = 0.0;
#ifdef _DEBUG
{
HL_CODE(GREEN);
fprintf(stderr, "0x%08X CMP       ", iIP);

STLW::string sMsg2;
if      (iDstReg <= ARG_DST_LASTREG) { sMsg2.append(1, (iDstReg >> 8) + 'A'); sMsg2.append("R(`"); sMsg2.append(oRegs[iDstReg >> 8].GetString());  sMsg2.append("`)"); }
else if (iDstReg == ARG_DST_STACK) { sMsg2.append("STACK[0](`"); sMsg2.append(oVMArgStack.GetTopElement(0).GetString()); sMsg2.append("`)"); }

STLW::string sMsg1;
if      (iSrcReg <= ARG_SRC_LASTREG) { sMsg1.append(1, iSrcReg + 'A'); sMsg1.append("R(`"); sMsg1.append(oRegs[iSrcReg].GetString());  sMsg1.append("`), "); }
else if (iSrcReg == ARG_SRC_STACK) { sMsg1.append("STACK[1](`"); sMsg1.append(oVMArgStack.GetTopElement(1).GetString()); sMsg1.append("`), "); }

fprintf(stderr, "%s%s\n", sMsg1.c_str(), sMsg2.c_str());
HL_RST;
}
#endif
									if (iDstReg <= ARG_DST_LASTREG)
									{
										dDst = oRegs[iDstReg >> 8].GetFloat();
									}
									else if (iDstReg == ARG_DST_STACK)
									{
										dDst = oVMArgStack.GetTopElement(0).GetFloat();
										oVMArgStack.PopElement();
									}

									if (iSrcReg <= ARG_SRC_LASTREG)
									{
										dSrc = oRegs[iSrcReg].GetFloat();
									}
									else if (iSrcReg == ARG_SRC_STACK)
									{
										dSrc = oVMArgStack.GetTopElement(0).GetFloat();
										oVMArgStack.PopElement();
									}

									W_FLOAT dTMP = dSrc - dDst;
									if      (dTMP < 0.0) { iFlags = FL_LT | FL_NE; }
									else if (dTMP > 0.0) { iFlags = FL_GT | FL_NE; }
									else                 { iFlags = FL_EQ; }

									const UINT_64 iTMP = UINT_64(dSrc);
									if ((iTMP % 2) == 0) { iFlags |= FL_PF;  }
									else                 { iFlags |= FL_NPF; }
								}
								break;

							// SCMP
							case SYSCALL_OPCODE_LO(SCMP):
								{
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									STLW::string sSrc;
									STLW::string sDst;
#ifdef _DEBUG
{
HL_CODE(GREEN);
fprintf(stderr, "0x%08X SCMP      ", iIP);

STLW::string sMsg2;
if      (iDstReg <= ARG_DST_LASTREG) { sMsg2.append(1, (iDstReg >> 8) + 'A'); sMsg2.append("R(`"); sMsg2.append(oRegs[iDstReg >> 8].GetString());  sMsg2.append("`)"); }
else if (iDstReg == ARG_DST_STACK) { sMsg2.append("STACK[0](`"); sMsg2.append(oVMArgStack.GetTopElement(0).GetString()); sMsg2.append("`)"); }

STLW::string sMsg1;
if      (iSrcReg <= ARG_SRC_LASTREG) { sMsg1.append(1, iSrcReg + 'A'); sMsg1.append("R(`"); sMsg1.append(oRegs[iSrcReg].GetString());  sMsg1.append("`), "); }
else if (iSrcReg == ARG_SRC_STACK) { sMsg1.append("STACK[1](`"); sMsg1.append(oVMArgStack.GetTopElement(1).GetString()); sMsg1.append("`), "); }

fprintf(stderr, "%s%s\n", sMsg1.c_str(), sMsg2.c_str());
HL_RST;
}
#endif
									if (iDstReg <= ARG_DST_LASTREG)
									{
										sDst = oRegs[iDstReg >> 8].GetString();
									}
									else if (iDstReg == ARG_DST_STACK)
									{
										sDst = oVMArgStack.GetTopElement(0).GetString();
										oVMArgStack.PopElement();
									}

									if (iSrcReg <= ARG_SRC_LASTREG)
									{
										sSrc = oRegs[iSrcReg].GetString();
									}
									else if (iSrcReg == ARG_SRC_STACK)
									{
										sSrc = oVMArgStack.GetTopElement(0).GetString();
										oVMArgStack.PopElement();
									}

									if      (sSrc < sDst) { iFlags = FL_LT | FL_NE; }
									else if (sSrc > sDst) { iFlags = FL_GT | FL_NE; }
									else                  { iFlags = FL_EQ; }
								}
								break;

							// Illegal Opcode?
							default:
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
							}
						}
					}
					++iIP;
					break;

				// Conditional ops.1 /// 0x-6-X----
				case 0x06:
					{
						const UINT_32 iOpCodeFlag = iOpCode & 0x00FF0000;
#ifdef _DEBUG
{
HL_CODE(GREEN);
CHAR_8 sFlags[8];
INT_32 iPos = 0;
for (iPos = 0; iPos < 8; ++iPos)  { sFlags[iPos] = ' '; }
sFlags[7] = '\0'; iPos = 0;
if(iOpCodeFlag & FL_NE)  { sFlags[iPos++] = 'N'; }
if(iOpCodeFlag & FL_LT)  { sFlags[iPos++] = 'L'; }
if(iOpCodeFlag & FL_GT)  { sFlags[iPos++] = 'G'; }
if(iOpCodeFlag & FL_EQ)  { sFlags[iPos++] = 'E'; }
if(iOpCodeFlag & FL_PF)  { sFlags[iPos++] = 'P'; }
if(iOpCodeFlag & FL_NPF) { sFlags[iPos++] = 'N'; sFlags[iPos++] = 'P'; }
fprintf(stderr, "0x%08X J%s  0x%08X\n", iIP, sFlags, aCode[iIP].argument);
HL_RST;
}
#endif
						// Check execution limit
						if (iExecutedSteps >= iMaxSteps)
						{
							UINT_32 iDataSize = 0;
							CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
							throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
						}

						// Check flags
						if (!(iOpCodeFlag & iFlags))
						{
							++iIP;
						}
						else
						{
							const UINT_32 iNewIP = aCode[iIP].argument;
							if (iNewIP >= iCodeLength)
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
							}
							iIP = iNewIP;
						}
					}
					break;

				// Conditional ops.2 /// 0x-7-X----
				case 0x07:
					{
						const UINT_32 iOpCodeFlag = iOpCode & 0x00FF0000;
#ifdef _DEBUG
{
HL_CODE(GREEN);
CHAR_8 sFlags[8];
INT_32 iPos = 0;
for (iPos = 0; iPos < 8; ++iPos)  { sFlags[iPos] = ' '; }
sFlags[7] = '\0'; iPos = 0;
if(iOpCodeFlag & FL_NE)  { sFlags[iPos++] = 'N'; }
if(iOpCodeFlag & FL_LT)  { sFlags[iPos++] = 'L'; }
if(iOpCodeFlag & FL_GT)  { sFlags[iPos++] = 'G'; }
if(iOpCodeFlag & FL_EQ)  { sFlags[iPos++] = 'E'; }
if(iOpCodeFlag & FL_PF)  { sFlags[iPos++] = 'P'; }
if(iOpCodeFlag & FL_NPF) { sFlags[iPos++] = 'N'; sFlags[iPos++] = 'P'; }
fprintf(stderr, "0x%08X RJ%s 0x%08X\n", iIP, sFlags, aCode[iIP].argument);
HL_RST;
}
#endif
						// Check execution limit
						if (iExecutedSteps >= iMaxSteps)
						{
							UINT_32 iDataSize = 0;
							CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
							throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
						}

						// Check flags
						if (!(iOpCodeFlag & iFlags))
						{
							++iIP;
						}
						else
						{
							const UINT_32 iNewIP = iIP + aCode[iIP].argument;
							if (iNewIP >= iCodeLength)
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
							}
							iIP = iNewIP;
						}
					}
					break;
				// Other ops. ////////// 0x-8-X----
				case 0x08:
					{
						switch(iOpCodeLo)
						{
							// CLEAR
							case SYSCALL_OPCODE_LO(CLEAR):
								{
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X CLEAR     ", iIP);
#endif
									// Clear register
									if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR\n", CHAR_8((iSrcReg >> 8) + 'A'));
HL_RST;
#endif
										const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
										oRegs[iDstReg >> 8] = CDT();
									}
									// Clear stack
									else if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](%s)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										oVMArgStack.GetTopElement(aCode[iIP].argument) = CDT(CDT::UNDEF);
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// OUTPUT
							case SYSCALL_OPCODE_LO(OUTPUT):
								{
									// Register
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
#ifdef _DEBUG
HL_CODE(YELLOW);
fprintf(stderr, "0x%08X OUTPUT    ", iIP);
#endif
									// From stack
									if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										const STLW::string sTMP = oVMArgStack.GetTopElement(0).GetString();
										pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
										oVMArgStack.ClearStack(1);
									}
									// From static text segment
									else if (iSrcReg == ARG_SRC_STR)
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
#ifdef _DEBUG
fprintf(stderr, "STRING POS: %d (VAL: `%s`)\n", aCode[iIP].argument, szTMP);
HL_RST;
#endif
										pOutputCollector -> Collect(szTMP, iDataSize);
									}
									// From static data segment (integer value)
									else if (iSrcReg == ARG_SRC_INT)
									{
#ifdef _DEBUG
fprintf(stderr, "INT POS: %d (VAL: %d)\n", aCode[iIP].argument, INT_32(pMemoryCore -> static_data.GetInt(aCode[iIP].argument)));
HL_RST;
#endif
										const CDT oTMP(pMemoryCore -> static_data.GetInt(aCode[iIP].argument));
										const STLW::string sTMP = oTMP.GetString();
										pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
									}
									// From static data segment (float value)
									else if (iSrcReg == ARG_SRC_FLOAT)
									{
#ifdef _DEBUG
fprintf(stderr, "FLOAT POS: %d (VAL: %f)\n", aCode[iIP].argument, pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
HL_RST;
#endif
										const CDT oTMP(pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
										STLW::string sTMP = oTMP.GetString();
										pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
									}
									// From register
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR\n", CHAR_8(iSrcReg + 'A'));
HL_RST;
#endif
										const STLW::string sTMP = oRegs[iSrcReg].GetString();
										pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
									}
									// Indirect operations works ONLY with registers
									else if (iSrcReg == ARG_SRC_IND_VAL)
									{
										const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
#ifdef _DEBUG
fprintf(stderr, "%cR[%d] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), aCode[iIP].argument, oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										if (iDstReg <= ARG_DST_LASTREG)
										{
											const STLW::string sTMP = oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument).GetString();
											pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Indirect operations works ONLY with registers
									else if (iSrcReg == ARG_SRC_IND_STR)
									{
										const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);

										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
#ifdef _DEBUG
fprintf(stderr, "%cR[\"%s\"] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), szTMP, oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize)).GetString().c_str());
HL_RST;
#endif
										if (iDstReg <= ARG_DST_LASTREG)
										{
											STLW::string sTMP = oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize)).GetString();
											pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// REPLACE
							case SYSCALL_OPCODE_LO(REPLACE):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X REPLACE   ", iIP);
#endif
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
									// From static text segment to stack
									if (iSrcReg == ARG_SRC_IND_STR)
									{
										if (iDstReg <= ARG_DST_LASTREG)
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
#ifdef _DEBUG
fprintf(stderr, "%cR[\"%s\"] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), szTMP, oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize)).GetString().c_str());
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize));
										}
										else if (iDstReg == ARG_DST_STACK)
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);

											CDT & oTopStack  = oVMArgStack.GetTopElement(0);
											CDT oTMP = oTopStack.GetCDT(STLW::string(szTMP, iDataSize));
#ifdef _DEBUG
fprintf(stderr, "TOP STACK[\"%s\"] (`%s`)\n", szTMP, oTMP.GetString().c_str());
HL_RST;
#endif
											oTopStack = oTMP;
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// From argument pointed to array element from register or stack to to stack
									else if (iSrcReg == ARG_SRC_IND_VAL)
									{
										if (iDstReg <= ARG_DST_LASTREG)
										{
#ifdef _DEBUG
fprintf(stderr, "%cR[\"%d\"] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), INT_32(aCode[iIP].argument), oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument);
										}
										else if (iDstReg == ARG_DST_STACK)
										{
											CDT & oTopStack  = oVMArgStack.GetTopElement(0);
											CDT oTMP = oTopStack.GetCDT(aCode[iIP].argument);
#ifdef _DEBUG
fprintf(stderr, "TOP STACK[\"%d\"] (`%s`)\n", INT_32(aCode[iIP].argument), oTMP.GetString().c_str());
HL_RST;
#endif
											oTopStack = oTMP;
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// From register to stack
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
										oVMArgStack.GetTopElement(0) = oRegs[iSrcReg];
									}
									// Illegal operation
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// EXIST, check existence of operand
							case SYSCALL_OPCODE_LO(EXIST):
								{
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X EXIST     ", iIP);
#endif
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](%c)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).Nonzero() ? 't':'f');
HL_RST;
#endif
										// Defined
										if (oVMArgStack.GetTopElement(aCode[iIP].argument).Nonzero()) { iFlags = FL_EQ; }
										// Undefined
										else { iFlags = FL_NE; }
									}
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
										// Defined
										if (oRegs[iSrcReg].Nonzero()) { iFlags = FL_EQ; }
										// Undefined
										else                          { iFlags = FL_NE; }
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;
							// REPLINT
							case SYSCALL_OPCODE_LO(REPLINT):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X REPLINT   ", iIP);
#endif
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](%d)\n", aCode[iIP].argument, INT_32(oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()));
HL_RST;
#endif
										oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()];
									}
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR (%d)\n", CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
HL_RST;
#endif
										oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetInt()];
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;

							// REPLSTR
							case SYSCALL_OPCODE_LO(REPLSTR):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X REPLSTR   ", iIP);
#endif
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
										oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetString()];
									}
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
										oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetString()];
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;
							// REPLIND
							case SYSCALL_OPCODE_LO(REPLIND):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X REPLIND   ", iIP);
#endif
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									if (iSrcReg == ARG_SRC_STACK)
									{
										CDT::eValType typ = oVMArgStack.GetTopElement(aCode[iIP].argument).GetType();
										switch (typ)
										{
										case CDT::INT_VAL:
										case CDT::REAL_VAL:
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](%d)\n", aCode[iIP].argument, INT_32(oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()));
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()];
											break;
										case CDT::STRING_VAL:
										case CDT::STRING_INT_VAL:
										case CDT::STRING_REAL_VAL:
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetString()];
											break;
										default:
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](UNDEF)\n", aCode[iIP].argument);
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = CDT();
											break;
										}
									}
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
										CDT::eValType typ = oRegs[iSrcReg].GetType();
										switch (typ)
										{
										case CDT::INT_VAL:
										case CDT::REAL_VAL:
#ifdef _DEBUG
fprintf(stderr, "%cR (%d)\n", CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetInt()];
											break;
										case CDT::STRING_VAL:
										case CDT::STRING_INT_VAL:
										case CDT::STRING_REAL_VAL:
#ifdef _DEBUG
fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetString()];
											break;
										default:
#ifdef _DEBUG
fprintf(stderr, "%cR (UNDEF)\n", CHAR_8(iSrcReg + 'A'));
HL_RST;
#endif
											oVMArgStack.GetTopElement(0) = CDT();
											break;
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;
							// XCHG
							case SYSCALL_OPCODE_LO(XCHG):
								{
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X XCHG      ", iIP);
#endif
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);

									if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](`%s`), ", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
#endif
										CDT oTMP = oVMArgStack.GetTopElement(aCode[iIP].argument);
										if (iDstReg == ARG_DST_STACK)
										{
											CDT &oTopStack = oVMArgStack.GetTopElement(0);
											oVMArgStack.GetTopElement(aCode[iIP].argument) = oTopStack;

#ifdef _DEBUG
fprintf(stderr, "TOP STACK[0] (`%s`)\n", oTopStack.GetString().c_str());
HL_RST;
#endif
											oTopStack = oTMP;
										}
										// Illegal Opcode?
										else
										{
											UINT_32 iDataSize = 0;
											CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
											throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
										}
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;
							// DEFINED, check existence of operand
							case SYSCALL_OPCODE_LO(DEFINED):
								{
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X DEFINED   ", iIP);
#endif
									const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
									if (iSrcReg == ARG_SRC_STACK)
									{
#ifdef _DEBUG
fprintf(stderr, "STACK[%d](%c)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetType() != CDT::UNDEF ? 't':'f');
HL_RST;
#endif
										// Defined
										if (oVMArgStack.GetTopElement(aCode[iIP].argument).GetType() != CDT::UNDEF) { iFlags = FL_EQ; }
										// Undefined
										else { iFlags = FL_NE; }
									}
									else if (iSrcReg <= ARG_SRC_LASTREG)
									{
#ifdef _DEBUG
fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
HL_RST;
#endif
										// Defined
										if (oRegs[iSrcReg].GetType() != CDT::UNDEF) { iFlags = FL_EQ; }
										// Undefined
										else                          { iFlags = FL_NE; }
									}
									// Illegal Opcode?
									else
									{
										UINT_32 iDataSize = 0;
										CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
										throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
									}
								}
								break;
							// SAVEBP, save base pointer
							case SYSCALL_OPCODE_LO(SAVEBP):
								{
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X SAVEBP", iIP);
if (aCode[iIP].argument > 0) {
	fprintf(stderr, " [-%d]\n", aCode[iIP].argument);
} else {
	fprintf(stderr, "\n");
}

#endif
									oVMArgStack.SaveBasePointer(aCode[iIP].argument);
								}
								break;
							// RESTBP, restore base pointer
							case SYSCALL_OPCODE_LO(RESTBP):
								{
#ifdef _DEBUG
HL_CODE(GREEN);
fprintf(stderr, "0x%08X RESTBP\n", iIP);
#endif
									oVMArgStack.RestoreBasePointer();
								}
								break;
							// Illegal Opcode?
							default:
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
							}
						}
					}
					++iIP;
					break;

				// HLT
				case 0xFF: // Halt
					{
						switch(iOpCodeLo)
						{
							// HLT
							case SYSCALL_OPCODE_LO(HLT):
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X HLT\n", iIP);
HL_RST;
#endif
								return 0;
							// BRK
							case SYSCALL_OPCODE_LO(BRK):
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X BRK\n", iIP);
HL_RST;
#endif
								if (iDebugLevel > 0) { return 0; }
								++iIP;
								break;
							// NOP
							case SYSCALL_OPCODE_LO(NOP):
#ifdef _DEBUG
HL_CODE(RED);
fprintf(stderr, "0x%08X NOP\n", iIP);
HL_RST;
#endif
								++iIP; // Do nothing
								break;
							// Illegal Opcode?
							default:
							{
								UINT_32 iDataSize = 0;
								CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
								throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
							}
						}
					}
					break;

				// Illegal Opcode?
				default:
					{
						UINT_32 iDataSize = 0;
						CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
						throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
					}
			} // switch(SYSCALL_OPCODE_HI(iOpCode))
			++iExecutedSteps;
		} // while (iIP < iCodeLength)
	}
	catch (StackOverflow  & e)
	{
		// Avoid MS VC warning "unised variable"; using paragma is not effective solution
		UINT_32 iTMP = e.GetIP() * 0;

		UINT_32 iDataSize = 0;
		CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);

		throw StackOverflow(iTMP + iIP, aCode[iIP].reserved, szTMP);
	}
	catch (StackUnderflow &e)
	{
		// Avoid MS VC warning "unised variable"; using paragma is not effective solution
		UINT_32 iTMP = e.GetIP() * 0;

		UINT_32 iDataSize = 0;
		CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);

		throw StackUnderflow(iTMP + iIP, aCode[iIP].reserved, szTMP);
	}

return 0;
}

//
// Reset virtual machine state
//
INT_32 VM::Reset()
{
	AR = CDT();
	BR = CDT();
	CR = CDT();
	DR = CDT();
	ER = CDT();
	FR = CDT();
	GR = CDT();
	HR = CDT();

	iFlags = 0;

	oVMArgStack.Reset();
	oVMCodeStack.Reset();

return 0;
}

//
//
//
void VM::CheckStackOnlyRegs(const UINT_32 iSrcReg, const UINT_32 iDstReg, const VMMemoryCore  * pMemoryCore, const UINT_32 iIP)
{
	if (iSrcReg != ARG_SRC_STACK || iDstReg != ARG_DST_STACK)
	{
		UINT_32 iDataSize = 0;
		CCHAR_P szTMP     = pMemoryCore -> static_text.GetData(VMDebugInfo(pMemoryCore -> instructions[iIP].reserved).GetDescrId(), iDataSize);
		throw IllegalOpcode(iIP, pMemoryCore -> instructions[iIP].instruction, pMemoryCore -> instructions[iIP].reserved, szTMP);
	}
}

//
// A destructor
//
VM::~VM() throw()
{
	if (aCallTranslationMap != 0) { delete [] aCallTranslationMap; }

}

} // namespace CTPP
// End.
