project-sls-6502-emulator / src / void_functions.c
void_functions.c
Raw
#include "6502.h"

byte getAccumulator() { return OurComputer->cpu_inst->accumulator; };
byte getRegisterX() { return OurComputer->cpu_inst->register_x; };
byte getRegisterY() { return OurComputer->cpu_inst->register_y; };
byte getStatusRegister() { return OurComputer->cpu_inst->status_register; };
byte getStackPointer() { return OurComputer->cpu_inst->stack_pointer; };
address getProgramCounter() { return OurComputer->cpu_inst->pc; };

void setNegativeFlag() { OurComputer->cpu_inst->status_register |=  0b1 << 7; }
void clearNegativeFlag() { OurComputer->cpu_inst->status_register &=  ~(0b1 << 7); }
byte getNegativeFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 7) >> 7; }

void setOverflowFlag() { OurComputer->cpu_inst->status_register |=  0b1 << 6; }
void clearOverflowFlag() { OurComputer->cpu_inst->status_register &=  ~(0b1 << 6); }
byte getOverflowFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 6) >> 6; }

void setBreakFlag() { OurComputer->cpu_inst->status_register |=  0b1 << 4; }
void clearBreakFlag() { OurComputer->cpu_inst->status_register &=  ~(0b1 << 4); }
byte getBreakFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 4) >> 4; }

void setIgnoreFlag() { OurComputer->cpu_inst->status_register |=  0b1 << 5; }
void clearIgnoreFlag() { OurComputer->cpu_inst->status_register &=  ~(0b1 << 5); }
byte getIgnoreFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 5) >> 5; }

void setDecimalFlag() { OurComputer->cpu_inst->status_register |=  0b1 << 3; }
void clearDecimalFlag() { OurComputer->cpu_inst->status_register &=  ~(0b1 << 3); }
byte getDecimalFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 3) >> 3; }

void setInterruptFlag() { OurComputer->cpu_inst->status_register |=  0b1 << 2; }
void clearInterruptFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 2); }
byte getInterruptFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 2) >> 2; }

void setZeroFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 1; }
void clearZeroFlag() { OurComputer->cpu_inst->status_register &=  ~(0b1 << 1); }
byte getZeroFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 1) >> 1; }

void setCarryFlag() { OurComputer->cpu_inst->status_register |= 0b1; }
void clearCarryFlag() { OurComputer->cpu_inst->status_register &= ~(0b1); }
byte getCarryFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1); }

address read_16(address pc) {
  return OurComputer->RAM[pc] | OurComputer->RAM[pc + 1] << 8;
}

int write_opcodes(byte a_mask) {
  return (a_mask == 0b110 || a_mask == 0b111 || a_mask == 0b100 || a_mask == 0b000 || a_mask == 0b001 || a_mask == 0b010 || a_mask == 0b011);
}

void update_PC(){
  OurComputer->cpu_inst->pc = ret.pc; 
}

