memory.c
1 /* 2 * memory.c 3 * 4 * Copyright (C) 1999 Jonathan St-André 5 * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com> 6 * 7 * This file is released under the GPLv2 8 */ 9 10 #include <stdbool.h> 11 #include <stdio.h> 12 #include <string.h> 13 14 #include "common.h" 15 #include "cpu8051.h" 16 #include "reg8051.h" 17 #include "hexfile.h" 18 #include "memory.h" 19 #include "options.h" 20 21 struct mem_infos_t { 22 int size; 23 int max_size; 24 uint8_t *buf; 25 }; 26 27 struct mem_infos_t mem_infos[MEM_ID_COUNT]; 28 29 extern struct options_t options; 30 31 /* Init each 8051 memory sections. */ 32 void 33 mem_init(void) 34 { 35 int k; 36 struct mem_infos_t *m; 37 38 /* Set desired and maximum allowable sizes for each memory type. */ 39 mem_infos[PGM_MEM_ID].size = options.pram_size; 40 mem_infos[PGM_MEM_ID].max_size = PGM_MEM_MAX_SIZE; 41 42 mem_infos[INT_MEM_ID].size = options.iram_size; 43 mem_infos[INT_MEM_ID].max_size = INT_MEM_MAX_SIZE; 44 45 mem_infos[EXT_MEM_ID].size = options.xram_size; 46 mem_infos[EXT_MEM_ID].max_size = EXT_MEM_MAX_SIZE; 47 48 /* Verify if desired sizes are valid, and if so allocate memory. */ 49 for (k = 0; k < MEM_ID_COUNT; k++) { 50 m = &mem_infos[k]; 51 52 if (m->size > m->max_size) { 53 log_fail("Memory size invalid (max = %d)", m->max_size); 54 } 55 56 m->buf = malloc(m->size); 57 if (m->buf == NULL) { 58 log_fail("%s", strerror(errno)); 59 } 60 61 memset(m->buf, 0x00, m->size); 62 } 63 } 64 65 /* Return true if address is valid, false otherwise. */ 66 int 67 mem_check_address(enum mem_id_t id, unsigned long address, int display_error) 68 { 69 if (address >= (unsigned long) mem_infos[id].max_size) { 70 if (display_error == DISPLAY_ERROR_YES) 71 log_err("Address out of range ($%X >= $%X", address, 72 mem_infos[id].max_size - 1); 73 return false; 74 } else { 75 return true; 76 } 77 } 78 79 void 80 mem_convert_bit_address(uint8_t bit_address, uint8_t *byte_address, 81 uint8_t *bit_number) 82 { 83 if (bit_address > 0x7F) { 84 /* SFR 80-FF */ 85 *byte_address = bit_address & 0xF8; 86 *bit_number = bit_address & 0x07; 87 } else { 88 /* 20-2F */ 89 *byte_address = (bit_address >> 3) + 0x20; 90 *bit_number = bit_address & 0x07; 91 } 92 } 93 94 uint8_t * 95 mem_getbuf(enum mem_id_t id, unsigned long address) 96 { 97 return &mem_infos[id].buf[address]; 98 } 99 100 void 101 mem_clear(enum mem_id_t id) 102 { 103 memset(mem_infos[id].buf, 0, mem_infos[id].size); 104 } 105 106 void 107 mem_write8(enum mem_id_t id, unsigned long address, uint8_t value) 108 { 109 if (address >= (unsigned long) mem_infos[id].max_size) { 110 log_err("Error writing to memory ID: %d\n" 111 " Address (%lu) greater than maximum memory size", 112 id, address); 113 return; 114 } else { 115 mem_infos[id].buf[address] = value; 116 } 117 } 118 119 /* Write with a direct addressing mode at Address the new Value */ 120 void 121 mem_write_direct(unsigned int address, unsigned char value) 122 { 123 mem_write8(INT_MEM_ID, address, value); 124 } 125 126 /* Write with an indirect addressing mode at Address the new Value */ 127 void 128 mem_write_indirect(unsigned int address, unsigned char value) 129 { 130 if (address > 0x7F) { 131 mem_write8(EXT_MEM_ID, address, value); 132 return; 133 } 134 135 mem_write8(INT_MEM_ID, address, value); 136 } 137 138 /* Write with a bit addressing mode at BitAddress the new Value */ 139 void 140 mem_write_bit(uint8_t bit_address, uint8_t value) 141 { 142 uint8_t byte_address; 143 uint8_t bit_number; 144 unsigned char byte_val, byte_mask; 145 146 mem_convert_bit_address(bit_address, &byte_address, &bit_number); 147 148 byte_mask = ((1 << bit_number) ^ 0xFF); 149 byte_val = mem_read_direct(byte_address) & byte_mask; 150 byte_val += value << bit_number; 151 mem_write_direct(byte_address, byte_val); 152 } 153 154 void 155 mem_sfr_write8(unsigned long address, uint8_t value) 156 { 157 /* SFR registers are from addresses $80 to $FF. */ 158 mem_write8(INT_MEM_ID, address, value); 159 } 160 161 void 162 mem_sfr_write_dptr(uint16_t value) 163 { 164 mem_write8(INT_MEM_ID, _DPTRHIGH_, value >> 8); 165 mem_write8(INT_MEM_ID, _DPTRLOW_, (uint8_t) value); 166 } 167 168 uint8_t 169 mem_read8(enum mem_id_t id, unsigned long address) 170 { 171 if (address >= (unsigned long) mem_infos[id].max_size) { 172 log_err("Error reading from memory ID: %d\n" 173 " Address (%lu) greater than maximum memory size", 174 id, address); 175 return 0; 176 } else { 177 return mem_infos[id].buf[address]; 178 } 179 } 180 181 /* Read with a direct addressing mode at Address */ 182 unsigned char 183 mem_read_direct(unsigned int address) 184 { 185 if (address > 0xFF) 186 return mem_read8(EXT_MEM_ID, address); 187 else 188 return mem_read8(INT_MEM_ID, address); 189 } 190 191 /* Read with a indirect addressing mode at Address */ 192 unsigned char 193 mem_read_indirect(unsigned int address) 194 { 195 if (address > 0x7F) 196 return mem_read8(EXT_MEM_ID, address); 197 else 198 return mem_read8(INT_MEM_ID, address); 199 } 200 201 /* Read with a bit addressing mode at bit_address */ 202 unsigned char 203 mem_read_bit(uint8_t bit_address) 204 { 205 uint8_t byte_address; 206 uint8_t bit_number; 207 unsigned char bit_value; 208 209 mem_convert_bit_address(bit_address, &byte_address, &bit_number); 210 211 bit_value = (mem_read_direct(byte_address) >> bit_number); 212 bit_value &= 1; 213 return bit_value; 214 } 215 216 uint8_t 217 mem_sfr_read8(unsigned long address) 218 { 219 /* SFR registers are from addresses $80 to $FF. */ 220 return mem_read8(INT_MEM_ID, address); 221 } 222 223 uint16_t 224 mem_sfr_read_dptr(void) 225 { 226 return (mem_read8(INT_MEM_ID, _DPTRHIGH_) << 8) + 227 mem_read8(INT_MEM_ID, _DPTRLOW_); 228 } 229 230 void 231 stack_push8(uint8_t value) 232 { 233 uint8_t sp; 234 235 sp = mem_read8(INT_MEM_ID, _SP_); 236 237 mem_write8(INT_MEM_ID, ++sp, value); 238 mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ 239 } 240 241 void 242 stack_push16(uint16_t value) 243 { 244 uint8_t sp; 245 246 sp = mem_read8(INT_MEM_ID, _SP_); 247 248 mem_write8(INT_MEM_ID, ++sp, (uint8_t) value); /* Write LSB */ 249 mem_write8(INT_MEM_ID, ++sp, value >> 8); /* Write MSB */ 250 mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ 251 } 252 253 uint8_t 254 stack_pop8(void) 255 { 256 uint8_t sp; 257 uint8_t value; 258 259 sp = mem_read8(INT_MEM_ID, _SP_); 260 261 value = mem_read8(INT_MEM_ID, sp--); 262 mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ 263 264 return value; 265 } 266 267 uint16_t 268 stack_pop16(void) 269 { 270 uint8_t sp; 271 uint16_t value; 272 273 sp = mem_read8(INT_MEM_ID, _SP_); 274 275 value = mem_read8(INT_MEM_ID, sp--) << 8; /* Read MSB */ 276 value |= mem_read8(INT_MEM_ID, sp--); /* Read LSB */ 277 mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ 278 279 return value; 280 } 281 282 /* Read a 16-bit address from PGM memory, starting at <base> offset */ 283 uint16_t 284 pgm_read_addr16(uint16_t base) 285 { 286 uint16_t addr; 287 288 addr = mem_read8(PGM_MEM_ID, base) << 8; /* MSB */ 289 addr |= mem_read8(PGM_MEM_ID, base + 1); /* LSB */ 290 291 return addr; 292 } 293 294 /* Dump memory */ 295 void 296 mem_dump(unsigned int address, int size, enum mem_id_t id) 297 { 298 int rc; 299 int offset, col; 300 301 if (size == 0) { 302 log_err("invalid size: 0"); 303 return; 304 } 305 306 /* Validate start address. */ 307 rc = mem_check_address(id, address, DISPLAY_ERROR_YES); 308 if (!rc) { 309 /* Validate end address. */ 310 rc = mem_check_address(id, address + (size - 1), 311 DISPLAY_ERROR_NO); 312 if (!rc) 313 log_err("Trying to read beyond memory limit"); 314 } 315 316 if (!rc) 317 return; 318 319 for (offset = 0; offset < size; offset += 16) { 320 uint8_t data[16]; 321 322 printf("%.4X ", address + offset); 323 324 for (col = 0; col < 16; col++) { 325 data[col] = mem_read8(id, address + offset + col); 326 printf(" %.2X", data[col]); 327 } 328 printf(" "); 329 330 /* Display any ASCII characters */ 331 for (col = 0; col < 16; col++) { 332 if ((int) data[col] >= 32 && 333 (int) data[col] <= 126) 334 printf("%c", (char) data[col]); 335 else 336 printf("."); 337 } 338 printf("\n"); 339 } 340 }