Skip to content

Commit d04811a

Browse files
Make load and store use a packed union for safe alignment, rather than memcpy.
Remove some pointless initialisation which is already done through memset
1 parent 17208a5 commit d04811a

File tree

2 files changed

+39
-65
lines changed

2 files changed

+39
-65
lines changed

uvm32/uvm32.c

Lines changed: 21 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ SOFTWARE.
4545

4646
#ifndef UVM32_MEMCPY
4747
#define UVM32_MEMCPY uvm32_memcpy
48-
void *uvm32_memcpy(void *dst, const void *src, size_t len) {
48+
static inline void *uvm32_memcpy(void *dst, const void *src, size_t len) {
4949
uint8_t *d = (uint8_t *)dst;
5050
const uint8_t *s = (const uint8_t *)src;
5151
while(len--) {
@@ -57,7 +57,7 @@ void *uvm32_memcpy(void *dst, const void *src, size_t len) {
5757

5858
#ifndef UVM32_MEMSET
5959
#define UVM32_MEMSET uvm32_memset
60-
void *uvm32_memset(void *buf, int c, size_t len) {
60+
static inline void *uvm32_memset(void *buf, int c, size_t len) {
6161
uint8_t *b = (uint8_t *)buf;
6262
while(len--) {
6363
*(b++) = c;
@@ -101,20 +101,22 @@ static void setStatusErr(uvm32_state_t *vmst, uvm32_err_t err) {
101101

102102
void uvm32_init(uvm32_state_t *vmst) {
103103
UVM32_MEMSET(vmst, 0x00, sizeof(uvm32_state_t));
104-
vmst->_status = UVM32_STATUS_PAUSED;
105104

106-
vmst->_extramLen = 0;
107-
vmst->_extram = (uint8_t *)NULL;
108-
vmst->_extramDirty = false;
105+
// handled by memset
106+
// vmst->_status = UVM32_STATUS_PAUSED;
107+
// vmst->_extramLen = 0;
108+
// vmst->_extram = (uint8_t *)NULL;
109+
// vmst->_extramDirty = false;
109110

110111
vmst->_core.pc = MINIRV32_RAM_IMAGE_OFFSET;
111112
// https://projectf.io/posts/riscv-cheat-sheet/
112113
// setup stack pointer
113114
// la sp, _sstack
114115
// addi sp,sp,-16
115116
vmst->_core.regs[2] = ((MINIRV32_RAM_IMAGE_OFFSET + UVM32_MEMORY_SIZE) & ~0xF) - 16; // 16 byte align stack
116-
vmst->_core.regs[10] = 0x00; //hart ID
117-
vmst->_core.regs[11] = 0;
117+
// handled by memset
118+
// vmst->_core.regs[10] = 0x00; //hart ID
119+
//vmst->_core.regs[11] = 0;
118120
vmst->_core.extraflags |= 3; // Machine-mode.
119121
}
120122

@@ -411,31 +413,31 @@ uvm32_slice_t uvm32_arg_getslice_fixed(uvm32_state_t *vmst, uvm32_evt_t *evt, uv
411413
static uint32_t _uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t accessTyp) {
412414
uvm32_state_t *vmst = (uvm32_state_t *)userdata;
413415
addr -= UVM32_EXTRAM_BASE;
416+
const uvm32_val_t *v = ((uvm32_val_t *)(&((uint8_t *)vmst->_extram)[addr]));
414417

415418
if (vmst->_extram != NULL) {
416419
if (addr < vmst->_extramLen) {
417420
// These are funct3 values for lX instructions
418421
// Any other value will have caused UVM32_ERR_INTERNAL_CORE
419422
switch(accessTyp) {
420423
case 0:
421-
return _uvm32_load1s(vmst->_extram, addr);
424+
return v->i8;
422425
break;
423426
case 1:
424-
return _uvm32_load2s(vmst->_extram, addr);
427+
return v->i16;
425428
break;
426429
case 2:
427-
return _uvm32_load4(vmst->_extram, addr);
430+
return v->u32;
428431
break;
429432
case 5:
430-
return _uvm32_load2(vmst->_extram, addr);
433+
return v->u16;
431434
break;
432435
// have a default case to keep coverage check happy
433436
// no other values are possible here
434437
default: // fall through
435438
case 4:
436-
return _uvm32_load1(vmst->_extram, addr);
439+
return v->u8;
437440
break;
438-
439441
}
440442
} else {
441443
// Out of bounds
@@ -448,19 +450,21 @@ static uint32_t _uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t access
448450
static uint32_t _uvm32_extramStore(void *userdata, uint32_t addr, uint32_t val, uint32_t accessTyp) {
449451
uvm32_state_t *vmst = (uvm32_state_t *)userdata;
450452
addr -= UVM32_EXTRAM_BASE;
453+
uvm32_val_t *v = ((uvm32_val_t *)(&((uint8_t *)vmst->_extram)[addr]));
454+
451455
if (vmst->_extram != NULL) {
452456
if (addr < vmst->_extramLen) {
453457
switch(accessTyp) {
454458
case 1:
455-
_uvm32_store2(vmst->_extram, addr, val);
459+
v->u16 = val;
456460
break;
457461
case 2:
458-
_uvm32_store4(vmst->_extram, addr, val);
462+
v->u32 = val;
459463
break;
460464
// no other values are valid here and will be stopped above
461465
default: // fall through
462466
case 0:
463-
_uvm32_store1(vmst->_extram, addr, val);
467+
v->u8 = val;
464468
break;
465469
}
466470
vmst->_extramDirty = true;
@@ -488,35 +492,4 @@ uint32_t uvm32_getProgramCounter(const uvm32_state_t *vmst) {
488492
return vmst->_core.pc;
489493
}
490494

491-
// Access of memory bus in alignment safe way
492-
static void _uvm32_store4(void *p, uint32_t off, uint32_t val) {
493-
UVM32_MEMCPY((uint8_t *)p + off, &val, 4);
494-
}
495-
static void _uvm32_store2(void *p, uint32_t off, uint16_t val) {
496-
UVM32_MEMCPY((uint8_t *)p + off, &val, 2);
497-
}
498-
static void _uvm32_store1(void *p, uint32_t off, uint8_t val) {
499-
((uint8_t *)p)[off] = val;
500-
}
501-
static uint32_t _uvm32_load4(void *p, uint32_t off) {
502-
uint32_t v;
503-
UVM32_MEMCPY(&v, (uint8_t *)p + off, 4);
504-
return v;
505-
}
506-
static uint16_t _uvm32_load2(void *p, uint32_t off) {
507-
uint16_t v;
508-
UVM32_MEMCPY(&v, (uint8_t *)p + off, 2);
509-
return v;
510-
}
511-
static uint8_t _uvm32_load1(void *p, uint32_t off) {
512-
return ((uint8_t *)p)[off];
513-
}
514-
static int16_t _uvm32_load2s(void *p, uint32_t off) {
515-
int16_t v;
516-
UVM32_MEMCPY(&v, (uint8_t *)p + off, 2);
517-
return v;
518-
}
519-
static int8_t _uvm32_load1s(void *p, uint32_t off) {
520-
return ((int8_t *)p)[off];
521-
}
522495

uvm32/uvm32.h

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ SOFTWARE.
3838
// Include definitions for required syscalls
3939
#include "uvm32_sys.h"
4040

41+
typedef union __attribute__((packed)) {
42+
uint32_t u32;
43+
uint16_t u16;
44+
uint8_t u8;
45+
int8_t i8;
46+
int16_t i16;
47+
int32_t i32;
48+
} uvm32_val_t;
49+
4150
// Setup and hooks for mini-rv32ima emulator core
4251
#define MINIRV32_DECORATE static
4352
#define MINIRV32_RETURN_TRAP
@@ -50,27 +59,19 @@ SOFTWARE.
5059
#define MINIRV32_HANDLE_MEM_LOAD_CONTROL( addy, rval ) rval = _uvm32_extramLoad(userdata, addy, ( ir >> 12 ) & 0x7);
5160
#define MINIRV32_HANDLE_MEM_STORE_CONTROL( addy, val ) if( _uvm32_extramStore(userdata, addy, val, ( ir >> 12 ) & 0x7) ) return val;
5261
#define MINIRV32_CUSTOM_MEMORY_BUS
53-
#define MINIRV32_STORE4( ofs, val ) _uvm32_store4(image, ofs, val)
54-
#define MINIRV32_STORE2( ofs, val ) _uvm32_store2(image, ofs, val)
55-
#define MINIRV32_STORE1( ofs, val ) _uvm32_store1(image, ofs, val)
56-
#define MINIRV32_LOAD4( ofs ) _uvm32_load4(image, ofs)
57-
#define MINIRV32_LOAD2( ofs ) _uvm32_load2(image, ofs)
58-
#define MINIRV32_LOAD1( ofs ) _uvm32_load1(image, ofs)
59-
#define MINIRV32_LOAD2_SIGNED( ofs ) _uvm32_load2s(image, ofs)
60-
#define MINIRV32_LOAD1_SIGNED( ofs ) _uvm32_load1s(image, ofs)
62+
#define MINIRV32_STORE4( ofs, val ) ((uvm32_val_t *)(&image[ofs]))->u32 = val
63+
#define MINIRV32_STORE2( ofs, val ) ((uvm32_val_t *)(&image[ofs]))->u16 = val
64+
#define MINIRV32_STORE1( ofs, val ) ((uvm32_val_t *)(&image[ofs]))->u8 = val
65+
#define MINIRV32_LOAD4( ofs ) ((uvm32_val_t *)(&image[ofs]))->u32
66+
#define MINIRV32_LOAD2( ofs ) ((uvm32_val_t *)(&image[ofs]))->u16
67+
#define MINIRV32_LOAD1( ofs ) ((uvm32_val_t *)(&image[ofs]))->u8
68+
#define MINIRV32_LOAD2_SIGNED( ofs ) ((uvm32_val_t *)(&image[ofs]))->i16
69+
#define MINIRV32_LOAD1_SIGNED( ofs ) ((uvm32_val_t *)(&image[ofs]))->i8
6170
#ifndef MINIRV32_IMPLEMENTATION
6271
#define MINIRV32_STEPPROTO
6372
#else
6473
static uint32_t _uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t accessTyp);
6574
static uint32_t _uvm32_extramStore(void *userdata, uint32_t addr, uint32_t val, uint32_t accessTyp);
66-
static void _uvm32_store4(void *p, uint32_t off, uint32_t val);
67-
static void _uvm32_store2(void *p, uint32_t off, uint16_t val);
68-
static void _uvm32_store1(void *p, uint32_t off, uint8_t val);
69-
static uint32_t _uvm32_load4(void *p, uint32_t off);
70-
static uint16_t _uvm32_load2(void *p, uint32_t off);
71-
static uint8_t _uvm32_load1(void *p, uint32_t off);
72-
static int16_t _uvm32_load2s(void *p, uint32_t off);
73-
static int8_t _uvm32_load1s(void *p, uint32_t off);
7475
#endif
7576
#include "mini-rv32ima.h"
7677

@@ -127,7 +128,7 @@ typedef struct {
127128

128129
/*! Internal state of uvm32 */
129130
typedef enum {
130-
UVM32_STATUS_PAUSED,
131+
UVM32_STATUS_PAUSED = 0,
131132
UVM32_STATUS_RUNNING,
132133
UVM32_STATUS_ERROR,
133134
UVM32_STATUS_ENDED,

0 commit comments

Comments
 (0)