More real ELF loading and brk handling; more tests pass.
This commit is contained in:
		
							parent
							
								
									396795105f
								
							
						
					
					
						commit
						2682c125e0
					
				
					 1 changed files with 80 additions and 41 deletions
				
			
		|  | @ -1,6 +1,8 @@ | |||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdarg.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
|  | @ -13,12 +15,11 @@ void disassemble_program(); | |||
| #define RAM_BASE 0x08000000 | ||||
| #define RAM_TOP  0x08100000 | ||||
| 
 | ||||
| #define BRK_TOP (RAM_TOP - 0x1000) | ||||
| 
 | ||||
| #define INIT_SP RAM_TOP | ||||
| #define INIT_PC 0x08000054 | ||||
| 
 | ||||
| #define BRK_BOTTOM (RAM_BASE + 0x20000) | ||||
| #define BRK_TOP (RAM_TOP - 0x1000) | ||||
| 
 | ||||
| /* Read/write macros */ | ||||
| #define READ_BYTE(BASE, ADDR) (BASE)[ADDR] | ||||
| #define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) |			\ | ||||
|  | @ -40,23 +41,24 @@ void disassemble_program(); | |||
| static void exit_error(char* fmt, ...); | ||||
| static void emulated_syscall(void); | ||||
| 
 | ||||
| unsigned int cpu_read_byte(unsigned int address); | ||||
| unsigned int cpu_read_word(unsigned int address); | ||||
| unsigned int cpu_read_long(unsigned int address); | ||||
| void cpu_write_byte(unsigned int address, unsigned int value); | ||||
| void cpu_write_word(unsigned int address, unsigned int value); | ||||
| void cpu_write_long(unsigned int address, unsigned int value); | ||||
| uint32_t cpu_read_byte(uint32_t address); | ||||
| uint32_t cpu_read_word(uint32_t address); | ||||
| uint32_t cpu_read_long(uint32_t address); | ||||
| void cpu_write_byte(uint32_t address, uint32_t value); | ||||
| void cpu_write_word(uint32_t address, uint32_t value); | ||||
| void cpu_write_long(uint32_t address, uint32_t value); | ||||
| 
 | ||||
| unsigned char g_ram[RAM_TOP - RAM_BASE]; | ||||
| unsigned int brkpos = BRK_BOTTOM; | ||||
| 
 | ||||
| uint32_t brkbase = RAM_BASE; | ||||
| uint32_t brkpos = RAM_BASE; | ||||
| uint32_t entrypoint = RAM_BASE; | ||||
| 
 | ||||
| /* Exit with an error message.  Use printf syntax. */ | ||||
| void exit_error(char* fmt, ...) | ||||
| { | ||||
| 	static int guard_val = 0; | ||||
| 	char buff[100]; | ||||
| 	unsigned int pc; | ||||
| 	uint32_t pc; | ||||
| 	va_list args; | ||||
| 
 | ||||
| 	if(guard_val) | ||||
|  | @ -75,71 +77,78 @@ void exit_error(char* fmt, ...) | |||
| 	exit(EXIT_FAILURE); | ||||
| } | ||||
| 
 | ||||
| static inline unsigned int transform_address(unsigned int address) | ||||
| static inline uint32_t transform_address(uint32_t address) | ||||
| { | ||||
| 	unsigned int i = (address & ADDRESS_MASK) - RAM_BASE; | ||||
| 	if (i >= (unsigned int)(RAM_TOP - RAM_BASE)) | ||||
| 	uint32_t i = (address & ADDRESS_MASK) - RAM_BASE; | ||||
| 	if (i >= (uint32_t)(RAM_TOP - RAM_BASE)) | ||||
| 		exit_error("Attempted to read from RAM address %08x", address); | ||||
| 	return i; | ||||
| } | ||||
| 
 | ||||
