include/hw/common: Fix _csr_rd_buf/_csr_wr_buf for sizeof(buf[0]) < CSR_DW_BYTES case.
- Shift in _csr_rd_buf should only been done when buf is set. - When CSR size is not an exact multiple of the CSR data-width, the gap is in the low addresses, not the high ones. So offset is introduced to take this into account.
This commit is contained in:
parent
b29a99cd0b
commit
bc77aa37f0
|
@ -144,24 +144,26 @@ static inline void csr_wr_uint64(uint64_t v, unsigned long a)
|
||||||
* of the if() branches! */
|
* of the if() branches! */
|
||||||
#define _csr_rd_buf(a, buf, cnt) \
|
#define _csr_rd_buf(a, buf, cnt) \
|
||||||
{ \
|
{ \
|
||||||
int i, j, nsubs, n_sub_elem; \
|
int i, j, offset, nsubregs, nsubelems; \
|
||||||
uint64_t r; \
|
uint64_t r; \
|
||||||
if (sizeof(buf[0]) >= CSR_DW_BYTES) { \
|
if (sizeof(buf[0]) >= CSR_DW_BYTES) { \
|
||||||
/* one or more subregisters per element */ \
|
/* One or more subregisters per element */ \
|
||||||
for (i = 0; i < cnt; i++) { \
|
for (i=0; i<cnt; i++) { \
|
||||||
buf[i] = _csr_rd(a, sizeof(buf[0])); \
|
buf[i] = _csr_rd(a, sizeof(buf[0])); \
|
||||||
a += CSR_OFFSET_BYTES * num_subregs(sizeof(buf[0])); \
|
a += CSR_OFFSET_BYTES * num_subregs(sizeof(buf[0])); \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
/* multiple elements per subregister (2, 4, or 8) */ \
|
/* Multiple elements per subregister (2, 4, or 8) */ \
|
||||||
nsubs = num_subregs(sizeof(buf[0]) * cnt); \
|
nsubregs = num_subregs(sizeof(buf[0]) * cnt); \
|
||||||
n_sub_elem = CSR_DW_BYTES / sizeof(buf[0]); \
|
nsubelems = CSR_DW_BYTES / sizeof(buf[0]); \
|
||||||
for (i = 0; i < nsubs; i++) { \
|
offset = nsubregs*nsubelems - cnt; \
|
||||||
r = csr_read_simple(a); \
|
for (i=0; i<nsubregs; i++) { \
|
||||||
for (j = n_sub_elem - 1; j >= 0; j--) { \
|
r = csr_read_simple(a); \
|
||||||
if (i * n_sub_elem + j < cnt) \
|
for (j= nsubelems - 1; j >= 0; j--) { \
|
||||||
buf[i * n_sub_elem + j] = r; \
|
if ((i * nsubelems + j - offset) >= 0) { \
|
||||||
r >>= sizeof(buf[0]) * 8; \
|
buf[i * nsubelems + j - offset] = r; \
|
||||||
|
r >>= sizeof(buf[0]) * 8; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
a += CSR_OFFSET_BYTES; \
|
a += CSR_OFFSET_BYTES; \
|
||||||
} \
|
} \
|
||||||
|
@ -175,25 +177,26 @@ static inline void csr_wr_uint64(uint64_t v, unsigned long a)
|
||||||
*/
|
*/
|
||||||
#define _csr_wr_buf(a, buf, cnt) \
|
#define _csr_wr_buf(a, buf, cnt) \
|
||||||
{ \
|
{ \
|
||||||
int i, j, nsubs, n_sub_elem; \
|
int i, j, offset, nsubregs, nsubelems; \
|
||||||
uint64_t v; \
|
uint64_t v; \
|
||||||
if (sizeof(buf[0]) >= CSR_DW_BYTES) { \
|
if (sizeof(buf[0]) >= CSR_DW_BYTES) { \
|
||||||
/* one or more subregisters per element */ \
|
/* One or more subregisters per element */ \
|
||||||
for (i = 0; i < cnt; i++) { \
|
for (i = 0; i < cnt; i++) { \
|
||||||
_csr_wr(a, buf[i], sizeof(buf[0])); \
|
_csr_wr(a, buf[i], sizeof(buf[0])); \
|
||||||
a += CSR_OFFSET_BYTES * num_subregs(sizeof(buf[0])); \
|
a += CSR_OFFSET_BYTES * num_subregs(sizeof(buf[0])); \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
/* multiple elements per subregister (2, 4, or 8) */ \
|
/* Multiple elements per subregister (2, 4, or 8) */ \
|
||||||
nsubs = num_subregs(sizeof(buf[0]) * cnt); \
|
nsubregs = num_subregs(sizeof(buf[0]) * cnt); \
|
||||||
n_sub_elem = CSR_DW_BYTES / sizeof(buf[0]); \
|
nsubelems = CSR_DW_BYTES / sizeof(buf[0]); \
|
||||||
for (i = 0; i < nsubs; i++) { \
|
offset = nsubregs*nsubelems - cnt; \
|
||||||
v = buf[i * n_sub_elem + 0]; \
|
for (i = 0; i < nsubregs; i++) { \
|
||||||
for (j = 1; j < n_sub_elem; j++) { \
|
v = 0; \
|
||||||
if (i * n_sub_elem + j == cnt) \
|
for (j= 0; j < nsubelems; j++) { \
|
||||||
break; \
|
if ((i * nsubelems + j - offset) >= 0) { \
|
||||||
v <<= sizeof(buf[0]) * 8; \
|
v <<= sizeof(buf[0]) * 8; \
|
||||||
v |= buf[i * n_sub_elem + j]; \
|
v |= buf[i * nsubelems + j - offset]; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
csr_write_simple(v, a); \
|
csr_write_simple(v, a); \
|
||||||
a += CSR_OFFSET_BYTES; \
|
a += CSR_OFFSET_BYTES; \
|
||||||
|
|
Loading…
Reference in New Issue