1 /******************************************************************************
2 *
3 * Copyright (C) 2006, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: vmrun 26.12.06 0.0.A.
11 *
12 * Author: Alexey Krivonogov ( gentee )
13 * Contributors: santy
14 *
15 * Summary:
16 *
17 ******************************************************************************/
18
19 #include "vmtype.h"
20 #include "vmload.h"
21 #include "../common/collection.h"
22 #include "../genteeapi/gentee.h"
23 //#include "../bytecode/bytecode.h"
24
25 //--------------------------------------------------------------------------
26
27 void STDCALL pseudo_i( pstackpos curpos )
28 {
29 uint cmd = *curpos->cmd;
30 pint pop1 = curpos->top - 1;
31 pint pop2 = curpos->top - 2;
32 int val1 = *pop1;
33 int val2 = *pop2;
34
35 switch ( cmd )
36 {
37 case CMulII: *pop2 *= val1; break; // Replaced with CMulUIUI
38 case CDivII: *pop2 /= val1; break;
39 case CModII: *pop2 %= val1; break;
40 case CLeftII: *pop2 <<= val1; break; // Replaced with CLeftUIUI
41 case CRightII: *pop2 >>= val1; break;
42 case CSignI: *pop1 = -val1; break;
43 case CLessII: *pop2 = val2 < val1 ? 1 : 0; break;
44 case CGreaterII: *pop2 = val2 > val1 ? 1 : 0; break;
45 case CMulI: *( pint )val2 *= val1; goto seti; // Replaced with CMulUI
46 case CDivI: *( pint )val2 /= val1; goto seti;
47 case CModI: *( pint )val2 %= val1; goto seti;
48 case CLeftI: *( pint )val2 <<= val1; goto seti; // Replaced with CLeftUI
49 case CRightI: *( pint )val2 >>= val1; goto seti;
50 case CMulB: *( pchar )val2 *= val1; goto setb;
51 case CDivB: *( pchar )val2 /= val1; goto setb;
52 case CModB: *( pchar )val2 %= val1; goto setb;
53 case CLeftB: *( pchar )val2 <<= val1; goto setb;
54 case CRightB: *( pchar )val2 >>= val1; goto setb;
55 case CMulS: *( pshort )val2 *= val1; goto sets;
56 case CDivS: *( pshort )val2 /= val1; goto sets;
57 case CModS: *( pshort )val2 %= val1; goto sets;
58 case CLeftS: *( pshort )val2 <<= val1; goto sets;
59 case CRightS: *( pshort )val2 >>= val1; goto sets;
60 case Cd2f: *( float* )pop2 = (float)*( double * )pop2; break;
61 case Cd2i: *( int* )pop2 = (int)*( double * )pop2; break;
62 case Cd2l: *( long64* )pop2 = ( long64 )*( double * )pop2; break;
63 case Cf2d: *( double* )pop1 = ( double )*( float * )pop1; break;
64 case Cf2i: *( int* )pop1 = ( int )*( float * )pop1; break;
65 case Cf2l: *( long64* )pop1 = ( long64 )*( float * )pop1; break;
66 case Ci2d: *( double* )pop1 = ( double )*( int * )pop1; break;
67 case Ci2f: *( float* )pop1 = (float)*( int * )pop1; break;
68 case Ci2l: *( long64* )pop1 = ( long64 )*( int * )pop1; break;
69 case Cl2d: *( double* )pop2 = ( double )*( long64 * )pop2; break;
70 case Cl2f: *( float* )pop2 = (float)*( long64 * )pop2; break;
71 case Cl2i: *( int* )pop2 = ( int )*( long64 * )pop2; break;
72 case Cui2d: *( double* )pop1 = ( double )*( uint * )pop1; break;
73 case Cui2f: *( float* )pop1 = (float)*( uint * )pop1; break;
74 case Cui2l: *( long64* )pop1 = ( long64 )*( uint * )pop1; break;
75 }
76 return;
77 seti:
78 *pop2 = *( pint )val2;
79 return;
80 setb:
81 *pop2 = *( pchar )val2;
82 return;
83 sets:
84 *pop2 = *( pshort )val2;
85 }
86
87 //--------------------------------------------------------------------------
88
89 void STDCALL pseudo_ul( pstackpos curpos )
90 {
91 uint cmd = *curpos->cmd;
92 pulong64 pop1 = ( pulong64 )curpos->top - 1;
93 pulong64 pop2 = ( pulong64 )curpos->top - 2;
94 ulong64 val1 = *pop1;
95 ulong64 val2 = *pop2;
96
97 switch ( cmd )
98 {
99 case CAddULUL: *pop2 += val1; break;
100 case CSubULUL: *pop2 -= val1; break;
101 case CMulULUL: *pop2 *= val1; break;
102 case CDivULUL: *pop2 /= val1; break;
103 case CModULUL: *pop2 %= val1; break;
104 case CAndULUL: *pop2 &= val1; break;
105 case COrULUL: *pop2 |= val1; break;
106 case CXorULUL: *pop2 ^= val1; break;
107 case CLeftULUL: *pop2 <<= val1; break;
108 case CRightULUL: *pop2 >>= val1; break;
109 case CLessULUL: *( puint )pop2 = val2 < val1 ? 1 : 0; break;
110 case CGreaterULUL: *( puint )pop2 = val2 > val1 ? 1 : 0; break;
111 case CEqULUL: *( puint )pop2 = val1 == val2 ? 1 : 0; break;
112 case CNotUL: *pop1 = ~val1; break;
113 }
114 }
115
116 //--------------------------------------------------------------------------
117
118 void STDCALL pseudo_pul( pstackpos curpos )
119 {
120 pulong64 pop1 = ( pulong64 )curpos->top - 1;
121 pulong64 pul = ( pulong64 )*( curpos->top - 1 );
122 puint pop2 = curpos->top - 3;
123 ulong64 val1 = *pop1;
124 uint val2 = *pop2;
125
126 switch ( *curpos->cmd )
127 {
128 case CIncLeftUL: *( pulong64 )( curpos->top - 1 ) = ++( *pul ); return;
129 case CIncRightUL: *( pulong64 )( curpos->top - 1 ) = ( *pul )++; return;
130 case CDecLeftUL: *( pulong64 )( curpos->top - 1 ) = --( *pul ); return;
131 case CDecRightUL: *( pulong64 )( curpos->top - 1 ) = ( *pul )--; return;
132 case CAddUL: *( pulong64 )val2 += val1; break;
133 case CSubUL: *( pulong64 )val2 -= val1; break;
134 case CMulUL: *( pulong64 )val2 *= val1; break;
135 case CDivUL: *( pulong64 )val2 /= val1; break;
136 case CModUL: *( pulong64 )val2 %= val1; break;
137 case CAndUL: *( pulong64 )val2 &= val1; break;
138 case COrUL: *( pulong64 )val2 |= val1; break;
139 case CXorUL: *( pulong64 )val2 ^= val1; break;
140 case CLeftUL: *( pulong64 )val2 <<= val1; break;
141 case CRightUL: *( pulong64 )val2 >>= val1; break;
142 }
143 *( pulong64 )pop2 = *( pulong64 )val2;
144 }
145
146 //--------------------------------------------------------------------------
147
148 void STDCALL pseudo_l( pstackpos curpos )
149 {
150 plong64 pop1 = ( plong64 )curpos->top - 1;
151 plong64 pop2 = ( plong64 )curpos->top - 2;
152 long64 val1 = *pop1;
153 long64 val2 = *pop2;
154
155 switch ( *curpos->cmd )
156 {
157 case CMulLL: *pop2 *= val1; break;
158 case CDivLL: *pop2 /= val1; break;
159 case CModLL: *pop2 %= val1; break;
160 case CLeftLL: *pop2 <<= val1; break;
161 case CRightLL: *pop2 >>= val1; break;
162 case CSignL: *pop1 = -val1; break;
163 case CLessLL: *( puint )pop2 = val2 < val1 ? 1 : 0; break;
164 case CGreaterLL: *( puint )pop2 = val2 > val1 ? 1 : 0; break;
165 }
166 }
167
168 //--------------------------------------------------------------------------
169
170 void STDCALL pseudo_pl( pstackpos curpos )
171 {
172 plong64 pop1 = ( plong64 )curpos->top - 1;
173 puint pop2 = curpos->top - 3;
174 long64 val1 = *pop1;
175 uint val2 = *pop2;
176
177 switch ( *curpos->cmd )
178 {
179 case CMulL: *( plong64 )val2 *= val1; break;
180 case CDivL: *( plong64 )val2 /= val1; break;
181 case CModL: *( plong64 )val2 %= val1; break;
182 case CLeftL: *( plong64 )val2 <<= val1; break;
183 case CRightL: *( plong64 )val2 >>= val1; break;
184 }
185 *( plong64 )pop2 = *( plong64 )val2;
186 }
187
188 //--------------------------------------------------------------------------
189
190 void STDCALL pseudo_f( pstackpos curpos )
191 {
192 float* pop1 = ( float* )curpos->top - 1;
193 float* pop2 = ( float* )curpos->top - 2;
194 float val1 = *pop1;
195 float val2 = *pop2;
196
197 switch ( *curpos->cmd )
198 {
199 case CAddFF: *pop2 += val1; break;
200 case CSubFF: *pop2 -= val1; break;
201 case CMulFF: *pop2 *= val1; break;
202 case CDivFF: *pop2 /= val1; break;
203 case CSignF: *pop1 = -val1; break;
204 case CLessFF: *( puint )pop2 = val2 < val1 ? 1 : 0; break;
205 case CGreaterFF: *( puint )pop2 = val2 > val1 ? 1 : 0; break;
206 case CEqFF: *( puint )pop2 = val1 == val2 ? 1 : 0; break;
207 }
208 }
209
210 //--------------------------------------------------------------------------
211
212 void STDCALL pseudo_pf( pstackpos curpos )
213 {
214 float* pop1 = ( float* )( curpos->top - 1 );
215 float* pf = ( float* )*( curpos->top - 1 );
216 puint pop2 = curpos->top - 2;
217 float val1 = *pop1;
218 uint val2 = *pop2;
219
220 switch ( *curpos->cmd )
221 {
222 case CIncLeftF: *pop1 = ++(*pf); return;
223 case CIncRightF: *pop1 = (*pf)++ ; return;
224 case CDecLeftF: *pop1 = --(*pf); return;
225 case CDecRightF: *pop1 = (*pf)--; return;
226 case CAddF: *( float* )val2 += val1; break;
227 case CSubF: *( float* )val2 -= val1; break;
228 case CMulF: *( float* )val2 *= val1; break;
229 case CDivF: *( float* )val2 /= val1; break;
230 }
231 *( float* )pop2 = *( float* )val2;
232 }
233
234 //--------------------------------------------------------------------------
235
236 void STDCALL pseudo_d( pstackpos curpos )
237 {
238 double* pop1 = ( double* )curpos->top - 1;
239 double* pop2 = ( double* )curpos->top - 2;
240 double val1 = *pop1;
241 double val2 = *pop2;
242
243 switch ( *curpos->cmd )
244 {
245 case CAddDD: *pop2 += val1; break;
246 case CSubDD: *pop2 -= val1; break;
247 case CMulDD: *pop2 *= val1; break;
248 case CDivDD: *pop2 /= val1; break;
249 case CSignD: *pop1 = -val1; break;
250 case CLessDD: *( puint )pop2 = val2 < val1 ? 1 : 0; break;
251 case CGreaterDD: *( puint )pop2 = val2 > val1 ? 1 : 0; break;
252 case CEqDD: *( puint )pop2 = val1 == val2 ? 1 : 0; break;
253 }
254 }
255
256 //--------------------------------------------------------------------------
257
258 void STDCALL pseudo_pd( pstackpos curpos )
259 {
260 double* pop1 = ( double* )curpos->top - 1;
261 double* pd = ( double* )*( curpos->top - 1 );
262 puint pop2 = curpos->top - 3;
263 double val1 = *pop1;
264 uint val2 = *pop2;
265
266 switch ( *curpos->cmd )
267 {
268 case CIncLeftD: *( double* )( curpos->top - 1 ) = ++( *pd ); return;
269 case CIncRightD: *( double* )( curpos->top - 1 ) = ( *pd )++; return;
270 case CDecLeftD: *( double* )( curpos->top - 1 ) = --( *pd ); return;
271 case CDecRightD: *( double* )( curpos->top - 1 ) = ( *pd )--; return;
272 case CAddD: *( double* )val2 += val1; break;
273 case CSubD: *( double* )val2 -= val1; break;
274 case CMulD: *( double* )val2 *= val1; break;
275 case CDivD: *( double* )val2 /= val1; break;
276 }
277 *( double* )pop2 = *( double* )val2;
278 }
279
280 //--------------------------------------------------------------------------
281
282 void STDCALL pseudo_ui( pstackpos curpos )
283 {
284 puint pop1 = curpos->top - 1;
285 puint pop2 = curpos->top - 2;
286 uint val1 = *pop1;
287 uint val2 = *pop2;
288
289 switch ( *curpos->cmd )
290 {
291 case CIncLeftUB: *pop1 = ++( *( pubyte )val1 ); break;
292 case CIncRightUB: *pop1 = ( *( pubyte )val1 )++; break;
293 case CDecLeftUB: *pop1 = --( *( pubyte )val1 ); break;
294 case CDecRightUB: *pop1 = ( *( pubyte )val1 )--; break;
295 case CAddUB: *( pubyte )val2 += ( ubyte )val1; goto setub;
296 case CSubUB: *( pubyte )val2 -= ( ubyte )val1; goto setub;
297 case CMulUB: *( pubyte )val2 *= ( ubyte )val1; goto setub;
298 case CDivUB: *( pubyte )val2 /= ( ubyte )val1; goto setub;
299 case CModUB: *( pubyte )val2 %= ( ubyte )val1; goto setub;
300 case CAndUB: *( pubyte )val2 &= ( ubyte )val1; goto setub;
301 case COrUB: *( pubyte )val2 |= ( ubyte )val1; goto setub;
302 case CXorUB: *( pubyte )val2 ^= ( ubyte )val1; goto setub;
303 case CLeftUB: *( pubyte )val2 <<= ( ubyte )val1; goto setub;
304 case CRightUB: *( pubyte )val2 >>= ( ubyte )val1; goto setub;
305 case CIncLeftUS: *pop1 = ++( *( pushort )val1 ); break;
306 case CIncRightUS: *pop1 = ( *( pushort )val1 )++; break;
307 case CDecLeftUS: *pop1 = --( *( pushort )val1 ); break;
308 case CDecRightUS: *pop1 = ( *( pushort )val1 )--; break;
309 case CAddUS: *( pushort )val2 += ( ushort )val1; goto setus;
310 case CSubUS: *( pushort )val2 -= ( ushort )val1; goto setus;
311 case CMulUS: *( pushort )val2 *= ( ushort )val1; goto setus;
312 case CDivUS: *( pushort )val2 /= ( ushort )val1; goto setus;
313 case CModUS: *( pushort )val2 %= ( ushort )val1; goto setus;
314 case CAndUS: *( pushort )val2 &= ( ushort )val1; goto setus;
315 case COrUS: *( pushort )val2 |= ( ushort )val1; goto setus;
316 case CXorUS: *( pushort )val2 ^= ( ushort )val1; goto setus;
317 case CLeftUS: *( pushort )val2 <<= ( ushort )val1; goto setus;
318 case CRightUS: *( pushort )val2 >>= ( ushort )val1; goto setus;
319 }
320 return;
321 setub:
322 *pop2 = *( pubyte )val2;
323 return;
324 setus:
325 *pop2 = *( pushort )val2;
326 }
327
328 //--------------------------------------------------------------------------
329
330 void STDCALL pseudo_collectadd( pstackpos curpos )
331 {
332 uint num, i, count = *( curpos->cmd + 1 );
333 puint start = curpos->top - count;
334 pcollect pclt;
335 buf stack;
336 puint cur = curpos->top - 1;
337
338 pclt = ( pcollect )*( start - 1 );
339
340 buf_reserve( buf_init( &stack ), 128 );
341 i = count;
342 if ( count > 2 || ( *cur >> 24 ))
343 {
344 buf_clear( &pclt->data );
345 pclt->count = 0;
346 }
347 while ( i )
348 {
349 num = *cur >> 24;
350 if ( !num )
351 num = 1;
352 buf_appenduint( &stack, num );
353 buf_appenduint( &stack, *cur & 0xFFFFFF );
354 // print("Num=%i Cur = %i\n", num, *cur & 0xFFFFFF );
355 cur--;
356 i -= 1 + num;
357 }
358 while ( stack.use )
359 {
360 stack.use -= 8;
361 num = *( puint )( stack.data + stack.use );
362 while ( num )
363 {
364 i = collect_add( pclt, start, *( puint )( stack.data +
365 stack.use + 4 ) ) - start;
366 num -= i;
367 start += i;
368 }
369 // start++;
370 }
371 buf_delete( &stack );
372 curpos->top -= count;
373 }
374
375 /*-----------------------------------------------------------------------------
376 *
377 * ID: vm_run 26.12.06 0.0.A.
378 *
379 * Summary: Execute VM
380 *
381 * Params: vmp - virtual machine
382 id - the id of the func to run
383 params - The pointer to parameters
384 result - The pointer for getting the result value
385 *
386 -----------------------------------------------------------------------------*/
387
388 //puint ivm;
389
390 uint STDCALL vm_run( uint id, puint params, puint result, uint stacksize )
391 {
392 //register puint ivm;
393 uint cmd, i;
394 puint stack; // The main stack
395 // слева у стэка идет стэк значений, а справа навстречу ему стэк состояний
396 // вызовов
397 pstackpos curpos; // текущее состояние вызова
398 pstackpos endpos; // первоначальное состояние вызова
399 uint load[2]; // load id + return
400 uint uiret; // The count of return uints
401 pvmfunc curfunc; // текущий байт-код
402 // pvmobj obj;
403 pvoid exfunc;
404 uint val1, val2;
405 puint pop1, pop2;
406 puint top;
407 double d;
408 uint val, valhi;
409 pvartype pvar;
410 pvarset pset;
411 povmbcode bcode;
412 povmtype ptype;
413
414 stack = ( puint )mem_alloc( stacksize );
415
416 curpos = ( pstackpos )( ( pubyte )stack + stacksize - sizeof( stackpos ));
417 endpos = curpos;
418 curpos->start = stack;
419
420 load[ 0 ] = id;
421 load[ 1 ] = CReturn;
422
423 curpos->cmd = ( puint )&load;
424
425 if ( id >= _vm.count )
426 {
427 cmd = id;
428 goto error;
429 }
430 // pcmd = ( puint )arr_ptr( &vmp->objtbl, 0 );
431
432 curfunc = ( pvmfunc )PCMD( id );// pcmd + id );
433 uiret = curfunc->dwret;
434 curpos->top = curpos->start;
435
436 // Для text функции определяем стандартный вывод как 0
437 if ( curfunc->vmo.flag & GHBC_TEXT )
438 *curpos->top++ = 0;
439
440 // заносим в стэк параметры
441 if ( params )
442 {
443 mem_copyui( curpos->top, params, curfunc->parsize );
444 curpos->top += curfunc->parsize;
445 }
446 curpos->clmark = curpos->top;
447 // print("Func=%x %s id=%i pars=%i Val=%x\n",
448 // curfunc, curfunc->vmobj.name, id, curfunc->dwpars, *curpos->start );
449 while ( 1 )
450 {
451 // Берем команду
452 if (( cmd = *curpos->cmd ) >= _vm.count )
453 goto error;
454 // if ( (uint)curpos->cmd & 3 || (uint)curpos->top & 3 )
455 // print("CMD=%x\n", cmd );
456 stackcmd:
457 // obj = *( pvmobj* )( pcmd + cmd );
458 curfunc = ( pvmfunc )PCMD( cmd );
459 switch ( curfunc->vmo.type )
460 {
461 case OVM_STACKCMD: goto stack;
462 case OVM_PSEUDOCMD: goto pseudo;
463 case OVM_BYTECODE: goto bcode;
464 case OVM_EXFUNC: goto exfunc;
465 case OVM_TYPE: goto type;
466 }
467 goto error;
468 //---------------- Stack commands --------------------------------------
469 stack:
470 pop1 = curpos->top - 1;
471 val1 = *pop1;
472 pop2 = curpos->top - 2;
473 val2 = *pop2;
474 // print("%x 1=%i 2=%i\n", curpos->top, val1, val2 );
475 switch ( cmd )
476 {
477 case CNop: break;
478 case CGoto:
479 curpos->top = curpos->clmark;
480 case CGotonocls:
481 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 ) - 2;
482 break;
483 case CIfze:
484 curpos->top = curpos->clmark;
485 case CIfznocls:
486 if ( !val1 )
487 {
488 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 );
489 continue;
490 }
491 break;
492 case CIfnze:
493 curpos->top = curpos->clmark;
494 case CIfnznocls:
495 if ( val1 )
496 {
497 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 );
498 continue;
499 }
500 break;
501 case CDwload:
502 case CCmdload:
503 case CResload:
504 *curpos->top = *( curpos->cmd + 1 );
505 break;
506 case CQwload:
507 *( pulong64 )curpos->top = *( pulong64 )( curpos->cmd + 1 );
508 break;
509 case CDwsload:
510 val = *++curpos->cmd;
511 while ( val-- )
512 *curpos->top++ = *++curpos->cmd;
513 break;
514 case CVarload:
515 case CVarptrload:
516 i = *( curpos->cmd + 1 );
517 if ( i < curpos->func->parcount )
518 {
519 pvar = curpos->func->params + i;
520 top = curpos->start + pvar->off;
521 }
522 else
523 {
524 pvar = BCODE( curpos )->vars + ( i - curpos->func->parcount );
525 top = ( puint )*( curpos->start + curpos->func->parsize ) +
526 pvar->off;
527 }
528 ptype = ( povmtype )PCMD( pvar->type );
529 // pvari = curpos->func->parvar + *( curpos->cmd + 1 );
530 // top = curpos->start + pvari->off;
531 if ( cmd == CVarload && ptype->vmo.flag & GHTY_STACK )
532 {
533 *curpos->top = *top;
534 if ( ptype->stsize > 1 )
535 *++curpos->top = *++top;
536 }
537 else
538 {
539 if ( pvar->flag & VAR_PARAM && //i < curpos->func->parcount &&
540 !( ptype->vmo.flag & GHTY_STACK ))
541 top = ( puint )*top; // For parameters
542 *curpos->top = ( uint )top;
543 }
544 // print("VARLOAD = ptr = %x %x off = %i %i\n",
545 // top, *top, pvar->off, i );
546 break;
547 case CDatasize:
548 val = *++curpos->cmd;
549 *curpos->top++ = ( uint )++curpos->cmd;
550 // Увеличиваем на 3 : 2 вместо 1 : 0 из-за команда и размера
551 curpos->cmd += ( val >> 2 ) + ( val & 3 ? 1 : 0 );
552 *curpos->top++ = val;
553 continue;
554 case CLoglongtrue: *pop2 = ( val1 || val2 ? 1 : 0 ); break;
555 case CLognot: *pop1 = !val1; break;
556 case CLoglongnot: *pop2 = ( val1 || val2 ? 0 : 1 ); break;
557 case CDup: *curpos->top = *pop1; break;
558 case CDuplong:
559 *curpos->top = *pop2;
560 *( curpos->top + 1 ) = *pop1;
561 break;
562 case CTop: *curpos->top = ( uint )( curpos->top ); break;
563 case CPop: break;
564 case CGetUB: *pop1 = *( pubyte )val1; break;
565 case CGetB: *( int *)pop1 = ( int )*( pchar )val1; break;
566 case CGetUS: *pop1 = *( pushort )val1; break;
567 case CGetS: *( int *)pop1 = ( int )*( pshort )val1; break;
568 case CGetI: *pop1 = *( puint )val1; break;
569 case CGetL: *( pulong64 )pop1 = *( pulong64 )val1; break;
570 case CSetUB:
571 case CSetB:
572 *( pubyte )val2 = ( ubyte )val1; goto set;
573 // case CSetB: *( pchar )val2 = ( byte )val1; goto set;
574 case CSetUS:
575 case CSetS:
576 *( pushort )val2 = ( ushort )val1; goto set;
577 // case CSetS: *( pshort )val2 = ( short )val1; goto set;
578 case CSetI: *( puint )val2 = val1; goto set;
579 case CSetL:
580 *( pulong64 )*( curpos->top - 3 ) = *( pulong64 )pop2;
581 *( curpos->top - 3 ) = val2;
582 goto set;
583 case CAddUIUI: *pop2 += val1; break;
584 case CSubUIUI: *pop2 -= val1; break;
585 case CMulUIUI: *pop2 *= val1; break;
586 case CDivUIUI: *pop2 /= val1; break;
587 case CModUIUI: *pop2 %= val1; break;
588 case CAndUIUI: *pop2 &= val1; break;
589 case COrUIUI: *pop2 |= val1; break;
590 case CXorUIUI: *pop2 ^= val1; break;
591 case CLeftUIUI: *pop2 <<= val1; break;
592 case CRightUIUI: *pop2 >>= val1; break;
593 case CLessUIUI: *pop2 = val2 < val1 ? 1 : 0; break;
594 case CGreaterUIUI: *pop2 = val2 > val1 ? 1 : 0; break;
595 case CEqUIUI: *pop2 = val1 == val2 ? 1 : 0; break;
596 case CNotUI: *pop1 = ~val1; break;
597 case CIncLeftUI: *pop1 = ++( *( puint )val1 ); break;
598 case CIncRightUI: *pop1 = ( *( puint )val1 )++; break;
599 case CDecLeftUI: *pop1 = --( *( puint )val1 ); break;
600 case CDecRightUI: *pop1 = ( *( puint )val1 )--; break;
601 case CAddUI: *( puint )val2 += val1; goto setui;
602 case CSubUI: *( puint )val2 -= val1; goto setui;
603 case CMulUI: *( puint )val2 *= val1; goto setui;
604 case CDivUI: *( puint )val2 /= val1; goto setui;
605 case CModUI: *( puint )val2 %= val1; goto setui;
606 case CAndUI: *( puint )val2 &= val1; goto setui;
607 case COrUI: *( puint )val2 |= val1; goto setui;
608 case CXorUI: *( puint )val2 ^= val1; goto setui;
609 case CLeftUI: *( puint )val2 <<= val1; goto setui;
610 case CRightUI: *( puint )val2 >>= val1; goto setui;
611 case CVarsInit: type_setinit( curpos, *( curpos->cmd + 1 )); break;
612 case CGetText: *curpos->top = curpos->func->vmo.flag & GHBC_TEXT ?
613 *( curpos->start - 1 ) : 0; break;
614 case CSetText:
615 if ( curpos->func->vmo.flag & GHBC_TEXT &&
616 ( val2 = *( curpos->start - 1 )) )
617 str_add( ( pstr )val2, ( pstr )val1 );
618 else
619 str_output( ( pstr )val1 );
620 break;
621 case CPtrglobal:
622 *curpos->top = ( uint )(( povmglobal )
623 PCMD( *( curpos->cmd + 1 )))->pval;
624 // print("Global PTR %x %i\n", *curpos->top, *( puint )*curpos->top );
625 break;
626 case CSubcall:
627 // Меняем стэк
628 *curpos->top++ = ( uint )( curpos->cmd + 2 ); // указатель на команду после выхода
629 *curpos->top++ = ( uint )curpos->clmark; // текущее значение clmark
630 *curpos->top++ = 0; // Количество возвращаемых dword
631 *curpos->top++ = 0; // Количество полученных dword в качестве параметров
632 curpos->clmark = curpos->top; // Новое значение clmark
633 // Указатель на первую команду подфункции
634 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 );
635 continue;
636 case CSubret:
637 *( curpos->clmark - 2 ) = *( curpos->cmd + 1 );
638 break;
639 case CSubpar:
640 pset = BCODE( curpos )->sets + *( curpos->cmd + 1 );
641 // копируем значения переменных из стэка
642 pvar = BCODE( curpos )->vars + pset->first;
643 top = ( puint )*( curpos->start + curpos->func->parsize ) + pvar->off;
644
645 // top = curpos->start + ( curpos->func->varb + *++curpos->cmd)->firstoff;
646 // curpos->cmd++;
647 // print("Top=%i %i\n", *top, *( top + 1 ));
648 mem_copyui( top, curpos->clmark - 4 - pset->size, pset->size );
649 *( curpos->clmark - 1 ) = pset->size;
650 break;
651 case CSubreturn:
652 // Выход из подфункции
653 top = curpos->clmark - 4; // Указатель на старый top
654 // Восстанавливаем команду
655 curpos->cmd = ( puint )*top;
656 curpos->clmark = ( puint )*( top + 1 );
657 i = *( top + 2 );
658 // записываем возвращаемое значение
659 if ( i )
660 mem_copyui( top - *( top + 3 ), curpos->top - i, i );
661 // Устанавливаем стэк
662 curpos->top = top + i - *( top + 3 );
663 continue;
664 case CCmdcall:
665 // Берем из стэка код команды
666 top = curpos->top - *++curpos->cmd - 1;
667 cmd = *top;
668 // Сдвигаем параметры вызова в стэке
669 mem_copyui( top, top + 1, *curpos->cmd );
670 // сразу устанавливаем указатель на следующую команду
671 curpos->top--;
672 goto stackcmd;
673 case CCallstd:
674 val1 = *++curpos->cmd; // Флаги вызова
675 val2 = *++curpos->cmd; // Размер параметров
676 top = curpos->top;
677 for ( i = 0; i < val2; i++ )
678 {
679 val = *--top;
680 #ifdef LINUX
681 __asm__ ("push %0"::"d"(val));
682 #else
683 #if defined ( __GNUC__) || defined (__TINYC__)
684 __asm__ ("push %0"::"d"(val));
685 #else
686 _asm {
687 push val
688 }
689 #endif
690 #endif
691 }
692 exfunc = ( pvoid )*--top;
693 #ifdef LINUX
694 __asm__ ("call *%0"::"m"(exfunc));
695 __asm__ ("mov %%eax,%0":"m="(val));
696 __asm__ ("mov %%edx,%0":"m="(valhi));
697 #else
698 #if defined (__GNUC__)
699
700 __asm__ ("call *%0"::"m"(exfunc));
701 __asm__ ("mov %%eax,%0":"m="(val));
702 __asm__ ("mov %%edx,%0":"m="(valhi));
703
704 #elif defined (__TINYC__)
705 __asm__ ("call *%0"::"m"(exfunc));
706 __asm__ ("mov %%eax,%0":"m"(val));
707 __asm__ ("mov %%edx,%0":"m"(valhi));
708 #else
709 _asm {
710 call exfunc
711 mov val,eax
712 mov valhi,edx
713 }
714 #endif
715 #endif
716
717 #ifdef LINUX
718 #else
719 if ( val1 )// & GHEX_CDECL )
720 #endif
721 {
722 i = val2 << 2;
723 #ifdef LINUX
724 __asm__ ("add %0, %%esp"::"m"(i));
725 #else
726 #if defined ( __GNUC__) || defined (__TINYC__)
727 __asm__ ("add %0, %%esp"::"m"(i));
728 #else
729 _asm {
730 add esp, i
731 }
732 #endif
733 #endif
734 }
735 // if ( (( psovmfunc )curfunc)->dwret )
736 *top++ = val;
737 curpos->top = top;
738 curpos->cmd++;
739 continue;
740 case CReturn:
741 if ( curpos == endpos ) // Все выполнили
742 goto end;
743 // !!! Insert exception here
744 /* if ( vm->lastexcept->start == curpos->start )
745 {
746 vm->lastexcept--;
747 }*/
748 if ( _gentee.debug )
749 _gentee.debug( curpos );
750
751 // Free all variables
752 bcode = BCODE( curpos );
753
754 if ( bcode->setcount )
755 {
756 for ( i = 0; i < bcode->setcount; i++ )
757 type_setdelete( curpos, i );
758 // Освобождаем память под структуры
759 // ??? if ( *( curpos->start + pbcode->dwsize - 1 ))
760 if ( bcode->varsize > VAR_SIZE )
761 mem_free( ( pvoid )*( curpos->start + curpos->func->parsize ));
762 }
763 // Возвращаемся в предыдущее состояние
764 // если функция возвращает значение, то сохраняем необходимое
765 // количество верхних элементов
766 if ( curpos->uiret )
767 {
768 mem_copyui( ( curpos + 1 )->top, curpos->top - curpos->uiret,
769 curpos->uiret );
770 ( curpos + 1 )->top += curpos->uiret;
771 }
772 curpos++;
773 /* if ( exceptfunc )
774 {
775 curpos->cmd = curpos->func->finally;
776 *curpos->top++ = 0;
777 *curpos->top++ = 0;
778 if ( curpos->start == exceptfunc )
779 exceptfunc = 0;
780 continue;
781 }*/
782 // cmdshift for CReturn == 1 - shift the calling command
783 break;
784 case CAsm:
785 #ifdef _ASM
786 val1 = (uint)(curpos->cmd + 2);
787 val2 = (uint)curpos->start;
788 pop2 = ( puint )*( curpos->start + curpos->func->parsize );
789 //print( "ASM0 %x %x\n", curpos->top, curpos->cmd );
790 __asm {
791 //pushad
792 push edi
793 push esi
794 push ebp //Сохранение машинной базы беременных
795 push ebx
796 pushf
797 mov ecx, curpos
798
799 mov edi, pop2 //Переменные
800 mov esi, pop1 //Новый указатель стэка
801 mov eax, val1 //Адрес блока машинных кодов
802 mov ebp, val2 //Адрес блока параметров
803
804 std
805 call eax
806 popf
807 //cld
808 pop ebx
809 pop ebp //Восстановление машинной базы переменных
810 //mov pop1, esi//ebx
811
812 add esi, 4
813 mov dword ptr [ecx+0x08], esi
814
815 mov dword ptr [ecx+0x04], eax
816
817 pop esi
818 pop edi
819 }
820 curpos->cmd = (uint)curpos->cmd + ( puint )curpos->func->func;
821 //print( "ASM1 %x %x %x\n", curpos->top, curpos->cmd, curfunc->func );
822 continue;
823 #else
824 break;
825 #endif // _ASM
826 #ifndef RUNTIME
827 case CDbgTrace:
828 case CDbgFunc:
829 if ( _gentee.debug )
830 {
831 curpos->nline = ( cmd == CDbgFunc ? *( puint )val2 : val1 );
832 _gentee.debug( curpos );
833 }
834 break;
835 #endif
836 }
837 goto shift;
838 pseudo: // Pseudo stack commands
839 (( stackfunc )curfunc->func)( curpos );
840 goto shift;
841 set:
842 *pop2 = val1; goto shift;
843 setui:
844 *pop2 = *( puint )val2; goto shift;
845
846 shift:
847 curpos->top += (( povmstack )curfunc)->topshift;
848 curpos->cmd += (( povmstack )curfunc)->cmdshift;
849 continue;
850 //---------------- Bytecode command --------------------------------------
851 bcode:
852 // Проверка переполнения стэка
853 if ( curpos->top + 128 > ( puint )curpos )
854 msg( MFullstack | MSG_DVAL, stacksize );
855 // Сохраняем текущее состояние увеличив стэк
856 curpos->top -= curfunc->parsize;
857 curpos--;
858 curpos->cmd = curfunc->func;
859 curpos->start = ( curpos + 1 )->top;
860
861 curpos->top = curpos->start + curfunc->parsize + 1 +
862 (( povmbcode )curfunc)->setcount;
863 if ( (( povmbcode )curfunc)->varsize > VAR_SIZE )
864 {
865 // All variable are in the extern memory
866 ( puint )*( curpos->start + curfunc->parsize ) = mem_alloc( (( povmbcode )curfunc)->varsize << 2 );
867 }
868 else
869 { // All variables are in the stack
870 ( puint )*( curpos->start + curfunc->parsize ) = curpos->top;
871 curpos->top += (( povmbcode )curfunc)->varsize;
872 }
873 curpos->clmark = curpos->top;
874 curpos->uiret = curfunc->dwret;
875 curpos->func = curfunc;
876 // Зануляем признак отведения памяти для локальных структур
877 // *( curpos->top - 1 ) = 0;
878
879 // Зануляем признаки инициализации блоков переменных
880 if ( (( povmbcode )curfunc)->setcount )
881 mem_zeroui( curpos->start + curfunc->parsize + 1,
882 (( povmbcode )curfunc)->setcount );
883 if ( !curpos->cmd )
884 msg( MUndefcmd | MSG_VALSTRERR, curfunc->vmo.name, cmd );
885 continue;
886
887 //---------------- Exfunc commands --------------------------------------
888 exfunc:
889 exfunc = curfunc->func;
890 if ( !exfunc )
891 msg( MUndefcmd | MSG_VALSTRERR, curfunc->vmo.name, cmd );
892 top = curpos->top;
893
894 #ifdef LINUX
895 if ( curfunc->vmobj.flag & GHEX_SYSCALL )
896 {
897 curpos->top = syscall( curfunc, top );
898 goto next;
899 }
900 #endif
901 // print("PAR=%i parsize=%i ret=%i %s\n", curfunc->parcount,
902 // curfunc->parsize, curfunc->dwret, curfunc->vmo.name );
903 for ( i = 0; i < curfunc->parsize; i++ )
904 {
905 val = *--top;
906 #ifdef LINUX
907 __asm__ ("push %0"::"d"(val));
908 #else
909 #if defined (__GNUC__) || defined (__TINYC__)
910 __asm__ ("push %0"::"d"(val));
911 #else
912 _asm { push val }
913 #endif
914 #endif
915 }
916 if ( curfunc->vmo.flag & GHEX_FLOAT )
917 {
918 if ( curfunc->dwret == 1 )
919 {
920 #ifdef LINUX
921 __asm__ ("call *%0"::"m"(exfunc));
922 __asm__ ("fstp %%st":"=m"(val));
923 #else
924 #if defined ( __GNUC__) || defined (__TINYC__)
925 __asm__ ("call *%0"::"m"(exfunc));
926 __asm__ ("fstp %%st":"=m"(val));
927
928 #else
929 _asm {
930 call exfunc
931 fstp dword ptr [val]
932 }
933 #endif
934 #endif
935 }
936 else
937 {
938 #ifdef LINUX
939 __asm__ ("call *%0"::"m"(exfunc));
940 __asm__ ("fstp %%st":"=t"(d):"0"(d));
941 //__asm__ ("fstp %0":"=r"(&d));
942 #else
943 #if defined (__GNUC__)
944 __asm__ ("call *%0"::"m"(exfunc));
945 __asm__ ("fstp %%st":"=t"(d):"0"(d));
946 //__asm__ ("fstp %0":"=r"(&d));
947 #elif defined (__TINYC__)
948 __asm__ ("call *%0"::"m"(exfunc));
949 __asm__ ("fstp %%st":"m"(d):"0"(d));
950 #else
951 _asm {
952 call exfunc
953 // fstp qword ptr [d]
954 fstp d
955 }
956 #endif
957 #endif
958 val = *(uint*)&d;
959 valhi = *((uint*)&d + 1 );
960 }
961 }
962 else
963 {
964 #ifdef LINUX
965 //print( "\07exfunc=%x val=%x\n", exfunc, val );
966 __asm__ ("call *%0"::"m"(exfunc));
967 __asm__ ("mov %%eax,%0":"m="(val));
968 __asm__ ("mov %%edx,%0":"m="(valhi));
969 #else
970 #if defined (__GNUC__)
971 __asm__ ("call *%0"::"m"(exfunc));
972 __asm__ ("mov %%eax,%0":"m="(val));
973 __asm__ ("mov %%edx,%0":"m="(valhi));
974 #elif defined (__TINYC__)
975 __asm__ ("call *%0"::"m"(exfunc));
976 __asm__ ("mov %%eax,%0":"m"(val));
977 __asm__ ("mov %%edx,%0":"m"(valhi));
978 #else
979 _asm {
980 call exfunc
981 mov val,eax
982 mov valhi,edx
983 }
984 #endif
985 #endif
986 }
987 #ifdef LINUX
988 #else
989 if ( curfunc->vmo.flag & GHEX_CDECL )
990 #endif
991 {
992 i = curfunc->parsize << 2;
993 #ifdef LINUX
994 __asm__ ("add %0, %%esp"::"m"(i));
995 #else
996 #if defined (__GNUC__) || defined (__TINYC__)
997 __asm__ ("add %0, %%esp"::"m"(i));
998 #else
999 _asm { add esp, i }
1000 #endif
1001 #endif
1002 }
1003 if ( curfunc->dwret )
1004 *top++ = val;
1005 if ( curfunc->dwret == 2 )
1006 *top++ = valhi;
1007 curpos->top = top;
1008 goto next;
1009
1010 //---------------- Type command --------------------------------------
1011 type:
1012 *curpos->top++ = cmd;
1013 goto next;
1014
1015 //---------------- Getting next command ------------------------------
1016 next:
1017 curpos->cmd++;
1018 }
1019
1020 end:
1021 // Copy the result value
1022 if ( result )
1023 mem_copyui( result, curpos->top - uiret, uiret );
1024 // Free stack
1025 mem_free( stack );
1026
1027 return 1;
1028 error:
1029 msg( MUnkbcode | MSG_DVAL, cmd );
1030 return 0;
1031 }
1032
1033 //--------------------------------------------------------------------------
1034
1035 uint STDCALL vm_runone( uint id, uint first )
1036 {
1037 uint ret;
1038 // Изменяем размеры стэка для функций вызываемых из виртуальной машины
1039 // _vm.stacksize = 8192;
1040 vm_run( id, &first, &ret, 8192 );
1041 // _vm.stacksize = size;
1042 return ret;
1043 }
1044
1045 //--------------------------------------------------------------------------
1046
1047 uint STDCALL vm_runtwo( uint id, uint first, uint second )
1048 {
1049 uint ret;
1050 // uint size = _vm.stacksize;
1051 uint params[4];
1052
1053 // Изменяем размеры стэка для функций вызываемых из виртуальной машины
1054 // _vm.stacksize = 8192;
1055 params[0] = first;
1056 params[1] = second;
1057 vm_run( id, ( puint )¶ms, &ret, 8192 );
1058 // _vm.stacksize = size;
1059 return ret;
1060 }
1061
1062 /*-----------------------------------------------------------------------------
1063 ** Id: gentee_call F
1064 *
1065 * Summary: Call the function from the bytecode. The bytecode should be
1066 previously loaded with the $[gentee_load] or $[gentee_compile]
1067 functions.
1068 *
1069 * Params: id - The identifier of the called object. Can be obtained by /
1070 $[gentee_getid] function.
1071 result - Pointer to the memory space, to which the result will be /
1072 written. It can be the pointer to #b(uint), #b(long) or /
1073 #b(double).
1074 ... - Required parameters of the function.
1075 *
1076 * Return: #lng/retf#
1077 *
1078 -----------------------------------------------------------------------------*/
1079
1080 uint CDECLCALL gentee_call( uint id, puint result, ... )
1081 {
1082 uint ok = 0;
1083 pvmfunc curfunc;
1084 va_list argptr;
1085 uint i = 0;
1086 uint params[ 64 ];
1087 // uint size = _vm.stacksize;
1088
1089 // _vm.stacksize = 0x8000; // 32KB
1090 va_start( argptr, result );
1091
1092 curfunc = ( pvmfunc )PCMD( id );
1093 if ( curfunc->vmo.flag & GHRT_MAYCALL )
1094 {
1095 while ( i < curfunc->parsize )
1096 params[ i++ ] = va_arg( argptr, uint );
1097
1098 ok = vm_run( id, ( puint )¶ms, result, 0x8000 );
1099 }
1100 va_end( argptr );
1101 // _vm.stacksize = size;
1102
1103 return ok;
1104 }
1105
1106 uint STDCALL vm_calladdr( void )
1107 {
1108 return ( uint )&gentee_call;
1109 }
1110
1111 //-----------------------------------------------------------------------------