/*[ sbb.c LOCAL CHAR SccsID[]="@(#)sbb.c 1.5 02/09/94"; SBB CPU functions. ------------------ ]*/ #include #include #include #include #include #include #include #include #include #include #include #include /* ===================================================================== EXTERNAL FUNCTIONS START HERE. ===================================================================== */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Generic - one size fits all 'sbb'. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 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 */ }