void decode(byte opcode) {
  int a_mask, b_mask, c_mask; 
  a_mask = (opcode & 0b11100000) >> 5;
  b_mask = (opcode & 0b00011100) >> 2; 
  c_mask = opcode & 0b00000011;
  if (c_mask == 0b00) {
    switch(b_mask) {
      // immedate 
      case 0:
        ret.arg = OurComputer->RAM[getProgramCounter() + 1];
        ret.pc = getProgramCounter() + 2;
        break;
      // zeropage 
      case 1: 
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        if (a_mask == 0b100) {  // STY 
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 2;
        break;
      // absolute
      case 3: 
        ret.pc = read_16(getProgramCounter() + 1);
        if (a_mask == 0b010) {  // JMP
          break;
        }
        if (a_mask == 0b011) {  // JMP (abs)
          ret.pc = read_16(ret.pc);
          break;
        }
        if (a_mask == 0b100) {  // STY 
          ret.arg = 3;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 3;
        break;
      // zeropage, x
      case 5:
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        ret.pc += getRegisterX();
        if (a_mask == 0b100) {  // STY 
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 2;
        break;
      // absolute, x
      case 7:
        ret.pc = read_16(getProgramCounter() + 1);
        ret.pc += getRegisterX();
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 3;
        break;

      default:
        break;
    }
  }
  else if (c_mask == 0b01) {
    switch(b_mask) {
      // (zeropage, x)
      case 0:
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        ret.pc += getRegisterX();
        ret.pc = read_16(ret.pc);
        if (a_mask == 0b100) {  // STA
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 2;
        break;
      // zeropage
      case 1:
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        if (a_mask == 0b100) {  // STA
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 2;
        break;
      // immediate
      case 2: 
        ret.arg = OurComputer->RAM[getProgramCounter() + 1];
        ret.pc = getProgramCounter() + 2;
        break;
      // absolute
      case 3: 
        ret.pc = read_16(getProgramCounter() + 1);
        if (a_mask == 0b100) {  // STA 
          ret.arg = 3;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 3;
        break;
      // (zeropage), y
      case 4:
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        ret.pc = read_16(ret.pc);
        ret.pc += getRegisterY();
        ret.pc = read_16(ret.pc);
        if (a_mask == 0b100) {  // STA
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];   
        ret.pc = getProgramCounter() + 2;
        break;
      // zeropage, x
      case 5:
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        ret.pc += getRegisterX();
        if (a_mask == 0b100) {  // STA
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 2;
        break;
      // absolute, y
      case 6:
        ret.pc = read_16(getProgramCounter() + 1);
        ret.pc += getRegisterY();
        if (a_mask == 0b100) {  // STA
          ret.arg = 3;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 3;
        break;
      // absolute, x
      case 7:
        ret.pc = read_16(getProgramCounter() + 1);
        ret.pc += getRegisterX();
        if (a_mask == 0b100) {  // STA
          ret.arg = 3;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 3;
        break;
      default:
        break;
    }
  }
  else if (c_mask == 0b10) {
    switch(b_mask) {
      // immedate 
      case 0:
        ret.arg = OurComputer->RAM[getProgramCounter() + 1];
        ret.pc = getProgramCounter() + 2;
        break;
      // zeropage 
      case 1: 
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR 
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 2;
        break;
      // accumulator
      case 2: 
        ret.arg = getAccumulator();
        ret.pc = getProgramCounter() + 1;
        break;
      // absolute
      case 3: 
        ret.pc = read_16(getProgramCounter() + 1);
        if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR 
          ret.arg = 3;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 3;
        break;
      // zeropage, x
      case 5:
        ret.pc = OurComputer->RAM[getProgramCounter() + 1];
        if (a_mask == 0b100 || a_mask == 0b101){ // STX or LDX
          ret.pc += getRegisterY();
        }
        else{
          ret.pc += getRegisterX();
        }
        if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR 
          ret.arg = 2;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 2;
        break;
      // absolute, x
      case 7:
        ret.pc = read_16(getProgramCounter() + 1);
        if (a_mask == 0b100 || a_mask == 0b101){ // STX or LDX
          ret.pc += getRegisterY();
        }
        else{
          ret.pc += getRegisterX();
        }
        if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR 
          ret.arg = 3;
          break;
        }
        ret.arg = OurComputer->RAM[ret.pc];
        ret.pc = getProgramCounter() + 3;
        break;

      default:
        break;
    }
  }
  return;
}

void stack_push(byte val){
  if(OurComputer->cpu_inst->stack_pointer == 0){
    printf("Stack full"); 
    exit(-1); 
  }
  address stack_ptr = 1U << 8 | OurComputer->cpu_inst->stack_pointer; 
  OurComputer->RAM[stack_ptr] = val; 
  OurComputer->cpu_inst->stack_pointer--; 
}

byte stack_pull(){
  if(OurComputer->cpu_inst->stack_pointer == 0xFF){
    printf("Stack empty"); 
    exit(-1); 
  }
  OurComputer->cpu_inst->stack_pointer++; 
  address stack_ptr = 1U << 8 | OurComputer->cpu_inst->stack_pointer; 
  return OurComputer->RAM[stack_ptr]; 
}

 // May need to figure out how to adjust bases for decimal, binary addition

  /*
  // set carry flag if result bigger than max value
  // in decimal mode
  if(getDecimalFlag()){
    if(res > 99){
      setCarryFlag();
    }else{
      clearCarryFlag();
    }
  } // in binary (normal) mode
  else{
    if(res > 255){
      setCarryFlag();
    }else{
      clearCarryFlag();
    } 
  }*/
void ADC(byte opcode, address pc) {
  decode(opcode);
  // pull high bits to test for overflow later
  byte acc_hi = ((getAccumulator() & 0x80) >> 7);
  byte arg_hi = ((ret.arg & 0x80) >> 7);
  // perform addition, cull result to 2 bytes
  int16_t res = (int16_t) (getAccumulator() + ret.arg);

  printf("res = %d \n", res); 
  printf("ret.arg = %d \n", ret.arg); 
  printf("Accumulator = %u \n", getAccumulator()); 
  
  OurComputer->cpu_inst->accumulator = (byte) (res & 0x00ff);
  // add 1 if carry flag set 
  if(getCarryFlag()){
    OurComputer->cpu_inst->accumulator += 1;
    res += 1; 
  }

  if(res > 255){
      setCarryFlag();
  }else{
      clearCarryFlag();
  } 

  // pull high bits of result to test for overflow 
  byte res_hi = ((getAccumulator() & 0x80) >> 7);
  if(acc_hi == arg_hi && acc_hi != res_hi){
    setOverflowFlag();
  }else{
    clearOverflowFlag();
  }
  // test high bit of result to see if negative 
  if(res_hi){
    setNegativeFlag();
  }else{
    clearNegativeFlag();
  }
  // if result is 0, set zero flag 
  if(getAccumulator() == 0x00){
    setZeroFlag();
  }else{
    clearZeroFlag();
  }
  update_PC(); 
}

void AND(byte opcode, address pc) {
  decode(opcode); 
  OurComputer->cpu_inst->accumulator &= ret.arg; 
  if(OurComputer->cpu_inst->accumulator == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->accumulator >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  update_PC(); 
}




void ASL(byte opcode, address pc) {
  byte inp; 
  decode(opcode);

  if (opcode == 0xa) {
    inp = ret.arg;  
  } else {
    inp = OurComputer->RAM[ret.pc];
  }

  // set carry (with 0th bit)
  printf("inp = %u \n", inp);

  clearCarryFlag();
  OurComputer->cpu_inst->status_register |= (inp >> 7);


  // perform shift 
  inp = inp << 1;
  printf("inp = %u \n", inp);
  // set zero
  if(inp == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }

  // get high bit of result to set negative 
  byte res_hi = inp >> 7;
  // set negative
  if(res_hi){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }

  // check opcode to see if using accumulator 
  if(opcode == 0xa){
    printf("inp = %u \n", inp);
    printf("Accumulator = %u \n", OurComputer->cpu_inst->accumulator);
    OurComputer->cpu_inst->accumulator = inp;
    OurComputer->cpu_inst->pc++;
  }
  else{
    OurComputer->RAM[ret.pc] = inp;
    OurComputer->cpu_inst->pc += ret.arg;
  }
}

// BCC - branch on Carry Flag = 0
void BCC(byte opcode, address pc){
  if (!getCarryFlag()) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }

  OurComputer->cpu_inst->pc += 2;
  return;
}

// BCS - branch on Carry Flag = 1
void BCS(byte opcode, address pc){
  if (getCarryFlag()) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }
  OurComputer->cpu_inst->pc += 2;
  return; 
}

// BEQ - branch on Zero Flag = 1
void BEQ(byte opcode, address pc) {
  if (getZeroFlag()) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }
  OurComputer->cpu_inst->pc += 2;
  return; 
}

void BIT(byte opcode, address pc) {
  decode(opcode); 

  int BIT6_mask = 0b1 << 6;
  int BIT7_mask = 0b1 << 7;

  clearOverflowFlag();
  clearNegativeFlag();
  clearZeroFlag();
  OurComputer->cpu_inst->status_register |= (((BIT6_mask & ret.arg) >> 6) << 6) ; 
  OurComputer->cpu_inst->status_register |= (((BIT7_mask & ret.arg) >> 7) << 7) ; 
  OurComputer->cpu_inst->status_register |= (((OurComputer->cpu_inst->accumulator & ret.arg) & 0b10)); 
  
  update_PC();
  return; 
}

void CLC(byte opcode, address pc) {
  clearCarryFlag();
  OurComputer->cpu_inst->pc++;    // update PC
  return; 
}

// BMI - branch on Negative Flag = 1
void BMI (byte opcode, address pc) {
  if (getNegativeFlag()) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }
  OurComputer->cpu_inst->pc += 2;
  return; 
}

// BNE - branch on Zero Flag = 0
void BNE (byte opcode, address pc) {
  if (!getZeroFlag()) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }
  OurComputer->cpu_inst->pc += 2;
  return; 
}

// BPL - branch on Negative Flag = 0
void BPL (byte opcode, address pc) {
  if (!getNegativeFlag()) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }
  OurComputer->cpu_inst->pc += 2;
  return; 
}

//BVC - branch on Overflow = 0
void BVC (byte opcode, address pc) {
  if (getOverflowFlag() == 0) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }
  OurComputer->cpu_inst->pc+=2; 
}

// BVS - branch on Overflow = 1
void BVS (byte opcode, address pc) {
  if(getOverflowFlag() == 1) {
    OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1];
  }
  OurComputer->cpu_inst->pc+=2; 
}

void CLD(byte opcode, address pc) {
  clearDecimalFlag();
  OurComputer->cpu_inst->pc++;    // update PC
}

void CLI(byte opcode, address pc) {
  clearInterruptFlag();
  OurComputer->cpu_inst->pc++;    // update PC
}

void CLV(byte opcode, address pc) {
  clearOverflowFlag();
  OurComputer->cpu_inst->pc++;    // update PC
}

/*
The use of the CMP affects the following flags: Z flag is
set on an equal comparison, reset otherwise; the N flag is Set or
reset by the result bit 7, the carry flag is Set when the value in
memory is less than or equal to the accumulator, reset when it is
greater than the accumulator. */
void CMP(byte opcode, address pc) {
  decode(opcode);
  byte res = getAccumulator() - ret.arg;

  if (res == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  if ((res >> 7) & 0b1 ){
    setNegativeFlag();
  } else{
    clearNegativeFlag();
  }
  if (ret.arg <= getAccumulator()){
    setCarryFlag();
  } else{
    clearCarryFlag();
  }
  update_PC();
}

/*  The  CPX instruction does not affect any register in the machine;
it also does not affect the overflow flag.  It causes the carry to be
set on if the absolute value of the index register X is equal to or
greater than the data from memory.  If the value of the memory is
greater than the content of the index register X, carry is reset.
If the results of the subtraction contain a bit 7, then the N flag
is set, if not, it is reset.  If the value in memory is equal to the
value in index register X, the Z flag is set, otherwise it is reset. */
void CPX(byte opcode, address pc) {
  decode(opcode);
  byte res = getRegisterX() - ret.arg;

  printf("res = %d \n", res); 
  printf("ret.arg = %d \n", ret.arg); 
  printf("Register x = %u \n", getRegisterX()); 
  printf("7th bit = %u \n", (res >> 7U) & 0b1); 

  if(abs( (int8_t) getRegisterX()) >= ret.arg){
    setCarryFlag();
  } else{
    clearCarryFlag();
  }
  if ((res >> 7) & 0b1) {
    setNegativeFlag();
  } else {
    clearNegativeFlag();
  }
  if (res == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  update_PC(); 
}

/*  If the value in the index register Y is
equal to or greater than the value in the memory, the carry flag will
be set, otherwise it will be cleared.  If the results of the subtract-
tion contain bit 7 on the N bit will be set, otherwise it will be
cleared.  If the value in the index register Y and the value in the
memory are equal, the zero flag will be set, otherwise it will be
cleared.*/
void CPY(byte opcode, address pc) {
  decode(opcode);
  byte res = getRegisterY() - ret.arg;
  if(abs( (int8_t) getRegisterY()) >= ret.arg){
    setCarryFlag();
  } else{
    clearCarryFlag();
  }
  if((res >> 7) & 0b1){
    setNegativeFlag();
  } else {
    clearNegativeFlag();
  }
  if (res == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  update_PC();
}

//Flags: N+ Z+ 
void DEC(byte opcode, address pc) {
  decode(opcode);
  OurComputer->RAM[ret.pc] -= 1;
  //set flags
  if ((OurComputer->RAM[ret.pc] & (0b1 << 7)) >> 7 )  {
    setNegativeFlag();
  }
  else {
    clearNegativeFlag();
  }
  if (OurComputer->RAM[ret.pc] == 0) {
    setZeroFlag();
  }
  else {
    clearZeroFlag();
  }
  OurComputer->cpu_inst->pc += ret.arg; // update PC
}

void DEX(byte opcode, address pc) {
  OurComputer->cpu_inst->register_x -= 1;
  if((OurComputer->cpu_inst->register_x >> 7) & 0b1){
    setNegativeFlag();
  } else {
    clearNegativeFlag();
  }
  if (OurComputer->cpu_inst->register_x == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  OurComputer->cpu_inst->pc++; 
}

void DEY(byte opcode, address pc) {
  OurComputer->cpu_inst->register_y -= 1;
  if((OurComputer->cpu_inst->register_y >> 7) & 0b1){
    setNegativeFlag();
  } else {
    clearNegativeFlag();
  }
  if (OurComputer->cpu_inst->register_y == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  OurComputer->cpu_inst->pc++; 
}

//Flags: N+ Z+ 
void INC(byte opcode, address pc) {
  decode(opcode);
  OurComputer->RAM[ret.pc] += 1;
  //set flags
  if ((OurComputer->RAM[ret.pc] & (0b1 << 7)) >> 7 )  {
    setNegativeFlag();
  }
  else {
    clearNegativeFlag();
  }
  if (OurComputer->RAM[ret.pc] == 0) {
    setZeroFlag();
  }
  else {
    clearZeroFlag();
  }
  OurComputer->cpu_inst->pc += ret.arg; // update PC
}

void INX(byte opcode, address pc) {
  OurComputer->cpu_inst->register_x += 1;
  if((OurComputer->cpu_inst->register_x >> 7) & 0b1){
    setNegativeFlag();
  } else {
    clearNegativeFlag();
  }
  if (OurComputer->cpu_inst->register_x == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  OurComputer->cpu_inst->pc++; 
}

void INY(byte opcode, address pc) {
  OurComputer->cpu_inst->register_y += 1;
  if((OurComputer->cpu_inst->register_y >> 7) & 0b1){
    setNegativeFlag();
  } else {
    clearNegativeFlag();
  }
  if (OurComputer->cpu_inst->register_y == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  OurComputer->cpu_inst->pc++; 
}

void EOR(byte opcode, address pc) {
  decode(opcode);
  OurComputer->cpu_inst->accumulator ^= ret.arg; 
  if((OurComputer->cpu_inst->accumulator >> 7) & 0b1){
    setNegativeFlag();
  } else {
    clearNegativeFlag();
  }
  if (OurComputer->cpu_inst->accumulator == 0) {
    setZeroFlag();
  } else {
    clearZeroFlag();
  }
  update_PC();
}

void LDA(byte opcode, address pc) {
  decode(opcode);
  OurComputer->cpu_inst->accumulator = ret.arg;
  if(OurComputer->cpu_inst->accumulator == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if(OurComputer->cpu_inst->accumulator >> 7){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  update_PC();
}

void LDX(byte opcode, address pc) {
  decode(opcode);
  OurComputer->cpu_inst->register_x  = ret.arg;
  if(OurComputer->cpu_inst->register_x == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->register_x >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  update_PC();
}

void LDY(byte opcode, address pc) {
  decode(opcode);
  OurComputer->cpu_inst->register_y  = ret.arg;
  if(OurComputer->cpu_inst->register_y == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->register_y >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  update_PC();
}

void NOP(byte opcode, address pc) { 
  OurComputer->cpu_inst->pc += 1;   // update PC
}

void ORA(byte opcode, address pc) {
  decode(opcode); 
  OurComputer->cpu_inst->accumulator |= ret.arg;
  if(OurComputer->cpu_inst->accumulator == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->accumulator >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  update_PC();
}

// N+ Z+ C+ 
void ROL(byte opcode, address pc) {

  decode(opcode);
  byte rotated; 
  byte carry = getCarryFlag();

  clearCarryFlag();

  if(opcode == 0x2a){
    OurComputer->cpu_inst->status_register |= OurComputer->cpu_inst->accumulator >> 7;
    OurComputer->cpu_inst->accumulator = OurComputer->cpu_inst->accumulator  << 1U; 
    rotated =  OurComputer->cpu_inst->accumulator | carry ;  
    OurComputer->cpu_inst->accumulator = rotated; 
  }
  else{ // memory
    OurComputer->cpu_inst->status_register |= OurComputer->RAM[ret.pc] >> 7;
    OurComputer->RAM[ret.pc] = OurComputer->RAM[ret.pc]  << 1U; //shift OurComputer->RAM[ret.pc] over one bit
    rotated = OurComputer->RAM[ret.pc] | carry;
    OurComputer->RAM[ret.pc] = rotated; //move carry into the 7th bit
  }

  if( rotated >> 7 ) {
    setNegativeFlag();
  }
  else {
    clearNegativeFlag();
  }

  if (rotated == 0) {
    setZeroFlag();
  }
  else {
    clearZeroFlag();
  }

  if (opcode == 0x2a) {
    OurComputer->cpu_inst->pc++;
  }
  else {
    OurComputer->RAM[ret.pc] += ret.arg;
  }
  
}

//void ROR(byte opcode, byte* pc) {decode(opcode); rotate *ret.arg by 1 bit right};
void ROR(byte opcode, address pc) {
  decode(opcode);
  byte rotated; 
  byte carry = getCarryFlag();

  clearCarryFlag();

  if(opcode == 0x6a){
    OurComputer->cpu_inst->status_register |= OurComputer->cpu_inst->accumulator & 1;
    OurComputer->cpu_inst->accumulator = OurComputer->cpu_inst->accumulator  >> 1U; 
    rotated =  (carry << 7) | OurComputer->cpu_inst->accumulator; 
    OurComputer->cpu_inst->accumulator = rotated; 
  }
  else{ // memory
    OurComputer->cpu_inst->status_register |= OurComputer->RAM[ret.pc] & 1;
    OurComputer->RAM[ret.pc] = OurComputer->RAM[ret.pc]  >> 1; //shift OurComputer->RAM[ret.pc] over one bit
    rotated = (carry << 7) | OurComputer->RAM[ret.pc];
    OurComputer->RAM[ret.pc] = rotated; //move carry into the 7th bit
  }

  if(rotated >> 7) {
    setNegativeFlag();
  }
  else {
    clearNegativeFlag();
  }

  if (rotated == 0) {
    setZeroFlag();
  }
  else {
    clearZeroFlag();
  }

  if (opcode == 0x6a) {
    OurComputer->cpu_inst->pc++;
  }
  else {
    OurComputer->RAM[ret.pc] += ret.arg;
  }
}

void SBC(byte opcode, address pc) {
  decode(opcode);
  // pull high bits to test for overflow later

  ret.arg = ~(ret.arg);

  byte acc_hi = ((getAccumulator() & 0x80) >> 7);
  byte arg_hi = ((ret.arg & 0x80) >> 7);
  // perform addition, cull result to 2 bytes
  int16_t res = (int16_t) (getAccumulator() + ret.arg);

  printf("res = %d \n", res); 
  printf("ret.arg = %d \n", ret.arg); 
  printf("Accumulator = %u \n", getAccumulator()); 
  
  OurComputer->cpu_inst->accumulator = (byte) (res & 0x00ff);
  // add 1 if carry flag set 
  if(getCarryFlag()){
    OurComputer->cpu_inst->accumulator += 1;
    res += 1; 
  }

  if(res > 255){
      setCarryFlag();
  }else{
      clearCarryFlag();
  } 

  // pull high bits of result to test for overflow 
  byte res_hi = ((getAccumulator() & 0x80) >> 7);
  if(acc_hi == arg_hi && acc_hi != res_hi){
    setOverflowFlag();
  }else{
    clearOverflowFlag();
  }
  // test high bit of result to see if negative 
  if(res_hi){
    setNegativeFlag();
  }else{
    clearNegativeFlag();
  }
  // if result is 0, set zero flag 
  if(getAccumulator() == 0x00){
    setZeroFlag();
  }else{
    clearZeroFlag();
  }
  update_PC(); 
}

void SEC(byte opcode, address pc) {
  setCarryFlag();
  OurComputer->cpu_inst->pc++;    // update PC
}

void SED(byte opcode, address pc) {
  setDecimalFlag();
  OurComputer->cpu_inst->pc++;    // update PC
}

void SEI(byte opcode, address pc) {
  setInterruptFlag();
  OurComputer->cpu_inst->pc++;
}

void STA(byte opcode, address pc) {
  decode(opcode);
  OurComputer->RAM[ret.pc] = getAccumulator();
  OurComputer->cpu_inst->pc += ret.arg;
}

void STX(byte opcode, address pc) {
  decode(opcode);
  OurComputer->RAM[ret.pc] = getRegisterX();
  OurComputer->cpu_inst->pc += ret.arg;
}

void STY(byte opcode, address pc) {
  decode(opcode);
  OurComputer->RAM[ret.pc] = getRegisterY();
  OurComputer->cpu_inst->pc += ret.arg;
}

void TAX(byte opcode, address pc) {
  OurComputer->cpu_inst->register_x = getAccumulator();
  if(OurComputer->cpu_inst->register_x == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->register_x >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  OurComputer->cpu_inst->pc++;    // update PC
}

void TAY(byte opcode, address pc) {
  OurComputer->cpu_inst->register_y = getAccumulator();
  if(OurComputer->cpu_inst->register_y == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->register_y >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  OurComputer->cpu_inst->pc++;    // update PC
}

void TSX(byte opcode, address pc) {
  OurComputer->cpu_inst->register_x = getStackPointer();
  if(OurComputer->cpu_inst->register_x == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->register_x >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  OurComputer->cpu_inst->pc++;    // update PC
}

void TXA(byte opcode, address pc) {
  OurComputer->cpu_inst->accumulator = getRegisterX();
  if(OurComputer->cpu_inst->accumulator == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->accumulator >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  OurComputer->cpu_inst->pc++;    // update PC
}

void TXS(byte opcode, address pc) {
  OurComputer->cpu_inst->stack_pointer = getRegisterX();
  OurComputer->cpu_inst->pc++;    // update PC
}

void TYA(byte opcode, address pc) {
  OurComputer->cpu_inst->accumulator = getRegisterY();
   if(OurComputer->cpu_inst->accumulator == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  if((OurComputer->cpu_inst->accumulator >> 7) & 1){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }
  OurComputer->cpu_inst->pc++;    // update PC
}

void JMP(byte opcode, address pc) {
  decode(opcode);
  OurComputer->cpu_inst->pc = ret.pc;
  return; 
}

void LSR(byte opcode, address pc) {
  byte inp; 
  decode(opcode);

  if (opcode == 0x4a) {
    inp = ret.arg;  
  } else {
    inp = OurComputer->RAM[ret.pc];
  }
  // get low bit of input to set carry 
  byte inp_low = inp & 0x01;

  // set carry (with 0th bit)

  printf("inp = %u \n", inp);

  clearCarryFlag();
  OurComputer->cpu_inst->status_register |= inp_low;

  // perform shift 
  inp = inp >> 1;
  printf("inp = %u \n", inp);
  // set zero
  if(inp == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }

  // get high bit of result to set negative 
  byte res_hi = inp >> 7;
  // set negative
  if(res_hi){
    setNegativeFlag();
  }
  else{
    clearNegativeFlag();
  }

  // check opcode to see if using accumulator 
  if(opcode == 0x4a){
    printf("inp = %u \n", inp);
    printf("Accumulator = %u \n", OurComputer->cpu_inst->accumulator);
    OurComputer->cpu_inst->accumulator = inp;
    OurComputer->cpu_inst->pc++;
  }
  else{
    OurComputer->RAM[ret.pc] = inp;
    OurComputer->cpu_inst->pc += ret.arg;
  }
}

void PHP(byte opcode, address pc) {
  setBreakFlag();
  setIgnoreFlag();
  stack_push(getStatusRegister()); 
  OurComputer->cpu_inst->pc++; 
  return; 
}

void PLP(byte opcode, address pc) {
  OurComputer->cpu_inst->status_register = stack_pull(); 
  clearBreakFlag();
  //clearIgnoreFlag();
  OurComputer->cpu_inst->pc++; 
  return; 
}


void PHA(byte opcode, address pc) {
  stack_push(getAccumulator()); 
  OurComputer->cpu_inst->pc++;
  return; 
}

void PLA(byte opcode, address pc) {
  OurComputer->cpu_inst->accumulator = stack_pull(); 


  if((OurComputer->cpu_inst->accumulator & 1 << 7)){ // if 7th bit is set in accumulator 
    setNegativeFlag(); 
  }
  else{
    clearNegativeFlag(); 
  }
  if(OurComputer->cpu_inst->accumulator == 0){
    setZeroFlag();
  }
  else{
    clearZeroFlag();
  }
  OurComputer->cpu_inst->pc++; 
  return; 
}

void RTI(byte opcode, address pc) {
  byte PCLOW, PCHIGH; 
  OurComputer->cpu_inst->status_register = stack_pull(); 
  //PCHIGH = stack_pull();
  PCLOW = stack_pull() - 1;  
  PCHIGH = stack_pull();
  OurComputer->cpu_inst->pc = PCHIGH << 8 | PCLOW; 
  OurComputer->cpu_inst->pc++; 
  return; 
}

void RTS(byte opcode, address pc) {
  byte PCLOW, PCHIGH; 
  //PCHIGH = stack_pull(); 
  PCLOW = stack_pull() - 1;
  PCHIGH = stack_pull(); 
  OurComputer->cpu_inst->pc = PCHIGH << 8 | PCLOW; 
  OurComputer->cpu_inst->pc += 2; 
  return; 
}

void BRK(byte opcode, address pc) {
  setBreakFlag();
  setInterruptFlag();
  // software interrupt 
  byte PCLOW, PCHIGH;
  PCHIGH = (getProgramCounter()) >> 8; 
  PCLOW = 0x00FF & (getProgramCounter() + 2); 
  stack_push(PCHIGH); 
  stack_push(PCLOW);

  stack_push(getStatusRegister()); 
  return; 
}

void JSR(byte opcode, address pc) {
  byte PCLOW, PCHIGH; 
  PCHIGH = (getProgramCounter()) >> 8; 
  PCLOW = 0x00FF & (getProgramCounter() + 2); 
  stack_push(PCHIGH); 
  stack_push(PCLOW);

  OurComputer->cpu_inst->pc = read_16(getProgramCounter() + 1); 
  return; 
}