1.1 --- a/src/memory.c Thu Apr 17 01:58:05 2014 -0600 1.2 +++ b/src/memory.c Fri Apr 18 01:26:01 2014 -0600 1.3 @@ -20,6 +20,15 @@ 1.4 1.5 #define MAPRAM(addr) (((uint16_t)state.map[addr*2] << 8) + ((uint16_t)state.map[(addr*2)+1])) 1.6 1.7 +static uint32_t map_address_debug(uint32_t addr) 1.8 +{ 1.9 + uint16_t page = (addr >> 12) & 0x3FF; 1.10 + 1.11 + // Look it up in the map RAM and get the physical page address 1.12 + uint32_t new_page_addr = MAPRAM(page) & 0x3FF; 1.13 + return (new_page_addr << 12) + (addr & 0xFFF); 1.14 +} 1.15 + 1.16 uint32_t mapAddr(uint32_t addr, bool writing)/*{{{*/ 1.17 { 1.18 if (addr < 0x400000) { 1.19 @@ -70,7 +79,7 @@ 1.20 } 1.21 }/*}}}*/ 1.22 1.23 -MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing)/*{{{*/ 1.24 +MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing, bool dma)/*{{{*/ 1.25 { 1.26 // Get the page bits for this page. 1.27 uint16_t page = (addr >> 12) & 0x3FF; 1.28 @@ -83,7 +92,7 @@ 1.29 } 1.30 1.31 // Are we in Supervisor mode? 1.32 - if (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000) 1.33 + if (dma || (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000)) 1.34 // Yes. We can do anything we like. 1.35 return MEM_ALLOWED; 1.36 1.37 @@ -96,7 +105,7 @@ 1.38 1.39 // User attempt to access the kernel 1.40 // A19, A20, A21, A22 low (kernel access): RAM addr before paging; not in Supervisor mode 1.41 - if (((addr >> 19) & 0x0F) == 0) { 1.42 + if (((addr >> 19) & 0x0F) == 0 && !(!writing && addr <= 0x1000)) { 1.43 LOGS("Attempt by user code to access kernel space"); 1.44 return MEM_KERNEL; 1.45 } 1.46 @@ -107,32 +116,13 @@ 1.47 addr, page, MAPRAM(page), state.map[page*2], state.map[(page*2)+1], pagebits); 1.48 return MEM_PAGE_NO_WE; 1.49 } 1.50 - 1.51 // Page access allowed. 1.52 return MEM_ALLOWED; 1.53 }/*}}}*/ 1.54 1.55 - 1.56 - 1.57 -/******************************************************** 1.58 - * m68k memory read/write support functions for Musashi 1.59 - ********************************************************/ 1.60 - 1.61 -/** 1.62 - * @brief Check memory access permissions for a write operation. 1.63 - * @note This used to be a single macro (merged with ACCESS_CHECK_RD), but 1.64 - * gcc throws warnings when you have a return-with-value in a void 1.65 - * function, even if the return-with-value is completely unreachable. 1.66 - * Similarly it doesn't like it if you have a return without a value 1.67 - * in a non-void function, even if it's impossible to ever reach the 1.68 - * return-with-no-value. UGH! 1.69 - */ 1.70 -/*{{{ macro: ACCESS_CHECK_WR(address, bits)*/ 1.71 -#define ACCESS_CHECK_WR(address, bits) \ 1.72 +#define _ACCESS_CHECK_WR_BYTE(address) \ 1.73 do { \ 1.74 - bool fault = false; \ 1.75 - MEM_STATUS st; \ 1.76 - switch (st = checkMemoryAccess(address, true)) { \ 1.77 + switch (st = checkMemoryAccess(address, true, false)) { \ 1.78 case MEM_ALLOWED: \ 1.79 /* Access allowed */ \ 1.80 break; \ 1.81 @@ -154,7 +144,33 @@ 1.82 fault = true; \ 1.83 break; \ 1.84 } \ 1.85 - \ 1.86 + }while (0) 1.87 + 1.88 + 1.89 + 1.90 +/******************************************************** 1.91 + * m68k memory read/write support functions for Musashi 1.92 + ********************************************************/ 1.93 + 1.94 +/** 1.95 + * @brief Check memory access permissions for a write operation. 1.96 + * @note This used to be a single macro (merged with ACCESS_CHECK_RD), but 1.97 + * gcc throws warnings when you have a return-with-value in a void 1.98 + * function, even if the return-with-value is completely unreachable. 1.99 + * Similarly it doesn't like it if you have a return without a value 1.100 + * in a non-void function, even if it's impossible to ever reach the 1.101 + * return-with-no-value. UGH! 1.102 + */ 1.103 +/*{{{ macro: ACCESS_CHECK_WR(address, bits)*/ 1.104 +#define ACCESS_CHECK_WR(address, bits) \ 1.105 + do { \ 1.106 + bool fault = false; \ 1.107 + MEM_STATUS st; \ 1.108 + _ACCESS_CHECK_WR_BYTE(address); \ 1.109 + if (!fault && bits == 32 \ 1.110 + && ((address + 3) & ~0xfff) != ((address & ~0xfff))){ \ 1.111 + _ACCESS_CHECK_WR_BYTE(address + 3); \ 1.112 + } \ 1.113 if (fault) { \ 1.114 if (bits >= 16) \ 1.115 state.bsr0 = 0x7C00; \ 1.116 @@ -169,21 +185,9 @@ 1.117 } while (0) 1.118 /*}}}*/ 1.119 1.120 -/** 1.121 - * @brief Check memory access permissions for a read operation. 1.122 - * @note This used to be a single macro (merged with ACCESS_CHECK_WR), but 1.123 - * gcc throws warnings when you have a return-with-value in a void 1.124 - * function, even if the return-with-value is completely unreachable. 1.125 - * Similarly it doesn't like it if you have a return without a value 1.126 - * in a non-void function, even if it's impossible to ever reach the 1.127 - * return-with-no-value. UGH! 1.128 - */ 1.129 -/*{{{ macro: ACCESS_CHECK_RD(address, bits)*/ 1.130 -#define ACCESS_CHECK_RD(address, bits) \ 1.131 +#define _ACCESS_CHECK_RD_BYTE(address) \ 1.132 do { \ 1.133 - bool fault = false; \ 1.134 - MEM_STATUS st; \ 1.135 - switch (st = checkMemoryAccess(address, false)) { \ 1.136 + switch (st = checkMemoryAccess(address, false, false)) { \ 1.137 case MEM_ALLOWED: \ 1.138 /* Access allowed */ \ 1.139 break; \ 1.140 @@ -205,15 +209,38 @@ 1.141 fault = true; \ 1.142 break; \ 1.143 } \ 1.144 + } while (0) 1.145 + 1.146 +/** 1.147 + * @brief Check memory access permissions for a read operation. 1.148 + * @note This used to be a single macro (merged with ACCESS_CHECK_WR), but 1.149 + * gcc throws warnings when you have a return-with-value in a void 1.150 + * function, even if the return-with-value is completely unreachable. 1.151 + * Similarly it doesn't like it if you have a return without a value 1.152 + * in a non-void function, even if it's impossible to ever reach the 1.153 + * return-with-no-value. UGH! 1.154 + */ 1.155 +/*{{{ macro: ACCESS_CHECK_RD(address, bits)*/ 1.156 +#define ACCESS_CHECK_RD(address, bits) \ 1.157 + do { \ 1.158 + bool fault = false; \ 1.159 + uint32_t faultAddr = address; \ 1.160 + MEM_STATUS st; \ 1.161 + _ACCESS_CHECK_RD_BYTE(address); \ 1.162 + if (!fault && bits == 32 \ 1.163 + && ((address + 2) & ~0xfff) != (address & ~0xfff)){ \ 1.164 + _ACCESS_CHECK_RD_BYTE(address + 2); \ 1.165 + if (fault) faultAddr = address + 2; \ 1.166 + } \ 1.167 \ 1.168 if (fault) { \ 1.169 if (bits >= 16) \ 1.170 state.bsr0 = 0x7C00; \ 1.171 else \ 1.172 - state.bsr0 = (address & 1) ? 0x7E00 : 0x7D00; \ 1.173 - state.bsr0 |= (address >> 16); \ 1.174 - state.bsr1 = address & 0xffff; \ 1.175 - LOG("Bus Error while reading, addr %08X, statcode %d", address, st); \ 1.176 + state.bsr0 = (faultAddr & 1) ? 0x7E00 : 0x7D00; \ 1.177 + state.bsr0 |= (faultAddr >> 16); \ 1.178 + state.bsr1 = faultAddr & 0xffff; \ 1.179 + LOG("Bus Error while reading, addr %08X, statcode %d", faultAddr, st); \ 1.180 if (state.ee) m68k_pulse_bus_error(); \ 1.181 if (bits >= 32) \ 1.182 return EMPTY & 0xFFFFFFFF; \ 1.183 @@ -227,7 +254,7 @@ 1.184 { 1.185 // Check memory access permissions 1.186 bool access_ok = false; 1.187 - switch (checkMemoryAccess(state.dma_address, !reading)) { 1.188 + switch (checkMemoryAccess(state.dma_address, !reading, true)) { 1.189 case MEM_PAGEFAULT: 1.190 // Page fault 1.191 state.genstat = 0xABFF 1.192 @@ -717,6 +744,20 @@ 1.193 * m68k memory read/write support functions for Musashi 1.194 ********************************************************/ 1.195 1.196 + 1.197 +static uint16_t ram_read_16(uint32_t address) 1.198 +{ 1.199 + if (address <= 0x1fffff) { 1.200 + // Base memory wraps around 1.201 + return RD16(state.base_ram, address, state.base_ram_size - 1); 1.202 + } else { 1.203 + if ((address <= (state.exp_ram_size + 0x200000 - 1)) && (address >= 0x200000)){ 1.204 + return RD16(state.exp_ram, address - 0x200000, state.exp_ram_size - 1); 1.205 + }else 1.206 + return EMPTY & 0xffff; 1.207 + } 1.208 +} 1.209 + 1.210 /** 1.211 * @brief Read M68K memory, 32-bit 1.212 */ 1.213 @@ -737,15 +778,11 @@ 1.214 } else if (address <= 0x3fffff) { 1.215 // RAM access 1.216 uint32_t newAddr = mapAddr(address, false); 1.217 - if (newAddr <= 0x1fffff) { 1.218 - // Base memory wraps around 1.219 - return RD32(state.base_ram, newAddr, state.base_ram_size - 1); 1.220 - } else { 1.221 - if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000)) 1.222 - return RD32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1); 1.223 - else 1.224 - return EMPTY & 0xffffffff; 1.225 - } 1.226 + // Base memory wraps around 1.227 + data = ((ram_read_16(newAddr) << 16) | 1.228 + ram_read_16(mapAddr(address + 2, false))); 1.229 + 1.230 + return (data); 1.231 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.232 // I/O register space, zone A 1.233 switch (address & 0x0F0000) { 1.234 @@ -867,6 +904,20 @@ 1.235 return data; 1.236 }/*}}}*/ 1.237 1.238 + 1.239 +static void ram_write_16(uint32_t address, uint32_t value)/*{{{*/ 1.240 +{ 1.241 + if (address <= 0x1fffff) { 1.242 + if (address < state.base_ram_size) { 1.243 + WR16(state.base_ram, address, state.base_ram_size - 1, value); 1.244 + } 1.245 + } else { 1.246 + if ((address - 0x200000) < state.exp_ram_size) { 1.247 + WR16(state.exp_ram, address - 0x200000, state.exp_ram_size - 1, value); 1.248 + } 1.249 + } 1.250 +} 1.251 + 1.252 /** 1.253 * @brief Write M68K memory, 32-bit 1.254 */ 1.255 @@ -878,21 +929,13 @@ 1.256 1.257 // Check access permissions 1.258 ACCESS_CHECK_WR(address, 32); 1.259 - 1.260 if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.261 // ROM access 1.262 } else if (address <= 0x3FFFFF) { 1.263 // RAM access 1.264 uint32_t newAddr = mapAddr(address, true); 1.265 - if (newAddr <= 0x1fffff) { 1.266 - if (newAddr < state.base_ram_size) { 1.267 - WR32(state.base_ram, newAddr, state.base_ram_size - 1, value); 1.268 - } 1.269 - } else { 1.270 - if ((newAddr - 0x200000) < state.exp_ram_size) { 1.271 - WR32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, value); 1.272 - } 1.273 - } 1.274 + ram_write_16(newAddr, (value & 0xffff0000) >> 16); 1.275 + ram_write_16(mapAddr(address + 2, true), (value & 0xffff)); 1.276 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.277 // I/O register space, zone A 1.278 switch (address & 0x0F0000) { 1.279 @@ -1008,20 +1051,12 @@ 1.280 uint32_t m68k_read_disassembler_32(uint32_t addr) 1.281 { 1.282 if (addr < 0x400000) { 1.283 - uint16_t page = (addr >> 12) & 0x3FF; 1.284 - uint32_t new_page_addr = MAPRAM(page) & 0x3FF; 1.285 - uint32_t newAddr = (new_page_addr << 12) + (addr & 0xFFF); 1.286 - if (newAddr <= 0x1fffff) { 1.287 - if (newAddr >= state.base_ram_size) 1.288 - return EMPTY; 1.289 - else 1.290 - return RD32(state.base_ram, newAddr, state.base_ram_size - 1); 1.291 - } else { 1.292 - if ((newAddr <= (state.exp_ram_size + 0x200000 - 1)) && (newAddr >= 0x200000)) 1.293 - return RD32(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1); 1.294 - else 1.295 - return EMPTY; 1.296 - } 1.297 + uint32_t newAddrHigh, newAddrLow; 1.298 + newAddrHigh = map_address_debug(addr); 1.299 + newAddrLow = map_address_debug(addr + 2); 1.300 + return ((ram_read_16(newAddrHigh) << 16) | 1.301 + ram_read_16(newAddrLow)); 1.302 + 1.303 } else { 1.304 printf(">>> WARNING Disassembler RD32 out of range 0x%08X\n", addr); 1.305 return EMPTY;