X-Git-Url: https://git.distorted.org.uk/~mdw/xchg-rax-rax/blobdiff_plain/58c897797c6c3df96528413a2c4744e4b85ba575..90c4eee32bd52dbdba4913a5030c7b27cffaa103:/main.c diff --git a/main.c b/main.c index 9ab4c2e..df4b941 100644 --- a/main.c +++ b/main.c @@ -12,10 +12,42 @@ union reg { long u; }; +#if defined(__i386__) +# define GPREGS(_) \ + _(a) _(b) _(c) _(d) _(si) _(di) _(bp) +#elif defined(__x86_64__) +# define GPREGS(_) \ + _(a) _(b) _(c) _(d) _(si) _(di) _(bp) \ + _(r8) _(r9) _(r10) _(r11) _(r12) _(r13) _(r14) _(r15) +#elif defined(__arm__) +# define GPREGS(_) \ + _(r0) _(r1) _(r2) _(r3) _(r4) _(r5) _(r6) _(r7) \ + _(r8) _(r9) _(r10) _(r11) _(r12) +#elif defined(__aarch64__) +# define GPREGS(_) \ + _(x0) _(x1) _(x2) _(x3) _(x4) _(x5) _(x6) _(x7) \ + _(x8) _(x9) _(x10) _(x11) _(x12) _(x13) _(x14) _(x15) +#else +# error "not supported" +#endif + +enum { +#define DEFCONST(r) R_##r, + GPREGS(DEFCONST) +#undef DEFCONST + R_flags, + NREGS +}; + +static const char *const rname[] = { +#define DEFNAME(r) #r, + GPREGS(DEFNAME) +#undef DEFNAME + "f" +}; + struct regs { - union reg - a, b, c, d, si, di, bp, f, - r8, r9, r10, r11, r12, r13, r14, r15; + union reg r[NREGS]; }; struct seg { @@ -25,6 +57,8 @@ struct seg { #define N(v) (sizeof(v)/sizeof((v)[0])) +#define STRCMP(a, op, b) (strcmp((a), (b)) op 0) +#define STRNCMP(a, op, b, n) (strncmp((a), (b), (n)) op 0) #define CTYPE_HACK(func, ch) func((unsigned char)(ch)) #define ISDIGIT(ch) CTYPE_HACK(isdigit, ch) #define ISSPACE(ch) CTYPE_HACK(isspace, ch) @@ -106,12 +140,10 @@ static int hex_digit(char ch) else return (-1); } -static void setreg(union reg *r, - struct seg **seg_inout, - int *i_inout, int argc, char *argv[]) +static void setreg(union reg *r, struct seg **seg_inout, const char *p) { struct seg *seg; - const char *p, *pp; + const char *pp; unsigned char *q; int hi, lo; size_t n; @@ -119,11 +151,9 @@ static void setreg(union reg *r, #define LONG_REG(p) (parse_long("signed register", (p), LONG_MIN, LONG_MAX)) #define ULONG_REG(p) (parse_ulong("unsigned register", (p), 0, ULONG_MAX)) - p = *i_inout >= argc ? "-" : argv[(*i_inout)++]; switch (*p) { case '-': if (p[1]) r->i = LONG_REG(p); - else r->u = 0xdeadbeefdeadbeef; break; case 'i': if (p[1] != ':') goto bad; @@ -154,6 +184,12 @@ static void setreg(union reg *r, } r->p = seg->p; break; + case 'z': + if (p[1] != ':') goto bad; + n = parse_ulong("buffer length", p + 2, 0, ~(size_t)0); + seg = (*seg_inout)++; seg->p = q = xmalloc(n); seg->sz = n; + r->p = q; memset(q, 0, n); + break; default: if (ISDIGIT(*p)) r->u = ULONG_REG(p); else if (*p == '+') r->i = LONG_REG(p); @@ -173,7 +209,11 @@ static void dumpreg(const char *name, const union reg *r, { size_t i; +#if ULONG_MAX == 0xffffffff + printf("%3s = 0x%08lx = %20ld = %20lu", name, r->u, r->i, r->u); +#else printf("%3s = 0x%016lx = %20ld = %20lu", name, r->u, r->i, r->u); +#endif if (r->u >= ' ' && r->u <= '~') printf(" = '%c'", (int)r->u); for (i = 0; i < nseg; i++) { if (r->p == seg[i].p) @@ -212,54 +252,54 @@ int main(int argc, char *argv[]) { struct regs r; struct seg seg[16], *segp = seg; - size_t nseg; - int i, j; + size_t nseg, n; + const char *p; + char *q; + unsigned long f; + int i, j, k; + unsigned long l; prog = strrchr(argv[0], '/'); if (prog) prog++; else prog = argv[0]; if (argc < 2) - barf("usage: %s I [A B C D SI DI BP R8 R9 R10 R11 R12 R13 R14 R15 F]", + barf("usage: %s I [REG...]", prog); j = parse_long("program index", argv[1], -1, N(x) - 1); - i = 2; - setreg(&r.a, &segp, &i, argc, argv); - setreg(&r.b, &segp, &i, argc, argv); - setreg(&r.c, &segp, &i, argc, argv); - setreg(&r.d, &segp, &i, argc, argv); - setreg(&r.si, &segp, &i, argc, argv); - setreg(&r.di, &segp, &i, argc, argv); - setreg(&r.bp, &segp, &i, argc, argv); - setreg(&r.r8, &segp, &i, argc, argv); - setreg(&r.r9, &segp, &i, argc, argv); - setreg(&r.r10, &segp, &i, argc, argv); - setreg(&r.r11, &segp, &i, argc, argv); - setreg(&r.r12, &segp, &i, argc, argv); - setreg(&r.r13, &segp, &i, argc, argv); - setreg(&r.r14, &segp, &i, argc, argv); - setreg(&r.r15, &segp, &i, argc, argv); - setreg(&r.f, &segp, &i, argc, argv); - nseg = segp - seg; +#if ULONG_MAX == 0xffffffff +# define DEAD 0xdeadbeef +#else +# define DEAD 0xdeadbeefdeadbeef +#endif + for (i = 0; i < NREGS - 1; i++) r.r[i].u = DEAD; +#undef DEAD + r.r[R_flags].u = 0; + + i = 0; + argv += 2; + while (*argv) { + p = *argv++; + if (ISDIGIT(*p)) { + l = strtoul(p, &q, 10); + if (l < NREGS && *q == '=') { p = q + 1; i = l; } + } else for (k = 0; k < NREGS; k++) { + n = strlen(rname[k]); + if (STRNCMP(p, ==, rname[k], n) && p[n] == '=') + { i = k; p += n + 1; break; } + } + if (i >= NREGS) barf("too many registers"); + setreg(&r.r[i], &segp, p); i++; + } + nseg = segp - seg; call_example(j < 0 ? &nop : x[j], &r); - dumpreg("rax", &r.a, seg, nseg); - dumpreg("rbx", &r.b, seg, nseg); - dumpreg("rcx", &r.c, seg, nseg); - dumpreg("rdx", &r.d, seg, nseg); - dumpreg("rsi", &r.si, seg, nseg); - dumpreg("rdi", &r.di, seg, nseg); - dumpreg("rbp", &r.bp, seg, nseg); - dumpreg("rbp", &r.bp, seg, nseg); - dumpreg("r8", &r.r8, seg, nseg); - dumpreg("r9", &r.r9, seg, nseg); - dumpreg("r10", &r.r10, seg, nseg); - dumpreg("r11", &r.r11, seg, nseg); - dumpreg("r12", &r.r12, seg, nseg); - dumpreg("r13", &r.r13, seg, nseg); - dumpreg("r14", &r.r14, seg, nseg); - dumpreg("r15", &r.r15, seg, nseg); + for (i = 0; i < NREGS; i++) dumpreg(rname[i], &r.r[i], seg, nseg); + + f = r.r[R_flags].u; + +#if defined(__i386__) || defined(__x86_64__) #define CF (1 << 0) #define PF (1 << 2) @@ -267,38 +307,37 @@ int main(int argc, char *argv[]) #define SF (1 << 7) #define OF (1 << 11) - dumpreg("f", &r.f, seg, nseg); printf("\tstatus: %ccf %cpf %caf %czf %csf %cdf %cof\n", - (r.f.u >> 0)&1u ? '+' : '-', - (r.f.u >> 2)&1u ? '+' : '-', - (r.f.u >> 4)&1u ? '+' : '-', - (r.f.u >> 6)&1u ? '+' : '-', - (r.f.u >> 7)&1u ? '+' : '-', - (r.f.u >> 10)&1u ? '+' : '-', - (r.f.u >> 11)&1u ? '+' : '-'); + (f >> 0)&1u ? '+' : '-', + (f >> 2)&1u ? '+' : '-', + (f >> 4)&1u ? '+' : '-', + (f >> 6)&1u ? '+' : '-', + (f >> 7)&1u ? '+' : '-', + (f >> 10)&1u ? '+' : '-', + (f >> 11)&1u ? '+' : '-'); printf("\tcond:"); - if (r.f.u&CF) printf(" c/b/nae"); else printf(" nc/ae/nb"); - if (r.f.u&ZF) printf(" e/z"); else printf(" ne/nz"); - if (r.f.u&SF) printf(" s"); else printf(" ns"); - if (r.f.u&OF) printf(" o"); else printf(" no"); - if (r.f.u&PF) printf(" p"); else printf(" np"); - if ((r.f.u&CF) || (r.f.u&ZF)) printf(" be/na"); else printf(" a/nbe"); - if (!(r.f.u&OF) == !(r.f.u&SF)) printf(" ge/nl"); else printf(" l/nge"); - if (!(r.f.u&OF) == !(r.f.u&SF) && !(r.f.u&ZF)) + if (f&CF) printf(" c/b/nae"); else printf(" nc/ae/nb"); + if (f&ZF) printf(" e/z"); else printf(" ne/nz"); + if (f&SF) printf(" s"); else printf(" ns"); + if (f&OF) printf(" o"); else printf(" no"); + if (f&PF) printf(" p"); else printf(" np"); + if ((f&CF) || (f&ZF)) printf(" be/na"); else printf(" a/nbe"); + if (!(f&OF) == !(f&SF)) printf(" ge/nl"); else printf(" l/nge"); + if (!(f&OF) == !(f&SF) && !(f&ZF)) printf(" g/nle"); else printf(" le/ng"); putchar('\n'); printf("\tsystem: %ctf %cif iopl=%d %cnt " "%crf %cvm %cac %cvif %cvip %cid\n", - (r.f.u >> 8)&1u ? '+' : '-', - (r.f.u >> 9)&1u ? '+' : '-', - (int)((r.f.u >> 12)&1u), - (r.f.u >> 14)&1u ? '+' : '-', - (r.f.u >> 16)&1u ? '+' : '-', - (r.f.u >> 17)&1u ? '+' : '-', - (r.f.u >> 18)&1u ? '+' : '-', - (r.f.u >> 19)&1u ? '+' : '-', - (r.f.u >> 20)&1u ? '+' : '-', - (r.f.u >> 21)&1u ? '+' : '-'); + (f >> 8)&1u ? '+' : '-', + (f >> 9)&1u ? '+' : '-', + (int)((f >> 12)&1u), + (f >> 14)&1u ? '+' : '-', + (f >> 16)&1u ? '+' : '-', + (f >> 17)&1u ? '+' : '-', + (f >> 18)&1u ? '+' : '-', + (f >> 19)&1u ? '+' : '-', + (f >> 20)&1u ? '+' : '-', + (f >> 21)&1u ? '+' : '-'); #undef CF #undef PF @@ -306,6 +345,90 @@ int main(int argc, char *argv[]) #undef SF #undef OF +#elif defined(__arm__) + +#define NF (1u << 31) +#define ZF (1u << 30) +#define CF (1u << 29) +#define VF (1u << 28) + + { + static const char + *modetab[] = { "?00", "?01", "?02", "?03", "?04", "?05", "?06", "?07", + "?08", "?09", "?10", "?11", "?12", "?13", "?14", "?15", + "usr", "fiq", "irq", "svc", "?20", "?21", "mon", "abt", + "?24", "?25", "hyp", "und", "?28", "?29", "?30", "sys" }, + *condtab[] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" }; + + printf("\tuser: %cn %cz %cc %cv %cq ge=%c%c%c%c;", + (f >> 31)&1u ? '+' : '-', + (f >> 30)&1u ? '+' : '-', + (f >> 29)&1u ? '+' : '-', + (f >> 28)&1u ? '+' : '-', + (f >> 27)&1u ? '+' : '-', + (f >> 19)&1u ? '1' : '0', + (f >> 18)&1u ? '1' : '0', + (f >> 17)&1u ? '1' : '0', + (f >> 16)&1u ? '1' : '0'); + if (f&NF) printf(" mi"); else printf(" pl"); + if (f&ZF) printf(" eq"); else printf(" ne"); + if (f&CF) printf(" cs/hs"); else printf(" cc/lo"); + if (f&VF) printf(" vs"); else printf(" vc"); + if ((f&CF) && !(f&ZF)) printf(" hi"); else printf(" ls"); + if (!(f&VF) == !(f&NF)) printf(" ge"); else printf(" lt"); + if (!(f&VF) == !(f&NF) && !(f&ZF)) printf(" gt"); else printf(" le"); + putchar('\n'); + printf("\tsystem: %cj it=%s:%c%c%c%c %ce %ca %ci %cf %ct m=%s\n", + (f >> 24)&1u ? '+' : '-', + condtab[(f >> 12)&15u], + (f >> 11)&1u ? '1' : '0', + (f >> 10)&1u ? '1' : '0', + (f >> 26)&1u ? '1' : '0', + (f >> 25)&1u ? '1' : '0', + (f >> 9)&1u ? '+' : '-', + (f >> 8)&1u ? '+' : '-', + (f >> 7)&1u ? '+' : '-', + (f >> 6)&1u ? '+' : '-', + (f >> 5)&1u ? '+' : '-', + modetab[(f >> 0)&31u]); + } + +#undef NF +#undef ZF +#undef CF +#undef VF + +#elif defined(__aarch64__) + +#define NF (1u << 31) +#define ZF (1u << 30) +#define CF (1u << 29) +#define VF (1u << 28) + + printf("\tuser: %cn %cz %cc %cv;", + (f >> 31)&1u ? '+' : '-', + (f >> 30)&1u ? '+' : '-', + (f >> 29)&1u ? '+' : '-', + (f >> 28)&1u ? '+' : '-'); + if (f&NF) printf(" mi"); else printf(" pl"); + if (f&ZF) printf(" eq"); else printf(" ne"); + if (f&CF) printf(" cs/hs"); else printf(" cc/lo"); + if (f&VF) printf(" vs"); else printf(" vc"); + if ((f&CF) && !(f&ZF)) printf(" hi"); else printf(" ls"); + if (!(f&VF) == !(f&NF)) printf(" ge"); else printf(" lt"); + if (!(f&VF) == !(f&NF) && !(f&ZF)) printf(" gt"); else printf(" le"); + putchar('\n'); + +#undef NF +#undef ZF +#undef CF +#undef VF + +#else +# error "not supported" +#endif + for (i = 0; i < nseg; i++) { printf("seg[%d] (%p):\n", i, seg[i].p); dumpseg(&seg[i]); }