This commit is contained in:
julianb0 2019-06-02 16:33:28 +02:00
parent 710d2ca3f9
commit b6c4f3b8d3
No known key found for this signature in database
GPG Key ID: 9C7ACF0C053FB8A1
16 changed files with 302 additions and 436 deletions

View File

@ -103,6 +103,8 @@ struct ctx_t
FILE *disf;
};
#define R(X) ctx->r[X].val
static inline ushort bswap16(ushort u)
{ return ((u<<8) | (u>>8)); }

View File

@ -93,7 +93,7 @@ void disasm(ctx_t *ctx)
acc_t p1 = { 0 }, p2 = { 0 };
uint rep = 0;
ulong rip = ctx->r[RIP].val;
ulong orig_rip = rip;
ushort c = ctx->get(ctx);
if (ISPREF(c)) {
@ -118,17 +118,16 @@ void disasm(ctx_t *ctx)
}
#ifdef _NEED_DISASM
dumpinstr(ctx, rip, rep, c, &p1, &p2);
dumpinstr(ctx, orig_rip, rep, c, &p1, &p2);
#else
do_rep:
dumpinstr(ctx, rip, rep, c, &p1, &p2);
dumpinstr(ctx, orig_rip, rep, c, &p1, &p2);
i->func(ctx, &p1, &p2);
if (rep && ctx->r[RCX].val > 0) {
log("rcx::%lu\n", ctx->r[RCX].val);
ctx->r[RCX].val--;
if (rep && rcx > 0) {
rcx--;
goto do_rep;
}

View File

@ -44,13 +44,13 @@ void d_log(ctx_t *ctx, char *fmt, ...)
va_end(ap);
}
void dumpinstr(ctx_t *ctx, ulong rip, uint rep,
void dumpinstr(ctx_t *ctx, ulong _rip, uint rep,
ushort c, acc_t *p1, acc_t *p2)
{
acc_t *p = 0;
instr_t *i = &ctx->i[c];
d_log(ctx, "0x%08lX: %s%s", rip,
d_log(ctx, "0x%08lX: %s%s", _rip,
(rep ? "rep " : ""),
i->name);

View File

@ -8,361 +8,137 @@ nop
# Logical instructions
#
not r
not m
cnotz r
cnotz m
cnotnz r
cnotnz m
not rm
and rm rim
or rm rim
xor rm rim
shl rm rim
shr rm rim
and r r
and r i
and r m
and m r
and m i
and m m
cnotz rm
candz rm rim
corz rm rim
cxorz rm rim
cshlz rm rim
cshrz rm rim
candz r r
candz r i
candz r m
candz m r
candz m i
candz m m
candnz r r
candnz r i
candnz r m
candnz m r
candnz m i
candnz m m
or r r
or r i
or r m
or m r
or m i
or m m
corz r r
corz r i
corz r m
corz m r
corz m i
corz m m
cornz r r
cornz r i
cornz r m
cornz m r
cornz m i
cornz m m
xor r r
xor r i
xor r m
xor m r
xor m i
xor m m
cxorz r r
cxorz r i
cxorz r m
cxorz m r
cxorz m i
cxorz m m
cxornz r r
cxornz r i
cxornz r m
cxornz m r
cxornz m i
cxornz m m
# shift left logical
shl r r
shl r i
shl r m
shl m r
shl m i
shl m m
cshlz r r
cshlz r i
cshlz r m
cshlz m r
cshlz m i
cshlz m m
cshlnz r r
cshlnz r i
cshlnz r m
cshlnz m r
cshlnz m i
cshlnz m m
# shift right logical
shr r r
shr r i
shr r m
shr m r
shr m i
shr m m
cshrz r r
cshrz r i
cshrz r m
cshrz m r
cshrz m i
cshrz m m
cshrnz r r
cshrnz r i
cshrnz r m
cshrnz m r
cshrnz m i
cshrnz m m
cnotnz rm
candnz rm rim
cornz rm rim
cxornz rm rim
cshlnz rm rim
cshrnz rm rim
#
# Unsigned arithmetic instructions
#
add r r
add r i
add r m
add m r
add m i
add m m
caddz r r
caddz r i
caddz r m
caddz m r
caddz m i
caddz m m
caddnz r r
caddnz r i
caddnz r m
caddnz m r
caddnz m i
caddnz m m
sub r r
sub r i
sub r m
sub m r
sub m i
sub m m
csubz r r
csubz r i
csubz r m
csubz m r
csubz m i
csubz m m
csubnz r r
csubnz r i
csubnz r m
csubnz m r
csubnz m i
csubnz m m
# mul:
# rdx = hi(rax * $0)
# rax = lo(rax * $0)
mul r
mul i
cmulz r
cmulz i
cmulnz r
cmulnz i
# div:
# rdx = rax % $0
# rax = rax / $0
div r
div i
cdivz r
cdivz i
cdivnz r
cdivnz i
inc r
inc m
cincz r
cincz m
cincnz r
cincnz m
sgn rm rim
add rm rim
sub rm rim
mul rim
div rim
inc rm
dec rm
dec r
dec m
cdecz r
cdecz m
cdecnz r
cdecnz m
csgnz rm rim
caddz rm rim
csubz rm rim
cmulz rim
cdivz rim
cincz rm
cdecz rm
sgn r r
sgn r i
sgn r m
sgn m r
sgn m i
sgn m m
csgnz r r
csgnz r i
csgnz r m
csgnz m r
csgnz m i
csgnz m m
csgnnz r r
csgnnz r i
csgnnz r m
csgnnz m r
csgnnz m i
csgnnz m m
csgnnz rm rim
caddnz rm rim
csubnz rm rim
cmulnz rim
cdivnz rim
cincnz rm
cdecnz rm
#
# Comparison instruction
#
# Affects ZF and CF
cmp r r
cmp r i
cmp r m
cmp i r
cmp i i
cmp i m
cmp m r
cmp m i
cmp m m
cmp rim rim
cmpb rim rim
cmpw rim rim
cmpl rim rim
cmpt rim rim
# Only affects ZF
test r r
test r i
test r m
test i r
test i i
test i m
test m r
test m i
test m m
test rim rim
testb rim rim
testw rim rim
testl rim rim
testt rim rim
#
# Jump instructions
#
jmp r
jmp i
jmp ri
cjmpz r
cjmpz i
cjmpnz r
cjmpnz i
cjmpz ri
cjmpnz ri
cjmpa r
cjmpa i
cjmpae r
cjmpae i
cjmpa ri
cjmpae ri
cjmpb r
cjmpb i
cjmpbe r
cjmpbe i
cjmpb ri
cjmpbe ri
jcxz r
jcxz i
jcxnz r
jcxnz i
jcxz ri
jcxnz ri
loop r
loop i
cloopz r
cloopz i
cloopnz r
cloopnz i
loop ri
cloopz ri
cloopnz ri
#
# Movement instructions
#
mov r r
mov r i
mov r m
mov m r
mov m i
mov m m
cmovz r r
cmovz r i
cmovz r m
cmovz m r
cmovz m i
cmovz m m
cmovnz r r
cmovnz r i
cmovnz r m
cmovnz m r
cmovnz m i
cmovnz m m
lea rm m
mov rm rim
xchg rm rim
cmpxchg rm rim
xchg r r
xchg r i
xchg r m
xchg m r
xchg m i
xchg m m
cxchgz r r
cxchgz r i
cxchgz r m
cxchgz m r
cxchgz m i
cxchgz m m
cxchgnz r r
cxchgnz r i
cxchgnz r m
cxchgnz m r
cxchgnz m i
cxchgnz m m
cleaz rm m
cmovz rm rim
cxchgz rm rim
ccmpxchgz rm rim
lea r m
lea m m
cleaz r m
cleaz m m
cleanz r m
cleanz m m
cleanz rm m
cmovnz rm rim
cxchgnz rm rim
ccmpxchgnz rm rim
#
# Stack manipulation instructions
#
push i
push r
push m
cpushz i
cpushz r
cpushz m
cpushnz i
cpushnz r
cpushnz m
pop r
pop m
cpopz r
cpopz m
cpopnz r
cpopnz m
call r
call i
call m
ccallz r
ccallz i
ccallz m
ccallnz r
ccallnz i
ccallnz m
push rim
call rim
pop rm
ret
cpushz rim
ccallz rim
cpopz rm
cretz
cpushnz rim
ccallnz rim
cpopnz rm
cretnz
# push rbp
@ -391,9 +167,7 @@ sti
#
# Prints a character on the screen
prn r
prn i
prn m
prn rim
#
# Debugging instructions

View File

@ -3,6 +3,8 @@
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
from tempfile import TemporaryFile
fi = open("INSTRS")
hd = open("arch_i.h", "w")
ls = open("instrs.lst", "w")
@ -15,6 +17,8 @@ hd.write("#ifdef _NEED_ARCH_I\n")
hd.write("instr_t arch_i[] =\n{\n\n")
hd.write("#endif\n")
fp = TemporaryFile(mode="w+")
def getflag(s):
if s == "r":
return "P_REG"
@ -27,12 +31,42 @@ def getflag(s):
return "__ERROR__"
# "instr ri ri" => "instr r r\ninstr r i\ninstr i r..."
# not optimal but will do for now
for _, line in enumerate(fi):
if line[0] == '#' or line[0] == ' ' or line[0] == '\n':
continue
tok = line.strip().split(' ')
if len(tok) == 0:
continue
i = tok[0].strip()
if len(tok) == 1:
fp.write("{}\n".format(i))
continue
if len(tok) == 2:
p = tok[1].strip()
for c in p:
fp.write("{} {}\n".format(i, c))
continue
assert(len(tok) == 3)
p1 = tok[1].strip()
p2 = tok[2].strip()
for c1 in p1:
for c2 in p2:
fp.write("{} {} {}\n".format(i, c1, c2))
fp.seek(0)
for _, line in enumerate(fp):
tok = line.strip().split(' ')
if len(tok) == 1:
name = tok[0]
p1 = "NOPRM"

View File

@ -32,7 +32,7 @@ IMPL_START_1(mul)
{
// Adapted from www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
ulong v2 = v1;
v1 = ctx->r[RAX].val;
v1 = rax;
ulong u1 = (v1 & 0xffffffff);
ulong u2 = (v2 & 0xffffffff);
@ -49,15 +49,15 @@ IMPL_START_1(mul)
t = (u1 * v2) + k;
k = (t >> 32);
ctx->r[RDX].val = (v1 * v2) + w1 + k;
ctx->r[RAX].val = (t << 32) + w3;
rdx = (v1 * v2) + w1 + k;
rax = (t << 32) + w3;
}
IMPL_END;
IMPL_START_1(div)
{
ctx->r[RDX].val = ctx->r[RAX].val % v1;
ctx->r[RAX].val = ctx->r[RAX].val / v1;
rdx = rax % v1;
rax = rax / v1;
}
IMPL_END;

View File

@ -10,30 +10,30 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
#define IMPL_START_1(name) \
void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
{ \
ulong v1 = (p1->type == A_REG ? ctx->r[p1->val].val : p1->val); \
ulong v1 = (p1->type == A_REG ? R(p1->val) : p1->val); \
if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->mlen);
#define IMPL_START_2(name) \
void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
{ \
ulong v1 = (p1->type == A_REG ? ctx->r[p1->val].val : p1->val); \
ulong v2 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val); \
ulong v1 = (p1->type == A_REG ? R(p1->val) : p1->val); \
ulong v2 = (p2->type == A_REG ? R(p2->val) : p2->val); \
if (p1->mem) v1 = readmem(ctx, v1 + p1->off, p1->mlen); \
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen);
#define IMPL_START_3(name) \
void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
{ \
ulong v2 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val); \
ulong v2 = (p2->type == A_REG ? R(p2->val) : p2->val); \
if (p2->mem) v2 = readmem(ctx, v2 + p2->off, p2->mlen);
#define IMPL_OUT \
assert(p1->type == A_REG || p1->mem); \
if (p1->mem) { \
ulong addr = p1->type == A_REG ? ctx->r[p1->val].val : p1->val; \
ulong addr = p1->type == A_REG ? R(p1->val) : p1->val; \
writemem(ctx, v1, addr + p1->off, p1->mlen); \
} \
else ctx->r[p1->val].val = v1; \
else R(p1->val) = v1; \
}
#define IMPL_END \
@ -46,7 +46,7 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \
#define IMPL_CxxxZ(name) \
IMPL_START_0(c##name##z) \
{ \
if (ctx->r[FLG].val & ZF) { \
if (flg & ZF) { \
i_##name(ctx, p1, p2); \
} \
} \
@ -55,7 +55,7 @@ IMPL_END
#define IMPL_CxxxNZ(name) \
IMPL_START_0(c##name##nz) \
{ \
if (!(ctx->r[FLG].val & ZF)) { \
if (!(flg & ZF)) { \
i_##name(ctx, p1, p2); \
} \
} \
@ -71,16 +71,16 @@ IMPL_END
#define CHK_SUPERV() \
do { \
if ((ctx->r[CR0].val & UF) == 1) { \
if ((cr0 & UF) == 1) { \
_except(ctx, E_SYS, "Supervisor-only INSTR"); \
} \
} while (0)
#define CHK_STACK(op) \
if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) { \
if (rsp % 8 > 0 || rbp % 8 > 0) { \
_except(ctx, E_STK, "Misaligned stack REGS"); \
} \
if (ctx->r[RBP].val op ctx->r[RSP].val) { \
if (rbp op rsp) { \
_except(ctx, E_STK, "RSP above RBP"); \
}
@ -90,13 +90,13 @@ IMPL_END
//
#define PUSH(v) \
writemem64(ctx, v, ctx->r[RSP].val); \
ctx->r[RSP].val -= 8;
writemem64(ctx, v, rsp); \
rsp -= 8;
#define POP(v) \
ctx->r[RSP].val += 8; \
v = readmem64(ctx, ctx->r[RSP].val);
rsp += 8; \
v = readmem64(ctx, rsp);
#define JUMP(v) \
ctx->r[RIP].val = v + ctx->r[CR1].val
rip = v + cr1

View File

@ -19,8 +19,8 @@ IMPL_END;
IMPL_START_1(loop)
{
if (ctx->r[RCX].val > 0) {
ctx->r[RCX].val--;
if (rcx > 0) {
rcx--;
JUMP(v1);
}
}
@ -28,42 +28,42 @@ IMPL_END;
IMPL_START_1(cjmpa)
{
if (!(ctx->r[FLG].val & ZF) && !(ctx->r[FLG].val & CF))
if (!(flg & ZF) && !(flg & CF))
JUMP(v1);
}
IMPL_END;
IMPL_START_1(cjmpae)
{
if (!(ctx->r[FLG].val & CF))
if (!(flg & CF))
JUMP(v1);
}
IMPL_END;
IMPL_START_1(cjmpb)
{
if (!(ctx->r[FLG].val & ZF) && ctx->r[FLG].val & CF)
if (!(flg & ZF) && flg & CF)
JUMP(v1);
}
IMPL_END;
IMPL_START_1(cjmpbe)
{
if (ctx->r[FLG].val & CF)
if (flg & CF)
JUMP(v1);
}
IMPL_END;
IMPL_START_1(jcxz)
{
if (!ctx->r[RCX].val)
if (!rcx)
JUMP(v1);
}
IMPL_END;
IMPL_START_1(jcxnz)
{
if (ctx->r[RCX].val)
if (rcx)
JUMP(v1);
}
IMPL_END;

View File

@ -11,6 +11,20 @@ IMPL_COND(xor);
IMPL_COND(shl);
IMPL_COND(shr);
#define CMP(v1, v2) \
if (v1 == v2) { \
flg |= ZF; \
flg &= ~CF; \
} \
else if (v1 < v2) { \
flg &= ~ZF; \
flg |= CF; \
} \
else { \
flg &= ~ZF; \
flg &= ~CF; \
}
//
// Comparison instructions
//
@ -19,27 +33,77 @@ IMPL_START_2(test)
{
ulong v = v1 & v2;
if (v == 0) ctx->r[FLG].val |= ZF;
else ctx->r[FLG].val &= ~ZF;
CMP(v, 0);
}
IMPL_END;
IMPL_START_2(testb)
{
ulong v = v1 & v2 & 0x00000000000000FF;
CMP(v, 0);
}
IMPL_END;
IMPL_START_2(testw)
{
ulong v = v1 & v2 & 0x000000000000FFFF;
CMP(v, 0);
}
IMPL_END;
IMPL_START_2(testl)
{
ulong v = v1 & v2 & 0x00000000FFFFFFFF;
CMP(v, 0);
}
IMPL_END;
IMPL_START_2(testt)
{
ulong v = v1 & v2 & 0x0000FFFFFFFFFFFF;
CMP(v, 0);
}
IMPL_END;
IMPL_START_2(cmp)
{
if (v1 == v2) {
ctx->r[FLG].val |= ZF;
ctx->r[FLG].val &= ~CF;
}
CMP(v1, v2);
}
IMPL_END;
else if (v1 < v2) {
ctx->r[FLG].val &= ~ZF;
ctx->r[FLG].val |= CF;
}
IMPL_START_2(cmpb)
{
v1 &= 0x00000000000000FF;
v2 &= 0x00000000000000FF;
CMP(v1, v2);
}
IMPL_END;
else {
ctx->r[FLG].val &= ~ZF;
ctx->r[FLG].val &= ~CF;
}
IMPL_START_2(cmpw)
{
v1 &= 0x000000000000FFFF;
v2 &= 0x000000000000FFFF;
CMP(v1, v2);
}
IMPL_END;
IMPL_START_2(cmpl)
{
v1 &= 0x00000000FFFFFFFF;
v2 &= 0x00000000FFFFFFFF;
CMP(v1, v2);
}
IMPL_END;
IMPL_START_2(cmpt)
{
v1 &= 0x0000FFFFFFFFFFFF;
v2 &= 0x0000FFFFFFFFFFFF;
CMP(v1, v2);
}
IMPL_END;

View File

@ -7,6 +7,7 @@
IMPL_COND(mov);
IMPL_COND(lea);
IMPL_COND(xchg);
IMPL_COND(cmpxchg);
//
// Movement instructions
@ -28,13 +29,27 @@ IMPL_OUT;
IMPL_START_1(lea)
{
v1 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val) + p2->off;
v1 = (p2->type == A_REG ? R(p2->val) : p2->val) + p2->off;
}
IMPL_OUT;
IMPL_START_1(gcs)
{
v1 = ctx->r[CR1].val;
v1 = cr1;
}
IMPL_OUT;
IMPL_START_2(cmpxchg)
{
if (rax == v1) {
flg |= ZF;
v1 = v2;
}
else {
flg &= ~ZF;
rax = v1;
}
}
IMPL_OUT;

View File

@ -31,7 +31,7 @@ IMPL_OUT;
IMPL_START_1(call)
{
CHK_STACK(<);
PUSH(ctx->r[RIP].val);
PUSH(rip);
JUMP(v1);
}
IMPL_END;
@ -39,7 +39,7 @@ IMPL_END;
IMPL_START_0(ret)
{
CHK_STACK(<=);
POP(ctx->r[RIP].val);
POP(rip);
}
IMPL_END;
@ -48,8 +48,8 @@ IMPL_START_0(enter)
// We don't CHK_STACK(<) here because ENTER
// (should) always be preceded by a CALL,
// which already checks the stack
PUSH(ctx->r[RBP].val);
ctx->r[RBP].val = ctx->r[RSP].val;
PUSH(rbp);
rbp = rsp;
}
IMPL_END;
@ -57,16 +57,14 @@ IMPL_START_0(leave)
{
// Do NOT check stack here
// (it would always fail)
POP(ctx->r[RBP].val);
POP(rbp);
}
IMPL_END;
IMPL_START_0(pushf)
{
CHK_STACK(<);
writemem64(ctx, ctx->r[FLG].val, ctx->r[RSP].val);
ctx->r[RSP].val -= 8;
PUSH(flg);
}
IMPL_END;
@ -77,8 +75,7 @@ IMPL_START_0(popf)
// XXX
CHK_SUPERV();
ctx->r[RSP].val += 8;
ctx->r[FLG].val = readmem64(ctx, ctx->r[RSP].val);
POP(flg);
}
IMPL_END;

View File

@ -11,19 +11,20 @@
IMPL_START_0(cli)
{
CHK_SUPERV();
ctx->r[FLG].val &= ~IF;
flg &= ~IF;
}
IMPL_END;
IMPL_START_0(sti)
{
CHK_SUPERV();
ctx->r[FLG].val |= IF;
flg |= IF;
}
IMPL_END;
IMPL_START_0(stop)
{
CHK_SUPERV();
_except(ctx, E_SHT, "STOP INSTR");
}
IMPL_END;

View File

@ -9,19 +9,19 @@ static ushort *fwprog;
ushort bget(ctx_t *ctx)
{
if (ctx->r[RIP].val % 2) {
if (rip % 2) {
_except(ctx, E_ALI, "Misaligned RIP register: 0x%016lX",
ctx->r[RIP].val);
rip);
}
if (addr2real(ctx->r[RIP].val) >= ctx->mz) {
if (addr2real(rip) >= ctx->mz) {
_except(ctx, E_ACC, "Executing out of memory: 0x%016lX",
ctx->r[RIP].val);
rip);
}
ushort c = ctx->mp[addr2real(ctx->r[RIP].val)];
ushort c = ctx->mp[addr2real(rip)];
ctx->r[RIP].val += 2;
rip += 2;
return c;
}
@ -36,7 +36,7 @@ ushort dget(ctx_t *ctx)
exit(0);
}
ctx->r[RIP].val += 2;
rip += 2;
return fwprog[i++];
}

View File

@ -16,7 +16,6 @@ ulong readmem(ctx_t *ctx, ulong addr, uint len)
void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
{
addr += ctx->r[CR2].val;
switch (len) {
case 1: writemem8(ctx, val, addr); break;
case 2: writemem16(ctx, val, addr); break;
@ -40,7 +39,7 @@ void writemem(ctx_t *ctx, ulong val, ulong addr, uint len)
}
#define GETREAL() \
addr += ctx->r[CR2].val; \
addr += cr2; \
ulong real = addr2real(addr)
ulong readmem8(ctx_t *ctx, ulong addr)

View File

@ -89,9 +89,6 @@ void dumpregs(ctx_t *ctx)
(strlen(r->name) == 2 ? "=" : ""), r->val);
}
log("\nrip=0x%-16lX rbp=0x%-16lX rsp=0x%-16lX flg=0x%-16lX\n",
ctx->r[RIP].val,
ctx->r[RBP].val,
ctx->r[RSP].val,
ctx->r[FLG].val);
rip, rbp, rsp, flg);
}

