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 function
; ;
main: 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 ret
itoa_test: itoa_test:

View File

@ -9,7 +9,6 @@
// //
dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2) dev_t *devctl_common(ctx_t *ctx, ulong v1, ulong v2)
{ {
dev_t *dev = devget(ctx, v1); dev_t *dev = devget(ctx, v1);
if (!dev) 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) void copystr(ctx_t *ctx, ulong addr, ulong maxn, char *str)
{ {
for (; *str && maxn > 0; str++, addr++, maxn--) { 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) IMPL_START_2(devctl)

View File

@ -273,6 +273,13 @@ lea rm m
# #
mov rm rim mov rm rim
#
# Movement with zero-extension (MOVZX) instruction
#
# $1 = ZeroExtend($2)
#
movzx rm m
# #
# Exchange (XCHG) instruction # Exchange (XCHG) instruction
# #
@ -297,12 +304,6 @@ xchg rm rim
# #
cmpxchg rm rim cmpxchg rm rim
# Undocumented
# movb rm rim
# movw rm rim
# movl rm rim
# movt rm rim
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
# Stack manipulation instructions # # Stack manipulation instructions #
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
@ -375,6 +376,10 @@ enter i
# #
leave leave
#---------------------------------------------------------------------------#
# String manipulation instructions #
#---------------------------------------------------------------------------#
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
# Supervisor only instructions # # Supervisor only instructions #
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
@ -382,15 +387,6 @@ leave
pushf pushf
popf 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) # Call an architecture-reserved function slot of device (DEVCTL)
# #
@ -405,6 +401,32 @@ devctl rim rim
# #
iocall 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 # # Misc. instructions #
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
@ -422,7 +444,7 @@ iocall rim rim
nop nop
# #
# Get code/date offset (GCO/GCD) # Get code/data offset (GCO/GCD)
# #
# $1 = CR1 (GCO) # $1 = CR1 (GCO)
# $1 = CR2 (GCD) # $1 = CR2 (GCD)
@ -430,31 +452,6 @@ nop
gco rm gco rm
gcd 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) # Send a character to standard output (PRN)
# #
@ -488,4 +485,32 @@ break
step rim 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; IMPL_END;
// //----------------------------------------------------------------------------//
// Misc. instructions
//
IMPL_START_1(prn) IMPL_START_1(prn)
{ {
if (p1->mlen > 1) { if (p1->mlen > 1) {
log("prn warning: large access size\n"); 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); putchar((int)v1);
} }
IMPL_END; 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) IMPL_START_0(clr)
{ {
rax = rbx = rcx = rdx = 0; rax = rbx = rcx = rdx = 0;
@ -53,3 +79,5 @@ IMPL_START_0(cln)
} }
IMPL_END; IMPL_END;
//----------------------------------------------------------------------------//

View File

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

View File

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

View File

@ -92,18 +92,12 @@ void decode(ctx_t *ctx);
// Address of boot firmware stack // Address of boot firmware stack
#define FWSTACK (MEMOFF * 2) // 2MB #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); 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); 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/regs.h>
#include <pc/decd.h> #include <pc/decd.h>
#include <in/arch_i.h> #include <in/arch_i.h>

View File

@ -3,33 +3,7 @@
#include <pc/arch.h> #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) \ #define CHK_ALIGN(type) \
if (addr % alignof(type) > 0) { \ if (addr % alignof(type) > 0) { \
@ -38,32 +12,23 @@ void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
addr, real, alignof(type)); \ 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; if (addr % 2 == 0) return (ulong)ctx->mp[real] & 0xFF;
else return ((ulong)ctx->mp[real] & 0xFF00) >> 8; 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); CHK_ALIGN(ushort);
return (ulong)ctx->mp[real]; 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); CHK_ALIGN(uint);
ulong val = ctx->mp[real++]; ulong val = ctx->mp[real++];
@ -72,10 +37,8 @@ ulong readmem32(ctx_t *ctx, ulong addr)
return val; 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); CHK_ALIGN(ulong);
ulong val = (ulong)ctx->mp[real++]; ulong val = (ulong)ctx->mp[real++];
@ -86,11 +49,10 @@ ulong readmem64(ctx_t *ctx, ulong addr)
return val; 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]; ushort v = ctx->mp[real];
if (!(addr % 2)) { 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); CHK_ALIGN(ushort);
ctx->mp[real] = val & 0xFFFF; 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); CHK_ALIGN(uint);
ctx->mp[real++] = val & 0xFFFF; ctx->mp[real++] = val & 0xFFFF;
ctx->mp[real] = (val >> 16) & 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); CHK_ALIGN(ulong);
ctx->mp[real++] = val; ctx->mp[real++] = val;
@ -133,3 +89,103 @@ void writemem64(ctx_t *ctx, ulong val, ulong addr)
ctx->mp[real] = (val >> 48) & 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() \
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();
}
}