static void opCVTS(void) { float val1=u2f(GETREG(GET1)); SET_OV(0); SET_Z((val1==0.0)?1:0); SET_S((val1<0.0)?1:0); SETREG(GET2,(INT32)val1); }
static UINT32 opNOTr(void) // not r1,r2 { UINT32 op1=GETREG(GET1); UINT32 op2=~op1; CHECK_ZS(op2); SET_OV(0); SETREG(GET2,op2); return clkIF; }
static void opCVTW(void) { //TODO: CY float val1=GETREG(GET1); SET_OV(0); SET_Z((val1==0.0)?1:0); SET_S((val1<0.0)?1:0); SETREG(GET2,f2u(val1)); }
static void opCMPF(void) { float val1=u2f(GETREG(GET1)); float val2=u2f(GETREG(GET2)); SET_OV(0); SET_CY((val2<val1)?1:0); val2-=val1; SET_Z((val2==0.0)?1:0); SET_S((val2<0.0)?1:0); }
static UINT32 opXORr(void) // xor r1,r2 { UINT32 op1=GETREG(GET1); UINT32 op2=GETREG(GET2); op2^=op1; CHECK_ZS(op2); SET_OV(0); SETREG(GET2,op2); return clkIF; }
static UINT32 opANDr(void) // and r1,r2 { UINT32 op1=GETREG(GET1); UINT32 op2=GETREG(GET2); op2&=op1; CHECK_ZS(op2); SET_OV(0); SETREG(GET2,op2); return clkIF; }
static void opMULF(void) { //TODO: CY float val1=u2f(GETREG(GET1)); float val2=u2f(GETREG(GET2)); SET_OV(0); val2*=val1; SET_Z((val2==0.0)?1:0); SET_S((val2<0.0)?1:0); SETREG(GET2,f2u(val2)); }
/*From several sources, since none said the same thing: The decimal adjust instruction is associated with the use of the ADD and ADDC instructions. The eight-bit value in the accumulator is adjusted to form two BCD digits of four bits each. If the accumulator contents bits 0-3 are greater than 9, OR the AC flag is set, then six is added to produce a proper BCD digit. If the carry is set, OR the four high bits 4-7 exceed nine, six is added to the value of these bits. The carry flag will be set if the result is > 0x99, but not cleared otherwise */ UINT16 new_acc = R_ACC & 0xff; if(GET_AC || (new_acc & 0x0f) > 0x09) new_acc += 0x06; if(GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff)) new_acc += 0x60; SFR_W(ACC,new_acc&0xff); if(new_acc & ~0xff) SET_CY(1); } //DEC A /* 1: 0001 0100 */ INLINE void dec_a(void) { SFR_W(ACC,R_ACC-1); } //DEC data addr /* 1: 0001 0101 */ INLINE void dec_mem(void) { UINT8 addr = ROP_ARG(PC++); //Grab data address UINT8 data = IRAM_R(addr); IRAM_W(addr,data-1); } //DEC @R0/@R1 /* 1: 0001 011i */ INLINE void dec_ir(int r) { UINT8 data = IRAM_IR(R_R(r)); IRAM_W(R_R(r),data-1); } //DEC R0 to R7 /* 1: 0001 1rrr */ INLINE void dec_r(int r) { R_R(r) = R_R(r) - 1; } //DIV AB /* 1: 1000 0100 */ INLINE void div_ab(void) { if( R_B == 0 ) { //Overflow flag is set! SET_OV(1); //Really the values are undefined according to the manual, but we'll just leave them as is.. //SFR_W(ACC,0xff); //SFR_W(B,0xff); } else { int a = (int)R_ACC/R_B; int b = (int)R_ACC%R_B; //A gets quotient byte, B gets remainder byte SFR_W(ACC,a); SFR_W(B, b); //Overflow flag is cleared SET_OV(0); } //Carry Flag is always cleared SET_CY(0); }
static void opDIVF(void) { //TODO: CY float val1=u2f(GETREG(GET1)); float val2=u2f(GETREG(GET2)); SET_OV(0); if(val1!=0) val2/=val1; SET_Z((val2==0.0)?1:0); SET_S((val2<0.0)?1:0); SETREG(GET2,f2u(val2)); }
static UINT32 opXORI(void) // xori imm16,r1,r2 { UINT32 op1=GETREG(GET1); UINT32 op2=R_OP(PC); PC+=2; op2=UI16(op2); op2^=op1; CHECK_ZS(op2); SET_OV(0); SET_S(0); SETREG(GET2,op2); return clkIF; }
static UINT32 opDIVUr(void) // divu r1,r2 { UINT32 op1=GETREG(GET1); UINT32 op2=GETREG(GET2); if(op1) { SETREG(30,(INT32)(op2%op1)); SETREG(GET2,(INT32)(op2/op1)); SET_OV((op1^op2^GETREG(GET2)) == 0x80000000); CHECK_ZS(GETREG(GET2)); } return clkIF; }
static UINT32 opMULUr(void) // mulu r1,r2 { UINT32 op1=GETREG(GET1); UINT32 op2=GETREG(GET2); UINT64 tmp; tmp=(UINT64)op1*(UINT64)op2; op2=tmp&0xffffffff; tmp>>=32; CHECK_ZS(tmp);//z = bad! SET_Z( (tmp|op2)==0 ); SET_OV((tmp!=0)); SET_CY((tmp!=0)); SETREG(GET2,op2); SETREG(30,tmp); return clkIF; }
static UINT32 opSHRi(void) // shr imm5,r2 { UINT64 tmp; UINT32 count=UI5(OP); SET_OV(0); SET_CY(0); if(count) { tmp=GETREG(GET2); tmp>>=count-1; SET_CY(tmp&1); tmp>>=1; SETREG(GET2,tmp&0xffffffff); } CHECK_ZS(GETREG(GET2)); return clkIF; }
static UINT32 opSARi(void) // sar imm5,r2 { UINT64 tmp; UINT32 count=UI5(OP); SET_OV(0); SET_CY(0); if(count) { tmp=GETREG(GET2); tmp>>=count-1; SET_CY(tmp&1); tmp>>=1; SETREG(GET2,(tmp&0xffffffff)|(~(((GETREG(GET2)&0x80000000)>>count)-1))); } CHECK_ZS(GETREG(GET2)); return clkIF; }
static UINT32 opSHRr(void) // shr r1,r2 { UINT64 tmp; UINT32 count=GETREG(GET1); count&=0x1f; SET_OV(0); SET_CY(0); if(count) { tmp=GETREG(GET2); tmp>>=count-1; SET_CY(tmp&1); SETREG(GET2,(tmp>>1)&0xffffffff); } CHECK_ZS(GETREG(GET2)); return clkIF; }
static UINT32 opSHLi(void) // shl imm5,r2 { UINT64 tmp; UINT32 count=UI5(OP); SET_OV(0); SET_CY(0); if(count) { tmp=GETREG(GET2); tmp<<=count; CHECK_CY(tmp); SETREG(GET2,tmp&0xffffffff); } CHECK_ZS(GETREG(GET2)); return clkIF; }
static UINT32 opSHLr(void) // shl r1,r2 { UINT64 tmp; UINT32 count=GETREG(GET1); count&=0x1f; SET_OV(0); SET_CY(0); if(count) { tmp=GETREG(GET2); tmp<<=count; CHECK_CY(tmp); SETREG(GET2,tmp&0xffffffff); CHECK_ZS(GETREG(GET2)); } return clkIF; }