sign extension

This commit is contained in:
julianb0 2019-06-13 15:00:48 +02:00
parent b6f7b3ec16
commit 434e3ff63d
No known key found for this signature in database
GPG Key ID: 9C7ACF0C053FB8A1
8 changed files with 266 additions and 159 deletions

View File

@ -5,6 +5,21 @@
; Main function
;
main:
enter 1
mov q[rsp], 0xFABC1234CCCCDDDD
mov rax, b[rsp]
mov rbx, w[rsp]
mov rcx, l[rsp]
mov rdx, q[rsp]
movzx rsx, b[rsp]
movzx rbi, w[rsp]
movzx rdi, l[rsp]
movzx rsi, q[rsp]
leave
ret
itoa_test:

View File

@ -9,7 +9,6 @@
//
dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
{
dev_t *dev = devget(ctx, v1);
if (!dev)
@ -33,10 +32,10 @@ dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
void copystr(ctx_t *ctx, ulong addr, ulong maxn, char *str)
{
for (; *str && maxn > 0; str++, addr++, maxn--) {
writemem8(ctx, *str, addr);
writemem(ctx, *str, addr, 1);
}
writemem8(ctx, 0, addr);
writemem(ctx, 0, addr, 1);
}
IMPL_START_2(devctl)

View File

@ -273,6 +273,13 @@ lea rm m
#
mov rm rim
#
# Movement with zero-extension (MOVZX) instruction
#
# $1 = ZeroExtend($2)
#
movzx rm m
#
# Exchange (XCHG) instruction
#
@ -297,12 +304,6 @@ xchg rm rim
#
cmpxchg rm rim
# Undocumented
# movb rm rim
# movw rm rim
# movl rm rim
# movt rm rim
#---------------------------------------------------------------------------#
# Stack manipulation instructions #
#---------------------------------------------------------------------------#
@ -375,6 +376,10 @@ enter i
#
leave
#---------------------------------------------------------------------------#
# String manipulation instructions #
#---------------------------------------------------------------------------#
#---------------------------------------------------------------------------#
# Supervisor only instructions #
#---------------------------------------------------------------------------#
@ -382,15 +387,6 @@ leave
pushf
popf
#
# Clear or set interrupt flag (CLI/STI)
#
# Throws:
# #SYS if not in supervisor mode
#
cli
sti
#
# Call an architecture-reserved function slot of device (DEVCTL)
#
@ -405,6 +401,32 @@ devctl rim rim
#
iocall rim rim
#---------------------------------------------------------------------------#
# Flag manipulation instructions #
#---------------------------------------------------------------------------#
#
# Clear or set interrupt flag (CLI/STI)
#
# Throws:
# #SYS if not in supervisor mode
#
cli
sti
#
# Clear or set direction flag (CLD/STD)
#
cld
std
#
# Complement, clear or set carry flag (CMC/CLC/STC)
#
cmc
clc
stc
#---------------------------------------------------------------------------#
# Misc. instructions #
#---------------------------------------------------------------------------#
@ -422,7 +444,7 @@ iocall rim rim
nop
#
# Get code/date offset (GCO/GCD)
# Get code/data offset (GCO/GCD)
#
# $1 = CR1 (GCO)
# $1 = CR2 (GCD)
@ -430,31 +452,6 @@ nop
gco rm
gcd rm
#
# Clear base volatile registers (CLR)
#
# RAX = RBX = RCX = RDX = 0
# RSX = RBI = RDI = RSI = 0
#
clr
#
# Clear argument registers (CLA)
#
# AX0 = AX1 = AX2 = AX3 = 0
# AX4 = AX5 = AX6 = AX7 = 0
#
cla
#
# Clear base non-volatile registers (CLN)
#
# NX0 = NX1 = NX2 = NX3 = 0
# NX4 = NX5 = NX6 = NX7 = 0
#
cln
#
# Send a character to standard output (PRN)
#
@ -488,4 +485,32 @@ break
step rim
#---------------------------------------------------------------------------#
# Clean-up misc. instructions #
#---------------------------------------------------------------------------#
#
# Clear base volatile registers (CLR)
#
# RAX = RBX = RCX = RDX = 0
# RSX = RBI = RDI = RSI = 0
#
clr
#
# Clear argument registers (CLA)
#
# AX0 = AX1 = AX2 = AX3 = 0
# AX4 = AX5 = AX6 = AX7 = 0
#
cla
#
# Clear base non-volatile registers (CLN)
#
# NX0 = NX1 = NX2 = NX3 = 0
# NX4 = NX5 = NX6 = NX7 = 0
#
cln
#---------------------------------------------------------------------------#

View File

@ -11,27 +11,53 @@ IMPL_START_0(nop)
}
IMPL_END;
//
// Misc. instructions
//
//----------------------------------------------------------------------------//
IMPL_START_1(prn)
{
if (p1->mlen > 1) {
log("prn warning: large access size\n");
}
/*
if (!(v1 >= ' ' && v1 < 128) && v1 != '\t' && v1 != '\n') {
log("prn on invalid character: %ld\n", v1);
return;
}
*/
putchar((int)v1);
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(cld)
{
flg &= ~DF;
}
IMPL_END;
IMPL_START_0(std)
{
flg |= DF;
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(cmc)
{
flg = (flg&CF ? flg&~CF : flg|CF);
}
IMPL_END;
IMPL_START_0(clc)
{
flg &= ~CF;
}
IMPL_END;
IMPL_START_0(stc)
{
flg |= CF;
}
IMPL_END;
//----------------------------------------------------------------------------//
IMPL_START_0(clr)
{
rax = rbx = rcx = rdx = 0;
@ -53,3 +79,5 @@ IMPL_START_0(cln)
}
IMPL_END;
//----------------------------------------------------------------------------//

View File

@ -6,6 +6,8 @@
#include <in/flags.h>
#include <in/arch_i.h>
//----------------------------------------------------------------------------//
#define GETV(v, p) \
ulong v; \
assert(p); \
@ -13,6 +15,14 @@
v = readmem(ctx, p->addr, p->mlen); \
else v = p->val
#define GETVZX(v, p) \
ulong v; \
assert(p); \
if (ACC_FMT_IS_MEM(p->type)) \
v = readmemzx(ctx, p->addr, p->mlen); \
else v = p->val
//----------------------------------------------------------------------------//
#define IMPL_START_0(name) \
bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
@ -48,9 +58,7 @@ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
return 0; \
}
//
// Consistency checks
//
//----------------------------------------------------------------------------//
#define CHK_SUPERV() \
do { \
@ -67,18 +75,18 @@ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
_except(ctx, E_STU, "Stack underflow"); \
}
//
// Common operations
//
//----------------------------------------------------------------------------//
#define PUSH(v) \
rsp -= 8; \
writemem64(ctx, v, rsp);
writemem(ctx, v, rsp, 8);
#define POP(v) \
v = readmem64(ctx, rsp); \
v = readmem(ctx, rsp, 8); \
rsp += 8;
#define JUMP(v) \
rip = v + cr1
//----------------------------------------------------------------------------//

View File

@ -3,9 +3,13 @@
#include <in/instrs.h>
//
// Movement instructions
//
IMPL_START_1(lea)
{
v1 = p2->addr;
}
IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_2(mov)
{
@ -13,33 +17,14 @@ IMPL_START_2(mov)
}
IMPL_OUT;
IMPL_START_2(movb)
IMPL_START_1(movzx)
{
v1 = (v1 & 0xFFFFFFFFFFFFFF00)
| (v2 & 0x00000000000000FF);
GETVZX(v2, p2);
v1 = v2;
}
IMPL_OUT;
IMPL_START_2(movw)
{
v1 = (v1 & 0xFFFFFFFFFFFF0000)
| (v2 & 0x000000000000FFFF);
}
IMPL_OUT;
IMPL_START_2(movl)
{
v1 = (v1 & 0xFFFFFFFF00000000)
| (v2 & 0x00000000FFFFFFFF);
}
IMPL_OUT;
IMPL_START_2(movt)
{
v1 = (v1 & 0xFFFF000000000000)
| (v2 & 0x0000FFFFFFFFFFFF);
}
IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_2(xchg)
{
@ -49,11 +34,6 @@ IMPL_START_2(xchg)
}
IMPL_OUT_2;
IMPL_START_1(lea)
{
v1 = p2->addr;
}
IMPL_OUT;
IMPL_START_2(cmpxchg)
{
@ -69,6 +49,8 @@ IMPL_START_2(cmpxchg)
}
IMPL_OUT;
//----------------------------------------------------------------------------//
IMPL_START_1(gco)
{
v1 = cr1;

View File

@ -92,18 +92,12 @@ void decode(ctx_t *ctx);
// Address of boot firmware stack
#define FWSTACK (MEMOFF * 2) // 2MB
ulong readmem8(ctx_t *, ulong addr);
ulong readmem16(ctx_t *, ulong addr);
ulong readmem32(ctx_t *, ulong addr);
ulong readmem64(ctx_t *, ulong addr);
ulong readmem(ctx_t *c, ulong addr, uint len);
void writemem8(ctx_t *, ulong val, ulong addr);
void writemem16(ctx_t *, ulong val, ulong addr);
void writemem32(ctx_t *, ulong val, ulong addr);
void writemem64(ctx_t *, ulong val, ulong addr);
void writemem(ctx_t *, ulong val, ulong addr, uint len);
ulong readmemzx(ctx_t *c, ulong addr, uint len);
void writememzx(ctx_t *, ulong val, ulong addr, uint len);
#include <pc/regs.h>
#include <pc/decd.h>
#include <in/arch_i.h>

View File

@ -3,33 +3,7 @@
#include <pc/arch.h>
ulong readmem(ctx_t *ctx, ulong addr, uint len)
{
switch (len) {
case 1: return readmem8(ctx, addr); break;
case 2: return readmem16(ctx, addr); break;
case 4: return readmem32(ctx, addr); break;
case 8: return readmem64(ctx, addr); break;
default: log("readmem() bad length!\n"); abort();
}
}
void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
{
switch (len) {
case 1: writemem8(ctx, val, addr); break;
case 2: writemem16(ctx, val, addr); break;
case 4: writemem32(ctx, val, addr); break;
case 8: writemem64(ctx, val, addr); break;
default: log("writemem() bad length!\n"); abort();
}
}
#define CHK_RANGE() \
if (addr < MEMOFF || real >= MEMSIZE) { \
_except(ctx, E_ACC, \
"Invalid MEM access: 0x%012lX (0x%012lX)", addr, real); \
}
//----------------------------------------------------------------------------//
#define CHK_ALIGN(type) \
if (addr % alignof(type) > 0) { \
@ -38,32 +12,23 @@ void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
addr, real, alignof(type)); \
}
#define GETREAL() \
addr += cr2; \
ulong real = addr2real(addr)
//----------------------------------------------------------------------------//
ulong readmem8(ctx_t *ctx, ulong addr)
static ulong readmem8(ctx_t *ctx, ulong real, ulong addr)
{
GETREAL();
CHK_RANGE();
if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF;
else return ((ulong)ctx->mp[real] & 0xFF00) >> 8;
}
ulong readmem16(ctx_t *ctx, ulong addr)
static ulong readmem16(ctx_t *ctx, ulong real, ulong addr)
{
GETREAL();
CHK_RANGE();
CHK_ALIGN(ushort);
return (ulong)ctx->mp[real];
}
ulong readmem32(ctx_t *ctx, ulong addr)
static ulong readmem32(ctx_t *ctx, ulong real, ulong addr)
{
GETREAL();
CHK_RANGE();
CHK_ALIGN(uint);
ulong val = ctx->mp[real++];
@ -72,10 +37,8 @@ ulong readmem32(ctx_t *ctx, ulong addr)
return val;
}
ulong readmem64(ctx_t *ctx, ulong addr)
static ulong readmem64(ctx_t *ctx, ulong real, ulong addr)
{
GETREAL();
CHK_RANGE();
CHK_ALIGN(ulong);
ulong val = (ulong)ctx->mp[real++];
@ -86,11 +49,10 @@ ulong readmem64(ctx_t *ctx, ulong addr)
return val;
}
void writemem8(ctx_t *ctx, ulong val, ulong addr)
{
GETREAL();
CHK_RANGE();
//----------------------------------------------------------------------------//
static void writemem8(ctx_t *ctx, ulong val, ulong real, ulong addr)
{
ushort v = ctx->mp[real];
if (!(addr % 2)) {
@ -102,29 +64,23 @@ void writemem8(ctx_t *ctx, ulong val, ulong addr)
}
}
void writemem16(ctx_t *ctx, ulong val, ulong addr)
static void writemem16(ctx_t *ctx, ulong val, ulong real, ulong addr)
{
GETREAL();
CHK_RANGE();
CHK_ALIGN(ushort);
ctx->mp[real] = val & 0xFFFF;
}
void writemem32(ctx_t *ctx, ulong val, ulong addr)
static void writemem32(ctx_t *ctx, ulong val, ulong real, ulong addr)
{
GETREAL();
CHK_RANGE();
CHK_ALIGN(uint);
ctx->mp[real++] = val & 0xFFFF;
ctx->mp[real] = (val >> 16) & 0xFFFF;
}
void writemem64(ctx_t *ctx, ulong val, ulong addr)
static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr)
{
GETREAL();
CHK_RANGE();
CHK_ALIGN(ulong);
ctx->mp[real++] = val;
@ -133,3 +89,103 @@ void writemem64(ctx_t *ctx, ulong val, ulong addr)
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() \
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();
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();
}
}