mirror of
https://github.com/radareorg/radare2
synced 2026-08-22 20:23:32 -04:00
Fix the x86 mul, div and movbe esil and model the bit counters ##esil
This commit is contained in:
parent
323fe03d2b
commit
3e2a8f4cfa
3 changed files with 477 additions and 61 deletions
|
|
@ -355,6 +355,65 @@ static void zext_prefix(struct Getarg *gop, const char *reg, char *out, size_t s
|
|||
}
|
||||
}
|
||||
|
||||
// the implicit operands of the one-operand mul, imul, div and idiv
|
||||
static void muldiv_regs(int width, const char **quot, const char **rema) {
|
||||
*quot = (width == 1)? "al": (width == 2)? "ax": (width == 4)? "eax": "rax";
|
||||
*rema = (width == 1)? "ah": (width == 2)? "dx": (width == 4)? "edx": "rdx";
|
||||
}
|
||||
|
||||
// the byte form divides ax alone, the wider ones the rema:quot pair
|
||||
static char *muldiv_dividend(int width, const char *quot, const char *rema, bool sign) {
|
||||
char *num = (width == 1)
|
||||
? strdup ("ax")
|
||||
: r_str_newf ("%d,%s,<<,%s,+", width * 8, rema, quot);
|
||||
if (sign && width < 4) {
|
||||
// the dividend is signed at twice the operand width
|
||||
char *snum = r_str_newf ("%d,%s,~", width * 16, num);
|
||||
free (num);
|
||||
return snum;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
// counts the set bits of a register in place, by the usual halving sums
|
||||
static void popcnt_esil(RStrBuf *sb, const char *reg, int bits) {
|
||||
const int sh = 64 - bits;
|
||||
const ut64 m1 = 0x5555555555555555ULL >> sh;
|
||||
const ut64 m2 = 0x3333333333333333ULL >> sh;
|
||||
const ut64 m4 = 0x0f0f0f0f0f0f0f0fULL >> sh;
|
||||
const ut64 m8 = 0x0101010101010101ULL >> sh;
|
||||
r_strbuf_appendf (sb, ",1,%s,>>,0x%"PFMT64x",&,%s,-,%s,=", reg, m1, reg, reg);
|
||||
r_strbuf_appendf (sb, ",0x%"PFMT64x",%s,&,2,%s,>>,0x%"PFMT64x",&,+,%s,=",
|
||||
m2, reg, reg, m2, reg);
|
||||
r_strbuf_appendf (sb, ",4,%s,>>,%s,+,0x%"PFMT64x",&,%s,=", reg, reg, m4, reg);
|
||||
// the byte sums land in the top byte, which can carry out of bits
|
||||
r_strbuf_appendf (sb, ",%d,0x%"PFMT64x",%s,*,>>,0x7f,&,%s,=",
|
||||
bits - 8, m8, reg, reg);
|
||||
}
|
||||
|
||||
// esil for the byte-reversed value of an expression of the given byte width
|
||||
static char *byteswap_expr(const char *v, int bytes) {
|
||||
RStrBuf *sb = r_strbuf_new ("");
|
||||
int i;
|
||||
for (i = 0; i < bytes; i++) {
|
||||
const int shr = 8 * i;
|
||||
const int shl = 8 * (bytes - 1 - i);
|
||||
if (i) {
|
||||
r_strbuf_append (sb, ",");
|
||||
}
|
||||
if (shl) {
|
||||
r_strbuf_appendf (sb, "%d,", shl);
|
||||
}
|
||||
if (shr) {
|
||||
r_strbuf_appendf (sb, "%d,%s,>>,0xff,&", shr, v);
|
||||
} else {
|
||||
r_strbuf_appendf (sb, "0xff,%s,&", v);
|
||||
}
|
||||
r_strbuf_appendf (sb, "%s%s", shl? ",<<": "", i? ",|": "");
|
||||
}
|
||||
return r_strbuf_drain (sb);
|
||||
}
|
||||
|
||||
static char *getarg(struct Getarg* gop, int n, int set, char *setop, ut32 *bitsize) {
|
||||
const char *setarg = r_str_get (setop);
|
||||
cs_insn *insn = gop->insn;
|
||||
|
|
@ -1093,7 +1152,6 @@ static void anop_esil(RArchSession *as, RAnalOp *op, ut64 addr, const ut8 *buf,
|
|||
case X86_INS_MOVHPS:
|
||||
case X86_INS_MOVLPD:
|
||||
case X86_INS_MOVLPS:
|
||||
case X86_INS_MOVBE:
|
||||
case X86_INS_MOVSX:
|
||||
case X86_INS_MOVSXD:
|
||||
case X86_INS_MOVQ:
|
||||
|
|
@ -2039,22 +2097,76 @@ static void anop_esil(RArchSession *as, RAnalOp *op, ut64 addr, const ut8 *buf,
|
|||
{
|
||||
dst = getarg (&gop, 0, 0, NULL, NULL);
|
||||
zext_opnd (&gop, 0);
|
||||
if (INSOP(0).size == 4) {
|
||||
esilprintf (op, "0xff000000,24,%s,NUM,<<,&,24,%s,NUM,>>,|,"
|
||||
"8,0x00ff0000,%s,NUM,&,>>,|,"
|
||||
"8,0x0000ff00,%s,NUM,&,<<,|,"
|
||||
"%s,=", dst, dst, dst, dst, dst);
|
||||
} else {
|
||||
esilprintf (op, "0xff00000000000000,56,%s,NUM,<<,&,"
|
||||
"56,%s,NUM,>>,|,40,0xff000000000000,%s,NUM,&,>>,|,"
|
||||
"40,0xff00,%s,NUM,&,<<,|,24,0xff0000000000,%s,NUM,&,>>,|,"
|
||||
"24,0xff0000,%s,NUM,&,<<,|,8,0xff00000000,%s,NUM,&,>>,|,"
|
||||
"8,0xff000000,%s,NUM,&,<<,|,"
|
||||
"%s,=", dst, dst, dst, dst, dst, dst, dst, dst, dst);
|
||||
}
|
||||
char *sw = byteswap_expr (dst, (INSOP (0).size == 4)? 4: 8);
|
||||
esilprintf (op, "%s,%s,=", sw, dst);
|
||||
free (sw);
|
||||
R_FREE (dst);
|
||||
}
|
||||
break;
|
||||
case X86_INS_POPCNT:
|
||||
case X86_INS_LZCNT:
|
||||
case X86_INS_TZCNT:
|
||||
{
|
||||
const int dst_idx = norm_op (0, gop.syntax, INSOPS);
|
||||
const char *reg = (INSOP (dst_idx).type == X86_OP_REG)
|
||||
? cs_reg_name (handle, INSOP (dst_idx).reg): NULL;
|
||||
src = getarg (&gop, 1, 0, NULL, NULL);
|
||||
if (reg && src) {
|
||||
const int id = insn->id;
|
||||
const int bits = INSOP (dst_idx).size * 8;
|
||||
RStrBuf *sb = r_strbuf_new ("");
|
||||
zext_reg (&gop, reg);
|
||||
r_strbuf_appendf (sb, "%s,%s,=", src, reg);
|
||||
if (id != X86_INS_POPCNT) {
|
||||
r_strbuf_appendf (sb, ",%s,!,cf,:=", reg);
|
||||
}
|
||||
if (id == X86_INS_TZCNT) {
|
||||
// tzcnt = popcount(~x & (x - 1))
|
||||
r_strbuf_appendf (sb, ",0x%"PFMT64x",%s,^,1,%s,-,&,%s,=",
|
||||
UT64_MAX >> (64 - bits), reg, reg, reg);
|
||||
} else if (id == X86_INS_LZCNT) {
|
||||
int i;
|
||||
// smear: one bit per non-leading zero
|
||||
for (i = 1; i < bits; i *= 2) {
|
||||
r_strbuf_appendf (sb, ",%d,%s,>>,%s,|,%s,=", i, reg, reg, reg);
|
||||
}
|
||||
}
|
||||
popcnt_esil (sb, reg, bits);
|
||||
if (id == X86_INS_LZCNT) {
|
||||
r_strbuf_appendf (sb, ",%s,%d,-,%s,=", reg, bits, reg);
|
||||
} else if (id == X86_INS_POPCNT) {
|
||||
r_strbuf_append (sb, ",0,cf,:=,0,of,:=,0,sf,:=,0,af,:=,0,pf,:=");
|
||||
}
|
||||
r_strbuf_appendf (sb, ",%s,!,zf,:=", reg);
|
||||
esilprintf (op, "%s", r_strbuf_get (sb));
|
||||
r_strbuf_free (sb);
|
||||
}
|
||||
free (src);
|
||||
}
|
||||
break;
|
||||
case X86_INS_MOVBE:
|
||||
{
|
||||
const int dst_idx = norm_op (0, gop.syntax, INSOPS);
|
||||
const int src_idx = norm_op (1, gop.syntax, INSOPS);
|
||||
src = getarg (&gop, 1, 0, NULL, NULL);
|
||||
dst = getarg (&gop, 0, 1, NULL, NULL);
|
||||
if (src && dst) {
|
||||
// swapping in place reads memory once
|
||||
const bool to_reg = INSOP (dst_idx).type == X86_OP_REG;
|
||||
const char *val = to_reg
|
||||
? cs_reg_name (handle, INSOP (dst_idx).reg): src;
|
||||
char *sw = byteswap_expr (val, INSOP (src_idx).size);
|
||||
if (to_reg) {
|
||||
esilprintf (op, "%s,%s,%s,%s", src, dst, sw, dst);
|
||||
} else {
|
||||
esilprintf (op, "%s,%s", sw, dst);
|
||||
}
|
||||
free (sw);
|
||||
}
|
||||
free (src);
|
||||
free (dst);
|
||||
}
|
||||
break;
|
||||
case X86_INS_OR:
|
||||
// The OF and CF flags are cleared; the SF, ZF, and PF flags are
|
||||
// set according to the result. The state of the AF flag is
|
||||
|
|
@ -2249,26 +2361,17 @@ static void anop_esil(RArchSession *as, RAnalOp *op, ut64 addr, const ut8 *buf,
|
|||
// IDIV does not change flags
|
||||
op->sign = true;
|
||||
if (!arg2 && !arg1) {
|
||||
// TODO: IDIV rbx not implemented. this is just a workaround
|
||||
//
|
||||
// https://www.tptp.cc/mirrors/siyobik.info/instruction/IDIV.html
|
||||
// Divides (signed) the value in the AX, DX:AX, or EDX:EAX registers (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL), DX:AX, or EDX:EAX registers. The source operand can be a general-purpose register or a memory location. The action of this instruction depends on the operand size (dividend/divisor), as shown in the following table:
|
||||
// IDIV RBX == RDX:RAX /= RBX
|
||||
|
||||
//
|
||||
// TODO: 64-bit idiv needs a 128-bit dividend
|
||||
if (arg0) {
|
||||
int width = INSOP(0).size;
|
||||
const char *r_quot = (width == 1)?"al": (width == 2)?"ax": (width == 4)?"eax":"rax";
|
||||
const char *r_rema = (width == 1)?"ah": (width == 2)?"dx": (width == 4)?"edx":"rdx";
|
||||
const char *r_nume = (width == 1)?"ax": r_quot;
|
||||
|
||||
const char *r_quot, *r_rema;
|
||||
muldiv_regs (width, &r_quot, &r_rema);
|
||||
char *num = muldiv_dividend (width, r_quot, r_rema, true);
|
||||
zext_reg (&gop, r_quot);
|
||||
zext_reg (&gop, r_rema);
|
||||
esilprintf (op, "%d,%s,~,%d,%s,<<,%s,+,~%%,%d,%s,~,%d,%s,<<,%s,+,~/,%s,=,%s,=",
|
||||
width*8, arg0, width*8, r_rema, r_nume, width*8, arg0, width*8, r_rema, r_nume, r_quot, r_rema);
|
||||
}
|
||||
else {
|
||||
/* should never happen */
|
||||
esilprintf (op, "%d,%s,~,%s,~%%,%d,%s,~,%s,~/,%s,=,%s,=",
|
||||
width*8, arg0, num, width*8, arg0, num, r_quot, r_rema);
|
||||
free (num);
|
||||
}
|
||||
} else {
|
||||
// does this instruction even exist?
|
||||
|
|
@ -2282,17 +2385,18 @@ static void anop_esil(RArchSession *as, RAnalOp *op, ut64 addr, const ut8 *buf,
|
|||
break;
|
||||
case X86_INS_DIV:
|
||||
{
|
||||
// DIV does not change flags and is unsigned
|
||||
// TODO: 64-bit div needs a 128-bit dividend, so rdx is ignored there
|
||||
int width = INSOP(0).size;
|
||||
dst = getarg (&gop, 0, 0, NULL, NULL);
|
||||
const char *r_quot = (width == 1)?"al": (width == 2)?"ax": (width == 4)?"eax":"rax";
|
||||
const char *r_rema = (width == 1)?"ah": (width == 2)?"dx": (width == 4)?"edx":"rdx";
|
||||
const char *r_nume = (width == 1)?"ax": r_quot;
|
||||
// DIV does not change flags and is unsigned
|
||||
|
||||
const char *r_quot, *r_rema;
|
||||
muldiv_regs (width, &r_quot, &r_rema);
|
||||
char *num = muldiv_dividend (width, r_quot, r_rema, false);
|
||||
zext_reg (&gop, r_quot);
|
||||
zext_reg (&gop, r_rema);
|
||||
esilprintf (op, "%s,%d,%s,<<,%s,+,%%,%s,%d,%s,<<,%s,+,/,%s,=,%s,=",
|
||||
dst, width*8, r_rema, r_nume, dst, width*8, r_rema, r_nume, r_quot, r_rema);
|
||||
esilprintf (op, "%s,%s,%%,%s,%s,/,%s,=,%s,=",
|
||||
dst, num, dst, num, r_quot, r_rema);
|
||||
free (num);
|
||||
free (dst);
|
||||
}
|
||||
break;
|
||||
|
|
@ -2312,21 +2416,19 @@ static void anop_esil(RArchSession *as, RAnalOp *op, ut64 addr, const ut8 *buf,
|
|||
zext_opnd (&gop, 0);
|
||||
esilprintf (op, "%d,%s,~,%d,%s,~,*,DUP,%s,=,%d,%s,~,-,!,!,DUP,cf,:=,of,:=",
|
||||
width*8, multiplier, width*8, arg1, arg0, width*8, arg0);
|
||||
} else {
|
||||
if (arg0) {
|
||||
const char *r_quot = (width == 1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
|
||||
const char *r_rema = (width == 1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
|
||||
const char *r_nume = (width == 1)?"ax": r_quot;
|
||||
|
||||
zext_reg (&gop, r_nume);
|
||||
zext_reg (&gop, r_rema);
|
||||
if (width == 8) { // TODO still needs to be fixed to handle correct signed 128 bit value
|
||||
esilprintf (op, "%s,%s,L*,%s,=,DUP,%s,=,!,!,DUP,cf,:=,of,:=", // flags will be sometimes wrong
|
||||
arg0, r_nume, r_nume, r_rema);
|
||||
} else {
|
||||
esilprintf (op, "%d,%s,~,%d,%s,~,*,DUP,DUP,%s,=,%d,SWAP,>>,%s,=,%d,%s,~,-,!,!,DUP,cf,:=,of,:=",
|
||||
width*8, arg0, width*8, r_nume, r_nume, width*8, r_rema, width*8, r_nume);
|
||||
}
|
||||
} else if (arg0) {
|
||||
const char *r_quot, *r_rema;
|
||||
muldiv_regs (width, &r_quot, &r_rema);
|
||||
zext_reg (&gop, r_quot);
|
||||
zext_reg (&gop, r_rema);
|
||||
if (width == 8) {
|
||||
// L* is unsigned, so fix the high half; the source is
|
||||
// staged in rema first, to read a memory one once
|
||||
esilprintf (op, "%s,%s,=,63,%s,>>,%s,*,63,%s,>>,%s,*,+,%s,%s,L*,%s,=,-,DUP,%s,=,63,%s,>>,0,-,^,!,!,DUP,cf,:=,of,:=",
|
||||
arg0, r_rema, r_quot, r_rema, r_rema, r_quot, r_rema, r_quot, r_quot, r_rema, r_quot);
|
||||
} else {
|
||||
esilprintf (op, "%d,%s,~,%d,%s,~,*,DUP,DUP,%s,=,%d,SWAP,>>,%s,=,%d,%s,~,-,!,!,DUP,cf,:=,of,:=",
|
||||
width*8, arg0, width*8, r_quot, r_quot, width*8, r_rema, width*8, r_quot);
|
||||
}
|
||||
}
|
||||
free (arg0);
|
||||
|
|
@ -2338,19 +2440,18 @@ static void anop_esil(RArchSession *as, RAnalOp *op, ut64 addr, const ut8 *buf,
|
|||
{
|
||||
src = getarg (&gop, 0, 0, NULL, NULL);
|
||||
if (src) {
|
||||
// mul multiplies al, not ax, at a byte width
|
||||
int width = INSOP(0).size;
|
||||
const char *r_quot = (width == 1)?"al": (width == 2)?"ax": (width == 4)?"eax":"rax";
|
||||
const char *r_rema = (width == 1)?"ah": (width == 2)?"dx": (width == 4)?"edx":"rdx";
|
||||
const char *r_nume = (width == 1)?"ax": r_quot;
|
||||
|
||||
zext_reg (&gop, r_nume);
|
||||
const char *r_quot, *r_rema;
|
||||
muldiv_regs (width, &r_quot, &r_rema);
|
||||
zext_reg (&gop, r_quot);
|
||||
zext_reg (&gop, r_rema);
|
||||
if (width == 8 ) {
|
||||
if (width == 8) {
|
||||
esilprintf (op, "%s,%s,L*,%s,=,DUP,%s,=,!,!,DUP,cf,:=,of,:=",
|
||||
src, r_nume, r_nume, r_rema);
|
||||
src, r_quot, r_quot, r_rema);
|
||||
} else {
|
||||
esilprintf (op, "%s,%s,*,DUP,%s,=,%d,SWAP,>>,DUP,%s,=,!,!,DUP,cf,:=,of,:=",
|
||||
src, r_nume, r_nume, width*8, r_rema); // this should be ok for width == 1 also
|
||||
src, r_quot, r_quot, width*8, r_rema);
|
||||
}
|
||||
free (src);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2616,3 +2616,31 @@ EXPECT=<<EOF
|
|||
0x00000001
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=byte mul and idiv use al and ax in 32-bit mode too
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 32
|
||||
CMDS=<<EOF
|
||||
wx f6e1
|
||||
aei
|
||||
ar eax=0x112233ff
|
||||
ar ecx=0x99aabbff
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar ax
|
||||
wx f6f9
|
||||
ar eax=0x1122fff9
|
||||
ar ecx=0x99aabb02
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar al
|
||||
ar ah
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x0000fe01
|
||||
0x000000fd
|
||||
0x000000ff
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ e asm.bits=64
|
|||
EOF
|
||||
EXPECT=<<EOF
|
||||
imul r9
|
||||
0x00000000 r9,rax,L*,rax,=,DUP,rdx,=,!,!,DUP,cf,:=,of,:=
|
||||
0x00000000 r9,rdx,=,63,rax,>>,rdx,*,63,rdx,>>,rax,*,+,rdx,rax,L*,rax,=,-,DUP,rdx,=,63,rax,>>,0,-,^,!,!,DUP,cf,:=,of,:=
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
@ -1617,3 +1617,290 @@ EXPECT=<<EOF
|
|||
0x00000000
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=byte mul div and idiv use al and ax, not the whole eax
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx f6e1
|
||||
aei
|
||||
ar rax=0x112233ff
|
||||
ar rcx=0x99aabbff
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar ax
|
||||
ar cf
|
||||
wx f6f1
|
||||
ar rax=0x112233ff
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar al
|
||||
ar ah
|
||||
wx f6f9
|
||||
ar rax=0x1122fff9
|
||||
ar rcx=0x99aabb02
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar al
|
||||
ar ah
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x0000fe01
|
||||
0x00000001
|
||||
0x00000034
|
||||
0x00000033
|
||||
0x000000fd
|
||||
0x000000ff
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=idiv sign-extends the dx:ax dividend
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx 66f7f9
|
||||
aei
|
||||
ar rax=0x1122fff9
|
||||
ar rdx=0x9999ffff
|
||||
ar rcx=0x77770002
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar ax
|
||||
ar dx
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x0000fffd
|
||||
0x0000ffff
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=imul multiplies the whole signed product at 64 bits
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx 48f7e9
|
||||
aei
|
||||
ar rax=-1
|
||||
ar rcx=2
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rdx
|
||||
ar rax
|
||||
ar cf
|
||||
ar rax=0x8000000000000000
|
||||
ar rcx=2
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rdx
|
||||
ar rax
|
||||
ar cf
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0xffffffffffffffff
|
||||
0xfffffffffffffffe
|
||||
0x00000000
|
||||
0xffffffffffffffff
|
||||
0x00000000
|
||||
0x00000001
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=movbe swaps the bytes it loads and stores
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx 1122334455667788 @ 0x40
|
||||
aei
|
||||
aeim
|
||||
ar rsi=0x40
|
||||
wx 480f38f00e @ 0
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
wx 660f38f00e @ 0
|
||||
ar rcx=0xaabbccdd
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
wx 480f38f10e @ 0
|
||||
wx a5a5a5a5a5a5a5a5 @ 0x40
|
||||
ar rcx=0x1122334455667788
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
p8 8 @ 0x40
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x1122334455667788
|
||||
0xaabb1122
|
||||
1122334455667788
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=popcnt lzcnt and tzcnt count bits and flag a zero source
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx f30fb8c8
|
||||
aei
|
||||
ar rax=0x80000100
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
ar zf
|
||||
wx f30fbdc8
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
wx f30fbcc8
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
ar cf
|
||||
ar rax=0
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
ar cf
|
||||
wx f30fb8c8
|
||||
ar rax=0
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
ar zf
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00000002
|
||||
0x00000000
|
||||
0x00000000
|
||||
0x00000008
|
||||
0x00000000
|
||||
0x00000020
|
||||
0x00000001
|
||||
0x00000000
|
||||
0x00000001
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=att syntax keeps the popcnt and movbe operand order
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64 -e asm.syntax=att
|
||||
CMDS=<<EOF
|
||||
wx f30fb8c3
|
||||
aei
|
||||
ar rax=0
|
||||
ar rbx=0x80000100
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rax
|
||||
wx 1122334455667788 @ 0x40
|
||||
aeim
|
||||
ar rsi=0x40
|
||||
wx 0f38f006 @ 0
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rax
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00000002
|
||||
0x11223344
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=the 64-bit imul reads a memory source once
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx 48f72e
|
||||
ao 1~esilcost
|
||||
wx 0102030405060708 @ 0x40
|
||||
aei
|
||||
aeim
|
||||
ar rsi=0x40
|
||||
ar rax=-2
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rdx
|
||||
ar rax
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
esilcost: 8
|
||||
0xffffffffffffffff
|
||||
0xeff1f3f5f7f9fbfe
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=popcnt lzcnt and tzcnt at the other operand widths
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx f3480fb8c8
|
||||
aei
|
||||
ar rax=0x8000000000000100
|
||||
ar rcx=0
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
wx f3480fbdc8
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
wx f3480fbcc8
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
wx 66f30fb8c8
|
||||
ar rax=0x11228100
|
||||
ar rcx=0x99aabbcc
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar rcx
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00000002
|
||||
0x00000000
|
||||
0x00000008
|
||||
0x99aa0002
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=unsigned div composes the dx:ax dividend
|
||||
FILE=malloc://0x200
|
||||
ARGS=-a x86 -b 64
|
||||
CMDS=<<EOF
|
||||
wx 66f7f1
|
||||
aei
|
||||
ar rax=0x11220010
|
||||
ar rdx=0x99990001
|
||||
ar rcx=0x77770003
|
||||
s 0
|
||||
aeip
|
||||
aes
|
||||
ar ax
|
||||
ar dx
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x0000555a
|
||||
0x00000002
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue