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