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;
38 case CDivII: *pop2 /= val1; break;
39 case CModII: *pop2 %= val1; break;
40 case CLeftII: *pop2 <<= val1; break;
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;
46 case CDivI: *( pint )val2 /= val1; goto seti;
47 case CModI: *( pint )val2 %= val1; goto seti;
48 case CLeftI: *( pint )val2 <<= val1; goto seti;
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
343 while ( i )
344 {
345 num = *cur >> 24;
346 buf_appenduint( &stack, num );
347 buf_appenduint( &stack, *cur & 0xFFFFFF );
348 // print("Num=%i Cur = %i\n", num, *cur & 0xFFFFFF );
349 cur--;
350 i -= 1 + num;
351 }
352 while ( stack.use )
353 {
354 stack.use -= 8;
355 num = *( puint )( stack.data + stack.use );
356 while ( num )
357 {
358 i = collect_add( pclt, start, *( puint )( stack.data +
359 stack.use + 4 ) ) - start;
360 num -= i;
361 start += i;
362 }
363 // start++;
364 }
365 buf_delete( &stack );
366 curpos->top -= count;
367 }
368
369 /*-----------------------------------------------------------------------------
370 *
371 * ID: vm_run 26.12.06 0.0.A.
372 *
373 * Summary: Execute VM
374 *
375 * Params: vmp - virtual machine
376 id - the id of the func to run
377 params - The pointer to parameters
378 result - The pointer for getting the result value
379 *
380 -----------------------------------------------------------------------------*/
381
382 //puint ivm;
383
384 uint STDCALL vm_run( uint id, puint params, puint result )
385 {
386 //register puint ivm;
387 uint cmd, i;
388 puint stack; // The main stack
389 // слева у стэка идет стэк значений, а справа навстречу ему стэк состояний
390 // вызовов
391 pstackpos curpos; // текущее состояние вызова
392 pstackpos endpos; // первоначальное состояние вызова
393 uint load[2]; // load id + return
394 uint uiret; // The count of return uints
395 pvmfunc curfunc; // текущий байт-код
396 // pvmobj obj;
397 pvoid exfunc;
398 uint val1, val2;
399 puint pop1, pop2;
400 puint top;
401 double d;
402 uint val, valhi;
403 pvartype pvar;
404 pvarset pset;
405 povmbcode bcode;
406 povmtype ptype;
407
408 stack = ( puint )mem_alloc( _vm.stacksize );
409
410 curpos = ( pstackpos )( ( pubyte )stack + _vm.stacksize - sizeof( stackpos ));
411 endpos = curpos;
412 curpos->start = stack;
413
414 load[ 0 ] = id;
415 load[ 1 ] = CReturn;
416
417 curpos->cmd = ( puint )&load;
418
419 if ( id >= _vm.count )
420 {
421 cmd = id;
422 goto error;
423 }
424 // pcmd = ( puint )arr_ptr( &vmp->objtbl, 0 );
425
426 curfunc = ( pvmfunc )PCMD( id );// pcmd + id );
427 uiret = curfunc->dwret;
428 curpos->top = curpos->start;
429
430 // Для text функции определяем стандартный вывод как 0
431 if ( curfunc->vmo.flag & GHBC_TEXT )
432 *curpos->top++ = 0;
433
434 // заносим в стэк параметры
435 if ( params )
436 {
437 mem_copyui( curpos->top, params, curfunc->parsize );
438 curpos->top += curfunc->parsize;
439 }
440 curpos->clmark = curpos->top;
441 // print("Func=%x %s id=%i pars=%i Val=%x\n",
442 // curfunc, curfunc->vmobj.name, id, curfunc->dwpars, *curpos->start );
443 while ( 1 )
444 {
445 // Берем команду
446 if (( cmd = *curpos->cmd ) >= _vm.count )
447 goto error;
448 // if ( (uint)curpos->cmd & 3 || (uint)curpos->top & 3 )
449 // print("CMD=%x\n", cmd );
450 stackcmd:
451 // obj = *( pvmobj* )( pcmd + cmd );
452 curfunc = ( pvmfunc )PCMD( cmd );
453 switch ( curfunc->vmo.type )
454 {
455 case OVM_STACKCMD: goto stack;
456 case OVM_PSEUDOCMD: goto pseudo;
457 case OVM_BYTECODE: goto bcode;
458 case OVM_EXFUNC: goto exfunc;
459 case OVM_TYPE: goto type;
460 }
461 goto error;
462 //---------------- Stack commands --------------------------------------
463 stack:
464 pop1 = curpos->top - 1;
465 val1 = *pop1;
466 pop2 = curpos->top - 2;
467 val2 = *pop2;
468 // print("%x 1=%i 2=%i\n", curpos->top, val1, val2 );
469 switch ( cmd )
470 {
471 case CNop: break;
472 case CGoto:
473 curpos->top = curpos->clmark;
474 case CGotonocls:
475 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 ) - 2;
476 break;
477 case CIfze:
478 curpos->top = curpos->clmark;
479 case CIfznocls:
480 if ( !val1 )
481 {
482 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 );
483 continue;
484 }
485 break;
486 case CIfnze:
487 curpos->top = curpos->clmark;
488 case CIfnznocls:
489 if ( val1 )
490 {
491 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 );
492 continue;
493 }
494 break;
495 case CDwload:
496 case CCmdload:
497 case CResload:
498 *curpos->top = *( curpos->cmd + 1 );
499 break;
500 case CQwload:
501 *( pulong64 )curpos->top = *( pulong64 )( curpos->cmd + 1 );
502 break;
503 case CDwsload:
504 val = *++curpos->cmd;
505 while ( val-- )
506 *curpos->top++ = *++curpos->cmd;
507 break;
508 case CVarload:
509 case CVarptrload:
510 i = *( curpos->cmd + 1 );
511 if ( i < curpos->func->parcount )
512 {
513 pvar = curpos->func->params + i;
514 top = curpos->start + pvar->off;
515 }
516 else
517 {
518 pvar = BCODE( curpos )->vars + ( i - curpos->func->parcount );
519 top = ( puint )*( curpos->start + curpos->func->parsize ) +
520 pvar->off;
521 }
522 ptype = ( povmtype )PCMD( pvar->type );
523 // pvari = curpos->func->parvar + *( curpos->cmd + 1 );
524 // top = curpos->start + pvari->off;
525 if ( cmd == CVarload && ptype->vmo.flag & GHTY_STACK )
526 {
527 *curpos->top = *top;
528 if ( ptype->stsize > 1 )
529 *++curpos->top = *++top;
530 }
531 else
532 {
533 if ( pvar->flag & VAR_PARAM && //i < curpos->func->parcount &&
534 !( ptype->vmo.flag & GHTY_STACK ))
535 top = ( puint )*top; // For parameters
536 *curpos->top = ( uint )top;
537 }
538 // print("VARLOAD = ptr = %x %x off = %i %i\n",
539 // top, *top, pvar->off, i );
540 break;
541 case CDatasize:
542 val = *++curpos->cmd;
543 *curpos->top++ = ( uint )++curpos->cmd;
544 // Увеличиваем на 3 : 2 вместо 1 : 0 из-за команда и размера
545 curpos->cmd += ( val >> 2 ) + ( val & 3 ? 1 : 0 );
546 *curpos->top++ = val;
547 continue;
548 case CLoglongtrue: *pop2 = ( val1 || val2 ? 1 : 0 ); break;
549 case CLognot: *pop1 = !val1; break;
550 case CLoglongnot: *pop2 = ( val1 || val2 ? 0 : 1 ); break;
551 case CDup: *curpos->top = *pop1; break;
552 case CDuplong:
553 *curpos->top = *pop2;
554 *( curpos->top + 1 ) = *pop1;
555 break;
556 case CTop: *curpos->top = ( uint )( curpos->top ); break;
557 case CPop: break;
558 case CGetUB: *pop1 = *( pubyte )val1; break;
559 case CGetB: *( int *)pop1 = ( int )*( pchar )val1; break;
560 case CGetUS: *pop1 = *( pushort )val1; break;
561 case CGetS: *( int *)pop1 = ( int )*( pshort )val1; break;
562 case CGetI: *pop1 = *( puint )val1; break;
563 case CGetL: *( pulong64 )pop1 = *( pulong64 )val1; break;
564 case CSetUB: *( pubyte )val2 = ( ubyte )val1; goto set;
565 case CSetB: *( pchar )val2 = ( byte )val1; goto set;
566 case CSetUS: *( pushort )val2 = ( ushort )val1; goto set;
567 case CSetS: *( pshort )val2 = ( short )val1; goto set;
568 case CSetI: *( puint )val2 = val1; goto set;
569 case CSetL:
570 *( pulong64 )*( curpos->top - 3 ) = *( pulong64 )pop2;
571 *( curpos->top - 3 ) = val2;
572 goto set;
573 case CAddUIUI: *pop2 += val1; break;
574 case CSubUIUI: *pop2 -= val1; break;
575 case CMulUIUI: *pop2 *= val1; break;
576 case CDivUIUI: *pop2 /= val1; break;
577 case CModUIUI: *pop2 %= val1; break;
578 case CAndUIUI: *pop2 &= val1; break;
579 case COrUIUI: *pop2 |= val1; break;
580 case CXorUIUI: *pop2 ^= val1; break;
581 case CLeftUIUI: *pop2 <<= val1; break;
582 case CRightUIUI: *pop2 >>= val1; break;
583 case CLessUIUI: *pop2 = val2 < val1 ? 1 : 0; break;
584 case CGreaterUIUI: *pop2 = val2 > val1 ? 1 : 0; break;
585 case CEqUIUI: *pop2 = val1 == val2 ? 1 : 0; break;
586 case CNotUI: *pop1 = ~val1; break;
587 case CIncLeftUI: *pop1 = ++( *( puint )val1 ); break;
588 case CIncRightUI: *pop1 = ( *( puint )val1 )++; break;
589 case CDecLeftUI: *pop1 = --( *( puint )val1 ); break;
590 case CDecRightUI: *pop1 = ( *( puint )val1 )--; break;
591 case CAddUI: *( puint )val2 += val1; goto setui;
592 case CSubUI: *( puint )val2 -= val1; goto setui;
593 case CMulUI: *( puint )val2 *= val1; goto setui;
594 case CDivUI: *( puint )val2 /= val1; goto setui;
595 case CModUI: *( puint )val2 %= val1; goto setui;
596 case CAndUI: *( puint )val2 &= val1; goto setui;
597 case COrUI: *( puint )val2 |= val1; goto setui;
598 case CXorUI: *( puint )val2 ^= val1; goto setui;
599 case CLeftUI: *( puint )val2 <<= val1; goto setui;
600 case CRightUI: *( puint )val2 >>= val1; goto setui;
601 case CVarsInit: type_setinit( curpos, *( curpos->cmd + 1 )); break;
602 case CGetText: *curpos->top = curpos->func->vmo.flag & GHBC_TEXT ?
603 *( curpos->start - 1 ) : 0; break;
604 case CSetText:
605 if ( curpos->func->vmo.flag & GHBC_TEXT &&
606 ( val2 = *( curpos->start - 1 )) )
607 str_add( ( pstr )val2, ( pstr )val1 );
608 else
609 str_output( ( pstr )val1 );
610 break;
611 case CPtrglobal:
612 *curpos->top = ( uint )(( povmglobal )
613 PCMD( *( curpos->cmd + 1 )))->pval;
614 // print("Global PTR %x %i\n", *curpos->top, *( puint )*curpos->top );
615 break;
616 case CSubcall:
617 // Меняем стэк
618 *curpos->top++ = ( uint )( curpos->cmd + 2 ); // указатель на команду после выхода
619 *curpos->top++ = ( uint )curpos->clmark; // текущее значение clmark
620 *curpos->top++ = 0; // Количество возвращаемых dword
621 *curpos->top++ = 0; // Количество полученных dword в качестве параметров
622 curpos->clmark = curpos->top; // Новое значение clmark
623 // Указатель на первую команду подфункции
624 curpos->cmd = ( puint )curpos->func->func + *( curpos->cmd + 1 );
625 continue;
626 case CSubret:
627 *( curpos->clmark - 2 ) = *( curpos->cmd + 1 );
628 break;
629 case CSubpar:
630 pset = BCODE( curpos )->sets + *( curpos->cmd + 1 );
631 // копируем значения переменных из стэка
632 pvar = BCODE( curpos )->vars + pset->first;
633 top = ( puint )*( curpos->start + curpos->func->parsize ) + pvar->off;
634
635 // top = curpos->start + ( curpos->func->varb + *++curpos->cmd)->firstoff;
636 // curpos->cmd++;
637 // print("Top=%i %i\n", *top, *( top + 1 ));
638 mem_copyui( top, curpos->clmark - 4 - pset->size, pset->size );
639 *( curpos->clmark - 1 ) = pset->size;
640 break;
641 case CSubreturn:
642 // Выход из подфункции
643 top = curpos->clmark - 4; // Указатель на старый top
644 // Восстанавливаем команду
645 curpos->cmd = ( puint )*top;
646 curpos->clmark = ( puint )*( top + 1 );
647 i = *( top + 2 );
648 // записываем возвращаемое значение
649 if ( i )
650 mem_copyui( top - *( top + 3 ), curpos->top - i, i );
651 // Устанавливаем стэк
652 curpos->top = top + i - *( top + 3 );
653 continue;
654 case CCmdcall:
655 // Берем из стэка код команды
656 top = curpos->top - *++curpos->cmd - 1;
657 cmd = *top;
658 // Сдвигаем параметры вызова в стэке
659 mem_copyui( top, top + 1, *curpos->cmd );
660 // сразу устанавливаем указатель на следующую команду
661 curpos->top--;
662 goto stackcmd;
663 case CCallstd:
664 val1 = *++curpos->cmd; // Флаги вызова
665 val2 = *++curpos->cmd; // Размер параметров
666 top = curpos->top;
667 for ( i = 0; i < val2; i++ )
668 {
669 val = *--top;
670 #ifdef LINUX
671 __asm__ ("push %0"::"d"(val));
672 #else
673 #if defined ( __GNUC__) || defined (__TINYC__)
674 __asm__ ("push %0"::"d"(val));
675 #else
676 _asm {
677 push val
678 }
679 #endif
680 #endif
681 }
682 exfunc = ( pvoid )*--top;
683 #ifdef LINUX
684 __asm__ ("call *%0"::"m"(exfunc));
685 __asm__ ("mov %%eax,%0":"m="(val));
686 __asm__ ("mov %%edx,%0":"m="(valhi));
687 #else
688 #if defined (__GNUC__)
689
690 __asm__ ("call *%0"::"m"(exfunc));
691 __asm__ ("mov %%eax,%0":"m="(val));
692 __asm__ ("mov %%edx,%0":"m="(valhi));
693
694 #elif defined (__TINYC__)
695 __asm__ ("call *%0"::"m"(exfunc));
696 __asm__ ("mov %%eax,%0":"m"(val));
697 __asm__ ("mov %%edx,%0":"m"(valhi));
698 #else
699 _asm {
700 call exfunc
701 mov val,eax
702 mov valhi,edx
703 }
704 #endif
705 #endif
706
707 #ifdef LINUX
708 #else
709 if ( val1 )// & GHEX_CDECL )
710 #endif
711 {
712 i = val2 << 2;
713 #ifdef LINUX
714 __asm__ ("add %0, %%esp"::"m"(i));
715 #else
716 #if defined ( __GNUC__) || defined (__TINYC__)
717 __asm__ ("add %0, %%esp"::"m"(i));
718 #else
719 _asm {
720 add esp, i
721 }
722 #endif
723 #endif
724 }
725 // if ( (( psovmfunc )curfunc)->dwret )
726 *top++ = val;
727 curpos->top = top;
728 break;
729 case CReturn:
730 if ( curpos == endpos ) // Все выполнили
731 goto end;
732 // !!! Insert exception here
733 /* if ( vm->lastexcept->start == curpos->start )
734 {
735 vm->lastexcept--;
736 }*/
737 if ( _gentee.debug )
738 _gentee.debug( curpos );
739
740 // Free all variables
741 bcode = BCODE( curpos );
742
743 if ( bcode->setcount )
744 {
745 for ( i = 0; i < bcode->setcount; i++ )
746 type_setdelete( curpos, i );
747 // Освобождаем память под структуры
748 // ??? if ( *( curpos->start + pbcode->dwsize - 1 ))
749 if ( bcode->varsize > VAR_SIZE )
750 mem_free( ( pvoid )*( curpos->start + curpos->func->parsize ));
751 }
752 // Возвращаемся в предыдущее состояние
753 // если функция возвращает значение, то сохраняем необходимое
754 // количество верхних элементов
755 if ( curpos->uiret )
756 {
757 mem_copyui( ( curpos + 1 )->top, curpos->top - curpos->uiret,
758 curpos->uiret );
759 ( curpos + 1 )->top += curpos->uiret;
760 }
761 curpos++;
762 /* if ( exceptfunc )
763 {
764 curpos->cmd = curpos->func->finally;
765 *curpos->top++ = 0;
766 *curpos->top++ = 0;
767 if ( curpos->start == exceptfunc )
768 exceptfunc = 0;
769 continue;
770 }*/
771 // cmdshift for CReturn == 1 - shift the calling command
772 break;
773 #ifndef RUNTIME
774 case CDbgTrace:
775 case CDbgFunc:
776 if ( _gentee.debug )
777 {
778 curpos->nline = ( cmd == CDbgFunc ? *( puint )val2 : val1 );
779 _gentee.debug( curpos );
780 }
781 break;
782 #endif
783 }
784 goto shift;
785 pseudo: // Pseudo stack commands
786 (( stackfunc )curfunc->func)( curpos );
787 goto shift;
788 set:
789 *pop2 = val1; goto shift;
790 setui:
791 *pop2 = *( puint )val2; goto shift;
792
793 shift:
794 curpos->top += (( povmstack )curfunc)->topshift;
795 curpos->cmd += (( povmstack )curfunc)->cmdshift;
796 continue;
797 //---------------- Bytecode command --------------------------------------
798 bcode:
799 // Проверка переполнения стэка
800 if ( curpos->top + 128 > ( puint )curpos )
801 msg( MFullstack | MSG_DVAL, _vm.stacksize );
802 // Сохраняем текущее состояние увеличив стэк
803 curpos->top -= curfunc->parsize;
804 curpos--;
805 curpos->cmd = curfunc->func;
806 curpos->start = ( curpos + 1 )->top;
807
808 curpos->top = curpos->start + curfunc->parsize + 1 +
809 (( povmbcode )curfunc)->setcount;
810 if ( (( povmbcode )curfunc)->varsize > VAR_SIZE )
811 {
812 // All variable ar in the extern memory
813 ( puint )*( curpos->start + curfunc->parsize ) = mem_alloc( (( povmbcode )curfunc)->varsize << 2 );
814 }
815 else
816 { // All variables are in the stack
817 ( puint )*( curpos->start + curfunc->parsize ) = curpos->top;
818 curpos->top += (( povmbcode )curfunc)->varsize;
819 }
820 curpos->clmark = curpos->top;
821 curpos->uiret = curfunc->dwret;
822 curpos->func = curfunc;
823 // Зануляем признак отведения памяти для локальных структур
824 // *( curpos->top - 1 ) = 0;
825
826 // Зануляем признаки инициализации блоков переменных
827 if ( (( povmbcode )curfunc)->setcount )
828 mem_zeroui( curpos->start + curfunc->parsize + 1,
829 (( povmbcode )curfunc)->setcount );
830 if ( !curpos->cmd )
831 msg( MUndefcmd | MSG_VALSTRERR, curfunc->vmo.name, cmd );
832 continue;
833
834 //---------------- Exfunc commands --------------------------------------
835 exfunc:
836 exfunc = curfunc->func;
837 if ( !exfunc )
838 msg( MUndefcmd | MSG_VALSTRERR, curfunc->vmo.name, cmd );
839 top = curpos->top;
840
841 #ifdef LINUX
842 if ( curfunc->vmobj.flag & GHEX_SYSCALL )
843 {
844 curpos->top = syscall( curfunc, top );
845 goto next;
846 }
847 #endif
848 // print("PAR=%i parsize=%i ret=%i %s\n", curfunc->parcount,
849 // curfunc->parsize, curfunc->dwret, curfunc->vmo.name );
850 for ( i = 0; i < curfunc->parsize; i++ )
851 {
852 val = *--top;
853 #ifdef LINUX
854 __asm__ ("push %0"::"d"(val));
855 #else
856 #if defined (__GNUC__) || defined (__TINYC__)
857 __asm__ ("push %0"::"d"(val));
858 #else
859 _asm { push val }
860 #endif
861 #endif
862 }
863 if ( curfunc->vmo.flag & GHEX_FLOAT )
864 {
865 if ( curfunc->dwret == 1 )
866 {
867 #ifdef LINUX
868 __asm__ ("call *%0"::"m"(exfunc));
869 __asm__ ("fstp %%st":"=m"(val));
870 #else
871 #if defined ( __GNUC__) || defined (__TINYC__)
872 __asm__ ("call *%0"::"m"(exfunc));
873 __asm__ ("fstp %%st":"=m"(val));
874
875 #else
876 _asm {
877 call exfunc
878 fstp dword ptr [val]
879 }
880 #endif
881 #endif
882 }
883 else
884 {
885 #ifdef LINUX
886 __asm__ ("call *%0"::"m"(exfunc));
887 __asm__ ("fstp %%st":"=t"(d):"0"(d));
888 //__asm__ ("fstp %0":"=r"(&d));
889 #else
890 #if defined (__GNUC__)
891 __asm__ ("call *%0"::"m"(exfunc));
892 __asm__ ("fstp %%st":"=t"(d):"0"(d));
893 //__asm__ ("fstp %0":"=r"(&d));
894 #elif defined (__TINYC__)
895 __asm__ ("call *%0"::"m"(exfunc));
896 __asm__ ("fstp %%st":"m"(d):"0"(d));
897 #else
898 _asm {
899 call exfunc
900 // fstp qword ptr [d]
901 fstp d
902 }
903 #endif
904 #endif
905 val = *(uint*)&d;
906 valhi = *((uint*)&d + 1 );
907 }
908 }
909 else
910 {
911 #ifdef LINUX
912 //print( "\07exfunc=%x val=%x\n", exfunc, val );
913 __asm__ ("call *%0"::"m"(exfunc));
914 __asm__ ("mov %%eax,%0":"m="(val));
915 __asm__ ("mov %%edx,%0":"m="(valhi));
916 #else
917 #if defined (__GNUC__)
918 __asm__ ("call *%0"::"m"(exfunc));
919 __asm__ ("mov %%eax,%0":"m="(val));
920 __asm__ ("mov %%edx,%0":"m="(valhi));
921 #elif defined (__TINYC__)
922 __asm__ ("call *%0"::"m"(exfunc));
923 __asm__ ("mov %%eax,%0":"m"(val));
924 __asm__ ("mov %%edx,%0":"m"(valhi));
925 #else
926 _asm {
927 call exfunc
928 mov val,eax
929 mov valhi,edx
930 }
931 #endif
932 #endif
933 }
934 #ifdef LINUX
935 #else
936 if ( curfunc->vmo.flag & GHEX_CDECL )
937 #endif
938 {
939 i = curfunc->parsize << 2;
940 #ifdef LINUX
941 __asm__ ("add %0, %%esp"::"m"(i));
942 #else
943 #if defined (__GNUC__) || defined (__TINYC__)
944 __asm__ ("add %0, %%esp"::"m"(i));
945 #else
946 _asm { add esp, i }
947 #endif
948 #endif
949 }
950 if ( curfunc->dwret )
951 *top++ = val;
952 if ( curfunc->dwret == 2 )
953 *top++ = valhi;
954 curpos->top = top;
955 goto next;
956
957 //---------------- Type command --------------------------------------
958 type:
959 *curpos->top++ = cmd;
960 goto next;
961
962 //---------------- Getting next command ------------------------------
963 next:
964 curpos->cmd++;
965 }
966
967 end:
968 // Copy the result value
969 if ( result )
970 mem_copyui( result, curpos->top - uiret, uiret );
971 // Free stack
972 mem_free( stack );
973
974 return 1;
975 error:
976 msg( MUnkbcode | MSG_DVAL, cmd );
977 return 0;
978 }
979
980 //--------------------------------------------------------------------------
981
982 uint STDCALL vm_runone( uint id, uint first )
983 {
984 uint ret;
985 uint size = _vm.stacksize;
986
987 // Изменяем размеры стэка для функций вызываемых из виртуальной машины
988 _vm.stacksize = 8192;
989 vm_run( id, &first, &ret );
990 _vm.stacksize = size;
991 return ret;
992 }
993
994 //--------------------------------------------------------------------------
995
996 uint STDCALL vm_runtwo( uint id, uint first, uint second )
997 {
998 uint ret;
999 uint size = _vm.stacksize;
1000 uint params[4];
1001
1002 // Изменяем размеры стэка для функций вызываемых из виртуальной машины
1003 _vm.stacksize = 8192;
1004 params[0] = first;
1005 params[1] = second;
1006 vm_run( id, ( puint )¶ms, &ret );
1007 _vm.stacksize = size;
1008 return ret;
1009 }
1010
1011 /*-----------------------------------------------------------------------------
1012 ** Id: gentee_call F
1013 *
1014 * Summary: Call the function from the bytecode. The bytecode should be
1015 previously loaded with the $[gentee_load] or $[gentee_compile]
1016 functions.
1017 *
1018 * Params: id - The identifier of the called object. Can be obtained by /
1019 $[gentee_getid] function.
1020 result - Pointer to the memory space, to which the result will be /
1021 written. It can be the pointer to #b(uint), #b(long) or /
1022 #b(double).
1023 ... - Required parameters of the function.
1024 *
1025 * Return: #lng/retf#
1026 *
1027 -----------------------------------------------------------------------------*/
1028
1029 uint CDECLCALL gentee_call( uint id, puint result, ... )
1030 {
1031 uint ok = 0;
1032 pvmfunc curfunc;
1033 va_list argptr;
1034 uint i = 0;
1035 uint params[ 64 ];
1036 uint size = _vm.stacksize;
1037
1038 _vm.stacksize = 0x8000; // 32KB
1039 va_start( argptr, result );
1040
1041 curfunc = ( pvmfunc )PCMD( id );
1042 if ( curfunc->vmo.flag & GHRT_MAYCALL )
1043 {
1044 while ( i < curfunc->parsize )
1045 params[ i++ ] = va_arg( argptr, uint );
1046
1047 ok = vm_run( id, ( puint )¶ms, result );
1048 }
1049 va_end( argptr );
1050 _vm.stacksize = size;
1051
1052 return ok;
1053 }
1054
1055 uint STDCALL vm_calladdr( void )
1056 {
1057 return ( uint )&gentee_call;
1058 }
1059
1060 //-----------------------------------------------------------------------------