/* * Upon a system call, the stack will look like: * * sp+32 parm1 * sp+28 parm0 * sp+24 return value * sp+20 return address * sp+16 local1 * sp+14 local0 * sp+12 arg1 * sp+8 arg0 * sp+4 return stack * sp return address * * An interpreted function will immediately execute an OP_ENTER instruction, * which will subtract space for locals from sp */ intptr_t QDECL VM_CallFunc(vm_t *vm, int callnum, ...) { vm_t *oldVM; intptr_t r; if (!vm) { Com_Error(ERR_FATAL, "VM_Call: NULL vm"); } oldVM = currentVM; currentVM = vm; lastVM = vm; if (vm_debugLevel) { Com_Printf("VM_Call( %i )\n", callnum); } // if we have a dll loaded, call it directly if (vm->entryPoint) { // rcg010207 - see dissertation at top of VM_DllSyscall() in this file. intptr_t args[VM_SYSCALL_ARGS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; va_list ap; int i; va_start(ap, callnum); for (i = 0; i < ARRAY_LEN(args); i++) { // We add the end of args point since windows at least just returns random values if there are no args // this way we know that only valid values are sent to the vm args[i] = va_arg(ap, intptr_t); if (args[i] == VM_CALL_END) { args[i] = 0; break; } } va_end(ap); r = vm->entryPoint(callnum, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15]); } #if 0 else if (vm->compiled) { r = VM_CallCompiled(vm, &callnum); } else { r = VM_CallInterpreted(vm, &callnum); } #else else {
intptr_t QDECL VM_Call( vm_t *vm, intptr_t callnum, ... ) { vm_t *oldVM; intptr_t r; #if ( defined __linux__ )// use "safer" ppc version int i; intptr_t args[16]; va_list ap; #endif if ( !vm ) { Com_Error( ERR_FATAL, "VM_Call with NULL vm" ); } oldVM = currentVM; currentVM = vm; lastVM = vm; if ( vm_debugLevel ) { Com_Printf( "VM_Call( %i )\n", callnum ); } // if we have a dll loaded, call it directly if ( vm->entryPoint ) { #if ( defined __linux__ )// use "safer" ppc version va_start( ap, callnum ); for ( i = 0; i < sizeof( args ) / sizeof( args[i] ); i++ ) args[i] = va_arg( ap, intptr_t ); va_end( ap ); r = vm->entryPoint( callnum, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15] ); #else // PPC above, original id code below r = vm->entryPoint( ( &callnum )[0], ( &callnum )[1], ( &callnum )[2], ( &callnum )[3], ( &callnum )[4], ( &callnum )[5], ( &callnum )[6], ( &callnum )[7], ( &callnum )[8], ( &callnum )[9], ( &callnum )[10], ( &callnum )[11], ( &callnum )[12] ); #endif } else if ( vm->compiled ) { r = VM_CallCompiled( vm, &callnum ); } else { r = VM_CallInterpreted( vm, &callnum ); } if ( oldVM != NULL ) { // bk001220 - assert(currentVM!=NULL) for oldVM==NULL currentVM = oldVM; } return r; }