/* Write byte at address */ static int arc_mem_write_block8(struct target *target, uint32_t addr, uint32_t count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); uint32_t i; LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* We will read data from memory, so we need to flush D$. */ CHECK_RETVAL(arc32_dcache_flush(target)); uint32_t buffer_he; uint8_t buffer_te[sizeof(uint32_t)]; /* non-word writes are less common, than 4-byte writes, so I suppose we can * allowe ourselves to write this in a cycle, instead of calling arc_jtag * with count > 1. */ for(i = 0; i < count; i++) { /* See comment in arc_mem_write_block16 for details. Since it is a byte * there is not need to convert write buffer to target endianness, but * we still have to convert read buffer. */ CHECK_RETVAL(arc_jtag_read_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he, arc_mem_is_slow_memory(arc32, (addr + i) & ~3, 4, 1))); target_buffer_set_u32(target, buffer_te, buffer_he); memcpy(buffer_te + ((addr + i) & 3), (uint8_t*)buf + i, 1); buffer_he = target_buffer_get_u32(target, buffer_te); CHECK_RETVAL(arc_jtag_write_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he)); } /* Invalidate caches. */ CHECK_RETVAL(arc32_cache_invalidate(target)); return ERROR_OK; }
/* Write half-word at half-word-aligned address */ static int arc_mem_write_block16(struct target *target, uint32_t addr, int count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); int retval = ERROR_OK; int i; LOG_DEBUG("Write memory (16bit): addr=0x%" PRIx32 ", count=%i", addr, count); /* Check arguments */ if (addr & 1u) return ERROR_TARGET_UNALIGNED_ACCESS; /* We will read data from memory, so we need to flush D$. */ retval = arc32_dcache_flush(target); if (ERROR_OK != retval) return retval; uint32_t buffer_he; uint8_t buffer_te[sizeof(uint32_t)]; uint8_t halfword_te[sizeof(uint16_t)]; /* non-word writes are less common, than 4-byte writes, so I suppose we can * allowe ourselves to write this in a cycle, instead of calling arc_jtag * with count > 1. */ for(i = 0; i < count; i++) { /* We can read only word at word-aligned address. Also *jtag_read_memory * functions return data in host endianness, so host endianness != * target endianness we have to convert data back to target endianness, * or bytes will be at the wrong places.So: * 1) read word * 2) convert to target endianness * 3) make changes * 4) convert back to host endianness * 5) write word back to target. */ retval = arc_jtag_read_memory(&arc32->jtag_info, (addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he); target_buffer_set_u32(target, buffer_te, buffer_he); /* buf is in host endianness, convert to target */ target_buffer_set_u16(target, halfword_te, ((uint16_t *)buf)[i]); memcpy(buffer_te + ((addr + i * sizeof(uint16_t)) & 3u), halfword_te, sizeof(uint16_t)); buffer_he = target_buffer_get_u32(target, buffer_te); retval = arc_jtag_write_memory(&arc32->jtag_info, (addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he); if (ERROR_OK != retval) return retval; } /* Invalidate caches. */ retval = arc32_cache_invalidate(target); return retval; }
/* Write word at word-aligned address */ static int arc_mem_write_block32(struct target *target, uint32_t addr, uint32_t count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* Check arguments */ assert(!(addr & 3)); /* No need to flush cache, because we don't read values from memory. */ CHECK_RETVAL(arc_jtag_write_memory( &arc32->jtag_info, addr, count, (uint32_t *)buf)); /* Invalidate caches. */ CHECK_RETVAL(arc32_cache_invalidate(target)); return ERROR_OK; }
/* Write word at word-aligned address */ static int arc_mem_write_block32(struct target *target, uint32_t addr, int count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); int retval = ERROR_OK; /* Check arguments */ if (addr & 0x3u) return ERROR_TARGET_UNALIGNED_ACCESS; /* No need to flush cache, because we don't read values from memory. */ retval = arc_jtag_write_memory( &arc32->jtag_info, addr, count, (uint32_t *)buf); if (ERROR_OK != retval) return retval; /* Invalidate caches. */ retval = arc32_cache_invalidate(target); return retval; }
/* Write byte at address */ static int arc_mem_write_block8(struct target *target, uint32_t addr, int count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); int retval = ERROR_OK; int i; /* We will read data from memory, so we need to flush D$. */ retval = arc32_dcache_flush(target); if (ERROR_OK != retval) return retval; uint32_t buffer_he; uint8_t buffer_te[sizeof(uint32_t)]; /* non-word writes are less common, than 4-byte writes, so I suppose we can * allowe ourselves to write this in a cycle, instead of calling arc_jtag * with count > 1. */ for(i = 0; i < count; i++) { /* See comment in arc_mem_write_block16 for details. Since it is a byte * there is not need to convert write buffer to target endianness, but * we still have to convert read buffer. */ retval = arc_jtag_read_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he); target_buffer_set_u32(target, buffer_te, buffer_he); memcpy(buffer_te + ((addr + i) & 3), (uint8_t*)buf + i, 1); buffer_he = target_buffer_get_u32(target, buffer_te); retval = arc_jtag_write_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he); if (ERROR_OK != retval) return retval; } /* Invalidate caches. */ retval = arc32_cache_invalidate(target); return retval; }