kvisc/vm/pc/mem.c

194 lines
5.3 KiB
C
Raw Normal View History

2019-05-22 18:39:46 +02:00
// The OS/K Team licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
2019-06-05 12:53:09 +02:00
#include <pc/arch.h>
2019-05-22 18:39:46 +02:00
2019-06-13 15:00:48 +02:00
//----------------------------------------------------------------------------//
2019-05-22 18:39:46 +02:00
2019-05-29 19:00:13 +02:00
#define CHK_ALIGN(type) \
if (addr % alignof(type) > 0) { \
_except(ctx, E_ALI, \
"Non-aligned memory access: 0x%012lX (0x%012lX) by %lu", \
addr, real, alignof(type)); \
2019-05-22 18:39:46 +02:00
}
2019-05-29 19:00:13 +02:00
2019-06-13 15:00:48 +02:00
//----------------------------------------------------------------------------//
2019-05-29 19:00:13 +02:00
2019-06-13 15:00:48 +02:00
static ulong readmem8(ctx_t *ctx, ulong real, ulong addr)
2019-05-29 19:00:13 +02:00
{
2019-05-29 16:57:22 +02:00
if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF;
2019-05-22 18:39:46 +02:00
else return ((ulong)ctx->mp[real] & 0xFF00) >> 8;
}
2019-06-13 15:00:48 +02:00
static ulong readmem16(ctx_t *ctx, ulong real, ulong addr)
2019-05-22 18:39:46 +02:00
{
2019-05-29 19:00:13 +02:00
CHK_ALIGN(ushort);
2019-05-22 18:39:46 +02:00
return (ulong)ctx->mp[real];
}
2019-06-13 15:00:48 +02:00
static ulong readmem32(ctx_t *ctx, ulong real, ulong addr)
2019-05-22 18:39:46 +02:00
{
2019-05-29 19:00:13 +02:00
CHK_ALIGN(uint);
2019-05-22 18:39:46 +02:00
2019-05-29 16:57:22 +02:00
ulong val = ctx->mp[real++];
val = val | ((ulong)ctx->mp[real] << 16);
2019-05-30 12:44:56 +02:00
2019-05-22 18:39:46 +02:00
return val;
}
2019-06-13 15:00:48 +02:00
static ulong readmem64(ctx_t *ctx, ulong real, ulong addr)
2019-05-22 18:39:46 +02:00
{
2019-05-29 19:00:13 +02:00
CHK_ALIGN(ulong);
2019-05-22 18:39:46 +02:00
ulong val = (ulong)ctx->mp[real++];
2019-05-29 16:57:22 +02:00
val = val | ((ulong)ctx->mp[real++] << 16);
val = val | ((ulong)ctx->mp[real++] << 32);
val = val | ((ulong)ctx->mp[real] << 48);
2019-05-30 12:44:56 +02:00
2019-05-22 18:39:46 +02:00
return val;
}
2019-06-13 15:00:48 +02:00
//----------------------------------------------------------------------------//
2019-05-22 18:39:46 +02:00
2019-06-13 15:00:48 +02:00
static void writemem8(ctx_t *ctx, ulong val, ulong real, ulong addr)
{
2019-05-22 18:39:46 +02:00
ushort v = ctx->mp[real];
2019-05-30 12:44:56 +02:00
2019-05-30 19:07:04 +02:00
if (!(addr % 2)) {
2019-05-22 18:39:46 +02:00
ctx->mp[real] = (v & 0xFF00) | (val & 0xFF);
}
2019-05-30 12:44:56 +02:00
2019-05-22 18:39:46 +02:00
else {
ctx->mp[real] = (v & 0xFF) | (((val & 0xFF) << 8));
}
}
2019-06-13 15:00:48 +02:00
static void writemem16(ctx_t *ctx, ulong val, ulong real, ulong addr)
2019-05-22 18:39:46 +02:00
{
2019-05-29 19:00:13 +02:00
CHK_ALIGN(ushort);
2019-05-22 18:39:46 +02:00
ctx->mp[real] = val & 0xFFFF;
}
2019-06-13 15:00:48 +02:00
static void writemem32(ctx_t *ctx, ulong val, ulong real, ulong addr)
2019-05-22 18:39:46 +02:00
{
2019-05-29 19:00:13 +02:00
CHK_ALIGN(uint);
2019-05-22 18:39:46 +02:00
2019-05-29 16:57:22 +02:00
ctx->mp[real++] = val & 0xFFFF;
ctx->mp[real] = (val >> 16) & 0xFFFF;
2019-05-22 18:39:46 +02:00
}
2019-06-13 15:00:48 +02:00
static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr)
2019-05-22 18:39:46 +02:00
{
2019-05-29 19:00:13 +02:00
CHK_ALIGN(ulong);
2019-05-22 18:39:46 +02:00
2019-05-29 16:57:22 +02:00
ctx->mp[real++] = val;
2019-05-22 18:39:46 +02:00
ctx->mp[real++] = (val >> 16) & 0xFFFF;
2019-05-29 16:57:22 +02:00
ctx->mp[real++] = (val >> 32) & 0xFFFF;
ctx->mp[real] = (val >> 48) & 0xFFFF;
2019-05-22 18:39:46 +02:00
}
2019-05-29 16:57:22 +02:00
2019-06-13 15:00:48 +02:00
//----------------------------------------------------------------------------//
#define CHK_RANGE() \
if (addr < MEMOFF || real >= MEMSIZE) { \
_except(ctx, E_ACC, \
"Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); \
}
#define GETREAL() \
addr += cr2; \
ulong real = addr2real(addr)
#define SIGN_EXTEND(val, mask) \
(val & ((mask + 1) >> 1) \
? (val | ~mask) \
: val)
//----------------------------------------------------------------------------//
ulong readmem(ctx_t *ctx, ulong addr, uint len)
{
GETREAL();
CHK_RANGE();
ulong val;
switch (len) {
case 1:
val = readmem8(ctx, real, addr);
val = SIGN_EXTEND(val, 0xFF);
break;
case 2:
val = readmem16(ctx, real, addr);
val = SIGN_EXTEND(val, 0xFFFF);
break;
case 4:
val = readmem32(ctx, real, addr);
val = SIGN_EXTEND(val, 0xFFFFFFFFUL);
break;
case 8:
return readmem64(ctx, real, addr);
default: log("readmem() bad length %d!\n", len); abort();
}
return val;
}
void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
{
GETREAL();
CHK_RANGE();
2019-06-19 13:47:10 +02:00
// log("writemem: 0x%lX: 0x%lX (%d)\n", addr, val, len);
2019-06-13 15:00:48 +02:00
switch (len) {
case 1: writemem8(ctx, val, real, addr); break;
case 2: writemem16(ctx, val, real, addr); break;
case 4: writemem32(ctx, val, real, addr); break;
case 8: writemem64(ctx, val, real, addr); break;
default: log("writemem() bad length %d!\n", len); abort();
}
}
//----------------------------------------------------------------------------//
//
// The following functions zero-extend rather than sign-extend
//
ulong readmemzx(ctx_t *ctx, ulong addr, uint len)
{
GETREAL();
CHK_RANGE();
switch (len) {
case 1: return readmem8(ctx, real, addr); break;
case 2: return readmem16(ctx, real, addr); break;
case 4: return readmem32(ctx, real, addr); break;
case 8: return readmem64(ctx, real, addr); break;
default: log("readmem() bad length %d!\n", len); abort();
}
}
void writememzx(ctx_t *ctx, ulong val, ulong addr, uint len)
{
GETREAL();
CHK_RANGE();
switch (len) {
case 1: writemem8(ctx, val, real, addr); break;
case 2: writemem16(ctx, val, real, addr); break;
case 4: writemem32(ctx, val, real, addr); break;
case 8: writemem64(ctx, val, real, addr); break;
default: log("writemem() bad length %d!\n", len); abort();
}
}