1 // See LICENSE for license details.
2
3 #include <algorithm>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <stdexcept>
7 #include "memif.h"
8
read(addr_t addr,size_t len,void * bytes)9 void memif_t::read(addr_t addr, size_t len, void* bytes)
10 {
11 size_t align = cmemif->chunk_align();
12 if (len && (addr & (align-1)))
13 {
14 size_t this_len = std::min(len, align - size_t(addr & (align-1)));
15 uint8_t chunk[align];
16
17 cmemif->read_chunk(addr & ~(align-1), align, chunk);
18 memcpy(bytes, chunk + (addr & (align-1)), this_len);
19
20 bytes = (char*)bytes + this_len;
21 addr += this_len;
22 len -= this_len;
23 }
24
25 if (len & (align-1))
26 {
27 size_t this_len = len & (align-1);
28 size_t start = len - this_len;
29 uint8_t chunk[align];
30
31 cmemif->read_chunk(addr + start, align, chunk);
32 memcpy((char*)bytes + start, chunk, this_len);
33
34 len -= this_len;
35 }
36
37 // now we're aligned
38 for (size_t pos = 0; pos < len; pos += cmemif->chunk_max_size())
39 cmemif->read_chunk(addr + pos, std::min(cmemif->chunk_max_size(), len - pos), (char*)bytes + pos);
40 }
41
write(addr_t addr,size_t len,const void * bytes)42 void memif_t::write(addr_t addr, size_t len, const void* bytes)
43 {
44 size_t align = cmemif->chunk_align();
45 if (len && (addr & (align-1)))
46 {
47 size_t this_len = std::min(len, align - size_t(addr & (align-1)));
48 uint8_t chunk[align];
49
50 cmemif->read_chunk(addr & ~(align-1), align, chunk);
51 memcpy(chunk + (addr & (align-1)), bytes, this_len);
52 cmemif->write_chunk(addr & ~(align-1), align, chunk);
53
54 bytes = (char*)bytes + this_len;
55 addr += this_len;
56 len -= this_len;
57 }
58
59 if (len & (align-1))
60 {
61 size_t this_len = len & (align-1);
62 size_t start = len - this_len;
63 uint8_t chunk[align];
64
65 cmemif->read_chunk(addr + start, align, chunk);
66 memcpy(chunk, (char*)bytes + start, this_len);
67 cmemif->write_chunk(addr + start, align, chunk);
68
69 len -= this_len;
70 }
71
72 // now we're aligned
73 bool all_zero = len != 0;
74 for (size_t i = 0; i < len; i++)
75 all_zero &= ((const char*)bytes)[i] == 0;
76
77 if (all_zero) {
78 cmemif->clear_chunk(addr, len);
79 } else {
80 size_t max_chunk = cmemif->chunk_max_size();
81 for (size_t pos = 0; pos < len; pos += max_chunk)
82 cmemif->write_chunk(addr + pos, std::min(max_chunk, len - pos), (char*)bytes + pos);
83 }
84 }
85
86 #define MEMIF_READ_FUNC \
87 if(addr & (sizeof(val)-1)) \
88 throw std::runtime_error("misaligned address"); \
89 this->read(addr, sizeof(val), &val); \
90 return val
91
92 #define MEMIF_WRITE_FUNC \
93 if(addr & (sizeof(val)-1)) \
94 throw std::runtime_error("misaligned address"); \
95 this->write(addr, sizeof(val), &val)
96
read_uint8(addr_t addr)97 target_endian<uint8_t> memif_t::read_uint8(addr_t addr)
98 {
99 target_endian<uint8_t> val;
100 MEMIF_READ_FUNC;
101 }
102
read_int8(addr_t addr)103 target_endian<int8_t> memif_t::read_int8(addr_t addr)
104 {
105 target_endian<int8_t> val;
106 MEMIF_READ_FUNC;
107 }
108
write_uint8(addr_t addr,target_endian<uint8_t> val)109 void memif_t::write_uint8(addr_t addr, target_endian<uint8_t> val)
110 {
111 MEMIF_WRITE_FUNC;
112 }
113
write_int8(addr_t addr,target_endian<int8_t> val)114 void memif_t::write_int8(addr_t addr, target_endian<int8_t> val)
115 {
116 MEMIF_WRITE_FUNC;
117 }
118
read_uint16(addr_t addr)119 target_endian<uint16_t> memif_t::read_uint16(addr_t addr)
120 {
121 target_endian<uint16_t> val;
122 MEMIF_READ_FUNC;
123 }
124
read_int16(addr_t addr)125 target_endian<int16_t> memif_t::read_int16(addr_t addr)
126 {
127 target_endian<int16_t> val;
128 MEMIF_READ_FUNC;
129 }
130
write_uint16(addr_t addr,target_endian<uint16_t> val)131 void memif_t::write_uint16(addr_t addr, target_endian<uint16_t> val)
132 {
133 MEMIF_WRITE_FUNC;
134 }
135
write_int16(addr_t addr,target_endian<int16_t> val)136 void memif_t::write_int16(addr_t addr, target_endian<int16_t> val)
137 {
138 MEMIF_WRITE_FUNC;
139 }
140
read_uint32(addr_t addr)141 target_endian<uint32_t> memif_t::read_uint32(addr_t addr)
142 {
143 target_endian<uint32_t> val;
144 MEMIF_READ_FUNC;
145 }
146
read_int32(addr_t addr)147 target_endian<int32_t> memif_t::read_int32(addr_t addr)
148 {
149 target_endian<int32_t> val;
150 MEMIF_READ_FUNC;
151 }
152
write_uint32(addr_t addr,target_endian<uint32_t> val)153 void memif_t::write_uint32(addr_t addr, target_endian<uint32_t> val)
154 {
155 MEMIF_WRITE_FUNC;
156 }
157
write_int32(addr_t addr,target_endian<int32_t> val)158 void memif_t::write_int32(addr_t addr, target_endian<int32_t> val)
159 {
160 MEMIF_WRITE_FUNC;
161 }
162
read_uint64(addr_t addr)163 target_endian<uint64_t> memif_t::read_uint64(addr_t addr)
164 {
165 target_endian<uint64_t> val;
166 MEMIF_READ_FUNC;
167 }
168
read_int64(addr_t addr)169 target_endian<int64_t> memif_t::read_int64(addr_t addr)
170 {
171 target_endian<int64_t> val;
172 MEMIF_READ_FUNC;
173 }
174
write_uint64(addr_t addr,target_endian<uint64_t> val)175 void memif_t::write_uint64(addr_t addr, target_endian<uint64_t> val)
176 {
177 MEMIF_WRITE_FUNC;
178 }
179
write_int64(addr_t addr,target_endian<int64_t> val)180 void memif_t::write_int64(addr_t addr, target_endian<int64_t> val)
181 {
182 MEMIF_WRITE_FUNC;
183 }
184