private IPiValue LoadProgramMemory(ref int ptr, VarType t) { PiConst rez=new PiConst(); switch(t) { case VarType.S1: rez.Set<long>((sbyte)_prg[ptr++]); break; case VarType.U1: rez.Set<long>(_prg[ptr++]); break; case VarType.S2: rez.Set<long>((short)((_prg[ptr++]<<8) | _prg[ptr++])); break; case VarType.U2: rez.Set<long>((_prg[ptr++]<<8) | _prg[ptr++]); break; case VarType.S4: rez.Set<long>((_prg[ptr++]<<24) | (_prg[ptr++]<<16) | (_prg[ptr++]<<8) | _prg[ptr++]); break; default: rez.Set<long>(0); break; } return rez; }
public bool Step() { if(_prg==null || _pc>=_prg.Count) { return false; } OP cmd=(OP)_prg[_pc++]; IPiValue tmp, tmp2; switch(cmd) { /* #region PUSH/POP case OP.DUP: PushS(_s[_sp]); break; case OP.DROP: PopS(); break; case OP.NIP: // (a b - b ) tmp=PopS(); _s[_sp]=tmp; break; case OP.SWAP: // (b a - a b) tmp=_s[_sp]; _s[_sp]=_s[_sp-1]; _s[_sp-1]=tmp; break; case OP.PUSH_S1: case OP.PUSH_S2: case OP.PUSH_S4: PushS(LoadProgramMemory(ref _pc, (VarType)(((byte)cmd)&0x07))); break; case OP.PUSH_U1: case OP.PUSH_U2: PushS(LoadProgramMemory(ref _pc, (VarType)((-1+(byte)cmd)&0x07))); break; case OP.PUSH_ZERO: PushS(0); break; case OP.PUSH_TRUE: PushS(1); break; case OP.PUSH_P0: case OP.PUSH_P1: case OP.PUSH_P2: case OP.PUSH_P3: case OP.PUSH_P4: case OP.PUSH_P5: case OP.PUSH_P6: case OP.PUSH_P7: case OP.PUSH_P8: case OP.PUSH_P9: case OP.PUSH_PA: case OP.PUSH_PB: case OP.PUSH_PC: case OP.PUSH_PD: case OP.PUSH_PE: case OP.PUSH_PF: PushS(_s[_sfp-2-(((byte)cmd) & 0x0f)]); break; case OP.PUSH_L0: case OP.PUSH_L1: case OP.PUSH_L2: case OP.PUSH_L3: case OP.PUSH_L4: case OP.PUSH_L5: case OP.PUSH_L6: case OP.PUSH_L7: case OP.PUSH_L8: case OP.PUSH_L9: case OP.PUSH_LA: case OP.PUSH_LB: case OP.PUSH_LC: case OP.PUSH_LD: case OP.PUSH_LE: case OP.PUSH_LF: PushS(_s[_sfp+1+(((byte)cmd) & 0x0f)]); break; case OP.POP_P0: case OP.POP_P1: case OP.POP_P2: case OP.POP_P3: case OP.POP_P4: case OP.POP_P5: case OP.POP_P6: case OP.POP_P7: case OP.POP_P8: case OP.POP_P9: case OP.POP_PA: case OP.POP_PB: case OP.POP_PC: case OP.POP_PD: case OP.POP_PE: case OP.POP_PF: _s[_sfp-2-(((byte)cmd) & 0x0f)]=PopS(); break; case OP.POP_L0: case OP.POP_L1: case OP.POP_L2: case OP.POP_L3: case OP.POP_L4: case OP.POP_L5: case OP.POP_L6: case OP.POP_L7: case OP.POP_L8: case OP.POP_L9: case OP.POP_LA: case OP.POP_LB: case OP.POP_LC: case OP.POP_LD: case OP.POP_LE: case OP.POP_LF: _s[_sfp+1+(((byte)cmd) & 0x0f)]=PopS(); break; case OP.PUSHM_B1_S16: // memory -> stack case OP.PUSHM_B1_CS8: case OP.PUSHM_B1_CS16: case OP.PUSHM_B1_C16: case OP.PUSHM_S1_S16: case OP.PUSHM_S1_CS8: case OP.PUSHM_S1_CS16: case OP.PUSHM_S1_C16: case OP.PUSHM_S2_S16: case OP.PUSHM_S2_CS8: case OP.PUSHM_S2_CS16: case OP.PUSHM_S2_C16: case OP.PUSHM_S4_S16: case OP.PUSHM_S4_CS8: case OP.PUSHM_S4_CS16: case OP.PUSHM_S4_C16: case OP.PUSHM_U1_S16: case OP.PUSHM_U1_CS8: case OP.PUSHM_U1_CS16: case OP.PUSHM_U1_C16: case OP.PUSHM_U2_S16: case OP.PUSHM_U2_CS8: case OP.PUSHM_U2_CS16: case OP.PUSHM_U2_C16: { int addr; switch(((byte)cmd)&0x03) { case 0: addr=PopS(); break; case 1: addr=PopS()+LoadProgramMemory(ref _pc, VarType.S1); break; case 2: addr=PopS()+LoadProgramMemory(ref _pc, VarType.S2); break; case 3: addr=LoadProgramMemory(ref _pc, VarType.U2); break; default: addr=-1; break; } PushS(LoadData(addr, (VarType)((((byte)cmd)>>2)&0x07))); } break; case OP.POPM_B1_S16: // stack -> memory case OP.POPM_B1_CS8: case OP.POPM_B1_CS16: case OP.POPM_B1_C16: case OP.POPM_S1_S16: case OP.POPM_S1_CS8: case OP.POPM_S1_CS16: case OP.POPM_S1_C16: case OP.POPM_S2_S16: case OP.POPM_S2_CS8: case OP.POPM_S2_CS16: case OP.POPM_S2_C16: case OP.POPM_S4_S16: case OP.POPM_S4_CS8: case OP.POPM_S4_CS16: case OP.POPM_S4_C16: case OP.POPM_U1_S16: case OP.POPM_U1_CS8: case OP.POPM_U1_CS16: case OP.POPM_U1_C16: case OP.POPM_U2_S16: case OP.POPM_U2_CS8: case OP.POPM_U2_CS16: case OP.POPM_U2_C16: { int addr; switch(((byte)cmd)&0x03) { case 0: addr=PopS(); break; case 1: addr=PopS()+LoadProgramMemory(ref _pc, VarType.S1); break; case 2: addr=PopS()+LoadProgramMemory(ref _pc, VarType.S2); break; case 3: addr=LoadProgramMemory(ref _pc, VarType.U2); break; default: addr=-1; break; } StoreData(addr, (VarType)((((byte)cmd)>>2)&0x07), PopS()); } break; #endregion PUSH/POP */ #region ALU case OP.ADD: tmp=PopS(); tmp2=PopS(); { PiConst r=new PiConst(); r.Set<double>(tmp.As<double>()+tmp2.As<double>()); PushS(r); } //_s[_sp]+=tmp; break; /* case OP.SUB: tmp=PopS(); _s[_sp]-=tmp; break; case OP.MUL: tmp=PopS(); _s[_sp]*=tmp; break; case OP.DIV: tmp=PopS(); _s[_sp]/=tmp; break; case OP.MOD: tmp=PopS(); _s[_sp]%=tmp; break; case OP.SHL: tmp=PopS(); _s[_sp]<<=tmp; break; case OP.SHR: tmp=PopS(); _s[_sp]>>=tmp; break; case OP.AND: tmp=PopS(); _s[_sp]&=tmp; break; case OP.OR: tmp=PopS(); _s[_sp]|=tmp; break; case OP.XOR: tmp=PopS(); _s[_sp]^=tmp; break; case OP.NOT: _s[_sp]=~_s[_sp]; break; case OP.NEG: _s[_sp]=-_s[_sp]; break; case OP.INC: _s[_sp]++; break; case OP.DEC: _s[_sp]--; break; case OP.CEQ: tmp=PopS(); _s[_sp]=_s[_sp]==tmp?1:0; break; case OP.CNE: tmp=PopS(); _s[_sp]=_s[_sp]!=tmp?1:0; break; case OP.CGT: tmp=PopS(); _s[_sp]=_s[_sp]>tmp?1:0; break; case OP.CGE: tmp=PopS(); _s[_sp]=_s[_sp]>=tmp?1:0; break; case OP.CLT: tmp=PopS(); _s[_sp]=_s[_sp]<tmp?1:0; break; case OP.CLE: tmp=PopS(); _s[_sp]=_s[_sp]<=tmp?1:0; break; case OP.NOT_L: _s[_sp]=_s[_sp]==0?1:0; break; case OP.AND_L: tmp=PopS(); _s[_sp]=_s[_sp]!=0 && tmp!=0?1:0; break; case OP.OR_L: tmp=PopS(); _s[_sp]=_s[_sp]!=0 || tmp!=0?1:0; break; case OP.XOR_L: tmp=PopS(); _s[_sp]=_s[_sp]!=0 ^ tmp!=0?1:0; break; */ #endregion ALU /* case OP.JMP: tmp=LoadProgramMemory(ref _pc, VarType.U2); _pc=(int)tmp.As<long>(); break; case OP.CALL: tmp=LoadProgramMemory(ref _pc, VarType.U2); PushS(_pc); PushS(_sfp); _sfp=_sp; _pc=tmp; break; case OP.JZ: tmp2=PopS(); if(tmp2==0) { tmp=LoadProgramMemory(ref _pc, VarType.U2); _pc=tmp; } else { _pc+=2; } break; case OP.JNZ: tmp2=PopS(); if(tmp2!=0) { tmp=LoadProgramMemory(ref _pc, VarType.U2); _pc=tmp; } else { _pc+=2; } break; case OP.TEST_EQ: _testNr++; tmp=PopS(); tmp2=LoadProgramMemory(ref _pc, VarType.S4); if(tmp!=tmp2) { Log.Warning("Test #{0} FAIL, cur={1}, exp={2}", _testNr, tmp, tmp2); } else { Log.Info("Test #{0} pass", _testNr); } break; */ case OP.RET: if(_sfp<0) { return false; } else { _sp=_sfp; _sfp=(int)PopS().As<long>(); _pc=(int)PopS().As<long>(); } break; default: Log.Error("unknown OP [{0:X4}]:{1}", _pc-1, cmd); return false; } return true; }