예제 #1
0
uint8_t CPU::fetch_destination(ADDRESSING_MODE mode) {
	switch (mode) {

	case ADDRESSING_ZEROPAGE:
	{
		return fetch_operand(ADDRESSING_IMMEDIATE);
	}
	case ADDRESSING_ZEROPAGE_X:
	{
		return fetch_operand(ADDRESSING_IMMEDIATE) + index_x;
	}
	case ADDRESSING_ZEROPAGE_Y:
	{
		return fetch_operand(ADDRESSING_IMMEDIATE) + index_y;
	}
	default:
	{
		printf("fetch_destination(): Invalid addressing mode %d", mode);
		std::exit(255);
	}

	}
}
예제 #2
0
//--------------------------------------------------------------------
// void execute(instr *i)
//
//   execute consists of the following tasks:
//        - fetch the operands
//        - execute the operation in the intruction
//        - write the data back in the destination
//        - compute the next address for (jmp, call, return...)
//
//--------------------------------------------------------------------
void cycle_model::execute(instr *i) {
  int in1, in2, out = 0;

  // fetch operands ---------------------------------------------------
  if(i->n_src>=1)
    in1 = fetch_operand(&(i->src1));

  if(i->n_src>=2)
    in2 = fetch_operand(&(i->src2));
 
#ifdef DEBUG
  printf("execute %d, with in1=%d and in2=%d\n",i->type,in1, in2); 
#endif

  // execute ----------------------------------------------------------
  switch(i->type) {
  case i_add: {
    out = in1 + in2;
    break;
  }
  case i_sub: {
    out = in1 - in2;
    break;
  }	
  case i_inc: {
    out = in1+1;
    break;
  }
  case i_dec: {
    out = in1-1;
    break;
  }
  case i_mul: {
    out = in1 * in2;
    break;
  }
  case i_div: {
    out = in1/in2;
    break;
  }
  // logic operations
  case i_and: {
    out = in1 & in2;
    break;
  }
  case i_or: {
    out = in1 | in2;
    break;
  }
  case i_xor: {
    out = in1 ^ in2;
    break;
  }
  case i_rl: {
    out = in1<<1;
    break;
  }
  case i_rr: {
    out = in2>>1;
    break;
  }
  // data transfer
  case i_mov: {
    out = in1;
    break;
  }
  // branching (out==0 -> don't branch)
  case i_call:
  case i_ret:
  case i_jmp:
  case i_sjmp: {
    out = 1;
    break;
  }
  case i_jz: {
    out = (A==0);
    break;
  }
  case i_jnz: {
    out = (A!=0);
    break;
  }
  case i_cjne: {
    out = (in1!=in2);
    break;
  }
  case i_djnz: {
    out=in1-1; // decrement reg/direct and jump if != 0
    break;
  }
  default: {
    break;
  }
  }


  // write back --------------------------------------------------------
  write_back(&(i->dst),out);

  // compute next address ----------------------------------------------
  switch(i->type) {
  case i_call: {
    stack_el *new_stack_el= (stack_el *) malloc(sizeof(stack_el));
    new_stack_el->up = my_stack;
    new_stack_el->address = in1;
    my_stack = new_stack_el;

    /* wait additional cycles */
    int result;
    exec_bus_cycle(OP_IDLE,0,0,&result);
    
    break;
  }
  case i_ret: {
    stack_el *new_stack_el = my_stack->up;
    free(my_stack);
    my_stack = new_stack_el;
    if(my_stack!=NULL)
      my_stack->address += 1; // increment address after jump

    /* wait additional cycles */
    int result;
    exec_bus_cycle(OP_IDLE,0,0,&result);
    exec_bus_cycle(OP_IDLE,0,0,&result);
    exec_bus_cycle(OP_IDLE,0,0,&result);
    break;
  }
  case i_jmp: {
    my_stack->address = in1;

    /* wait additional cycles */
    int result;
    exec_bus_cycle(OP_IDLE,0,0,&result);
     
    break;
  }
  case i_sjmp:
  case i_jz:
  case i_jnz: {
    if(out!=0)
      my_stack->address += in1+1;
    else
      my_stack->address += 1;

    /* wait additional cycles */
    int result;
    exec_bus_cycle(OP_IDLE,0,0,&result);
 
    break;
  }
  case i_cjne: {
    int in3 = fetch_operand(&i->dst); 
    if(out!=0)
      my_stack->address += in3+1;
    else
      my_stack->address += 1;

    /* wait additional cycles */
    int result;
    exec_bus_cycle(OP_IDLE,0,0,&result);

    break;
  }
  case i_djnz: {
    if(out!=0)
      my_stack->address += in2+1;
    else
      my_stack->address += 1;

    /* wait additional cycles */
    int result;
    exec_bus_cycle(OP_IDLE,0,0,&result);

    break;
  }
  default: {
     my_stack->address += 1;
     break;
  }
  }
}
예제 #3
0
uint8_t CPU::fetch_operand(ADDRESSING_MODE mode) {
	lastInstructionCrossedPageBoundary = false;

	switch (mode) {
	case ADDRESSING_IMMEDIATE:
	{
		uint8_t operand = fetch_memory_byte(program_counter, true);
		last_operand = operand;
		return operand;
	}

	case ADDRESSING_ZEROPAGE:
	{
		//TODO: Why is this here?
		uint8_t address = fetch_operand(ADDRESSING_IMMEDIATE);
		last_operand = address;
		return address;
	}

	case ADDRESSING_ZEROPAGE_X:
	{
		uint8_t address = fetch_operand(ADDRESSING_IMMEDIATE);
		lastInstructionCrossedPageBoundary = (address + index_x < address);
		uint8_t operand = fetch_zero_page_byte(address + index_x);
		last_operand = address;
		return operand;
	}

	case ADDRESSING_ZEROPAGE_Y:
	{
		uint8_t address = fetch_operand(ADDRESSING_IMMEDIATE);
		lastInstructionCrossedPageBoundary = (address + index_y < address);
		uint8_t operand = fetch_zero_page_byte(address + index_y);
		last_operand = address;
		return operand;
	}

	case ADDRESSING_ABSOLUTE:
	{
		uint8_t addrLow = fetch_memory_byte(program_counter);
		uint8_t addrHigh = fetch_memory_byte(program_counter);
		WideAddress address = { addrHigh, addrLow };
		uint8_t operand = fetch_memory_byte(address, false);
		last_operand = address;
		return operand;
	}

	case ADDRESSING_ABSOLUTE_X:
	{
		uint8_t addrLow = fetch_memory_byte(program_counter);
		uint8_t addrHigh = fetch_memory_byte(program_counter);
		WideAddress address = { addrHigh, addrLow };
		lastInstructionCrossedPageBoundary = (addrLow + index_x < addrLow);
		uint8_t operand = fetch_memory_byte(address.add(index_x, false), false);
		last_operand = address;
		return operand;
	}

	case ADDRESSING_ABSOLUTE_Y:
	{
		uint8_t addrLow = fetch_memory_byte(program_counter);
		uint8_t addrHigh = fetch_memory_byte(program_counter);
		WideAddress address = { addrHigh, addrLow };
		lastInstructionCrossedPageBoundary = (addrLow + index_y < addrLow);
		uint8_t operand = fetch_memory_byte(address.add(index_y, false), false);
		last_operand = address;
		return operand;
	}

	case ADDRESSING_INDIRECT_X:
	{
		WideAddress operand_address = fetch_dereferenced_zero_page_pointer(INDEX_X);
		last_operand = operand_address;
		uint8_t operand = fetch_memory_byte(operand_address, false);
		last_operand = operand;
		return operand;
	}

	case ADDRESSING_INDIRECT_Y:
	{
		WideAddress destination = fetch_dereferenced_zero_page_pointer(INDEX_NONE);
		lastInstructionCrossedPageBoundary = ((destination & 0xFF00) + index_y) > (destination & 0xFF00);
		destination = destination.add(index_y, false);
		uint8_t operand = fetch_memory_byte(destination);
		last_operand = operand;
		return operand;
	}
	default:
	{
		printf("fetch_operand(): Invalid addressing mode %d", mode);
		std::exit(255);
	}
	}

}