/* * Starting point for COMP1721 EMU assignment * Andrew Taylor (andrewt@cse.unsw.edu.au) September 2005 */ #include "emu.h" int main(int argc, char* argv[]) { const int program_memory_size = 32678; int bytes[program_memory_size*2]; int program_memory[program_memory_size]; int i; if (argc != 2 && argc != 3) { fprintf(stderr, "Usage: a.out [-execute] \n"); return 1; } char *filename; if (argc == 2) filename = argv[1]; else filename = argv[2]; for (i = 0; i < program_memory_size*2; i++) bytes[i] = 0; for (i = 0; i < program_memory_size; i++) program_memory[i] = 0; int bytes_read = read_ihex_file(filename, bytes, program_memory_size*2); convert_bytes_to_little_endian_words(bytes, program_memory_size*2, program_memory); if (argc == 3) { execute_command(program_memory, program_memory_size); return 0; } while (1) { printf("> "); char line[4096]; if (!fgets(line, sizeof line, stdin)) break; if (strncmp(line, "quit", 4) == 0) break; else if (strncmp(line, "run", 3) == 0) execute_command(program_memory, program_memory_size); else if (strncmp(line, "program", 4) == 0) program_command(program_memory, 0, bytes_read/2); else printf("unimplemented command\n"); } return 0; } void program_command(int program_memory[], int start, int finish) { int i; for (i = start; i < finish; i++) { printf("%5d ", i); print_word_as_16bit_binary(program_memory[i]); printf("\n"); } } void execute_command(int program_memory[], int program_memory_size) { printf("execution unimplemented\n"); } int read_ihex_file(char *filename, int bytes[], int bytes_array_size) { FILE *f = fopen(filename, "r"); if (f == NULL) { fprintf(stderr, "Can not open %s:", filename); perror(""); return 0; } int bytes_read = 0; while (1) { int line_bytes = read_ihex_line(f, bytes, bytes_array_size); if (line_bytes < 0) break; bytes_read += line_bytes; } return bytes_read; } int read_ihex_line(FILE *f, int bytes[], int bytes_array_size) { char line[4096]; if (fgets(line, sizeof line, f) == NULL) return -1; if (strlen(line) < 6 || line[0] != ':') // shouldn't happen return 0; int byte_count = hex_digit_array_to_int(line, 1, 2); int address = hex_digit_array_to_int(line, 3, 4); int type = hex_digit_array_to_int(line, 7, 2); if (type != 0) return 0; assert(address+byte_count <= bytes_array_size); int i; for (i = 0; i < byte_count; i++) bytes[address+i] = hex_digit_array_to_int(line, 9 + i*2, 2); return byte_count; } void convert_bytes_to_little_endian_words(int bytes[], int n_bytes, int words[]) { int i; assert(n_bytes % 2 == 0); for (i = 0; i < n_bytes; i += 2) words[i/2] = bytes[i+1]*256+bytes[i]; } void print_word_as_16bit_binary(int word) { int divisor; assert(sizeof (int) > 2); assert(word >= 0 && word <= 65535); for (divisor = 32768; divisor > 0; divisor /= 2) { printf("%d", word/divisor); word = word % divisor; } } int hex_digit_array_to_int(char c[], int offset, int n_digits) { int i, value = 0; for (i = 0; i < n_digits; i++) value = value*16 + hex_digit_to_int(c[offset+i]); return value; } int hex_digit_to_int(char c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'F') return c - 'A' + 10; else if (c >= 'a' && c <= 'f') return c - 'a' + 10; else return 0; // could print error message here }