/* memory.c */ #include #include #include #include #include #include "project.h" /* Memory file */ static unsigned* memory = NULL; static unsigned memory_size = 0; static int virgin = 1; /* Cleanup function. */ static void cleanup(void) { free(memory); } /* Returns the value of memory address 'addr'. */ unsigned mem_read(unsigned addr) { addr &= 0xffff; return addr >= memory_size ? 0xdeadbeef : memory[addr]; } /* Ensures that memory is large enough to hold this address. */ static void grow_memory(int min_size) { int i; int old_memory_size = memory_size; if (memory_size >= min_size) return; memory_size = memory_size == 0 ? 64 : memory_size * 2; if (memory_size < min_size) memory_size = min_size; memory = realloc(memory, memory_size * 4); if (memory == NULL) die("Out of memory\n"); if (virgin) { virgin = 0; if (atexit(cleanup) != 0) { perror("atexit"); exit(EXIT_FAILURE); } } for (i = old_memory_size; i < memory_size; i++) memory[i] = 0xdeadbeef; } /* Sets the value of memory address 'addr'. */ void mem_write(unsigned addr, unsigned val) { addr &= 0xffff; grow_memory(addr); memory[addr] = val & 0xffffffff; } /* Loads a memory image from a file. */ void mem_load_image(char* filename) { struct stat stat_buf; int file_size; FILE* handle; int i; /* Determine how many words are in the image file */ if (stat(filename, &stat_buf) == -1) { perror("stat"); exit(EXIT_FAILURE); } file_size = stat_buf.st_size / 4; if (file_size > 0xffff) die("Memory image too large\n"); /* Make sure there's enough memory handy */ grow_memory(file_size); /* Open the file */ handle = fopen(filename, "rb"); if (handle == NULL) { perror("fopen"); exit(EXIT_FAILURE); } /* Load the image */ for (i = 0; i < file_size; i++) { unsigned char buf[4]; if (fread(buf, 4, 1, handle) != 1) { perror("fread"); exit(EXIT_FAILURE); } memory[i] = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]); } /* Clean up */ if (fclose(handle) == EOF) { perror("fclose"); exit(EXIT_FAILURE); } } /* EOF */