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