/** * @brief Logical OR on Accumulator */ void Cpu::ora(uint8_t v, uint8_t cycles) { a(a()|v); SET_ZF(a()); SET_NF(a()); tick(cycles); }
GLOBAL VOID AAA() { if ( (GET_AL() & 0xf) > 9 || GET_AF() ) { SET_AX(GET_AX() + 6); SET_AH(GET_AH() + 1); SET_CF(1); SET_AF(1); } else { SET_CF(0); SET_AF(0); } SET_AL(GET_AL() & 0xf); /* Set undefined flag(s) */ #ifdef SET_UNDEFINED_FLAG SET_OF(UNDEFINED_FLAG); SET_SF(UNDEFINED_FLAG); SET_ZF(UNDEFINED_FLAG); SET_PF(UNDEFINED_FLAG); #endif }
/** * @brief PuLl Accumulator */ void Cpu::pla() { a(pop()); SET_ZF(a()); SET_NF(a()); tick(4); }
/** * @brief Transfer Accumulator to X */ void Cpu::tax() { x(a()); SET_ZF(x()); SET_NF(x()); tick(2); }
/** * @brief Transfer Accumulator to Y */ void Cpu::tay() { y(a()); SET_ZF(y()); SET_NF(y()); tick(2); }
/** * @brief LoaD Y */ void Cpu::ldy(uint8_t v, uint8_t cycles) { y(v); SET_ZF(y()); SET_NF(y()); tick(cycles); }
/** * @brief Transfer X to Accumulator */ void Cpu::txa() { a(x()); SET_ZF(a()); SET_NF(a()); tick(2); }
/** * @brief LoaD X */ void Cpu::ldx(uint8_t v, uint8_t cycles) { x(v); SET_ZF(x()); SET_NF(x()); tick(cycles); }
/** * @brief LoaD Accumulator */ void Cpu::lda(uint8_t v, uint8_t cycles) { a(v); SET_ZF(a()); SET_NF(a()); tick(cycles); }
/** * @brief Transfer Stack pointer to X */ void Cpu::tsx() { x(sp()); SET_ZF(x()); SET_NF(x()); tick(2); }
/** * @brief Logical AND */ void Cpu::_and(uint8_t v, uint8_t cycles) { a(a()&v); SET_ZF(a()); SET_NF(a()); tick(cycles); }
/** * @brief Transfer Y to Accumulator */ void Cpu::tya() { a(y()); SET_ZF(a()); SET_NF(a()); tick(2); }
GLOBAL VOID DAA() { IU8 temp_al; temp_al = GET_AL(); if ( (temp_al & 0xf) > 9 || GET_AF() ) { temp_al += 6; SET_AF(1); } if ( GET_AL() > 0x99 || GET_CF() ) { temp_al += 0x60; SET_CF(1); } SET_AL(temp_al); /* set ZF,SF,PF according to result */ SET_ZF(temp_al == 0); SET_SF((temp_al & BIT7_MASK) != 0); SET_PF(pf_table[temp_al]); /* Set undefined flag(s) */ #ifdef SET_UNDEFINED_FLAG SET_OF(UNDEFINED_FLAG); #endif }
/** * @brief ROtate Left */ uint8_t Cpu::rol(uint8_t v) { uint16_t t = (v << 1) | (uint8_t)cf(); cf((t&0x100)!=0); SET_ZF(t); SET_NF(t); return (uint8_t)t; }
/** * @brief BIT test */ void Cpu::bit(uint16_t addr, uint8_t cycles) { uint8_t t = load_byte(addr); of((t&0x40)!=0); SET_NF(t); SET_ZF(t&a()); tick(cycles); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID SBB IFN3( IU32 *, pop1, /* pntr to dst/lsrc operand */ IU32, op2, /* rsrc operand */ IUM8, op_sz /* 8, 16 or 32-bit */ ) { IU32 result; IU32 carry; IU32 msb; IU32 op1_msb; IU32 op2_msb; IU32 res_msb; msb = SZ2MSB(op_sz); /* Do operation */ result = *pop1 - op2 - GET_CF() & SZ2MASK(op_sz); op1_msb = (*pop1 & msb) != 0; /* Isolate all msb's */ op2_msb = (op2 & msb) != 0; res_msb = (result & msb) != 0; carry = *pop1 ^ op2 ^ result; /* Isolate carries */ /* Determine flags */ /* OF = (op1 == !op2) & (op1 ^ res) ie if operand signs differ and res sign different to original destination set OF. */ SET_OF((op1_msb != op2_msb) & (op1_msb ^ res_msb)); /* Formally:- CF = !op1 & op2 | res & !op1 | res & op2 Equivalently:- CF = OF ^ op1 ^ op2 ^ res */ SET_CF(((carry & msb) != 0) ^ GET_OF()); SET_PF(pf_table[result & BYTE_MASK]); SET_ZF(result == 0); SET_SF((result & msb) != 0); /* SF = MSB */ SET_AF((carry & BIT4_MASK) != 0); /* AF = Bit 4 carry */ *pop1 = result; /* Return answer */ }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID XOR IFN3( IU32 *, pop1, /* pntr to dst/lsrc operand */ IU32, op2, /* rsrc operand */ IUM8, op_sz /* 8, 16 or 32-bit */ ) { IU32 result; result = *pop1 ^ op2; /* Do operation */ SET_CF(0); /* Determine flags */ SET_OF(0); SET_AF(0); SET_PF(pf_table[result & BYTE_MASK]); SET_ZF(result == 0); SET_SF((result & SZ2MSB(op_sz)) != 0); /* SF = MSB */ *pop1 = result; /* Return answer */ }
GLOBAL VOID VERW IFN1( IU32, op1 /* src(selector) operand */ ) { BOOL writeable = FALSE; IU32 descr; IU8 AR; if ( !selector_outside_GDT_LDT((IU16)op1, &descr) ) { /* get access rights */ AR = spr_read_byte(descr+5); switch ( descriptor_super_type((IU16)AR) ) { case INVALID: case AVAILABLE_TSS: case LDT_SEGMENT: case BUSY_TSS: case CALL_GATE: case TASK_GATE: case INTERRUPT_GATE: case TRAP_GATE: case XTND_AVAILABLE_TSS: case XTND_BUSY_TSS: case XTND_CALL_GATE: case XTND_INTERRUPT_GATE: case XTND_TRAP_GATE: case CONFORM_NOREAD_CODE: case CONFORM_READABLE_CODE: case NONCONFORM_NOREAD_CODE: case NONCONFORM_READABLE_CODE: case EXPANDUP_READONLY_DATA: case EXPANDDOWN_READONLY_DATA: break; /* never writeable */ case EXPANDUP_WRITEABLE_DATA: case EXPANDDOWN_WRITEABLE_DATA: /* access depends on privilege, it is required that DPL >= CPL and DPL >= RPL */ if ( GET_AR_DPL(AR) >= GET_CPL() && GET_AR_DPL(AR) >= GET_SELECTOR_RPL(op1) ) writeable = TRUE; break; } } if ( writeable ) { SET_ZF(1); } else { SET_ZF(0); } }