// The OS/K Team licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #include //----------------------------------------------------------------------------// ulong readstr(ctx_t *ctx, ulong addr, ulong maxn, char *buf) { ulong orig_maxn = maxn; for (; maxn > 0; buf++, addr++, maxn--) { *buf = readmemzx(ctx, addr, 1) & 0xFF; if (*buf == 0) break; } *buf = 0; return orig_maxn - maxn; } ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str) { ulong orig_maxn = maxn; for (; *str && maxn > 0; str++, addr++, maxn--) { writemem(ctx, *str, addr, 1); } writemem(ctx, 0, addr, 1); return orig_maxn - maxn; } //----------------------------------------------------------------------------// #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)); \ } //----------------------------------------------------------------------------// static ulong readmem8(ctx_t *ctx, ulong real, ulong addr) { if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF; else return ((ulong)ctx->mp[real] & 0xFF00) >> 8; } static ulong readmem16(ctx_t *ctx, ulong real, ulong addr) { CHK_ALIGN(ushort); return (ulong)ctx->mp[real]; } static ulong readmem32(ctx_t *ctx, ulong real, ulong addr) { CHK_ALIGN(uint); ulong val = ctx->mp[real++]; val = val | ((ulong)ctx->mp[real] << 16); return val; } static ulong readmem64(ctx_t *ctx, ulong real, ulong addr) { CHK_ALIGN(ulong); ulong val = (ulong)ctx->mp[real++]; val = val | ((ulong)ctx->mp[real++] << 16); val = val | ((ulong)ctx->mp[real++] << 32); val = val | ((ulong)ctx->mp[real] << 48); return val; } //----------------------------------------------------------------------------// static void writemem8(ctx_t *ctx, ulong val, ulong real, ulong addr) { ushort v = ctx->mp[real]; if (!(addr % 2)) { ctx->mp[real] = (v & 0xFF00) | (val & 0xFF); } else { ctx->mp[real] = (v & 0xFF) | (((val & 0xFF) << 8)); } } static void writemem16(ctx_t *ctx, ulong val, ulong real, ulong addr) { CHK_ALIGN(ushort); ctx->mp[real] = val & 0xFFFF; } static void writemem32(ctx_t *ctx, ulong val, ulong real, ulong addr) { CHK_ALIGN(uint); ctx->mp[real++] = val & 0xFFFF; ctx->mp[real] = (val >> 16) & 0xFFFF; } static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr) { CHK_ALIGN(ulong); ctx->mp[real++] = val; ctx->mp[real++] = (val >> 16) & 0xFFFF; ctx->mp[real++] = (val >> 32) & 0xFFFF; ctx->mp[real] = (val >> 48) & 0xFFFF; } //----------------------------------------------------------------------------// #define CHK_RANGE() \ if (addr < MEMOFF || real >= MEMSIZE) { \ _except(ctx, E_ACC, \ "Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); \ } #define GETREAL() \ ulong real = addr2real(addr + cr2) //----------------------------------------------------------------------------// ulong readmem(ctx_t *ctx, ulong addr, uint len) { GETREAL(); CHK_RANGE(); ulong val; switch (len) { case 1: val = readmem8(ctx, real, addr); val = (ulong)(long)(char)(val & 0xFF); break; case 2: val = readmem16(ctx, real, addr); val = (ulong)(long)(short)(val & 0xFFFF); break; case 4: val = readmem32(ctx, real, addr); val = (ulong)(long)(int)(val & 0xFFFFFFFF); break; case 8: return readmem64(ctx, real, addr); default: logerr("readmem() bad length %d!\n", len); abort(); } return val; } void writemem(ctx_t *ctx, ulong val, ulong addr, uint len) { GETREAL(); CHK_RANGE(); // log("writemem: 0x%lX: 0x%lX (%d)\n", addr, val, len); 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: logerr("writemem() bad length %d!\n", len); abort(); } } //----------------------------------------------------------------------------// // // The following function 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: logerr("readmemzx() bad length %d!\n", len); abort(); } } //----------------------------------------------------------------------------//