X-Git-Url: http://gitweb.hugovil.com/?a=blobdiff_plain;f=src%2Fcommon%2Fmemory.c;h=daaa1faba2e22884020fbeab7eeb5d3e6b66d97f;hb=fbbb71d6d8aa93bccc87b17408a89432e4b8161c;hp=2e3721040b7c59dea76a0fe70a4acf22b9dce8c4;hpb=cc6633f78b5f497c347b656f0c854455871f5efb;p=emu8051.git diff --git a/src/common/memory.c b/src/common/memory.c index 2e37210..daaa1fa 100644 --- a/src/common/memory.c +++ b/src/common/memory.c @@ -4,21 +4,10 @@ * Copyright (C) 1999 Jonathan St-André * Copyright (C) 1999 Hugo Villeneuve * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * This file is released under the GPLv2 */ +#include #include #include @@ -32,7 +21,7 @@ struct mem_infos_t { int size; int max_size; - u_int8_t *buf; + uint8_t *buf; }; struct mem_infos_t mem_infos[MEM_ID_COUNT]; @@ -41,7 +30,7 @@ extern struct options_t options; /* Init each 8051 memory sections. */ void -memory_init(void) +mem_init(void) { int k; struct mem_infos_t *m; @@ -61,82 +50,181 @@ memory_init(void) m = &mem_infos[k]; if (m->size > m->max_size) { - log_err("Memory size invalid (max = %d)", m->max_size); - exit(1); + log_fail("Memory size invalid (max = %d)", m->max_size); } m->buf = malloc(m->size); if (m->buf == NULL) { - log_err("%s", strerror(errno)); - exit(1); + log_fail("%s", strerror(errno)); } memset(m->buf, 0x00, m->size); } } -u_int8_t * -memory_getbuf(enum mem_id_t id, unsigned long address) +/* Return true if address is valid, false otherwise. */ +int +mem_check_address(enum mem_id_t id, unsigned long address, int display_error) +{ + if (address >= (unsigned long) mem_infos[id].max_size) { + if (display_error == DISPLAY_ERROR_YES) + log_err("Address out of range ($%X >= $%X", address, + mem_infos[id].max_size - 1); + return false; + } else { + return true; + } +} + +void +mem_convert_bit_address(uint8_t bit_address, uint8_t *byte_address, + uint8_t *bit_number) +{ + if (bit_address > 0x7F) { + /* SFR 80-FF */ + *byte_address = bit_address & 0xF8; + *bit_number = bit_address & 0x07; + } else { + /* 20-2F */ + *byte_address = (bit_address >> 3) + 0x20; + *bit_number = bit_address & 0x07; + } +} + +uint8_t * +mem_getbuf(enum mem_id_t id, unsigned long address) { return &mem_infos[id].buf[address]; } void -memory_clear(enum mem_id_t id) +mem_clear(enum mem_id_t id) { memset(mem_infos[id].buf, 0, mem_infos[id].size); } void -memory_write8(enum mem_id_t id, unsigned long address, u_int8_t value) +mem_write8(enum mem_id_t id, unsigned long address, uint8_t value) { if (address >= (unsigned long) mem_infos[id].max_size) { log_err("Error writing to memory ID: %d\n" " Address (%lu) greater than maximum memory size", id, address); return; - } else + } else { mem_infos[id].buf[address] = value; + } +} + +/* Write with a direct addressing mode at Address the new Value */ +void +mem_write_direct(unsigned int address, unsigned char value) +{ + mem_write8(INT_MEM_ID, address, value); +} + +/* Write with an indirect addressing mode at Address the new Value */ +void +mem_write_indirect(unsigned int address, unsigned char value) +{ + if (address > 0x7F) { + mem_write8(EXT_MEM_ID, address, value); + return; + } + + mem_write8(INT_MEM_ID, address, value); } +/* Write with a bit addressing mode at BitAddress the new Value */ void -memory_sfr_write8(unsigned long address, u_int8_t value) +mem_write_bit(uint8_t bit_address, uint8_t value) +{ + uint8_t byte_address; + uint8_t bit_number; + unsigned char byte_val, byte_mask; + + mem_convert_bit_address(bit_address, &byte_address, &bit_number); + + byte_mask = ((1 << bit_number) ^ 0xFF); + byte_val = mem_read_direct(byte_address) & byte_mask; + byte_val += value << bit_number; + mem_write_direct(byte_address, byte_val); +} + +void +mem_sfr_write8(unsigned long address, uint8_t value) { /* SFR registers are from addresses $80 to $FF. */ - memory_write8(INT_MEM_ID, address, value); + mem_write8(INT_MEM_ID, address, value); } void -memory_sfr_write_dptr(u_int16_t value) +mem_sfr_write_dptr(uint16_t value) { - memory_write8(INT_MEM_ID, _DPTRHIGH_, value >> 8); - memory_write8(INT_MEM_ID, _DPTRLOW_, (uint8_t) value); + mem_write8(INT_MEM_ID, _DPTRHIGH_, value >> 8); + mem_write8(INT_MEM_ID, _DPTRLOW_, (uint8_t) value); } -u_int8_t -memory_read8(enum mem_id_t id, unsigned long address) +uint8_t +mem_read8(enum mem_id_t id, unsigned long address) { if (address >= (unsigned long) mem_infos[id].max_size) { log_err("Error reading from memory ID: %d\n" " Address (%lu) greater than maximum memory size", id, address); return 0; - } else + } else { return mem_infos[id].buf[address]; + } +} + +/* Read with a direct addressing mode at Address */ +unsigned char +mem_read_direct(unsigned int address) +{ + if (address > 0xFF) + return mem_read8(EXT_MEM_ID, address); + else + return mem_read8(INT_MEM_ID, address); +} + +/* Read with a indirect addressing mode at Address */ +unsigned char +mem_read_indirect(unsigned int address) +{ + if (address > 0x7F) + return mem_read8(EXT_MEM_ID, address); + else + return mem_read8(INT_MEM_ID, address); } -u_int8_t -memory_sfr_read8(unsigned long address) +/* Read with a bit addressing mode at bit_address */ +unsigned char +mem_read_bit(uint8_t bit_address) +{ + uint8_t byte_address; + uint8_t bit_number; + unsigned char bit_value; + + mem_convert_bit_address(bit_address, &byte_address, &bit_number); + + bit_value = (mem_read_direct(byte_address) >> bit_number); + bit_value &= 1; + return bit_value; +} + +uint8_t +mem_sfr_read8(unsigned long address) { /* SFR registers are from addresses $80 to $FF. */ - return memory_read8(INT_MEM_ID, address); + return mem_read8(INT_MEM_ID, address); } -u_int16_t -memory_sfr_read_dptr(void) +uint16_t +mem_sfr_read_dptr(void) { - return (memory_read8(INT_MEM_ID, _DPTRHIGH_) << 8) + - memory_read8(INT_MEM_ID, _DPTRLOW_); + return (mem_read8(INT_MEM_ID, _DPTRHIGH_) << 8) + + mem_read8(INT_MEM_ID, _DPTRLOW_); } void @@ -144,10 +232,10 @@ stack_push8(uint8_t value) { uint8_t sp; - sp = memory_read8(INT_MEM_ID, _SP_); + sp = mem_read8(INT_MEM_ID, _SP_); - memory_write8(INT_MEM_ID, ++sp, value); - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ + mem_write8(INT_MEM_ID, ++sp, value); + mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ } void @@ -155,11 +243,11 @@ stack_push16(uint16_t value) { uint8_t sp; - sp = memory_read8(INT_MEM_ID, _SP_); + sp = mem_read8(INT_MEM_ID, _SP_); - memory_write8(INT_MEM_ID, ++sp, (uint8_t) value); /* Write LSB */ - memory_write8(INT_MEM_ID, ++sp, value >> 8); /* Write MSB */ - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ + mem_write8(INT_MEM_ID, ++sp, (uint8_t) value); /* Write LSB */ + mem_write8(INT_MEM_ID, ++sp, value >> 8); /* Write MSB */ + mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ } uint8_t @@ -168,10 +256,10 @@ stack_pop8(void) uint8_t sp; uint8_t value; - sp = memory_read8(INT_MEM_ID, _SP_); + sp = mem_read8(INT_MEM_ID, _SP_); - value = memory_read8(INT_MEM_ID, sp--); - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ + value = mem_read8(INT_MEM_ID, sp--); + mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ return value; } @@ -182,11 +270,11 @@ stack_pop16(void) uint8_t sp; uint16_t value; - sp = memory_read8(INT_MEM_ID, _SP_); + sp = mem_read8(INT_MEM_ID, _SP_); - value = memory_read8(INT_MEM_ID, sp--) << 8; /* Read MSB */ - value |= memory_read8(INT_MEM_ID, sp--); /* Read LSB */ - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ + value = mem_read8(INT_MEM_ID, sp--) << 8; /* Read MSB */ + value |= mem_read8(INT_MEM_ID, sp--); /* Read LSB */ + mem_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ return value; } @@ -197,53 +285,54 @@ pgm_read_addr16(uint16_t base) { uint16_t addr; - addr = memory_read8(PGM_MEM_ID, base) << 8; /* MSB */ - addr |= memory_read8(PGM_MEM_ID, base + 1); /* LSB */ + addr = mem_read8(PGM_MEM_ID, base) << 8; /* MSB */ + addr |= mem_read8(PGM_MEM_ID, base + 1); /* LSB */ return addr; } /* Dump memory */ void -DumpMem(char *Address, char *Asize, int memory_id) +mem_dump(unsigned int address, int size, enum mem_id_t id) { - unsigned int MemAddress; - int size; - int Offset, Column; + int rc; + int offset, col; - if (strlen(Address) != 0) { - if (STREQ(Address, "PC")) - MemAddress = cpu8051.pc; - else - MemAddress = Ascii2Hex(Address, strlen(Address)); - } else { - MemAddress = 0; + if (size == 0) { + log_err("invalid size: 0"); + return; } - if (strlen(Asize) != 0) { - size = Ascii2Hex(Asize, strlen(Asize)); - } else { - size = 256; /* Default size if not specified. */ + /* Validate start address. */ + rc = mem_check_address(id, address, DISPLAY_ERROR_YES); + if (!rc) { + /* Validate end address. */ + rc = mem_check_address(id, address + (size - 1), + DISPLAY_ERROR_NO); + if (!rc) + log_err("Trying to read beyond memory limit"); } - for (Offset = 0; Offset < size; Offset += 16) { - unsigned char data[16]; + if (!rc) + return; + + for (offset = 0; offset < size; offset += 16) { + uint8_t data[16]; - printf("%.4X ", MemAddress + Offset); + printf("%.4X ", address + offset); - for (Column = 0; Column < 16; Column++) { - data[Column] = memory_read8(memory_id, MemAddress + - Offset + Column); - printf(" %.2X", (int) data[Column]); + for (col = 0; col < 16; col++) { + data[col] = mem_read8(id, address + offset + col); + printf(" %.2X", data[col]); } printf(" "); /* Display any ASCII characters */ - for (Column = 0; Column < 16; Column++) { - if ((int) data[Column] >= 32 && - (int) data[Column] <= 126) { - printf("%c", data[Column]); - } else + for (col = 0; col < 16; col++) { + if ((int) data[col] >= 32 && + (int) data[col] <= 126) + printf("%c", (char) data[col]); + else printf("."); } printf("\n");