View File

@ -5,56 +5,40 @@ enum
{
INV,
RIP,
FLG,
RIP, FLG, RBP, RSP,
#define rip R(RIP)
#define flg R(FLG)
#define rbp R(RBP)
#define rsp R(RSP)
RBP,
RSP,
RAX, RBX, RCX, RDX,
RSX, RBI, RDI, RSI,
#define rax R(RAX)
#define rbx R(RBX)
#define rcx R(RCX)
#define rdx R(RDX)
#define rsx R(RSX)
#define rbi R(RBI)
#define rdi R(RDI)
#define rsi R(RSI)
RAX,
RBX,
RCX,
RDX,
RSX,
RBI,
RDI,
RSI,
NX0, NX1, NX2, NX3,
NX4, NX5, NX6, NX7,
NX0,
NX1,
NX2,
NX3,
NX4,
NX5,
NX6,
NX7,
AX0, AX1, AX2, AX3,
AX4, AX5, AX6, AX7,
AX0,
AX1,
AX2,
AX3,
AX4,
AX5,
AX6,
AX7,
CR0, CR1, CR2, CR3,
CR4, CR5, CR6, CR7,
#define cr0 R(CR0)
#define cr1 R(CR1)
#define cr2 R(CR2)
#define cr3 R(CR3)
CR0,
CR1,
CR2,
CR3,
CR4,
CR5,
CR6,
CR7,
SA0,
SA1,
SA2,
SA3,
SA4,
SA5,
SA6,
SA7,
SA0, SA1,
SA2, SA3,
SA4, SA5,
SA6, SA7,
NREGS
};