src/cpu/cpu.cc
/*
 * Executes the data operation encoded by the given CPU operation.
 */
Executes the data operation encoded by the given CPU operation.
Executes the data operation encoded by the given CPU operation .
void Cpu::RunDataOperation(CpuOperation &op) {
  CpuReg data_src = GET_DAT_SRC(op);
  CpuReg data_dst = GET_DAT_DST(op);
  DataWord data_mask = GET_DAT_MASK(op);
  DataOpcode data_op = GET_DAT_OP(op);
  DataWord *regfile = reinterpret_cast<DataWord*>(regs_);
  DoubleWord res = 0;
  switch (data_op) {
    case DAT_INC: {
      regfile[data_dst]++;
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_INCNF: {
      regfile[data_dst]++;
      break;
    }
    case DAT_DEC: {
      regfile[data_dst]--;
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_DECNF: {
      regfile[data_dst]--;
      break;
    }
    case DAT_MOV: {
      regfile[data_dst] = regfile[data_src];
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_MOVNF: {
      regfile[data_dst] = regfile[data_src];
      break;
    }
    case DAT_CLS: {
      regs_->p &= (~data_mask);
      break;
    }
    case DAT_SET: {
      regs_->p |= data_mask;
      break;
    }
    case DAT_CMP: {
      P_UPDATE_N(regfile[data_dst] - regfile[data_src]);
      P_UPDATE_C(regfile[data_dst] >= regfile[data_src]);
      P_UPDATE_Z(regfile[data_dst] - regfile[data_src]);
      break;
    }
    case DAT_ASL: {
      P_UPDATE_C(regfile[data_dst] & 0x80);
      regfile[data_dst] <<= 1;
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_LSR: {
      P_UPDATE_C(regfile[data_dst] & 0x01);
      regfile[data_dst] >>= 1;
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_ROL: {
      res = (regfile[data_dst] << 1) | (regs_->p & P_FLAG_C);
      regfile[data_dst] = GET_WORD_LO(res);
      P_UPDATE_C(GET_WORD_HI(res));
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_ROR: {
      res = GET_DOUBLE_WORD(regfile[data_dst], regs_->p);
      regfile[data_dst] = res >> 1;
      P_UPDATE_C(res & 0x01);
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_XOR: {
      regfile[data_dst] ^= regfile[data_src];
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_OR: {
      regfile[data_dst] |= regfile[data_src];
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_AND: {
      regfile[data_dst] &= regfile[data_src];
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      break;
    }
    case DAT_ADD: {
      res = regfile[data_dst] + regfile[data_src];
      regfile[data_dst] = GET_WORD_LO(res);
      regfile[REG_TMP2] = GET_WORD_HI(res);
      break;
    }
    case DAT_SBC: {
      regfile[data_src] = ~(regfile[data_src]);
      [[fallthrough]];
    }
    case DAT_ADC: {
      res = regfile[data_dst] + regfile[data_src] + (regs_->p & P_FLAG_C);
      P_UPDATE_V(((~(regfile[data_dst] ^ regfile[data_src]))
                  & (regfile[data_dst] ^ GET_WORD_HI(res))) & 0x80);
      regfile[data_dst] = GET_WORD_LO(res);
      P_UPDATE_N(regfile[data_dst]);
      P_UPDATE_Z(regfile[data_dst]);
      P_UPDATE_C(GET_WORD_HI(res));
      break;
    }
    case DAT_BIT: {
      P_UPDATE_N(regfile[data_src]);
      P_UPDATE_V(regfile[data_src] & P_FLAG_V);
      P_UPDATE_Z(regfile[data_dst] & regfile[data_src]);
      break;
    }
    case DAT_VFIX: {
      if (regfile[data_src]) {
        regfile[data_dst] += regfile[data_src];
        inst_buffer_[0] = op & MEMORY_OPERATION_MASK;
        inst_buffer_[1] = current_sequence_[inst_pointer_];
        current_sequence_ = inst_buffer_;
        inst_pointer_ = 0;
      }
      break;
    }
    case DAT_NOP:
    default: {
      break;
    }
  }
  return;
}
void Cpu :: RunDataOperation ( CpuOperation & op ) { CpuReg data_src = GET_DAT_SRC ( op ) ; CpuReg data_dst = GET_DAT_DST ( op ) ; DataWord data_mask = GET_DAT_MASK ( op ) ; DataOpcode data_op = GET_DAT_OP ( op ) ; DataWord * regfile = reinterpret_cast < DataWord * > ( regs_ ) ; DoubleWord res = 0 ; switch ( data_op ) { case DAT_INC : { regfile [ data_dst ] ++ ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_INCNF : { regfile [ data_dst ] ++ ; break ; } case DAT_DEC : { regfile [ data_dst ] -- ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_DECNF : { regfile [ data_dst ] -- ; break ; } case DAT_MOV : { regfile [ data_dst ] = regfile [ data_src ] ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_MOVNF : { regfile [ data_dst ] = regfile [ data_src ] ; break ; } case DAT_CLS : { regs_ -> p &= ( ~ data_mask ) ; break ; } case DAT_SET : { regs_ -> p |= data_mask ; break ; } case DAT_CMP : { P_UPDATE_N ( regfile [ data_dst ] - regfile [ data_src ] ) ; P_UPDATE_C ( regfile [ data_dst ] >= regfile [ data_src ] ) ; P_UPDATE_Z ( regfile [ data_dst ] - regfile [ data_src ] ) ; break ; } case DAT_ASL : { P_UPDATE_C ( regfile [ data_dst ] & 0x80 ) ; regfile [ data_dst ] <<= 1 ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_LSR : { P_UPDATE_C ( regfile [ data_dst ] & 0x01 ) ; regfile [ data_dst ] >>= 1 ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_ROL : { res = ( regfile [ data_dst ] << 1 ) | ( regs_ -> p & P_FLAG_C ) ; regfile [ data_dst ] = GET_WORD_LO ( res ) ; P_UPDATE_C ( GET_WORD_HI ( res ) ) ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_ROR : { res = GET_DOUBLE_WORD ( regfile [ data_dst ] , regs_ -> p ) ; regfile [ data_dst ] = res >> 1 ; P_UPDATE_C ( res & 0x01 ) ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_XOR : { regfile [ data_dst ] ^= regfile [ data_src ] ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_OR : { regfile [ data_dst ] |= regfile [ data_src ] ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_AND : { regfile [ data_dst ] &= regfile [ data_src ] ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; break ; } case DAT_ADD : { res = regfile [ data_dst ] + regfile [ data_src ] ; regfile [ data_dst ] = GET_WORD_LO ( res ) ; regfile [ REG_TMP2 ] = GET_WORD_HI ( res ) ; break ; } case DAT_SBC : { regfile [ data_src ] = ~ ( regfile [ data_src ] ) ; [[ fallthrough ]] ; } case DAT_ADC : { res = regfile [ data_dst ] + regfile [ data_src ] + ( regs_ -> p & P_FLAG_C ) ; P_UPDATE_V ( ( ( ~ ( regfile [ data_dst ] ^ regfile [ data_src ] ) ) & ( regfile [ data_dst ] ^ GET_WORD_HI ( res ) ) ) & 0x80 ) ; regfile [ data_dst ] = GET_WORD_LO ( res ) ; P_UPDATE_N ( regfile [ data_dst ] ) ; P_UPDATE_Z ( regfile [ data_dst ] ) ; P_UPDATE_C ( GET_WORD_HI ( res ) ) ; break ; } case DAT_BIT : { P_UPDATE_N ( regfile [ data_src ] ) ; P_UPDATE_V ( regfile [ data_src ] & P_FLAG_V ) ; P_UPDATE_Z ( regfile [ data_dst ] & regfile [ data_src ] ) ; break ; } case DAT_VFIX : { if ( regfile [ data_src ] ) { regfile [ data_dst ] += regfile [ data_src ] ; inst_buffer_ [ 0 ] = op & MEMORY_OPERATION_MASK ; inst_buffer_ [ 1 ] = current_sequence_ [ inst_pointer_ ] ; current_sequence_ = inst_buffer_ ; inst_pointer_ = 0 ; } break ; } case DAT_NOP : default : { break ; } } return ; }
Executes the data operation encoded by the given CPU operation.
Executes the data operation encoded by the given CPU operation .
// Decodes the data information from the given operation. // Performs the specified data operation. /*
     * Increments the specified destination register.
     * Updates the N and Z flags according to the result.
     */ /*
     * Increments the specified destination register.
     */ /*
     * Decrements the specified destination register.
     * Updates the N and Z flags according to the result.
     */ /*
     * Decrements the specified destination register.
     */ /*
     * Moves the value of the source register into the destination register.
     * Updates the N and Z flags based on the result.
     */ /*
     * Moves the value of the source register into the destination register.
     */ /*
     * Masks out the bits specified in the data mask from P.
     */ /*
     * Sets the bits specified in the data mask in P.
     */ /*
     * Updates the N, Z, and C flags according to the result of (rd - rs).
     */ /*
     * Shifts the destination register left once, storing the lost bit in C
     * and updating N and Z according to the result.
     */ /*
     * Shifts the destination register right once, storing the lost bit in C
     * and updating N and Z according to the result. The high bit is filled
     * with 0.
     */ /*
     * Shifts the destination register left once, back filling with C.
     * Stores the lost bit in C and sets N and Z according to the result.
     */ /*
     * Shifts the destination register right once, back filling with C.
     * Stores the lost bit in C and sets N and Z according to the result.
     */ /*
     * XOR's the specified registers and sets the N and Z flags
     * according to the result.
     */ /*
     * OR's the specified registers and sets the N and Z flags
     * according to the result.
     */ /*
     * AND's the specified registers and sets the N and Z flags
     * according to the result.
     */ /*
     * Adds the specified registers, storing the carry out in tmp2.
     */ /*
     * Nots the source register, then passes off to ADC to perform the addition
     * and set the flags. This is the same as rd = rd - rs - (1 - C).
     */ /*
     * Adds the source register and the carry flag to the destination register.
     * Sets the N, V, Z, and C flags according to the result.
     */ /*
     * Moves the high 2 bits of the source register to P, then sets
     * the Z flag according to the result of (rd & rs).
     */ /*
     * Pushes the last addressing operation back onto the queue if the address
     * crossed a page bound and needed to be fixed.
     * The destination register is the high byte of the address, and the source
     * register is the carry out.
     */ /* Does nothing. */