1 /*-
2 * Copyright (c) 2004 - 2011 CTPP Team
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 4. Neither the name of the CTPP Team nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * CTPP2VM.cpp
29 *
30 * $CTPP$
31 */
32
33 #include "CTPP2VM.hpp"
34
35 #include "CTPP2OutputCollector.hpp"
36 #include "CTPP2SyscallFactory.hpp"
37 #include "CTPP2VMMemoryCore.hpp"
38
39 #include "CTPP2VMDebugInfo.hpp"
40 #include "CTPP2VMOpcodes.h"
41 #include "CTPP2VMException.hpp"
42 #include "CTPP2VMStackException.hpp"
43 #include "CTPP2VMInstruction.hpp"
44
45 #include <string.h>
46
47 #ifdef _DEBUG
48 #include <stdio.h>
49 #endif
50
51 /*
52 Foreground colors
53 30 Black
54 31 Red
55 32 Green
56 33 Yellow
57 34 Blue
58 35 Magenta
59 36 Cyan
60 37 White
61
62 Background colors
63 40 Black
64 41 Red
65 42 Green
66 43 Yellow
67 44 Blue
68 45 Magenta
69 46 Cyan
70 47 White
71 */
72 #define BRIGHT 1
73 #define RED 31
74 #define YELLOW 33
75 #define GREEN 32
76 #define BLUE 34
77 #define BG_BLACK 40
78
79
80 #ifndef WIN32 /* Windows console is not so funky */
81 #define HL_CODE(x) fprintf(stderr, "%c[%d;%d;%dm", 0x1B, BRIGHT, (x), BG_BLACK)
82 #define HL_RST fprintf(stderr, "%c[%dm", 0x1B, 0)
83 #else
84 #define HL_CODE(x)
85 #define HL_RST
86 #endif
87
88 // Aliases for registers
89 #define AR oRegs[0]
90 #define BR oRegs[1]
91 #define CR oRegs[2]
92 #define DR oRegs[3]
93 #define ER oRegs[4]
94 #define FR oRegs[5]
95 #define GR oRegs[6]
96 #define HR oRegs[7]
97
98 namespace CTPP // C++ Template Engine
99 {
100
101 //
102 // Constructor
103 //
VM(SyscallFactory * pISyscallFactory,const UINT_32 iIMaxArgStackSize,const UINT_32 iIMaxCodeStackSize,const UINT_32 iIMaxSteps,const UINT_32 iIDebugLevel)104 VM::VM(SyscallFactory * pISyscallFactory,
105 const UINT_32 iIMaxArgStackSize,
106 const UINT_32 iIMaxCodeStackSize,
107 const UINT_32 iIMaxSteps,
108 const UINT_32 iIDebugLevel): pSyscallFactory(pISyscallFactory),
109 iMaxArgStackSize(iIMaxArgStackSize),
110 iMaxCodeStackSize(iIMaxCodeStackSize),
111 iMaxSteps(iIMaxSteps),
112 iDebugLevel(iIDebugLevel),
113 iMaxCalls(0),
114 iMaxUsedCalls(0),
115 aCallTranslationMap(NULL),
116 oVMArgStack(iMaxArgStackSize),
117 oVMCodeStack(iMaxCodeStackSize)
118 {
119 ;;
120 }
121
122 //
123 // Initialize virtual machine
124 //
Init(const VMMemoryCore * pMemoryCore,OutputCollector * pOutputCollector,Logger * pLogger)125 INT_32 VM::Init(const VMMemoryCore * pMemoryCore,
126 OutputCollector * pOutputCollector,
127 Logger * pLogger)
128 {
129 // Create syscalls translation map
130 iMaxUsedCalls = pMemoryCore -> syscalls.GetRecordsNum();
131 // Cache
132 if (iMaxUsedCalls >= iMaxCalls)
133 {
134 delete [] aCallTranslationMap;
135 aCallTranslationMap = new SyscallHandler *[iMaxUsedCalls];
136 iMaxCalls = iMaxUsedCalls;
137 }
138
139 // Initialize program
140 for (UINT_32 iCallNum = 0; iCallNum < iMaxUsedCalls; ++iCallNum)
141 {
142 // Ugh
143 UINT_32 iCallNameLength = 0;
144 // NULL-terminated string, iCallNameLength will not used
145 CCHAR_P sCallName = pMemoryCore -> syscalls.GetData(iCallNum, iCallNameLength);
146
147 // Get syscall
148 SyscallHandler * pTMP = pSyscallFactory -> GetHandlerByName(sCallName);
149
150 // If this syscall is not present in factory, throw exception
151 if (pTMP == NULL)
152 {
153 UINT_32 iDataSize = 0;
154 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(pMemoryCore -> instructions[0].reserved).GetDescrId(), iDataSize);
155
156 throw InvalidSyscall(sCallName, 0, pMemoryCore -> instructions[0].reserved, szTMP);
157 }
158
159 // All OK
160 aCallTranslationMap[iCallNum] = pTMP;
161
162 // Initialize syscall handler
163 pTMP -> PreExecuteSetup(*pOutputCollector,
164 DR,
165 pMemoryCore -> syscalls,
166 pMemoryCore -> static_data,
167 pMemoryCore -> static_text,
168 *pLogger);
169 }
170
171 return 0;
172 }
173
174 //
175 // Run program
176 //
Run(const VMMemoryCore * pMemoryCore,OutputCollector * pOutputCollector,UINT_32 & iIP,CDT & oCDT,Logger * pLogger)177 INT_32 VM::Run(const VMMemoryCore * pMemoryCore,
178 OutputCollector * pOutputCollector,
179 UINT_32 & iIP,
180 CDT & oCDT,
181 Logger * pLogger)
182 {
183 DR = oCDT;
184 // Get code segment
185 const VMInstruction * aCode = pMemoryCore -> instructions;
186 const UINT_32 iCodeLength = pMemoryCore -> code_size;
187 UINT_32 iExecutedSteps = 0;
188
189 try
190 {
191 while (iIP < iCodeLength)
192 {
193 const UINT_32 iOpCode = aCode[iIP].instruction;
194 const UINT_32 iOpCodeHi = SYSCALL_OPCODE_HI(iOpCode);
195 const UINT_32 iOpCodeLo = SYSCALL_OPCODE_LO(iOpCode);
196 #ifdef _DEBUG
197 HL_CODE(BLUE);
198 fprintf(stderr, "CODE 0x%08X ARG 0x%08X RES 0x%016llX | ", iOpCode, aCode[iIP].argument, (long long)(aCode[iIP].reserved));
199 HL_RST;
200 #endif
201
202 switch(iOpCodeHi)
203 {
204 // Instructions //////// 0x-1-X----
205 case 0x01:
206 {
207 switch(iOpCodeLo)
208 {
209 // SYSCALL
210 case SYSCALL_OPCODE_LO(SYSCALL):
211 {
212 const UINT_32 iCallNum = (aCode[iIP].argument & 0xFFFF0000) >> 16;
213 const UINT_32 iCallArgNum = (aCode[iIP].argument & 0x0000FFFF);
214 #ifdef _DEBUG
215 {
216 UINT_32 iCallNameLength = 0;
217 // NULL-terminated string, iCallNameLength not need to use
218 CCHAR_P sCallName = pMemoryCore -> syscalls.GetData(iCallNum, iCallNameLength);
219 HL_CODE(YELLOW);
220 fprintf(stderr, "0x%08X SYSCALL 0x%08X %s(ARGS: %d)\n", iIP, iCallNum, sCallName, iCallArgNum);
221 HL_RST;
222 }
223 #endif
224 // Check call number
225 if (iCallNum > iMaxUsedCalls)
226 {
227 UINT_32 iDataSize = 0;
228 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
229 throw InvalidSyscall("*** CORRUPTED ***", iIP, aCode[iIP].reserved, szTMP);
230 }
231
232 CDT oResult(CDT::UNDEF);
233 // Invoke handler
234 if (aCallTranslationMap[iCallNum] -> Handler(oVMArgStack.GetStackFrame(), iCallArgNum, oResult, *pLogger) != 0)
235 {
236 UINT_32 iDataSize = 0;
237 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
238 throw InvalidSyscall("*** Internal syscall error ***", iIP, aCode[iIP].reserved, szTMP);
239 }
240
241 // Clear stack
242 oVMArgStack.ClearStack(iCallArgNum);
243
244 // Store execution result into stack
245 oVMArgStack.PushElement(oResult);
246
247 ++iIP;
248 }
249 break;
250
251 // CALLNAME
252 case SYSCALL_OPCODE_LO(CALLNAME):
253 {
254 // Get call name
255 UINT_32 iDataSize = 0;
256 CCHAR_P szCallName = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
257
258 UINT_32 iNewIP = UINT_32(pMemoryCore -> calls_table.Get(szCallName, iDataSize));
259 #ifdef _DEBUG
260 HL_CODE(RED);
261 fprintf(stderr, "0x%08X CALLNAME `%s` -> %d\n", iIP, szCallName, iNewIP);
262 HL_RST;
263 #endif
264 // Call exist?
265 if (iNewIP == (UINT_32)-1)
266 {
267 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
268 throw InvalidCall(iIP, aCode[iIP].reserved, szCallName, szTMP);
269 }
270
271 // New IP is correct?
272 if (iNewIP >= iCodeLength)
273 {
274 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
275 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
276 }
277
278 oVMCodeStack.PushAddress(iIP + 1);
279 iIP = iNewIP;
280 }
281 break;
282
283 // CALLIND
284 case SYSCALL_OPCODE_LO(CALLIND):
285 {
286 #ifdef _DEBUG
287 HL_CODE(RED);
288 fprintf(stderr, "0x%08X CALLIND ", iIP);
289 #endif
290 // Register
291 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
292
293 // Call name
294 STLW::string sCallName;
295
296 // From register?
297 if (iSrcReg <= ARG_SRC_HR)
298 {
299 #ifdef _DEBUG
300 fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
301 HL_RST;
302 #endif
303 sCallName = oRegs[iSrcReg].GetString();
304 }
305 // From Stack?
306 else if (iSrcReg == ARG_SRC_STACK)
307 {
308 #ifdef _DEBUG
309 fprintf(stderr, "STACK[%d] (`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
310 HL_RST;
311 #endif
312 sCallName = oVMArgStack.GetTopElement(aCode[iIP].argument).GetString();
313 STLW::vector<CDT> vArgs;
314 vArgs.reserve(aCode[iIP].argument);
315 for (UINT_32 iI = 0; iI < aCode[iIP].argument; ++iI)
316 {
317 vArgs.push_back(oVMArgStack.GetTopElement(iI));
318 }
319 oVMArgStack.ClearStack(aCode[iIP].argument + 1);
320 for (STLW::vector<CDT>::reverse_iterator vIt = vArgs.rbegin(); vIt != vArgs.rend(); ++vIt)
321 {
322 oVMArgStack.PushElement(*vIt);
323 }
324 }
325 // Illegal Opcode?
326 else
327 {
328 UINT_32 iDataSize = 0;
329 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
330 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
331 }
332
333 // Call exist?
334 if (sCallName.empty())
335 {
336 UINT_32 iDataSize = 0;
337 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
338 throw InvalidCall(iIP, aCode[iIP].reserved, "No name of call", szTMP);
339 }
340
341 // New IP
342 const UINT_32 iNewIP = UINT_32(pMemoryCore -> calls_table.Get(sCallName.c_str(), sCallName.size()));
343
344 // Call exist?
345 if (iNewIP == (UINT_32)-1)
346 {
347 UINT_32 iDataSize = 0;
348 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
349 throw InvalidCall(iIP, aCode[iIP].reserved, sCallName.c_str(), szTMP);
350 }
351
352 // New IP is correct?
353 if (iNewIP >= iCodeLength)
354 {
355 UINT_32 iDataSize = 0;
356 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
357 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
358 }
359
360 // Store return address
361 oVMCodeStack.PushAddress(iIP + 1);
362 iIP = iNewIP;
363 }
364 break;
365
366 // CALL
367 case SYSCALL_OPCODE_LO(CALL):
368 {
369 #ifdef _DEBUG
370 HL_CODE(RED);
371 fprintf(stderr, "0x%08X CALL 0x%08X\n", iIP, aCode[iIP].argument);
372 #endif
373 // Check execution limit
374 if (iExecutedSteps >= iMaxSteps)
375 {
376 UINT_32 iDataSize = 0;
377 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
378 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
379 }
380
381 const UINT_32 iNewIP = aCode[iIP].argument;
382 // New IP is correct?
383 if (iNewIP >= iCodeLength)
384 {
385 UINT_32 iDataSize = 0;
386 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
387 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
388 }
389
390 oVMCodeStack.PushAddress(iIP + 1);
391 iIP = iNewIP;
392 }
393 break;
394
395 // RET
396 case SYSCALL_OPCODE_LO(RET):
397 {
398 #ifdef _DEBUG
399 HL_CODE(RED);
400 fprintf(stderr, "0x%08X RET %d\n", iIP, aCode[iIP].argument);
401 HL_RST;
402 #endif
403 // Check execution limit
404 if (iExecutedSteps >= iMaxSteps)
405 {
406 UINT_32 iDataSize = 0;
407 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
408 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
409 }
410
411 // Clear stack
412 oVMArgStack.ClearStack(aCode[iIP].argument);
413 // Return
414 iIP = oVMCodeStack.PopAddress();
415 }
416 break;
417
418 // JMP
419 case SYSCALL_OPCODE_LO(JMP):
420 {
421 #ifdef _DEBUG
422 HL_CODE(GREEN);
423 fprintf(stderr, "0x%08X JMP 0x%08X\n", iIP, aCode[iIP].argument);
424 HL_RST;
425 #endif
426 // Check execution limit
427 if (iExecutedSteps >= iMaxSteps)
428 {
429 UINT_32 iDataSize = 0;
430 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
431 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
432 }
433
434 const UINT_32 iNewIP = aCode[iIP].argument;
435 // New IP is correct?
436 if (iNewIP >= iCodeLength)
437 {
438 UINT_32 iDataSize = 0;
439 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
440 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
441 }
442
443 iIP = iNewIP;
444 }
445 break;
446
447 // LOOP, cycle
448 case SYSCALL_OPCODE_LO(LOOP):
449 {
450 // Check execution limit
451 if (iExecutedSteps >= iMaxSteps)
452 {
453 UINT_32 iDataSize = 0;
454 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
455 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
456 }
457
458 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
459 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
460 if (iDstReg <= ARG_DST_LASTREG && iSrcReg <= ARG_SRC_LASTREG)
461 {
462 CDT & oLoopReg = oRegs[iSrcReg];
463
464 #ifdef _DEBUG
465 HL_CODE(GREEN);
466 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()));
467 HL_RST;
468 #endif
469 // Decrease number of iterations
470 --oLoopReg;
471 // End of cycle?
472 if (oLoopReg <= 0) { ++iIP; }
473 // New iteration
474 else
475 {
476 const UINT_32 iNewIP = aCode[iIP].argument;
477 // New IP is correct?
478 if (iNewIP >= iCodeLength)
479 {
480 UINT_32 iDataSize = 0;
481 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
482 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
483 }
484 iIP = iNewIP;
485
486 // Iteration counter
487 ++oRegs[iDstReg >> 8];
488 }
489 }
490 // Illegal Opcode?
491 else
492 {
493 UINT_32 iDataSize = 0;
494 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
495 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
496 }
497 }
498 break;
499
500 // RCALL
501 case SYSCALL_OPCODE_LO(RCALL):
502 {
503 #ifdef _DEBUG
504 HL_CODE(RED);
505 fprintf(stderr, "0x%08X RCALL 0x%08X\n", iIP, aCode[iIP].argument);
506 #endif
507 // Check execution limit
508 if (iExecutedSteps >= iMaxSteps)
509 {
510 UINT_32 iDataSize = 0;
511 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
512 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
513 }
514
515 const UINT_32 iNewIP = iIP + aCode[iIP].argument;
516 // New IP is correct?
517 if (iNewIP >= iCodeLength)
518 {
519 UINT_32 iDataSize = 0;
520 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
521 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
522 }
523
524 oVMCodeStack.PushAddress(iIP + 1);
525 iIP = iNewIP;
526 }
527 break;
528
529 // RJMP
530 case SYSCALL_OPCODE_LO(RJMP):
531 {
532 #ifdef _DEBUG
533 HL_CODE(GREEN);
534 fprintf(stderr, "0x%08X RJMP 0x%08X\n", iIP, aCode[iIP].argument);
535 HL_RST;
536 #endif
537 // Check execution limit
538 if (iExecutedSteps >= iMaxSteps)
539 {
540 UINT_32 iDataSize = 0;
541 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
542 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
543 }
544
545 const UINT_32 iNewIP = iIP + aCode[iIP].argument;
546 // New IP is correct?
547 if (iNewIP >= iCodeLength)
548 {
549 UINT_32 iDataSize = 0;
550 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
551 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
552 }
553
554 iIP = iNewIP;
555 }
556 break;
557
558 // Illegal Opcode?
559 default:
560 {
561 UINT_32 iDataSize = 0;
562 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
563 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
564 }
565 }
566 }
567 break;
568
569 // Stack operations //// 0x-2-X----
570 case 0x02:
571 {
572 switch(iOpCodeLo)
573 {
574 // PUSH
575 case SYSCALL_OPCODE_LO(PUSH):
576 {
577 #ifdef _DEBUG
578 HL_CODE(RED);
579 fprintf(stderr, "0x%08X PUSH ", iIP);
580 #endif
581 // Register
582 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
583
584 // From register to stack
585 if (iSrcReg <= ARG_SRC_LASTREG)
586 {
587 oVMArgStack.PushElement(oRegs[iSrcReg]);
588 #ifdef _DEBUG
589 fprintf(stderr, "%cR\n", CHAR_8(iOpCode + 'A'));
590 HL_RST;
591 #endif
592 }
593 // From static text segment to stack
594 else if (iSrcReg == ARG_SRC_STR)
595 {
596 UINT_32 iDataSize = 0;
597 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
598 oVMArgStack.PushElement(STLW::string(szTMP, iDataSize));
599 #ifdef _DEBUG
600 fprintf(stderr, "STRING POS: %d (VAL: `%s`)\n", aCode[iIP].argument, szTMP);
601 HL_RST;
602 #endif
603 }
604 // From static data segment to stack (integer value)
605 else if (iSrcReg == ARG_SRC_INT)
606 {
607 oVMArgStack.PushElement(pMemoryCore -> static_data.GetInt(aCode[iIP].argument));
608 #ifdef _DEBUG
609 fprintf(stderr, "INT POS: %d (VAL: %d)\n", aCode[iIP].argument, INT_32(pMemoryCore -> static_data.GetInt(aCode[iIP].argument)));
610 HL_RST;
611 #endif
612 }
613 // From static data segment to stack (float value)
614 else if (iSrcReg == ARG_SRC_FLOAT)
615 {
616 oVMArgStack.PushElement(pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
617 #ifdef _DEBUG
618 fprintf(stderr, "FLOAT POS: %d (VAL: %f)\n", aCode[iIP].argument, pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
619 HL_RST;
620 #endif
621 }
622 // From indirect ARRAY
623 else if (iSrcReg == ARG_SRC_IND_VAL)
624 {
625 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
626 // Indirect operations works ONLY with registers AR - HR and LR
627 if (iDstReg <= ARG_DST_LASTREG)
628 {
629 oVMArgStack.PushElement(oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument));
630 #ifdef _DEBUG
631 fprintf(stderr, "%cR[%d] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), aCode[iIP].argument, oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument).GetString().c_str());
632 HL_RST;
633 #endif
634 }
635 // Illegal Opcode?
636 else
637 {
638 UINT_32 iDataSize = 0;
639 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
640 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
641 }
642 }
643 // From indirect HASH
644 else if (iSrcReg == ARG_SRC_IND_STR)
645 {
646 UINT_32 iDataSize = 0;
647 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
648
649 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
650 // Indirect operations works ONLY with registers AR - HR and LR
651 if (iDstReg <= ARG_DST_LASTREG)
652 {
653 bool bCDTExist = false;
654 #ifdef _DEBUG
655 fprintf(stderr, "%cR[\"%s\"] ", CHAR_8((iDstReg >> 8) + 'A'), szTMP);
656 fprintf(stderr, "(`%s`)\n", oRegs[iDstReg >> 8].GetExistedCDT(STLW::string(szTMP, iDataSize), bCDTExist).GetString().c_str());
657 HL_RST;
658 #endif
659 oVMArgStack.PushElement(oRegs[iDstReg >> 8].GetExistedCDT(STLW::string(szTMP, iDataSize), bCDTExist));
660
661 // Found
662 if (bCDTExist) { iFlags = FL_EQ; }
663 // Not Found
664 else { iFlags = 0; }
665 }
666 // Illegal Opcode?
667 else
668 {
669 UINT_32 iDataSize = 0;
670 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
671 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
672 }
673 }
674 // From stack to stack
675 else if (iSrcReg == ARG_SRC_STACK)
676 {
677 #ifdef _DEBUG
678 fprintf(stderr, "STACK[%d](%s)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
679 HL_RST;
680 #endif
681 oVMArgStack.PushElement(oVMArgStack.GetTopElement(aCode[iIP].argument));
682 }
683 // Illegal Opcode?
684 else
685 {
686 UINT_32 iDataSize = 0;
687 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
688 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
689 }
690 }
691 break;
692
693 // POP
694 case SYSCALL_OPCODE_LO(POP):
695 {
696 #ifdef _DEBUG
697 HL_CODE(RED);
698 fprintf(stderr, "0x%08X POP ", iIP);
699 #endif
700 // Register
701 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
702
703 // From register to stack
704 if (iSrcReg <= ARG_SRC_LASTREG)
705 {
706 oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
707 oVMArgStack.ClearStack(1);
708 #ifdef _DEBUG
709 fprintf(stderr, "%cR\n", CHAR_8(iOpCode + 'A'));
710 HL_RST;
711 #endif
712 }
713 // Illegal Opcode?
714 else
715 {
716 UINT_32 iDataSize = 0;
717 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
718 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
719 }
720 }
721 break;
722
723 // PUSH13
724 case SYSCALL_OPCODE_LO(PUSH13):
725 {
726 #ifdef _DEBUG
727 HL_CODE(RED);
728 fprintf(stderr, "0x%08X PUSH13 \n", iIP);
729 #endif
730 for (INT_32 iSrcReg = ARG_SRC_AR; iSrcReg <= ARG_SRC_DR; ++iSrcReg)
731 {
732 oVMArgStack.PushElement(oRegs[iSrcReg]);
733 }
734 }
735 break;
736
737 // POP13
738 case SYSCALL_OPCODE_LO(POP13):
739 {
740 #ifdef _DEBUG
741 HL_CODE(RED);
742 fprintf(stderr, "0x%08X POP13 \n", iIP);
743 #endif
744 for (INT_32 iSrcReg = ARG_SRC_DR; iSrcReg >= ARG_SRC_AR; --iSrcReg)
745 {
746 oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
747 oVMArgStack.ClearStack(1);
748 }
749 }
750 break;
751
752 // PUSH47
753 case SYSCALL_OPCODE_LO(PUSH47):
754 {
755 #ifdef _DEBUG
756 HL_CODE(RED);
757 fprintf(stderr, "0x%08X PUSH47 \n", iIP);
758 #endif
759
760 for (INT_32 iSrcReg = ARG_SRC_ER; iSrcReg <= ARG_SRC_HR; ++iSrcReg)
761 {
762 oVMArgStack.PushElement(oRegs[iSrcReg]);
763 }
764 }
765 break;
766
767 // POP47
768 case SYSCALL_OPCODE_LO(POP47):
769 {
770 #ifdef _DEBUG
771 HL_CODE(RED);
772 fprintf(stderr, "0x%08X POP47 \n", iIP);
773 #endif
774
775 for (INT_32 iSrcReg = ARG_SRC_HR; iSrcReg >= ARG_SRC_ER; --iSrcReg)
776 {
777 oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
778 oVMArgStack.ClearStack(1);
779 }
780 }
781 break;
782
783 // PUSHA
784 case SYSCALL_OPCODE_LO(PUSHA):
785 {
786 #ifdef _DEBUG
787 HL_CODE(RED);
788 fprintf(stderr, "0x%08X PUSHA \n", iIP);
789 #endif
790
791 for (INT_32 iSrcReg = 0; iSrcReg <= ARG_SRC_LASTREG; ++iSrcReg)
792 {
793 oVMArgStack.PushElement(oRegs[iSrcReg]);
794 }
795 }
796 break;
797
798 // POPA
799 case SYSCALL_OPCODE_LO(POPA):
800 {
801 #ifdef _DEBUG
802 HL_CODE(RED);
803 fprintf(stderr, "0x%08X POPA \n", iIP);
804 #endif
805
806 for (INT_32 iSrcReg = ARG_SRC_LASTREG; iSrcReg >= 0; --iSrcReg)
807 {
808 oRegs[iSrcReg] = oVMArgStack.GetTopElement(0);
809 oVMArgStack.ClearStack(1);
810 }
811 }
812 break;
813
814 // Illegal Opcode?
815 default:
816 {
817 UINT_32 iDataSize = 0;
818 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
819 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
820 }
821 }
822 }
823 ++iIP;
824 break;
825
826 // Arithmetic ops. ///// 0x-3-X----
827 case 0x03:
828 {
829 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
830 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
831
832 switch(iOpCodeLo)
833 {
834 // ADD, Add values
835 case SYSCALL_OPCODE_LO(ADD):
836 {
837 CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
838 #ifdef _DEBUG
839 HL_CODE(RED);
840 fprintf(stderr, "0x%08X ADD ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
841 HL_RST;
842 #endif
843 oVMArgStack.GetTopElement(1) += oVMArgStack.GetTopElement(0);
844 oVMArgStack.ClearStack(1);
845 }
846 break;
847
848 // SUB, Substract values
849 case SYSCALL_OPCODE_LO(SUB):
850 {
851 CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
852 #ifdef _DEBUG
853 HL_CODE(RED);
854 fprintf(stderr, "0x%08X SUB ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
855 HL_RST;
856 #endif
857 oVMArgStack.GetTopElement(1) -= oVMArgStack.GetTopElement(0);
858 oVMArgStack.ClearStack(1);
859 }
860 break;
861
862 // MUL, Multiplicate values
863 case SYSCALL_OPCODE_LO(MUL):
864 {
865 CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
866 #ifdef _DEBUG
867 HL_CODE(RED);
868 fprintf(stderr, "0x%08X MUL ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
869 HL_RST;
870 #endif
871 oVMArgStack.GetTopElement(1) *= oVMArgStack.GetTopElement(0);
872 oVMArgStack.ClearStack(1);
873 }
874 break;
875
876 // DIV, Divide values
877 case SYSCALL_OPCODE_LO(DIV):
878 {
879 CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
880 #ifdef _DEBUG
881 HL_CODE(RED);
882 fprintf(stderr, "0x%08X DIV ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
883 HL_RST;
884 #endif
885 oVMArgStack.GetTopElement(1) /= oVMArgStack.GetTopElement(0);
886 oVMArgStack.ClearStack(1);
887 }
888 break;
889
890 // INC, Increment value
891 case SYSCALL_OPCODE_LO(INC):
892 {
893 if (iSrcReg <= ARG_SRC_LASTREG)
894 {
895 #ifdef _DEBUG
896 HL_CODE(RED);
897 fprintf(stderr, "0x%08X INC %cR (%d)\n", iIP, CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
898 HL_RST;
899 #endif
900 ++oRegs[iSrcReg];
901 }
902 else if (iSrcReg == ARG_SRC_STACK)
903 {
904 #ifdef _DEBUG
905 HL_CODE(RED);
906 fprintf(stderr, "0x%08X INC STACK[%d] (%d)\n", iIP, 0, INT_32(oVMArgStack.GetTopElement(0).GetInt()));
907 HL_RST;
908 #endif
909 ++oVMArgStack.GetTopElement(0);
910 }
911 }
912 break;
913
914 // DEC, Decrement value
915 case SYSCALL_OPCODE_LO(DEC):
916 {
917 if (iSrcReg <= ARG_SRC_LASTREG)
918 {
919 #ifdef _DEBUG
920 HL_CODE(RED);
921 fprintf(stderr, "0x%08X DEC %cR (%d)\n", iIP, CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
922 HL_RST;
923 #endif
924 --oRegs[iSrcReg];
925 }
926 else if (iSrcReg == ARG_SRC_STACK)
927 {
928 #ifdef _DEBUG
929 HL_CODE(RED);
930 fprintf(stderr, "0x%08X DEC STACK[%d] (%d)\n", iIP, 0, INT_32(oVMArgStack.GetTopElement(0).GetInt()));
931 HL_RST;
932 #endif
933 --oVMArgStack.GetTopElement(0);
934 }
935 }
936 break;
937
938 // IDIV, Integer division
939 case SYSCALL_OPCODE_LO(IDIV):
940 {
941 CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
942 #ifdef _DEBUG
943 HL_CODE(RED);
944 fprintf(stderr, "0x%08X IDIV ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
945 HL_RST;
946 #endif
947 const INT_64 iFirst = oVMArgStack.GetTopElement(1).GetInt();
948 const INT_64 iSecond = oVMArgStack.GetTopElement(0).GetInt();
949
950 if (iSecond == 0)
951 {
952 UINT_32 iDataSize = 0;
953 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
954 throw ZeroDivision(iIP, aCode[iIP].reserved, szTMP);
955 }
956
957 oVMArgStack.GetTopElement(1) = iFirst / iSecond;
958 oVMArgStack.ClearStack(1);
959 }
960 break;
961
962 // MOD, Divide two numbers and returns only the remainder
963 case SYSCALL_OPCODE_LO(MOD):
964 {
965 CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
966
967 #ifdef _DEBUG
968 HL_CODE(RED);
969 fprintf(stderr, "0x%08X MOD ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
970 HL_RST;
971 #endif
972 const INT_64 iFirst = oVMArgStack.GetTopElement(1).GetInt();
973 const INT_64 iSecond = oVMArgStack.GetTopElement(0).GetInt();
974
975 oVMArgStack.GetTopElement(1) = iFirst % iSecond;
976 oVMArgStack.ClearStack(1);
977 }
978 break;
979
980 // NEG, Negate
981 case SYSCALL_OPCODE_LO(NEG):
982 {
983
984 if (iSrcReg <= ARG_SRC_LASTREG)
985 {
986 #ifdef _DEBUG
987 HL_CODE(RED);
988 fprintf(stderr, "0x%08X NEG %cR (%d)\n", iIP, CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
989 HL_RST;
990 #endif
991 CDT & oTMP = oRegs[iSrcReg];
992 if (oTMP.GetType() <= CDT::REAL_VAL) { oTMP = 0 - oTMP; }
993 }
994 else if (iSrcReg == ARG_SRC_STACK)
995 {
996 #ifdef _DEBUG
997 HL_CODE(RED);
998 fprintf(stderr, "0x%08X NEG STACK[%d](%s)\n", iIP, aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
999 HL_RST;
1000 #endif
1001 CDT & oTMP = oVMArgStack.GetTopElement(aCode[iIP].argument);
1002 if (oTMP.GetType() <= CDT::REAL_VAL) { oTMP = 0 - oTMP; }
1003 }
1004 else
1005 {
1006 UINT_32 iDataSize = 0;
1007 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1008 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1009 }
1010 }
1011 break;
1012
1013 // NOT, Logical negation
1014 case SYSCALL_OPCODE_LO(NOT):
1015 {
1016 if (iSrcReg == ARG_SRC_STACK)
1017 {
1018 #ifdef _DEBUG
1019 fprintf(stderr, "0x%08X NOT STACK[%d](%c)\n", iIP, aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).Nonzero() ? 't':'f');
1020 HL_RST;
1021 #endif
1022 CDT & oTMP = oVMArgStack.GetTopElement(aCode[iIP].argument);
1023
1024 if (oTMP.Nonzero()) { oTMP = CDT(CDT::UNDEF); }
1025 // Undefined
1026 else { oTMP = 1; }
1027 }
1028 else if (iSrcReg <= ARG_SRC_LASTREG)
1029 {
1030 #ifdef _DEBUG
1031 fprintf(stderr, "0x%08X NOT %cR (`%s`)\n", iIP, CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
1032 HL_RST;
1033 #endif
1034 // Defined
1035 if (oRegs[iSrcReg].Nonzero()) { oRegs[iSrcReg] = CDT(CDT::UNDEF); }
1036 // Undefined
1037 else { oRegs[iSrcReg] = 1; }
1038 }
1039 else
1040 {
1041 UINT_32 iDataSize = 0;
1042 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1043 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1044 }
1045 }
1046 break;
1047
1048 // CONCAT, Concatenate strings
1049 case SYSCALL_OPCODE_LO(CONCAT):
1050 {
1051 CheckStackOnlyRegs(iSrcReg, iDstReg, pMemoryCore, iIP);
1052 #ifdef _DEBUG
1053 HL_CODE(RED);
1054 fprintf(stderr, "0x%08X CONCAT ('%s', '%s')\n", iIP, oVMArgStack.GetTopElement(1).GetString().c_str(), oVMArgStack.GetTopElement(0).GetString().c_str());
1055 HL_RST;
1056 #endif
1057 oVMArgStack.GetTopElement(1).Append(oVMArgStack.GetTopElement(0));
1058 oVMArgStack.ClearStack(1);
1059 }
1060 break;
1061
1062 // Illegal Opcode?
1063 default:
1064 {
1065 UINT_32 iDataSize = 0;
1066 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1067 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1068 }
1069 }
1070 }
1071 ++iIP;
1072 break;
1073
1074 // Register ops. /////// 0x-4------
1075 case 0x04:
1076 {
1077 switch(iOpCodeLo)
1078 {
1079 // MOV
1080 case SYSCALL_OPCODE_LO(MOV):
1081 {
1082 #ifdef _DEBUG
1083 HL_CODE(RED);
1084 fprintf(stderr, "0x%08X MOV ", iIP);
1085 #endif
1086 // Register
1087 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1088 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1089 // To register
1090 if (iDstReg <= ARG_DST_LASTREG)
1091 {
1092 #ifdef _DEBUG
1093 fprintf(stderr, "%cR, ", CHAR_8((iDstReg >> 8) + 'A'));
1094 #endif
1095 // Register-to-register
1096 if (iSrcReg <= ARG_SRC_LASTREG)
1097 {
1098 #ifdef _DEBUG
1099 fprintf(stderr, "%cR == `%s`\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
1100 HL_RST;
1101 #endif
1102 oRegs[iDstReg >> 8] = oRegs[iSrcReg];
1103 }
1104 // Register-to-stack
1105 else if (iSrcReg <= ARG_SRC_STACK)
1106 {
1107 #ifdef _DEBUG
1108 fprintf(stderr, "STACK[%d] = `%s`\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
1109 HL_RST;
1110 #endif
1111 oRegs[iDstReg >> 8] = oVMArgStack.GetTopElement(aCode[iIP].argument);
1112 }
1113 // Integer-to-register
1114 else if (iSrcReg == ARG_SRC_INT)
1115 {
1116 #ifdef _DEBUG
1117 fprintf(stderr, "INT POS: %d (VAL: %d)\n", aCode[iIP].argument, INT_32(pMemoryCore -> static_data.GetInt(aCode[iIP].argument)));
1118 HL_RST;
1119 #endif
1120 oRegs[iDstReg >> 8] = pMemoryCore -> static_data.GetInt(aCode[iIP].argument);
1121 }
1122 // Float-to-register
1123 else if (iSrcReg == ARG_SRC_FLOAT)
1124 {
1125 #ifdef _DEBUG
1126 fprintf(stderr, "FLOAT POS: %d (VAL: %f)\n", aCode[iIP].argument, pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
1127 HL_RST;
1128 #endif
1129 oRegs[iDstReg >> 8] = pMemoryCore -> static_data.GetFloat(aCode[iIP].argument);
1130 }
1131 // String-to-register
1132 else if (iSrcReg == ARG_SRC_STR)
1133 {
1134 UINT_32 iDataSize = 0;
1135 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
1136 #ifdef _DEBUG
1137 fprintf(stderr, "STRING POS: %d (VAL: `%s`)\n", aCode[iIP].argument, szTMP);
1138 HL_RST;
1139 #endif
1140 oRegs[iDstReg >> 8] = STLW::string(szTMP, iDataSize);
1141 }
1142 // Illegal Opcode?
1143 else
1144 {
1145 UINT_32 iDataSize = 0;
1146 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1147 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1148 }
1149 }
1150 // Illegal Opcode?
1151 else
1152 {
1153 UINT_32 iDataSize = 0;
1154 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1155 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1156 }
1157 }
1158 break;
1159
1160 // MOVIINT, Move indirect ARRAY to register
1161 case SYSCALL_OPCODE_LO(MOVIINT):
1162 {
1163 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1164 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1165 // To register
1166 if (iDstReg <= ARG_DST_LASTREG)
1167 {
1168 // Register-to-register
1169 if (iSrcReg <= ARG_SRC_LASTREG)
1170 {
1171 #ifdef _DEBUG
1172 HL_CODE(RED);
1173 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());
1174 HL_RST;
1175 #endif
1176
1177 oRegs[iDstReg >> 8] = oRegs[iSrcReg].GetCDT(aCode[iIP].argument);
1178 }
1179 // Illegal Opcode?
1180 else
1181 {
1182 UINT_32 iDataSize = 0;
1183 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1184 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1185 }
1186 }
1187 // Illegal Opcode?
1188 else
1189 {
1190 UINT_32 iDataSize = 0;
1191 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1192 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1193 }
1194 }
1195 break;
1196
1197 // MOVISTR, Move indirect HASH to register
1198 case SYSCALL_OPCODE_LO(MOVISTR):
1199 {
1200 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1201 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1202 // To register
1203 if (iDstReg <= ARG_DST_LASTREG)
1204 {
1205 // Register-to-register
1206 if (iSrcReg <= ARG_SRC_LASTREG)
1207 {
1208 UINT_32 iDataSize = 0;
1209 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
1210
1211 bool bCDTExist = false;
1212 oRegs[iDstReg >> 8] = oRegs[iSrcReg].GetExistedCDT(STLW::string(szTMP, iDataSize), bCDTExist);
1213
1214 // Found
1215 if (bCDTExist) { iFlags = FL_EQ; }
1216 // Not Found
1217 else { iFlags = FL_NE; }
1218
1219 #ifdef _DEBUG
1220 HL_CODE(RED);
1221 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());
1222 HL_RST;
1223 #endif
1224 }
1225 // Illegal Opcode?
1226 else
1227 {
1228 UINT_32 iDataSize = 0;
1229 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1230 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1231 }
1232 }
1233 // Illegal Opcode?
1234 else
1235 {
1236 UINT_32 iDataSize = 0;
1237 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1238 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1239 }
1240 }
1241 break;
1242
1243 // IMOVINT, Move register to indirect ARRAY
1244 case SYSCALL_OPCODE_LO(IMOVINT):
1245 {
1246 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1247 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1248 // To register
1249 if (iDstReg <= ARG_DST_LASTREG)
1250 {
1251 // Register-to-register
1252 if (iSrcReg <= ARG_SRC_LASTREG)
1253 {
1254 oRegs[iDstReg >> 8][aCode[iIP].argument] = oRegs[iSrcReg];
1255 #ifdef _DEBUG
1256 HL_CODE(RED);
1257 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());
1258 HL_RST;
1259 #endif
1260 }
1261 // Illegal Opcode?
1262 else
1263 {
1264 UINT_32 iDataSize = 0;
1265 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1266 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1267 }
1268 }
1269 // Illegal Opcode?
1270 else
1271 {
1272 UINT_32 iDataSize = 0;
1273 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1274 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1275 }
1276 }
1277 break;
1278
1279 // IMOVSTR
1280 case SYSCALL_OPCODE_LO(IMOVSTR):
1281 {
1282 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1283 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1284 // To register
1285 if (iDstReg <= ARG_DST_LASTREG)
1286 {
1287 // Register-to-register
1288 if (iSrcReg <= ARG_SRC_LASTREG)
1289 {
1290 UINT_32 iDataSize = 0;
1291 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
1292 oRegs[iDstReg >> 8][STLW::string(szTMP, iDataSize)] = oRegs[iSrcReg];
1293 #ifdef _DEBUG
1294 HL_CODE(RED);
1295 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());
1296 HL_RST;
1297 #endif
1298 }
1299 // Illegal Opcode?
1300 else
1301 {
1302 UINT_32 iDataSize = 0;
1303 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1304 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1305 }
1306 }
1307 // Illegal Opcode?
1308 else
1309 {
1310 UINT_32 iDataSize = 0;
1311 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1312 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1313 }
1314 }
1315 break;
1316
1317 // MOVSIZE, Get object size
1318 case SYSCALL_OPCODE_LO(MOVSIZE):
1319 {
1320 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1321 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1322
1323 // To register
1324 if (iDstReg <= ARG_DST_LASTREG)
1325 {
1326 // Register-to-register
1327 if (iSrcReg <= ARG_SRC_LASTREG)
1328 {
1329 #ifdef _DEBUG
1330 HL_CODE(RED);
1331 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()));
1332 HL_RST;
1333 #endif
1334 const UINT_64 iSize = oRegs[iSrcReg].Size();
1335 oRegs[iDstReg >> 8] = iSize;
1336
1337 if (iSize == 0) { iFlags = FL_EQ; }
1338 else { iFlags = 0; }
1339 }
1340 // Stack-to-register
1341 else if (iSrcReg <= ARG_SRC_STACK)
1342 {
1343 #ifdef _DEBUG
1344 HL_CODE(RED);
1345 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());
1346 HL_RST;
1347 #endif
1348 const UINT_64 iSize = oVMArgStack.GetTopElement(aCode[iIP].argument).Size();
1349 oRegs[iDstReg >> 8] = iSize;
1350
1351 if (iSize == 0) { iFlags = FL_EQ; }
1352 else { iFlags = 0; }
1353 }
1354 // Illegal Opcode?
1355 else
1356 {
1357 UINT_32 iDataSize = 0;
1358 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1359 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1360 }
1361 }
1362 // To stack
1363 else if (iDstReg <= ARG_DST_STACK)
1364 {
1365 // Register-to-stack
1366 if (iSrcReg <= ARG_SRC_LASTREG)
1367 {
1368 #ifdef _DEBUG
1369 HL_CODE(RED);
1370 fprintf(stderr, "0x%08X MOVSIZE STACK[%d], %cR (%d)\n", iIP, aCode[iIP].argument, CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].Size());
1371 HL_RST;
1372 #endif
1373 const UINT_64 iSize = oRegs[iSrcReg].Size();
1374 oVMArgStack.GetTopElement(aCode[iIP].argument) = iSize;
1375
1376 if (iSize == 0) { iFlags = FL_EQ; }
1377 else { iFlags = 0; }
1378 }
1379 // Illegal Opcode?
1380 else
1381 {
1382 UINT_32 iDataSize = 0;
1383 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1384 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1385 }
1386 }
1387 // Illegal Opcode?
1388 else
1389 {
1390 UINT_32 iDataSize = 0;
1391 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1392 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1393 }
1394 }
1395 break;
1396
1397 // MOVIREGI
1398 case SYSCALL_OPCODE_LO(MOVIREGI):
1399 {
1400 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1401 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1402
1403 // To register
1404 if (iDstReg <= ARG_DST_LASTREG)
1405 {
1406 // Register-to-register
1407 if (iSrcReg <= ARG_SRC_LASTREG)
1408 {
1409 const UINT_32 iArgNum = aCode[iIP].argument;
1410 // Illegal Opcode?
1411 if (iArgNum > ARG_SRC_LASTREG)
1412 {
1413 UINT_32 iDataSize = 0;
1414 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1415 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1416 }
1417 // AR <- CR[BR]
1418 //oRegs[iDstReg >> 8] = oRegs[iSrcReg][oRegs[iArgNum].GetInt()];
1419 #ifdef _DEBUG
1420 HL_CODE(GREEN);
1421 fprintf(stderr, "0x%08X MOVIREG %cR, %cR[%cR] ", iIP, CHAR_8((iDstReg >> 8) + 'A'), CHAR_8(iSrcReg + 'A'), CHAR_8(iArgNum + 'A'));
1422 #endif
1423 const INT_32 iIdx = oRegs[iArgNum].GetInt();
1424 CDT oItVal(CDT::HASH_VAL);
1425 if (iIdx == 0)
1426 {
1427 oItVal["__first__"] = 1;
1428 }
1429 else if (UINT_32(iIdx + 1) == oRegs[iSrcReg].Size())
1430 {
1431 oItVal["__last__"] = 1;
1432 }
1433 else
1434 {
1435 oItVal["__inner__"] = 1;
1436 }
1437
1438 if ((iIdx + 1) % 2 == 1) { oItVal["__odd__"] = 1; }
1439 else { oItVal["__even__"] = 1; }
1440
1441 if (oRegs[iSrcReg].GetType() == CDT::HASH_VAL)
1442 {
1443 CDTIterator it = oRegs[iSrcReg].Begin();
1444 for (INT_32 iI = 0; iI < iIdx; ++iI) { ++it; }
1445 #ifdef _DEBUG
1446 fprintf(stderr, "(`%s`): %s\n", it->first.c_str(), it->second.GetString().c_str());
1447 HL_RST;
1448 #endif
1449 oItVal["__value__"] = it->second;
1450 oItVal["__key__"] = it->first;
1451 oRegs[iDstReg >> 8] = oItVal;
1452 }
1453 else
1454 {
1455 #ifdef _DEBUG
1456 fprintf(stderr, "(%d): %s\n", iIdx, oRegs[iSrcReg][iIdx].GetString().c_str());
1457 HL_RST;
1458 #endif
1459 oItVal["__value__"] = oRegs[iSrcReg][iIdx];
1460 oItVal["__index__"] = iIdx;
1461 oRegs[iDstReg >> 8] = oItVal;
1462 }
1463 }
1464 // Illegal Opcode?
1465 else
1466 {
1467 UINT_32 iDataSize = 0;
1468 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1469 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1470 }
1471 }
1472 // Illegal Opcode?
1473 else
1474 {
1475 UINT_32 iDataSize = 0;
1476 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1477 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1478 }
1479 }
1480 break;
1481 // MOVIREGS
1482 case SYSCALL_OPCODE_LO(MOVIREGS):
1483 {
1484 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1485 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1486
1487 // To register
1488 if (iDstReg <= ARG_DST_LASTREG)
1489 {
1490 // Register-to-register
1491 if (iSrcReg <= ARG_SRC_LASTREG)
1492 {
1493 const UINT_32 iArgNum = aCode[iIP].argument;
1494 // Illegal Opcode?
1495 if (iArgNum > ARG_SRC_LASTREG)
1496 {
1497 UINT_32 iDataSize = 0;
1498 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1499 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1500 }
1501 #ifdef _DEBUG
1502 HL_CODE(GREEN);
1503 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());
1504 HL_RST;
1505 #endif
1506 // AR <- CR[BR]
1507 oRegs[iDstReg >> 8] = oRegs[iSrcReg][oRegs[iArgNum].GetString()];
1508 }
1509 // Illegal Opcode?
1510 else
1511 {
1512 UINT_32 iDataSize = 0;
1513 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1514 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1515 }
1516 }
1517 // Illegal Opcode?
1518 else
1519 {
1520 UINT_32 iDataSize = 0;
1521 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1522 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1523 }
1524 }
1525 break;
1526 // Illegal Opcode?
1527 default:
1528 {
1529 UINT_32 iDataSize = 0;
1530 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1531 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1532 }
1533 }
1534 }
1535 ++iIP;
1536 break;
1537
1538 // Comparison ops. ///// 0x-5-X----
1539 case 0x05:
1540 {
1541 switch(iOpCodeLo)
1542 {
1543 // CMP
1544 case SYSCALL_OPCODE_LO(CMP):
1545 {
1546 // Register
1547 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1548 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1549 W_FLOAT dSrc = 0.0;
1550 W_FLOAT dDst = 0.0;
1551 #ifdef _DEBUG
1552 {
1553 HL_CODE(GREEN);
1554 fprintf(stderr, "0x%08X CMP ", iIP);
1555
1556 STLW::string sMsg2;
1557 if (iDstReg <= ARG_DST_LASTREG) { sMsg2.append(1, (iDstReg >> 8) + 'A'); sMsg2.append("R(`"); sMsg2.append(oRegs[iDstReg >> 8].GetString()); sMsg2.append("`)"); }
1558 else if (iDstReg == ARG_DST_STACK) { sMsg2.append("STACK[0](`"); sMsg2.append(oVMArgStack.GetTopElement(0).GetString()); sMsg2.append("`)"); }
1559
1560 STLW::string sMsg1;
1561 if (iSrcReg <= ARG_SRC_LASTREG) { sMsg1.append(1, iSrcReg + 'A'); sMsg1.append("R(`"); sMsg1.append(oRegs[iSrcReg].GetString()); sMsg1.append("`), "); }
1562 else if (iSrcReg == ARG_SRC_STACK) { sMsg1.append("STACK[1](`"); sMsg1.append(oVMArgStack.GetTopElement(1).GetString()); sMsg1.append("`), "); }
1563
1564 fprintf(stderr, "%s%s\n", sMsg1.c_str(), sMsg2.c_str());
1565 HL_RST;
1566 }
1567 #endif
1568 if (iDstReg <= ARG_DST_LASTREG)
1569 {
1570 dDst = oRegs[iDstReg >> 8].GetFloat();
1571 }
1572 else if (iDstReg == ARG_DST_STACK)
1573 {
1574 dDst = oVMArgStack.GetTopElement(0).GetFloat();
1575 oVMArgStack.PopElement();
1576 }
1577
1578 if (iSrcReg <= ARG_SRC_LASTREG)
1579 {
1580 dSrc = oRegs[iSrcReg].GetFloat();
1581 }
1582 else if (iSrcReg == ARG_SRC_STACK)
1583 {
1584 dSrc = oVMArgStack.GetTopElement(0).GetFloat();
1585 oVMArgStack.PopElement();
1586 }
1587
1588 W_FLOAT dTMP = dSrc - dDst;
1589 if (dTMP < 0.0) { iFlags = FL_LT | FL_NE; }
1590 else if (dTMP > 0.0) { iFlags = FL_GT | FL_NE; }
1591 else { iFlags = FL_EQ; }
1592
1593 const UINT_64 iTMP = UINT_64(dSrc);
1594 if ((iTMP % 2) == 0) { iFlags |= FL_PF; }
1595 else { iFlags |= FL_NPF; }
1596 }
1597 break;
1598
1599 // SCMP
1600 case SYSCALL_OPCODE_LO(SCMP):
1601 {
1602 // Register
1603 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1604 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1605 STLW::string sSrc;
1606 STLW::string sDst;
1607 #ifdef _DEBUG
1608 {
1609 HL_CODE(GREEN);
1610 fprintf(stderr, "0x%08X SCMP ", iIP);
1611
1612 STLW::string sMsg2;
1613 if (iDstReg <= ARG_DST_LASTREG) { sMsg2.append(1, (iDstReg >> 8) + 'A'); sMsg2.append("R(`"); sMsg2.append(oRegs[iDstReg >> 8].GetString()); sMsg2.append("`)"); }
1614 else if (iDstReg == ARG_DST_STACK) { sMsg2.append("STACK[0](`"); sMsg2.append(oVMArgStack.GetTopElement(0).GetString()); sMsg2.append("`)"); }
1615
1616 STLW::string sMsg1;
1617 if (iSrcReg <= ARG_SRC_LASTREG) { sMsg1.append(1, iSrcReg + 'A'); sMsg1.append("R(`"); sMsg1.append(oRegs[iSrcReg].GetString()); sMsg1.append("`), "); }
1618 else if (iSrcReg == ARG_SRC_STACK) { sMsg1.append("STACK[1](`"); sMsg1.append(oVMArgStack.GetTopElement(1).GetString()); sMsg1.append("`), "); }
1619
1620 fprintf(stderr, "%s%s\n", sMsg1.c_str(), sMsg2.c_str());
1621 HL_RST;
1622 }
1623 #endif
1624 if (iDstReg <= ARG_DST_LASTREG)
1625 {
1626 sDst = oRegs[iDstReg >> 8].GetString();
1627 }
1628 else if (iDstReg == ARG_DST_STACK)
1629 {
1630 sDst = oVMArgStack.GetTopElement(0).GetString();
1631 oVMArgStack.PopElement();
1632 }
1633
1634 if (iSrcReg <= ARG_SRC_LASTREG)
1635 {
1636 sSrc = oRegs[iSrcReg].GetString();
1637 }
1638 else if (iSrcReg == ARG_SRC_STACK)
1639 {
1640 sSrc = oVMArgStack.GetTopElement(0).GetString();
1641 oVMArgStack.PopElement();
1642 }
1643
1644 if (sSrc < sDst) { iFlags = FL_LT | FL_NE; }
1645 else if (sSrc > sDst) { iFlags = FL_GT | FL_NE; }
1646 else { iFlags = FL_EQ; }
1647 }
1648 break;
1649
1650 // Illegal Opcode?
1651 default:
1652 {
1653 UINT_32 iDataSize = 0;
1654 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1655 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1656 }
1657 }
1658 }
1659 ++iIP;
1660 break;
1661
1662 // Conditional ops.1 /// 0x-6-X----
1663 case 0x06:
1664 {
1665 const UINT_32 iOpCodeFlag = iOpCode & 0x00FF0000;
1666 #ifdef _DEBUG
1667 {
1668 HL_CODE(GREEN);
1669 CHAR_8 sFlags[8];
1670 INT_32 iPos = 0;
1671 for (iPos = 0; iPos < 8; ++iPos) { sFlags[iPos] = ' '; }
1672 sFlags[7] = '\0'; iPos = 0;
1673 if(iOpCodeFlag & FL_NE) { sFlags[iPos++] = 'N'; }
1674 if(iOpCodeFlag & FL_LT) { sFlags[iPos++] = 'L'; }
1675 if(iOpCodeFlag & FL_GT) { sFlags[iPos++] = 'G'; }
1676 if(iOpCodeFlag & FL_EQ) { sFlags[iPos++] = 'E'; }
1677 if(iOpCodeFlag & FL_PF) { sFlags[iPos++] = 'P'; }
1678 if(iOpCodeFlag & FL_NPF) { sFlags[iPos++] = 'N'; sFlags[iPos++] = 'P'; }
1679 fprintf(stderr, "0x%08X J%s 0x%08X\n", iIP, sFlags, aCode[iIP].argument);
1680 HL_RST;
1681 }
1682 #endif
1683 // Check execution limit
1684 if (iExecutedSteps >= iMaxSteps)
1685 {
1686 UINT_32 iDataSize = 0;
1687 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1688 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
1689 }
1690
1691 // Check flags
1692 if (!(iOpCodeFlag & iFlags))
1693 {
1694 ++iIP;
1695 }
1696 else
1697 {
1698 const UINT_32 iNewIP = aCode[iIP].argument;
1699 if (iNewIP >= iCodeLength)
1700 {
1701 UINT_32 iDataSize = 0;
1702 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1703 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
1704 }
1705 iIP = iNewIP;
1706 }
1707 }
1708 break;
1709
1710 // Conditional ops.2 /// 0x-7-X----
1711 case 0x07:
1712 {
1713 const UINT_32 iOpCodeFlag = iOpCode & 0x00FF0000;
1714 #ifdef _DEBUG
1715 {
1716 HL_CODE(GREEN);
1717 CHAR_8 sFlags[8];
1718 INT_32 iPos = 0;
1719 for (iPos = 0; iPos < 8; ++iPos) { sFlags[iPos] = ' '; }
1720 sFlags[7] = '\0'; iPos = 0;
1721 if(iOpCodeFlag & FL_NE) { sFlags[iPos++] = 'N'; }
1722 if(iOpCodeFlag & FL_LT) { sFlags[iPos++] = 'L'; }
1723 if(iOpCodeFlag & FL_GT) { sFlags[iPos++] = 'G'; }
1724 if(iOpCodeFlag & FL_EQ) { sFlags[iPos++] = 'E'; }
1725 if(iOpCodeFlag & FL_PF) { sFlags[iPos++] = 'P'; }
1726 if(iOpCodeFlag & FL_NPF) { sFlags[iPos++] = 'N'; sFlags[iPos++] = 'P'; }
1727 fprintf(stderr, "0x%08X RJ%s 0x%08X\n", iIP, sFlags, aCode[iIP].argument);
1728 HL_RST;
1729 }
1730 #endif
1731 // Check execution limit
1732 if (iExecutedSteps >= iMaxSteps)
1733 {
1734 UINT_32 iDataSize = 0;
1735 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1736 throw ExecutionLimitReached(iIP, aCode[iIP].reserved, szTMP);
1737 }
1738
1739 // Check flags
1740 if (!(iOpCodeFlag & iFlags))
1741 {
1742 ++iIP;
1743 }
1744 else
1745 {
1746 const UINT_32 iNewIP = iIP + aCode[iIP].argument;
1747 if (iNewIP >= iCodeLength)
1748 {
1749 UINT_32 iDataSize = 0;
1750 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1751 throw CodeSegmentOverrun(iIP, aCode[iIP].reserved, szTMP);
1752 }
1753 iIP = iNewIP;
1754 }
1755 }
1756 break;
1757 // Other ops. ////////// 0x-8-X----
1758 case 0x08:
1759 {
1760 switch(iOpCodeLo)
1761 {
1762 // CLEAR
1763 case SYSCALL_OPCODE_LO(CLEAR):
1764 {
1765 // Register
1766 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1767 #ifdef _DEBUG
1768 HL_CODE(RED);
1769 fprintf(stderr, "0x%08X CLEAR ", iIP);
1770 #endif
1771 // Clear register
1772 if (iSrcReg <= ARG_SRC_LASTREG)
1773 {
1774 #ifdef _DEBUG
1775 fprintf(stderr, "%cR\n", CHAR_8((iSrcReg >> 8) + 'A'));
1776 HL_RST;
1777 #endif
1778 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1779 oRegs[iDstReg >> 8] = CDT();
1780 }
1781 // Clear stack
1782 else if (iSrcReg == ARG_SRC_STACK)
1783 {
1784 #ifdef _DEBUG
1785 fprintf(stderr, "STACK[%d](%s)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
1786 HL_RST;
1787 #endif
1788 oVMArgStack.GetTopElement(aCode[iIP].argument) = CDT(CDT::UNDEF);
1789 }
1790 // Illegal Opcode?
1791 else
1792 {
1793 UINT_32 iDataSize = 0;
1794 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1795 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1796 }
1797 }
1798 break;
1799
1800 // OUTPUT
1801 case SYSCALL_OPCODE_LO(OUTPUT):
1802 {
1803 // Register
1804 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1805 #ifdef _DEBUG
1806 HL_CODE(YELLOW);
1807 fprintf(stderr, "0x%08X OUTPUT ", iIP);
1808 #endif
1809 // From stack
1810 if (iSrcReg == ARG_SRC_STACK)
1811 {
1812 #ifdef _DEBUG
1813 fprintf(stderr, "STACK[%d](`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
1814 HL_RST;
1815 #endif
1816 const STLW::string sTMP = oVMArgStack.GetTopElement(0).GetString();
1817 pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
1818 oVMArgStack.ClearStack(1);
1819 }
1820 // From static text segment
1821 else if (iSrcReg == ARG_SRC_STR)
1822 {
1823 UINT_32 iDataSize = 0;
1824 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
1825 #ifdef _DEBUG
1826 fprintf(stderr, "STRING POS: %d (VAL: `%s`)\n", aCode[iIP].argument, szTMP);
1827 HL_RST;
1828 #endif
1829 pOutputCollector -> Collect(szTMP, iDataSize);
1830 }
1831 // From static data segment (integer value)
1832 else if (iSrcReg == ARG_SRC_INT)
1833 {
1834 #ifdef _DEBUG
1835 fprintf(stderr, "INT POS: %d (VAL: %d)\n", aCode[iIP].argument, INT_32(pMemoryCore -> static_data.GetInt(aCode[iIP].argument)));
1836 HL_RST;
1837 #endif
1838 const CDT oTMP(pMemoryCore -> static_data.GetInt(aCode[iIP].argument));
1839 const STLW::string sTMP = oTMP.GetString();
1840 pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
1841 }
1842 // From static data segment (float value)
1843 else if (iSrcReg == ARG_SRC_FLOAT)
1844 {
1845 #ifdef _DEBUG
1846 fprintf(stderr, "FLOAT POS: %d (VAL: %f)\n", aCode[iIP].argument, pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
1847 HL_RST;
1848 #endif
1849 const CDT oTMP(pMemoryCore -> static_data.GetFloat(aCode[iIP].argument));
1850 STLW::string sTMP = oTMP.GetString();
1851 pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
1852 }
1853 // From register
1854 else if (iSrcReg <= ARG_SRC_LASTREG)
1855 {
1856 #ifdef _DEBUG
1857 fprintf(stderr, "%cR\n", CHAR_8(iSrcReg + 'A'));
1858 HL_RST;
1859 #endif
1860 const STLW::string sTMP = oRegs[iSrcReg].GetString();
1861 pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
1862 }
1863 // Indirect operations works ONLY with registers
1864 else if (iSrcReg == ARG_SRC_IND_VAL)
1865 {
1866 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1867 #ifdef _DEBUG
1868 fprintf(stderr, "%cR[%d] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), aCode[iIP].argument, oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument).GetString().c_str());
1869 HL_RST;
1870 #endif
1871 if (iDstReg <= ARG_DST_LASTREG)
1872 {
1873 const STLW::string sTMP = oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument).GetString();
1874 pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
1875 }
1876 // Illegal Opcode?
1877 else
1878 {
1879 UINT_32 iDataSize = 0;
1880 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1881 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1882 }
1883 }
1884 // Indirect operations works ONLY with registers
1885 else if (iSrcReg == ARG_SRC_IND_STR)
1886 {
1887 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1888
1889 UINT_32 iDataSize = 0;
1890 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
1891 #ifdef _DEBUG
1892 fprintf(stderr, "%cR[\"%s\"] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), szTMP, oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize)).GetString().c_str());
1893 HL_RST;
1894 #endif
1895 if (iDstReg <= ARG_DST_LASTREG)
1896 {
1897 STLW::string sTMP = oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize)).GetString();
1898 pOutputCollector -> Collect(sTMP.c_str(), sTMP.size());
1899 }
1900 // Illegal Opcode?
1901 else
1902 {
1903 UINT_32 iDataSize = 0;
1904 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1905 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1906 }
1907 }
1908 // Illegal Opcode?
1909 else
1910 {
1911 UINT_32 iDataSize = 0;
1912 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1913 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1914 }
1915 }
1916 break;
1917
1918 // REPLACE
1919 case SYSCALL_OPCODE_LO(REPLACE):
1920 {
1921 #ifdef _DEBUG
1922 HL_CODE(RED);
1923 fprintf(stderr, "0x%08X REPLACE ", iIP);
1924 #endif
1925 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
1926 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
1927 // From static text segment to stack
1928 if (iSrcReg == ARG_SRC_IND_STR)
1929 {
1930 if (iDstReg <= ARG_DST_LASTREG)
1931 {
1932 UINT_32 iDataSize = 0;
1933 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
1934 #ifdef _DEBUG
1935 fprintf(stderr, "%cR[\"%s\"] (`%s`)\n", CHAR_8((iDstReg >> 8) + 'A'), szTMP, oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize)).GetString().c_str());
1936 HL_RST;
1937 #endif
1938 oVMArgStack.GetTopElement(0) = oRegs[iDstReg >> 8].GetCDT(STLW::string(szTMP, iDataSize));
1939 }
1940 else if (iDstReg == ARG_DST_STACK)
1941 {
1942 UINT_32 iDataSize = 0;
1943 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(aCode[iIP].argument, iDataSize);
1944
1945 CDT & oTopStack = oVMArgStack.GetTopElement(0);
1946 CDT oTMP = oTopStack.GetCDT(STLW::string(szTMP, iDataSize));
1947 #ifdef _DEBUG
1948 fprintf(stderr, "TOP STACK[\"%s\"] (`%s`)\n", szTMP, oTMP.GetString().c_str());
1949 HL_RST;
1950 #endif
1951 oTopStack = oTMP;
1952 }
1953 // Illegal Opcode?
1954 else
1955 {
1956 UINT_32 iDataSize = 0;
1957 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1958 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1959 }
1960 }
1961 // From argument pointed to array element from register or stack to to stack
1962 else if (iSrcReg == ARG_SRC_IND_VAL)
1963 {
1964 if (iDstReg <= ARG_DST_LASTREG)
1965 {
1966 #ifdef _DEBUG
1967 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());
1968 HL_RST;
1969 #endif
1970 oVMArgStack.GetTopElement(0) = oRegs[iDstReg >> 8].GetCDT(aCode[iIP].argument);
1971 }
1972 else if (iDstReg == ARG_DST_STACK)
1973 {
1974 CDT & oTopStack = oVMArgStack.GetTopElement(0);
1975 CDT oTMP = oTopStack.GetCDT(aCode[iIP].argument);
1976 #ifdef _DEBUG
1977 fprintf(stderr, "TOP STACK[\"%d\"] (`%s`)\n", INT_32(aCode[iIP].argument), oTMP.GetString().c_str());
1978 HL_RST;
1979 #endif
1980 oTopStack = oTMP;
1981 }
1982 // Illegal Opcode?
1983 else
1984 {
1985 UINT_32 iDataSize = 0;
1986 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
1987 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
1988 }
1989 }
1990 // From register to stack
1991 else if (iSrcReg <= ARG_SRC_LASTREG)
1992 {
1993 #ifdef _DEBUG
1994 fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
1995 HL_RST;
1996 #endif
1997 oVMArgStack.GetTopElement(0) = oRegs[iSrcReg];
1998 }
1999 // Illegal operation
2000 else
2001 {
2002 UINT_32 iDataSize = 0;
2003 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2004 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2005 }
2006 }
2007 break;
2008
2009 // EXIST, check existence of operand
2010 case SYSCALL_OPCODE_LO(EXIST):
2011 {
2012 #ifdef _DEBUG
2013 HL_CODE(GREEN);
2014 fprintf(stderr, "0x%08X EXIST ", iIP);
2015 #endif
2016 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
2017 if (iSrcReg == ARG_SRC_STACK)
2018 {
2019 #ifdef _DEBUG
2020 fprintf(stderr, "STACK[%d](%c)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).Nonzero() ? 't':'f');
2021 HL_RST;
2022 #endif
2023 // Defined
2024 if (oVMArgStack.GetTopElement(aCode[iIP].argument).Nonzero()) { iFlags = FL_EQ; }
2025 // Undefined
2026 else { iFlags = FL_NE; }
2027 }
2028 else if (iSrcReg <= ARG_SRC_LASTREG)
2029 {
2030 #ifdef _DEBUG
2031 fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
2032 HL_RST;
2033 #endif
2034 // Defined
2035 if (oRegs[iSrcReg].Nonzero()) { iFlags = FL_EQ; }
2036 // Undefined
2037 else { iFlags = FL_NE; }
2038 }
2039 // Illegal Opcode?
2040 else
2041 {
2042 UINT_32 iDataSize = 0;
2043 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2044 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2045 }
2046 }
2047 break;
2048 // REPLINT
2049 case SYSCALL_OPCODE_LO(REPLINT):
2050 {
2051 #ifdef _DEBUG
2052 HL_CODE(RED);
2053 fprintf(stderr, "0x%08X REPLINT ", iIP);
2054 #endif
2055 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
2056 if (iSrcReg == ARG_SRC_STACK)
2057 {
2058 #ifdef _DEBUG
2059 fprintf(stderr, "STACK[%d](%d)\n", aCode[iIP].argument, INT_32(oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()));
2060 HL_RST;
2061 #endif
2062 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()];
2063 }
2064 else if (iSrcReg <= ARG_SRC_LASTREG)
2065 {
2066 #ifdef _DEBUG
2067 fprintf(stderr, "%cR (%d)\n", CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
2068 HL_RST;
2069 #endif
2070 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetInt()];
2071 }
2072 // Illegal Opcode?
2073 else
2074 {
2075 UINT_32 iDataSize = 0;
2076 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2077 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2078 }
2079 }
2080 break;
2081
2082 // REPLSTR
2083 case SYSCALL_OPCODE_LO(REPLSTR):
2084 {
2085 #ifdef _DEBUG
2086 HL_CODE(RED);
2087 fprintf(stderr, "0x%08X REPLSTR ", iIP);
2088 #endif
2089 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
2090 if (iSrcReg == ARG_SRC_STACK)
2091 {
2092 #ifdef _DEBUG
2093 fprintf(stderr, "STACK[%d](`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
2094 HL_RST;
2095 #endif
2096 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetString()];
2097 }
2098 else if (iSrcReg <= ARG_SRC_LASTREG)
2099 {
2100 #ifdef _DEBUG
2101 fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
2102 HL_RST;
2103 #endif
2104 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetString()];
2105 }
2106 // Illegal Opcode?
2107 else
2108 {
2109 UINT_32 iDataSize = 0;
2110 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2111 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2112 }
2113 }
2114 break;
2115 // REPLIND
2116 case SYSCALL_OPCODE_LO(REPLIND):
2117 {
2118 #ifdef _DEBUG
2119 HL_CODE(RED);
2120 fprintf(stderr, "0x%08X REPLIND ", iIP);
2121 #endif
2122 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
2123 if (iSrcReg == ARG_SRC_STACK)
2124 {
2125 CDT::eValType typ = oVMArgStack.GetTopElement(aCode[iIP].argument).GetType();
2126 switch (typ)
2127 {
2128 case CDT::INT_VAL:
2129 case CDT::REAL_VAL:
2130 #ifdef _DEBUG
2131 fprintf(stderr, "STACK[%d](%d)\n", aCode[iIP].argument, INT_32(oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()));
2132 HL_RST;
2133 #endif
2134 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetInt()];
2135 break;
2136 case CDT::STRING_VAL:
2137 case CDT::STRING_INT_VAL:
2138 case CDT::STRING_REAL_VAL:
2139 #ifdef _DEBUG
2140 fprintf(stderr, "STACK[%d](`%s`)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
2141 HL_RST;
2142 #endif
2143 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oVMArgStack.GetTopElement(aCode[iIP].argument).GetString()];
2144 break;
2145 default:
2146 #ifdef _DEBUG
2147 fprintf(stderr, "STACK[%d](UNDEF)\n", aCode[iIP].argument);
2148 HL_RST;
2149 #endif
2150 oVMArgStack.GetTopElement(0) = CDT();
2151 break;
2152 }
2153 }
2154 else if (iSrcReg <= ARG_SRC_LASTREG)
2155 {
2156 CDT::eValType typ = oRegs[iSrcReg].GetType();
2157 switch (typ)
2158 {
2159 case CDT::INT_VAL:
2160 case CDT::REAL_VAL:
2161 #ifdef _DEBUG
2162 fprintf(stderr, "%cR (%d)\n", CHAR_8(iSrcReg + 'A'), INT_32(oRegs[iSrcReg].GetInt()));
2163 HL_RST;
2164 #endif
2165 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetInt()];
2166 break;
2167 case CDT::STRING_VAL:
2168 case CDT::STRING_INT_VAL:
2169 case CDT::STRING_REAL_VAL:
2170 #ifdef _DEBUG
2171 fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
2172 HL_RST;
2173 #endif
2174 oVMArgStack.GetTopElement(0) = oVMArgStack.GetTopElement(0)[oRegs[iSrcReg].GetString()];
2175 break;
2176 default:
2177 #ifdef _DEBUG
2178 fprintf(stderr, "%cR (UNDEF)\n", CHAR_8(iSrcReg + 'A'));
2179 HL_RST;
2180 #endif
2181 oVMArgStack.GetTopElement(0) = CDT();
2182 break;
2183 }
2184 }
2185 // Illegal Opcode?
2186 else
2187 {
2188 UINT_32 iDataSize = 0;
2189 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2190 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2191 }
2192 }
2193 break;
2194 // XCHG
2195 case SYSCALL_OPCODE_LO(XCHG):
2196 {
2197 #ifdef _DEBUG
2198 HL_CODE(RED);
2199 fprintf(stderr, "0x%08X XCHG ", iIP);
2200 #endif
2201 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
2202 const UINT_32 iDstReg = SYSCALL_REG_DST(iOpCode);
2203
2204 if (iSrcReg == ARG_SRC_STACK)
2205 {
2206 #ifdef _DEBUG
2207 fprintf(stderr, "STACK[%d](`%s`), ", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetString().c_str());
2208 #endif
2209 CDT oTMP = oVMArgStack.GetTopElement(aCode[iIP].argument);
2210 if (iDstReg == ARG_DST_STACK)
2211 {
2212 CDT &oTopStack = oVMArgStack.GetTopElement(0);
2213 oVMArgStack.GetTopElement(aCode[iIP].argument) = oTopStack;
2214
2215 #ifdef _DEBUG
2216 fprintf(stderr, "TOP STACK[0] (`%s`)\n", oTopStack.GetString().c_str());
2217 HL_RST;
2218 #endif
2219 oTopStack = oTMP;
2220 }
2221 // Illegal Opcode?
2222 else
2223 {
2224 UINT_32 iDataSize = 0;
2225 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2226 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2227 }
2228 }
2229 // Illegal Opcode?
2230 else
2231 {
2232 UINT_32 iDataSize = 0;
2233 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2234 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2235 }
2236 }
2237 break;
2238 // DEFINED, check existence of operand
2239 case SYSCALL_OPCODE_LO(DEFINED):
2240 {
2241 #ifdef _DEBUG
2242 HL_CODE(GREEN);
2243 fprintf(stderr, "0x%08X DEFINED ", iIP);
2244 #endif
2245 const UINT_32 iSrcReg = SYSCALL_REG_SRC(iOpCode);
2246 if (iSrcReg == ARG_SRC_STACK)
2247 {
2248 #ifdef _DEBUG
2249 fprintf(stderr, "STACK[%d](%c)\n", aCode[iIP].argument, oVMArgStack.GetTopElement(aCode[iIP].argument).GetType() != CDT::UNDEF ? 't':'f');
2250 HL_RST;
2251 #endif
2252 // Defined
2253 if (oVMArgStack.GetTopElement(aCode[iIP].argument).GetType() != CDT::UNDEF) { iFlags = FL_EQ; }
2254 // Undefined
2255 else { iFlags = FL_NE; }
2256 }
2257 else if (iSrcReg <= ARG_SRC_LASTREG)
2258 {
2259 #ifdef _DEBUG
2260 fprintf(stderr, "%cR (`%s`)\n", CHAR_8(iSrcReg + 'A'), oRegs[iSrcReg].GetString().c_str());
2261 HL_RST;
2262 #endif
2263 // Defined
2264 if (oRegs[iSrcReg].GetType() != CDT::UNDEF) { iFlags = FL_EQ; }
2265 // Undefined
2266 else { iFlags = FL_NE; }
2267 }
2268 // Illegal Opcode?
2269 else
2270 {
2271 UINT_32 iDataSize = 0;
2272 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2273 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2274 }
2275 }
2276 break;
2277 // SAVEBP, save base pointer
2278 case SYSCALL_OPCODE_LO(SAVEBP):
2279 {
2280 #ifdef _DEBUG
2281 HL_CODE(GREEN);
2282 fprintf(stderr, "0x%08X SAVEBP", iIP);
2283 if (aCode[iIP].argument > 0) {
2284 fprintf(stderr, " [-%d]\n", aCode[iIP].argument);
2285 } else {
2286 fprintf(stderr, "\n");
2287 }
2288
2289 #endif
2290 oVMArgStack.SaveBasePointer(aCode[iIP].argument);
2291 }
2292 break;
2293 // RESTBP, restore base pointer
2294 case SYSCALL_OPCODE_LO(RESTBP):
2295 {
2296 #ifdef _DEBUG
2297 HL_CODE(GREEN);
2298 fprintf(stderr, "0x%08X RESTBP\n", iIP);
2299 #endif
2300 oVMArgStack.RestoreBasePointer();
2301 }
2302 break;
2303 // Illegal Opcode?
2304 default:
2305 {
2306 UINT_32 iDataSize = 0;
2307 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2308 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2309 }
2310 }
2311 }
2312 ++iIP;
2313 break;
2314
2315 // HLT
2316 case 0xFF: // Halt
2317 {
2318 switch(iOpCodeLo)
2319 {
2320 // HLT
2321 case SYSCALL_OPCODE_LO(HLT):
2322 #ifdef _DEBUG
2323 HL_CODE(RED);
2324 fprintf(stderr, "0x%08X HLT\n", iIP);
2325 HL_RST;
2326 #endif
2327 return 0;
2328 // BRK
2329 case SYSCALL_OPCODE_LO(BRK):
2330 #ifdef _DEBUG
2331 HL_CODE(RED);
2332 fprintf(stderr, "0x%08X BRK\n", iIP);
2333 HL_RST;
2334 #endif
2335 if (iDebugLevel > 0) { return 0; }
2336 ++iIP;
2337 break;
2338 // NOP
2339 case SYSCALL_OPCODE_LO(NOP):
2340 #ifdef _DEBUG
2341 HL_CODE(RED);
2342 fprintf(stderr, "0x%08X NOP\n", iIP);
2343 HL_RST;
2344 #endif
2345 ++iIP; // Do nothing
2346 break;
2347 // Illegal Opcode?
2348 default:
2349 {
2350 UINT_32 iDataSize = 0;
2351 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2352 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2353 }
2354 }
2355 }
2356 break;
2357
2358 // Illegal Opcode?
2359 default:
2360 {
2361 UINT_32 iDataSize = 0;
2362 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2363 throw IllegalOpcode(iIP, iOpCode, aCode[iIP].reserved, szTMP);
2364 }
2365 } // switch(SYSCALL_OPCODE_HI(iOpCode))
2366 ++iExecutedSteps;
2367 } // while (iIP < iCodeLength)
2368 }
2369 catch (StackOverflow & e)
2370 {
2371 // Avoid MS VC warning "unised variable"; using paragma is not effective solution
2372 UINT_32 iTMP = e.GetIP() * 0;
2373
2374 UINT_32 iDataSize = 0;
2375 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2376
2377 throw StackOverflow(iTMP + iIP, aCode[iIP].reserved, szTMP);
2378 }
2379 catch (StackUnderflow &e)
2380 {
2381 // Avoid MS VC warning "unised variable"; using paragma is not effective solution
2382 UINT_32 iTMP = e.GetIP() * 0;
2383
2384 UINT_32 iDataSize = 0;
2385 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(aCode[iIP].reserved).GetDescrId(), iDataSize);
2386
2387 throw StackUnderflow(iTMP + iIP, aCode[iIP].reserved, szTMP);
2388 }
2389
2390 return 0;
2391 }
2392
2393 //
2394 // Reset virtual machine state
2395 //
Reset()2396 INT_32 VM::Reset()
2397 {
2398 AR = CDT();
2399 BR = CDT();
2400 CR = CDT();
2401 DR = CDT();
2402 ER = CDT();
2403 FR = CDT();
2404 GR = CDT();
2405 HR = CDT();
2406
2407 iFlags = 0;
2408
2409 oVMArgStack.Reset();
2410 oVMCodeStack.Reset();
2411
2412 return 0;
2413 }
2414
2415 //
2416 //
2417 //
CheckStackOnlyRegs(const UINT_32 iSrcReg,const UINT_32 iDstReg,const VMMemoryCore * pMemoryCore,const UINT_32 iIP)2418 void VM::CheckStackOnlyRegs(const UINT_32 iSrcReg, const UINT_32 iDstReg, const VMMemoryCore * pMemoryCore, const UINT_32 iIP)
2419 {
2420 if (iSrcReg != ARG_SRC_STACK || iDstReg != ARG_DST_STACK)
2421 {
2422 UINT_32 iDataSize = 0;
2423 CCHAR_P szTMP = pMemoryCore -> static_text.GetData(VMDebugInfo(pMemoryCore -> instructions[iIP].reserved).GetDescrId(), iDataSize);
2424 throw IllegalOpcode(iIP, pMemoryCore -> instructions[iIP].instruction, pMemoryCore -> instructions[iIP].reserved, szTMP);
2425 }
2426 }
2427
2428 //
2429 // A destructor
2430 //
~VM()2431 VM::~VM() throw()
2432 {
2433 if (aCallTranslationMap != 0) { delete [] aCallTranslationMap; }
2434
2435 }
2436
2437 } // namespace CTPP
2438 // End.
2439