| unsigned int cpu_read_long(unsigned int address) | ||||
| uint32_t cpu_read_long(uint32_t address) | ||||
| { | ||||
| 	switch (address) | ||||
| 	{ | ||||
| 		case 0x00: return INIT_SP; | ||||
| 		case 0x04: return INIT_PC; | ||||
| 		case 0x04: return entrypoint; | ||||
| 		case 0x80: emulated_syscall(); return 0x10000; | ||||
| 		case 0x10000: return 0x4e734e73; /* rte; rte */ | ||||
| 		case 0x10004: return 0; | ||||
| 		default: return READ_LONG(g_ram, transform_address(address)); | ||||
| 		default: | ||||
| 		{ | ||||
| 			uint32_t value = READ_LONG(g_ram, transform_address(address)); | ||||
| 			#if 0 | ||||
| 			printf("read %08x from %08x\n", value, address); | ||||
| 			#endif | ||||
| 			return value; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| unsigned int cpu_read_word(unsigned int address) | ||||
| uint32_t cpu_read_word(uint32_t address) | ||||
| { | ||||
| 	unsigned int l = cpu_read_long(address & ~3); | ||||
| 	uint32_t l = cpu_read_long(address & ~3); | ||||
| 	l >>= 16 - (address & 2)*8; | ||||
| 	return l & 0xffff; | ||||
| } | ||||
| 
 | ||||
| unsigned int cpu_read_byte(unsigned int address) | ||||
| uint32_t cpu_read_byte(uint32_t address) | ||||
| { | ||||
| 	unsigned int l = cpu_read_long(address & ~3); | ||||
| 	uint32_t l = cpu_read_long(address & ~3); | ||||
| 	l >>= 24 - (address & 3)*8; | ||||
| 	return l & 0xff; | ||||
| } | ||||
| 
 | ||||
| unsigned int cpu_read_word_dasm(unsigned int address) | ||||
| uint32_t cpu_read_word_dasm(uint32_t address) | ||||
| { | ||||
| 	return cpu_read_word(address); | ||||
| } | ||||
| 
 | ||||
| unsigned int cpu_read_long_dasm(unsigned int address) | ||||
| uint32_t cpu_read_long_dasm(uint32_t address) | ||||
| { | ||||
| 	return cpu_read_long(address); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Write data to RAM or a device */ | ||||
| void cpu_write_byte(unsigned int address, unsigned int value) | ||||
| void cpu_write_byte(uint32_t address, uint32_t value) | ||||
| { | ||||
| 	WRITE_BYTE(g_ram, transform_address(address), value); | ||||
| } | ||||
| 
 | ||||
| void cpu_write_word(unsigned int address, unsigned int value) | ||||
| void cpu_write_word(uint32_t address, uint32_t value) | ||||
| { | ||||
| 	WRITE_WORD(g_ram, transform_address(address), value); | ||||
| } | ||||
| 
 | ||||
| void cpu_write_long(unsigned int address, unsigned int value) | ||||
| void cpu_write_long(uint32_t address, uint32_t value) | ||||
| { | ||||
| 	WRITE_LONG(g_ram, transform_address(address), value); | ||||
| } | ||||
| 
 | ||||
| /* Disassembler */ | ||||
| void make_hex(char* buff, unsigned int pc, unsigned int length) | ||||
| void make_hex(char* buff, uint32_t pc, uint32_t length) | ||||
| { | ||||
| 	char* ptr = buff; | ||||
| 
 | ||||
|  | @ -155,8 +164,8 @@ void make_hex(char* buff, unsigned int pc, unsigned int length) | |||
| 
 | ||||
| void disassemble_program() | ||||
| { | ||||
| 	unsigned int pc; | ||||
| 	unsigned int instr_size; | ||||
| 	uint32_t pc; | ||||
| 	uint32_t instr_size; | ||||
| 	char buff[100]; | ||||
| 	char buff2[100]; | ||||
| 
 | ||||
|  | @ -174,7 +183,7 @@ void disassemble_program() | |||
| 
 | ||||
| void cpu_instr_callback() | ||||
| { | ||||
| 	unsigned int pc = m68k_get_reg(NULL, M68K_REG_PC); | ||||
| 	uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC); | ||||
| 	if (pc == 0xc) | ||||
| 		exit_error("address exception"); | ||||
| 
 | ||||
|  | @ -183,7 +192,7 @@ void cpu_instr_callback() | |||
| #if 0 | ||||
| 	static char buff[100]; | ||||
| 	static char buff2[100]; | ||||
| 	static unsigned int instr_size; | ||||
| 	static uint32_t instr_size; | ||||
| 
 | ||||
| 	instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68020); | ||||
| 	make_hex(buff2, pc, instr_size); | ||||
|  | @ -220,19 +229,19 @@ static void emulated_syscall(void) | |||
| 			 | ||||
| 		case 4: /* write */ | ||||
| 		{ | ||||
| 			unsigned int fd = m68k_get_reg(NULL, M68K_REG_D1); | ||||
| 			unsigned int ptr = m68k_get_reg(NULL, M68K_REG_D2); | ||||
| 			unsigned int len = m68k_get_reg(NULL, M68K_REG_D3); | ||||
| 			uint32_t fd = m68k_get_reg(NULL, M68K_REG_D1); | ||||
| 			uint32_t ptr = m68k_get_reg(NULL, M68K_REG_D2); | ||||
| 			uint32_t len = m68k_get_reg(NULL, M68K_REG_D3); | ||||
| 			m68k_set_reg(M68K_REG_D0, write(fd, g_ram + transform_address(ptr), len)); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		case 45: /* brk */ | ||||
| 		{ | ||||
| 			unsigned int newpos = m68k_get_reg(NULL, M68K_REG_D1); | ||||
| 			uint32_t newpos = m68k_get_reg(NULL, M68K_REG_D1); | ||||
| 			if (newpos == 0) | ||||
| 				m68k_set_reg(M68K_REG_D0, brkpos); | ||||
| 			else if ((newpos < BRK_BOTTOM) || (newpos >= BRK_TOP)) | ||||
| 			else if ((newpos < brkbase) || (newpos >= BRK_TOP)) | ||||
| 				m68k_set_reg(M68K_REG_D0, -ENOMEM); | ||||
| 			else | ||||
| 			{ | ||||
|  | @ -251,6 +260,37 @@ static void emulated_syscall(void) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void load_program(FILE* fd) | ||||
| { | ||||
| 	fseek(fd, 0, SEEK_SET); | ||||
| 	if (fread(g_ram, 1, 0x34, fd) != 0x34) | ||||
| 		exit_error("couldn't read ELF header"); | ||||
| 	 | ||||
| 	uint32_t phoff = READ_LONG(g_ram, 0x1c); | ||||
| 	uint16_t phentsize = READ_WORD(g_ram, 0x2a); | ||||
| 	uint16_t phnum = READ_WORD(g_ram, 0x2c); | ||||
| 	entrypoint = READ_LONG(g_ram, 0x18); | ||||
| 	if ((phentsize != 0x20) || (phnum != 1)) | ||||
| 		exit_error("unsupported ELF file"); | ||||
| 
 | ||||
| 	fseek(fd, phoff, SEEK_SET); | ||||
| 	if (fread(g_ram, 1, phentsize, fd) != phentsize) | ||||
| 		exit_error("couldn't read program header"); | ||||
| 
 | ||||
| 	uint32_t offset = READ_LONG(g_ram, 0x04); | ||||
| 	uint32_t vaddr = READ_LONG(g_ram, 0x08); | ||||
| 	uint32_t filesz = READ_LONG(g_ram, 0x10); | ||||
| 	uint32_t memsz = READ_LONG(g_ram, 0x14); | ||||
| 	brkbase = brkpos = vaddr + memsz; | ||||
| 
 | ||||
| 	uint32_t vaddroffset = transform_address(vaddr); | ||||
| 	transform_address(vaddr + memsz); /* bounds check */ | ||||
| 	memset(g_ram+vaddroffset, 0, memsz); | ||||
| 	fseek(fd, offset, SEEK_SET); | ||||
| 	if (fread(g_ram+vaddroffset, 1, filesz, fd) != filesz) | ||||
| 		exit_error("couldn't read program data"); | ||||
| } | ||||
| 
 | ||||
| /* The main loop */ | ||||
| int main(int argc, char* argv[]) | ||||
| { | ||||
|  | @ -265,8 +305,7 @@ int main(int argc, char* argv[]) | |||
| 	if((fhandle = fopen(argv[1], "rb")) == NULL) | ||||
| 		exit_error("Unable to open %s", argv[1]); | ||||
| 
 | ||||
| 	if(fread(g_ram, 1, RAM_TOP - RAM_BASE, fhandle) <= 0) | ||||
| 		exit_error("Error reading %s", argv[1]); | ||||
| 	load_program(fhandle); | ||||
| 
 | ||||
| //	disassemble_program();
 | ||||
| 
 | ||||
|  | @ -287,9 +326,9 @@ int main(int argc, char* argv[]) | |||
| 	 */ | ||||
| 
 | ||||
| 	{ | ||||
| 		unsigned int sp = INIT_SP; | ||||
| 		uint32_t sp = INIT_SP; | ||||
| 		cpu_write_long(sp -= 4, 0); | ||||
| 		unsigned int envp = sp; | ||||
| 		uint32_t envp = sp; | ||||
| 		cpu_write_long(sp -= 4, envp); | ||||
| 		cpu_write_long(sp -= 4, 0); | ||||
| 		unsigned long argv = sp; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue