void sum_statistics(COUNTER *ptotalstats, COUNTER *pstats) { int i; COUNTER tmp; for(i=0; i<MaxStat; i++) { Add_Counter(tmp,pstats[i],ptotalstats[i]); ptotalstats[i]=tmp; } }
DBL POVFPU_RunDefault(FUNCTION fn) { StackFrame *pstack = POVFPU_Current_Context->pstackbase; DBL *dblstack = POVFPU_Current_Context->dblstackbase; unsigned int maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; DBL r0, r1, r2, r3, r4, r5, r6, r7; Instruction *program = NULL; unsigned int k = 0; unsigned int pc = 0; unsigned int ccr = 0; unsigned int sp = 0; unsigned int psp = 0; #if (SUPPORT_INTEGER_INSTRUCTIONS == 1) POV_LONG iA, iB, itemp; #endif #if (DEBUG_DEFAULTCPU == 1) COUNTER instr; Long_To_Counter(POVFPU_Functions[fn].fn.program_size, instr); Add_Counter(stats[Ray_Function_VM_Instruction_Est], stats[Ray_Function_VM_Instruction_Est], instr); #endif Increase_Counter(stats[Ray_Function_VM_Calls]); program = POVFPU_Functions[fn].fn.program; while(true) { k = GET_K(program[pc]); switch(GET_OP(program[pc])) { OP_MATH_AOP(0,+); // add Rs, Rd OP_MATH_AOP(1,-); // sub Rs, Rd OP_MATH_AOP(2,*); // mul Rs, Rd OP_MATH_AOP(3,/); // div Rs, Rd OP_MOD_A(4); // mod Rs, Rd OP_ASSIGN_ABOP(5,0,r0); // move R0, Rd OP_ASSIGN_ABOP(5,1,r1); // move R1, Rd OP_ASSIGN_ABOP(5,2,r2); // move R2, Rd OP_ASSIGN_ABOP(5,3,r3); // move R3, Rd OP_ASSIGN_ABOP(5,4,r4); // move R4, Rd OP_ASSIGN_ABOP(5,5,r5); // move R5, Rd OP_ASSIGN_ABOP(5,6,r6); // move R6, Rd OP_ASSIGN_ABOP(5,7,r7); // move R7, Rd OP_CMP_ABC(6,0,r0); // cmp R0, Rd OP_CMP_ABC(6,1,r1); // cmp R1, Rd OP_CMP_ABC(6,2,r2); // cmp R2, Rd OP_CMP_ABC(6,3,r3); // cmp R3, Rd OP_CMP_ABC(6,4,r4); // cmp R4, Rd OP_CMP_ABC(6,5,r5); // cmp R5, Rd OP_CMP_ABC(6,6,r6); // cmp R6, Rd OP_CMP_ABC(6,7,r7); // cmp R7, Rd OP_ASSIGN_ABOP(7,0,-r0); // neg R0, Rd OP_ASSIGN_ABOP(7,1,-r1); // neg R1, Rd OP_ASSIGN_ABOP(7,2,-r2); // neg R2, Rd OP_ASSIGN_ABOP(7,3,-r3); // neg R3, Rd OP_ASSIGN_ABOP(7,4,-r4); // neg R4, Rd OP_ASSIGN_ABOP(7,5,-r5); // neg R5, Rd OP_ASSIGN_ABOP(7,6,-r6); // neg R6, Rd OP_ASSIGN_ABOP(7,7,-r7); // neg R7, Rd OP_ABS_A(8); // abs Rs, Rd OP_MATH_ABCOP(9,0,POVFPU_Consts[k],+); // addi k, Rd OP_MATH_ABCOP(9,1,POVFPU_Consts[k],-); // subi k, Rd OP_MATH_ABCOP(9,2,POVFPU_Consts[k],*); // muli k, Rd OP_MATH_ABCOP(9,3,POVFPU_Consts[k],/); // divi k, Rd OP_MOD_ABC(9,4,POVFPU_Consts[k]); // modi k, Rd OP_ASSIGN_ABOP(9,5,POVFPU_Consts[k]); // loadi k, Rd OP_CMP_ABC(9,6,POVFPU_Consts[k]); // cmpi k, Rs OP_ASSIGN_ABOP(10,0,ccr == 1); // seq Rd OP_ASSIGN_ABOP(10,1,ccr != 1); // sne Rd OP_ASSIGN_ABOP(10,2,ccr == 2); // slt Rd OP_ASSIGN_ABOP(10,3,ccr >= 1); // sle Rd OP_ASSIGN_ABOP(10,4,ccr == 0); // sgt Rd OP_ASSIGN_ABOP(10,5,ccr <= 1); // sge Rd OP_MATH_ABCOP(10,6,0.0,==); // teq Rd OP_MATH_ABCOP(10,7,0.0,!=); // tne Rd OP_ASSIGN_ABOP(11,0,POVFPU_Globals[k]); // load 0(k), Rd OP_ASSIGN_ABOP(11,1,dblstack[sp+k]); // load SP(k), Rd OP_REVASSIGN_ABOP(12,0,POVFPU_Globals[k]); // store Rs, 0(k) OP_REVASSIGN_ABOP(12,1,dblstack[sp+k]); // store Rs, SP(k) OP_SPECIAL(13,0,0,if(ccr == 1) pc = k - 1); // beq k OP_SPECIAL(13,1,0,if(ccr != 1) pc = k - 1); // bne k OP_SPECIAL(13,2,0,if(ccr == 2) pc = k - 1); // blt k OP_SPECIAL(13,3,0,if(ccr >= 1) pc = k - 1); // ble k OP_SPECIAL(13,4,0,if(ccr == 0) pc = k - 1); // bgt k OP_SPECIAL(13,5,0,if(ccr <= 1) pc = k - 1); // bge k OP_XCC_ABOP(14,0,==); // xeq Rd OP_XCC_ABOP(14,1,!=); // xne Rd OP_XCC_ABOP(14,2,<); // xlt Rd OP_XCC_ABOP(14,3,<=); // xle Rd OP_XCC_ABOP(14,4,>); // xgt Rd OP_XCC_ABOP(14,5,>=); // xge Rd OP_SPECIAL(14,6,0,if((r0 == 0.0) && (r0 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R0 OP_SPECIAL(14,6,1,if((r0 == 0.0) && (r1 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R1 OP_SPECIAL(14,6,2,if((r0 == 0.0) && (r2 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R2 OP_SPECIAL(14,6,3,if((r0 == 0.0) && (r3 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R3 OP_SPECIAL(14,6,4,if((r0 == 0.0) && (r4 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R4 OP_SPECIAL(14,6,5,if((r0 == 0.0) && (r5 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R5 OP_SPECIAL(14,6,6,if((r0 == 0.0) && (r6 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R6 OP_SPECIAL(14,6,7,if((r0 == 0.0) && (r7 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R7 OP_SPECIAL_CASE(15,0,0) // jsr k pstack[psp].pc = pc; pstack[psp].fn = fn; psp++; if(psp >= MAX_CALL_STACK_SIZE) POVFPU_Exception(fn, "Maximum function evaluation recursion level reached."); pc = k; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,1) // jmp k pc = k; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,2) // rts if(psp == 0) return r0; psp--; pc = pstack[psp].pc; // old position, will be incremented fn = pstack[psp].fn; program = POVFPU_Functions[fn].fn.program; break; OP_SPECIAL_CASE(15,0,3) // call k pstack[psp].pc = pc; pstack[psp].fn = fn; psp++; if(psp >= MAX_CALL_STACK_SIZE) POVFPU_Exception(fn, "Maximum function evaluation recursion level reached."); fn = k; program = POVFPU_Functions[fn].fn.program; pc = 0; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,4) // sys1 k r0 = POVFPU_Sys1Table[k](r0); break; OP_SPECIAL_CASE(15,0,5) // sys2 k r0 = POVFPU_Sys2Table[k](r0,r1); break; OP_SPECIAL_CASE(15,0,6) // trap k r0 = POVFPU_TrapTable[k].fn(&dblstack[sp], fn); maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; dblstack = POVFPU_Current_Context->dblstackbase; break; OP_SPECIAL_CASE(15,0,7) // traps k POVFPU_TrapSTable[k].fn(&dblstack[sp], fn, sp); maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; dblstack = POVFPU_Current_Context->dblstackbase; break; OP_SPECIAL_CASE(15,1,0) // grow k if((unsigned int)((unsigned int)sp + (unsigned int)k) >= (unsigned int)MAX_K) { POVFPU_Exception(fn, "Stack full. Possible infinite recursive function call."); } else if(sp + k >= maxdblstacksize) { maxdblstacksize = POVFPU_Current_Context->maxdblstacksize = POVFPU_Current_Context->maxdblstacksize + max(k + 1, (unsigned int)256); dblstack = POVFPU_Current_Context->dblstackbase = (DBL *)POV_REALLOC(dblstack, sizeof(DBL) * maxdblstacksize, "fn: stack"); } break; OP_SPECIAL_CASE(15,1,1) // push k if(sp + k >= maxdblstacksize) POVFPU_Exception(fn, "Function evaluation stack overflow."); sp += k; break; OP_SPECIAL_CASE(15,1,2) // pop k if(k > sp) POVFPU_Exception(fn, "Function evaluation stack underflow."); sp -= k; break; #if (SUPPORT_INTEGER_INSTRUCTIONS == 1) OP_SPECIAL_CASE(15,1,3) // iconv iA = POV_LONG(r0); break; OP_SPECIAL_CASE(15,1,4) // fconv r0 = DBL(iA); break; OP_SPECIAL_CASE(15,1,5) // reserved POVFPU_Exception(fn, "Internal error - reserved function VM opcode found!"); break; OP_INT_MATH_ABOP(15,32,+); // add s, d OP_INT_MATH_ABOP(15,33,-); // sub s, d OP_INT_MATH_ABOP(15,34,*); // mul s, d OP_INT_SPECIAL(15,35,0,iA = iA / iB); // div B, A OP_INT_SPECIAL(15,35,1,iB = iB / iA); // div A, B OP_INT_SPECIAL(15,35,2,iA = iA % iB); // mod B, A OP_INT_SPECIAL(15,35,3,iB = iB % iA); // mod A, B OP_INT_SPECIAL(15,36,0,ccr = (((iB > iA) & 1) << 1) | ((iB == iA) & 1)); // cmp B, A OP_INT_SPECIAL(15,36,1,ccr = (((iA > iB) & 1) << 1) | ((iA == iB) & 1)); // cmp A, B OP_INT_SPECIAL(15,36,2,itemp = iA; iA = iB; iB = itemp); // exg A, B OP_INT_SPECIAL(15,36,3,iA = iB = 0); // clr A, B OP_INT_SPECIAL(15,37,0,iA = 0); // clr A OP_INT_SPECIAL(15,37,1,iB = 0); // clr B OP_INT_SPECIAL(15,37,2,iA = iB); // move B, A OP_INT_SPECIAL(15,37,3,iB = iA); // move A, B OP_INT_SPECIAL(15,38,0,iA = -iA); // neg A OP_INT_SPECIAL(15,38,1,iB = -iB); // neg B OP_INT_SPECIAL(15,38,2,iA = abs(iA)); // abs A OP_INT_SPECIAL(15,38,3,iB = abs(iB)); // abs B OP_INT_SPECIAL(15,39,0,iA = iA + k); // addi k, A OP_INT_SPECIAL(15,39,1,iB = iB + k); // addi k, B OP_INT_SPECIAL(15,39,2,iA = iA - k); // subi k, A OP_INT_SPECIAL(15,39,3,iB = iB - k); // subi k, B OP_INT_MATH_SHIFT_ABOP(15,40,<<,POV_LONG); // asl s, d OP_INT_MATH_SHIFT_ABOP(15,41,>>,POV_LONG); // asr s, d OP_INT_MATH_SHIFT_ABOP(15,42,<<,POV_ULONG); // lsl s, d OP_INT_MATH_SHIFT_ABOP(15,43,>>,POV_ULONG); // lsr s, d OP_INT_MATH_ABOP(15,44,&); // and s, d OP_INT_MATH_ABOP(15,45,|); // or s, d OP_INT_MATH_ABOP(15,46,^); // xor s, d OP_INT_SPECIAL(15,47,0,iA = !iA); // not A, A OP_INT_SPECIAL(15,47,1,iA = !iB); // not B, A OP_INT_SPECIAL(15,47,2,iB = !iA); // not A, B OP_INT_SPECIAL(15,47,3,iB = !iB); // not B, B OP_INT_SPECIAL(15,48,0,iA = k); // loadi A OP_INT_SPECIAL(15,48,1,iB = k); // loadi B OP_INT_SPECIAL(15,48,2,iA = (iA << 16) | k);// ldhi A OP_INT_SPECIAL(15,48,3,iB = (iB << 16) | k);// ldhi B OP_INT_SPECIAL(15,49,0,iA = max(POV_LONG(k), iA)); // max k, A OP_INT_SPECIAL(15,49,1,iB = max(POV_LONG(k), iB)); // max k, B OP_INT_SPECIAL(15,49,2,iA = min(POV_LONG(k), iA)); // min k, A OP_INT_SPECIAL(15,49,3,iB = min(POV_LONG(k), iB)); // min k, B OP_INT_SPECIAL(15,50,0,iA = (POV_LONG(iA) << k)); // asl k, A OP_INT_SPECIAL(15,50,1,iB = (POV_LONG(iB) >> k)); // asr k, B OP_INT_SPECIAL(15,50,2,iA = (POV_ULONG(iA) << k)); // lsl k, A OP_INT_SPECIAL(15,50,3,iB = (POV_ULONG(iB) >> k)); // lsr k, B #endif default: // nop break; } pc++; } #if (DEBUG_DEFAULTCPU == 1) printf("Registers\n"); printf("=========\n"); printf("PC = %d\n", (int)pc); printf("CCR = %x\n", (int)ccr); printf("R0 = %8f R4 = %8f\n", (float)r0, (float)r4); printf("R1 = %8f R5 = %8f\n", (float)r1, (float)r5); printf("R2 = %8f R6 = %8f\n", (float)r2, (float)r6); printf("R3 = %8f R7 = %8f\n", (float)r3, (float)r7); #endif }