Exemplo n.º 1
0
// Execute one instruction cycle
//
void one_instruction_cycle(int reg[], int nreg, int mem[], int memlen) {
	// If the CPU isn't running, say so and return.
	// If the pc is out of range, complain and stop running the CPU.
	//
	if (!running){
		printf("Error: CPU not running.\n");
		return;
	}

	// Get instruction and increment pc
	//
	int instr_loc = pc;  // Instruction's location (pc before increment)
	ir = mem[pc++];
	// Decode instruction into opcode, reg_R, addr_MM, and instruction sign
	//
	int opcode = abs(mem[instr_loc] / 1000);
	int	reg_R = abs((mem[instr_loc] / 100) % 10);
	int addr_MM = abs(mem[instr_loc] % 100);
	int instr_sign = 0;
	// double check we're not trying to divide by 0
	if (mem[instr_loc] != 0) {
		instr_sign = mem[instr_loc] / abs(mem[instr_loc]);
	} 
	 
	// Echo instruction
	//
	printf("At %02d instr %d %d %02d: ", instr_loc, opcode, reg_R, addr_MM);

	// basic bounds checks. bail if we're out of range
	if (reg_R < -1 || nreg < reg_R || addr_MM < -1 || 100 < addr_MM) {
		printf("Error: bad instruction. reg_R or addr_MM is out of bounds.\n");
		return;
	}

	switch (opcode) {
	case 0: exec_HLT(reg_R, addr_MM, reg, nreg, mem, memlen); break;
	case 1: exec_LD(reg_R, addr_MM, reg, nreg, mem, memlen); break;
	case 2: exec_ST(reg_R, addr_MM, reg, nreg, mem, memlen); break;
	case 3: exec_ADD(reg_R, addr_MM, reg, nreg, mem, memlen); break;
	case 4: exec_NEG(reg_R, reg, nreg); break;
	case 5: exec_LDM(reg_R, addr_MM, instr_sign, reg, nreg, mem, memlen); break;
	case 6: exec_ADDM(reg_R, addr_MM, instr_sign, reg, nreg, mem, memlen); break;
	case 7: exec_BR(addr_MM, mem, memlen); break;
	case 8: exec_BRC(reg_R, addr_MM, instr_sign, reg, nreg, mem, memlen); break;
	case 9:
		switch (reg_R) {
			case 0: exec_GETC(reg, nreg); break;
			case 1: exec_OUT(reg, nreg); break;
			case 2: exec_PUTS(addr_MM, mem, memlen); break;
			case 3: exec_DMP(addr_MM, reg, nreg, mem, memlen); break;
			case 4: exec_MEM(addr_MM, reg, nreg, mem, memlen); break;
			case 5: 
			case 6:
		   	case 7: 
			case 8:
		   	case 9: printf("Unknown I/O; skipped\n"); break;
		}
		break;
	default: printf("Bad opcode!? %d\n", opcode);
	}
}
void one_instruction_cycle(int reg[], int nreg,
                           int mem[], int memlen)
{
  int reg_R, addr_MM, instr_sign, opcode;

  /* Check if CPU is running */
  if (running == 0) {
    printf("The CPU is not running");
    return;
  }

  /* Make sure that we didn't hit any boundaries */
  if (pc >= memlen) {
    printf("Program counter out of range");
    exec_HLT();
  }

  /* Get instruction and increment PC */
  int instr_loc = pc;
  ir = mem[pc++];

  /* Check instruction sign */
  if (ir < 0) {
    instr_sign = -1;
    ir *= -1;
  } else if (ir > 0) {
    instr_sign = 1;
  }

  /* Decode instruction into opcode, register, and memory address */
  opcode = ir / 1000;
  reg_R = (ir % 1000) / 100;
  addr_MM = ir % 100;

  printf("At %02d instr %d %d %02d: ",
         instr_loc, opcode, reg_R, addr_MM);

  switch (opcode) {
  /* HALT */
  case 0:
    exec_HLT();
    break;

  /* LOAD */
  case 1: {
    reg[reg_R] = mem[addr_MM];
  } break;

  /* STORE */
  case 2: {
    mem[addr_MM] = reg[reg_R];
  } break;

  /* ADD-IM-MM */
  case 3: {
    reg[reg_R] += mem[addr_MM];
  } break;

  /* NOT */
  case 4: {
    reg[reg_R] = (-reg[reg_R]);
  } break;

  /* LOAD IMMEDIATE */
  case 5: {
    reg[reg_R] = addr_MM * instr_sign;
  } break;

  /* ADD IMMEDIATE */
  case 6: {
    reg[reg_R] += addr_MM * instr_sign;
  } break;

  /* JUMP */
  case 7: {
    pc = addr_MM;
  } break;

  /* BRANCH CONDITIONAL */
  case 8: {
    if (reg[reg_R] > 0 && instr_sign > 0) {
      pc = addr_MM;
    } else if (reg[reg_R] < 0 && instr_sign < 0)
      pc = addr_MM;
  } break;

  /* I/O Subroutines */
  case 9: {
    switch (reg_R) {
    /* GETCHAR */
    case 0: {
      printf("enter a character>> ");
      int k = getchar();
      reg[0] = k;
    } break;

    /* PRINTCHAR */
    case 1: {
      printf("%c\n", reg[0]);
    } break;

    /* PRINT-STRING */
    case 2: {
      while (mem[addr_MM] != 0) {
          printf("%c \n", mem[addr_MM++]);
      }
      printf("\n");
    } break;

    /* DUMP CU */
    case 3: {
      dump_control_unit(pc, ir, running, reg, nreg);
    } break;

    /* DUMP MEM */
    case 4: {
      dump_memory(mem, memlen);
    } break;

    default:
      return;
      break;
    }
  } break;
  default:
    printf("Bad opcode!? %d\n", opcode);
  }
}