#include "6502.h" #include "test_vals.h" typedef void (*opcode_function)(byte, address); opcode_function functions[] = {&ADC ,&ADC ,&ADC ,&ADC ,&ADC ,&ADC ,&ADC ,&ADC ,&AND ,&AND ,&AND ,&AND ,&AND ,&AND ,&AND ,&AND ,&ASL ,&ASL ,&ASL ,&ASL ,&BCC ,&BCS ,&BEQ ,&BIT ,&BIT ,&BMI ,&BNE ,&BPL ,&BVC ,&BVS ,&CMP ,&CMP ,&CMP ,&CMP ,&CMP ,&CMP ,&CMP ,&CMP ,&CPX ,&CPX ,&CPX ,&CPY ,&CPY ,&CPY ,&DEC ,&DEC ,&DEC ,&DEC ,&EOR ,&EOR ,&EOR ,&EOR ,&EOR ,&EOR ,&EOR ,&EOR ,&INC ,&INC ,&INC ,&INC ,&JMP ,&JMP ,&JSR ,&LDA ,&LDA ,&LDA ,&LDA ,&LDA ,&LDA ,&LDA ,&LDA ,&LDX ,&LDX ,&LDX ,&LDX ,&LDX ,&LDY ,&LDY ,&LDY ,&LDY ,&LDY ,&LSR ,&LSR ,&LSR ,&LSR ,&ORA ,&ORA ,&ORA ,&ORA ,&ORA ,&ORA ,&ORA ,&ORA ,&ROL ,&ROL ,&ROL ,&ROL ,&ROR ,&ROR ,&ROR ,&ROR ,&SBC ,&SBC ,&SBC ,&SBC ,&SBC ,&SBC ,&SBC ,&SBC ,&STA ,&STA ,&STA ,&STA ,&STA ,&STA ,&STA ,&STX ,&STX ,&STX ,&STY ,&STY ,&STY ,&BRK ,&CLC ,&CLD ,&CLI ,&CLV ,&DEX ,&DEY ,&INX ,&INY ,&NOP ,&PHA ,&PHP ,&PLA ,&PLP ,&RTI ,&RTS ,&SEC ,&SED ,&SEI ,&TAX ,&TAY ,&TSX ,&TXA ,&TXS ,&TYA}; void read_in_binary_image(char* image_name){ int n, fd; if((fd=open(image_name, O_RDONLY)) < 0){ exit(-1); } if((n = read(fd, OurComputer->RAM, RAMSIZE)) != RAMSIZE){ exit(-1); } close(fd); } void initialize_registers() { OurComputer->cpu_inst->pc = 0; OurComputer->cpu_inst->accumulator = 0; OurComputer->cpu_inst->register_x = 0; OurComputer->cpu_inst->register_y = 0; OurComputer->cpu_inst->status_register = 0; OurComputer->cpu_inst->stack_pointer = 0xFF; return; } void execute(byte opcode, address pc) { struct opcode_table *s; // used in execute(byte, address) HASH_FIND_BYTE(OurComputer->opcodes, &opcode, s); if(s == NULL){ printf("Byte not in table \n"); printf("opcode = %x \n", opcode); exit(-1); } (*s->opcode_function) (opcode, pc); return; } // Builds opcode table void build_opcode_table(){ int n, fd; byte* opcodes_keys; OurComputer->opcodes = NULL; // need to read in the opcodes if((opcodes_keys = (byte*) malloc((opcode_size) * sizeof(byte))) == NULL){ exit(-1); } if((fd=open("opcode_values", O_RDONLY)) < 0){ exit(-1); } if((n = read(fd, opcodes_keys, opcode_size)) != opcode_size){ exit(-1); } close(fd); struct opcode_table* s = NULL; for (int i = 0; i < opcode_size; i++){ s = (struct opcode_table*) malloc(sizeof(*s)); // check if NULL? if(s == NULL){ printf("Memory allocation err"); exit(-1); } s->opcodes_key = opcodes_keys[i]; // initializing key for s s->opcode_function = functions[i]; // initializing the value for s HASH_ADD(hh,OurComputer->opcodes, opcodes_key, sizeof(uint8_t),s); } s = (struct opcode_table*) malloc(sizeof(*s)); if(s == NULL){ printf("Memory allocation err"); exit(-1); } s->opcodes_key = 0x4a; // not stored in binary image correctly s->opcode_function = &LSR; HASH_ADD(hh,OurComputer->opcodes, opcodes_key, sizeof(uint8_t),s); s = (struct opcode_table*) malloc(sizeof(*s)); if(s == NULL){ printf("Memory allocation err"); exit(-1); } s->opcodes_key = 0xa; // not stored in binary image correctly s->opcode_function = &ASL; HASH_ADD(hh,OurComputer->opcodes, opcodes_key, sizeof(uint8_t),s); s = (struct opcode_table*) malloc(sizeof(*s)); if(s == NULL){ printf("Memory allocation err"); exit(-1); } s->opcodes_key = 0x6a; // not stored in binary image correctly s->opcode_function = &ROR; HASH_ADD(hh,OurComputer->opcodes, opcodes_key, sizeof(uint8_t),s); s = (struct opcode_table*) malloc(sizeof(*s)); if(s == NULL){ printf("Memory allocation err"); exit(-1); } s->opcodes_key = 0x2a; // not stored in binary image correctly s->opcode_function = &ROL; HASH_ADD(hh,OurComputer->opcodes, opcodes_key, sizeof(uint8_t),s); free(s); return; } // Assumes little endian void printBits(size_t const size, void const * const ptr) { unsigned char *b = (unsigned char*) ptr; unsigned char byte; int i, j; for (i = size-1; i >= 0; i--) { for (j = 7; j >= 0; j--) { byte = (b[i] >> j) & 1; printf("%u", byte); } } puts(""); } void test_registers(address index){ if(OurComputer->cpu_inst->pc != PCs[index]){ printf("Our PC = %x \n", OurComputer->cpu_inst->pc); printf("Correct PC = %x \n", PCs[index]); printf("Wrong pc address at index %hu \n", index); exit(-1); } if(OurComputer->cpu_inst->accumulator != A[index]){ printf("Our accumulator value ="); printBits(sizeof(OurComputer->cpu_inst->accumulator), &OurComputer->cpu_inst->accumulator); printf("\n"); printf("Correct accumulator value ="); printBits(sizeof(A[index]), &A[index]); printf("\n"); printf("Wrong accumulator value at index %hu \n", index); exit(-1); } if(OurComputer->cpu_inst->register_x != X[index]){ printf("Our register X value = %u \n", OurComputer->cpu_inst->register_x); printf("Correct register X value = %u \n", X[index]); printf("Wrong value in register X at index %hu \n", index); exit(-1); } if(OurComputer->cpu_inst->register_y != Y[index]){ printf("Our register Y value = %u \n", OurComputer->cpu_inst->register_y); printf("Correct register Y value = %u \n", Y[index]); printf("Wrong value in register Y at index %hu \n", index); exit(-1); } if(OurComputer->cpu_inst->stack_pointer != SP[index]){ printf("Our stack pointer value = %u \n", OurComputer->cpu_inst->stack_pointer); printf("Correct stack pointer value = %u \n", SP[index]); printf("Wrong stack pointer value at index %hu \n", index); exit(-1); } } void start_cpu(){ OurComputer->cpu_inst->pc = 0xC000; // starting address of the test opcodes OurComputer->cpu_inst->stack_pointer = 0xFD; address stack_ptr; byte temp_stck_ptr; for(address i = 0; i < 8991; i++){ // 8991 is the amount of test opcodes temp_stck_ptr = OurComputer->cpu_inst->stack_pointer + 1; stack_ptr = 1U << 8 | temp_stck_ptr; //printf("current index = %hu, carry flag = %d \n", i, ((OurComputer->cpu_inst->status_register) & 0b1) ); printf("current index = %hu, ", i); printf("Our stack register value ="); printBits(sizeof(OurComputer->cpu_inst->status_register), &OurComputer->cpu_inst->status_register); printf("\n"); test_registers(i); execute(OurComputer->RAM[OurComputer->cpu_inst->pc], OurComputer->cpu_inst->pc); } } int main(int argc, char* argv[]) { // user must pass in binary image to simulate RAM if (argc != 2){ printf("%s outfile", argv[0]); return 1; } char* file_name = argv[1]; // allocate memory for Computer Structure if((OurComputer = (struct Computer*) malloc(sizeof(struct Computer))) == NULL){ exit(-1); } // initializing size of the RAM to 2^16 if ((OurComputer->RAM = (byte*) malloc(RAMSIZE * sizeof(byte))) == NULL){ exit(-1); } // initializing cpu structure inside of computer if((OurComputer->cpu_inst = (struct cpu*) malloc(sizeof(struct cpu))) == NULL){ exit(-1); } read_in_binary_image(file_name); // fill struct->RAM with file_name build_opcode_table(); // link opcodes to functions in void_functions.c initialize_registers(); start_cpu(); free(OurComputer->RAM); free(OurComputer->cpu_inst); free(OurComputer); return 0; }