added cmov instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@32 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
60cd49d5d7
commit
5dd9488c09
1
TODO
1
TODO
@ -1,4 +1,3 @@
|
|||||||
- segment ops (minimal LDT/GDT support for wine)
|
|
||||||
- optimize translated cache chaining (DLL PLT like system)
|
- optimize translated cache chaining (DLL PLT like system)
|
||||||
- improved 16 bit support
|
- improved 16 bit support
|
||||||
- optimize inverse flags propagation (easy by generating intermediate
|
- optimize inverse flags propagation (easy by generating intermediate
|
||||||
|
@ -60,6 +60,19 @@ void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void)
|
|||||||
REG = A0;
|
REG = A0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* mov T1 to REG if T0 is true */
|
||||||
|
void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void)
|
||||||
|
{
|
||||||
|
if (T0)
|
||||||
|
REG = (REG & 0xffff0000) | (T1 & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OPPROTO glue(glue(op_cmovl,REGNAME),_T1_T0)(void)
|
||||||
|
{
|
||||||
|
if (T0)
|
||||||
|
REG = T1;
|
||||||
|
}
|
||||||
|
|
||||||
/* NOTE: T0 high order bits are ignored */
|
/* NOTE: T0 high order bits are ignored */
|
||||||
void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void)
|
void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void)
|
||||||
{
|
{
|
||||||
|
@ -385,6 +385,7 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
|
|||||||
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
|
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
|
||||||
{
|
{
|
||||||
int count, src;
|
int count, src;
|
||||||
|
/* XXX: testing */
|
||||||
count = T1 & SHIFT_MASK;
|
count = T1 & SHIFT_MASK;
|
||||||
if (count) {
|
if (count) {
|
||||||
CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
|
CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#define TEST_CMOV 0
|
||||||
|
|
||||||
#define xglue(x, y) x ## y
|
#define xglue(x, y) x ## y
|
||||||
#define glue(x, y) xglue(x, y)
|
#define glue(x, y) xglue(x, y)
|
||||||
#define stringify(s) tostring(s)
|
#define stringify(s) tostring(s)
|
||||||
@ -225,79 +227,99 @@ void test_lea(void)
|
|||||||
|
|
||||||
#define TEST_JCC(JCC, v1, v2)\
|
#define TEST_JCC(JCC, v1, v2)\
|
||||||
{\
|
{\
|
||||||
|
int res;\
|
||||||
asm("movl $1, %0\n\t"\
|
asm("movl $1, %0\n\t"\
|
||||||
"cmpl %2, %1\n\t"\
|
"cmpl %2, %1\n\t"\
|
||||||
JCC " 1f\n\t"\
|
"j" JCC " 1f\n\t"\
|
||||||
"movl $0, %0\n\t"\
|
"movl $0, %0\n\t"\
|
||||||
"1:\n\t"\
|
"1:\n\t"\
|
||||||
: "=r" (res)\
|
: "=r" (res)\
|
||||||
: "r" (v1), "r" (v2));\
|
: "r" (v1), "r" (v2));\
|
||||||
printf("%-10s %d\n", JCC, res);\
|
printf("%-10s %d\n", "j" JCC, res);\
|
||||||
|
\
|
||||||
|
asm("movl $0, %0\n\t"\
|
||||||
|
"cmpl %2, %1\n\t"\
|
||||||
|
"set" JCC " %b0\n\t"\
|
||||||
|
: "=r" (res)\
|
||||||
|
: "r" (v1), "r" (v2));\
|
||||||
|
printf("%-10s %d\n", "set" JCC, res);\
|
||||||
|
if (TEST_CMOV) {\
|
||||||
|
asm("movl $0x12345678, %0\n\t"\
|
||||||
|
"cmpl %2, %1\n\t"\
|
||||||
|
"cmov" JCC "l %3, %0\n\t"\
|
||||||
|
: "=r" (res)\
|
||||||
|
: "r" (v1), "r" (v2), "m" (1));\
|
||||||
|
printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\
|
||||||
|
asm("movl $0x12345678, %0\n\t"\
|
||||||
|
"cmpl %2, %1\n\t"\
|
||||||
|
"cmov" JCC "w %w3, %w0\n\t"\
|
||||||
|
: "=r" (res)\
|
||||||
|
: "r" (v1), "r" (v2), "r" (1));\
|
||||||
|
printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* various jump tests */
|
/* various jump tests */
|
||||||
void test_jcc(void)
|
void test_jcc(void)
|
||||||
{
|
{
|
||||||
int res;
|
TEST_JCC("ne", 1, 1);
|
||||||
|
TEST_JCC("ne", 1, 0);
|
||||||
|
|
||||||
TEST_JCC("jne", 1, 1);
|
TEST_JCC("e", 1, 1);
|
||||||
TEST_JCC("jne", 1, 0);
|
TEST_JCC("e", 1, 0);
|
||||||
|
|
||||||
TEST_JCC("je", 1, 1);
|
TEST_JCC("l", 1, 1);
|
||||||
TEST_JCC("je", 1, 0);
|
TEST_JCC("l", 1, 0);
|
||||||
|
TEST_JCC("l", 1, -1);
|
||||||
|
|
||||||
TEST_JCC("jl", 1, 1);
|
TEST_JCC("le", 1, 1);
|
||||||
TEST_JCC("jl", 1, 0);
|
TEST_JCC("le", 1, 0);
|
||||||
TEST_JCC("jl", 1, -1);
|
TEST_JCC("le", 1, -1);
|
||||||
|
|
||||||
TEST_JCC("jle", 1, 1);
|
TEST_JCC("ge", 1, 1);
|
||||||
TEST_JCC("jle", 1, 0);
|
TEST_JCC("ge", 1, 0);
|
||||||
TEST_JCC("jle", 1, -1);
|
TEST_JCC("ge", -1, 1);
|
||||||
|
|
||||||
TEST_JCC("jge", 1, 1);
|
TEST_JCC("g", 1, 1);
|
||||||
TEST_JCC("jge", 1, 0);
|
TEST_JCC("g", 1, 0);
|
||||||
TEST_JCC("jge", -1, 1);
|
TEST_JCC("g", 1, -1);
|
||||||
|
|
||||||
TEST_JCC("jg", 1, 1);
|
TEST_JCC("b", 1, 1);
|
||||||
TEST_JCC("jg", 1, 0);
|
TEST_JCC("b", 1, 0);
|
||||||
TEST_JCC("jg", 1, -1);
|
TEST_JCC("b", 1, -1);
|
||||||
|
|
||||||
TEST_JCC("jb", 1, 1);
|
TEST_JCC("be", 1, 1);
|
||||||
TEST_JCC("jb", 1, 0);
|
TEST_JCC("be", 1, 0);
|
||||||
TEST_JCC("jb", 1, -1);
|
TEST_JCC("be", 1, -1);
|
||||||
|
|
||||||
TEST_JCC("jbe", 1, 1);
|
TEST_JCC("ae", 1, 1);
|
||||||
TEST_JCC("jbe", 1, 0);
|
TEST_JCC("ae", 1, 0);
|
||||||
TEST_JCC("jbe", 1, -1);
|
TEST_JCC("ae", 1, -1);
|
||||||
|
|
||||||
TEST_JCC("jae", 1, 1);
|
TEST_JCC("a", 1, 1);
|
||||||
TEST_JCC("jae", 1, 0);
|
TEST_JCC("a", 1, 0);
|
||||||
TEST_JCC("jae", 1, -1);
|
TEST_JCC("a", 1, -1);
|
||||||
|
|
||||||
TEST_JCC("ja", 1, 1);
|
|
||||||
TEST_JCC("ja", 1, 0);
|
|
||||||
TEST_JCC("ja", 1, -1);
|
|
||||||
|
|
||||||
|
|
||||||
TEST_JCC("jp", 1, 1);
|
TEST_JCC("p", 1, 1);
|
||||||
TEST_JCC("jp", 1, 0);
|
TEST_JCC("p", 1, 0);
|
||||||
|
|
||||||
TEST_JCC("jnp", 1, 1);
|
TEST_JCC("np", 1, 1);
|
||||||
TEST_JCC("jnp", 1, 0);
|
TEST_JCC("np", 1, 0);
|
||||||
|
|
||||||
TEST_JCC("jo", 0x7fffffff, 0);
|
TEST_JCC("o", 0x7fffffff, 0);
|
||||||
TEST_JCC("jo", 0x7fffffff, -1);
|
TEST_JCC("o", 0x7fffffff, -1);
|
||||||
|
|
||||||
TEST_JCC("jno", 0x7fffffff, 0);
|
TEST_JCC("no", 0x7fffffff, 0);
|
||||||
TEST_JCC("jno", 0x7fffffff, -1);
|
TEST_JCC("no", 0x7fffffff, -1);
|
||||||
|
|
||||||
TEST_JCC("js", 0, 1);
|
TEST_JCC("s", 0, 1);
|
||||||
TEST_JCC("js", 0, -1);
|
TEST_JCC("s", 0, -1);
|
||||||
TEST_JCC("js", 0, 0);
|
TEST_JCC("s", 0, 0);
|
||||||
|
|
||||||
TEST_JCC("jns", 0, 1);
|
TEST_JCC("ns", 0, 1);
|
||||||
TEST_JCC("jns", 0, -1);
|
TEST_JCC("ns", 0, -1);
|
||||||
TEST_JCC("jns", 0, 0);
|
TEST_JCC("ns", 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CC_MASK
|
#undef CC_MASK
|
||||||
|
@ -44,19 +44,6 @@ int __op_param1, __op_param2, __op_param3;
|
|||||||
extern FILE *logfile;
|
extern FILE *logfile;
|
||||||
extern int loglevel;
|
extern int loglevel;
|
||||||
|
|
||||||
/* supress that */
|
|
||||||
static void error(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
vfprintf(stderr, fmt, ap);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
va_end(ap);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PREFIX_REPZ 1
|
#define PREFIX_REPZ 1
|
||||||
#define PREFIX_REPNZ 2
|
#define PREFIX_REPNZ 2
|
||||||
#define PREFIX_LOCK 4
|
#define PREFIX_LOCK 4
|
||||||
@ -352,6 +339,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
|
||||||
|
[0] = {
|
||||||
|
gen_op_cmovw_EAX_T1_T0,
|
||||||
|
gen_op_cmovw_ECX_T1_T0,
|
||||||
|
gen_op_cmovw_EDX_T1_T0,
|
||||||
|
gen_op_cmovw_EBX_T1_T0,
|
||||||
|
gen_op_cmovw_ESP_T1_T0,
|
||||||
|
gen_op_cmovw_EBP_T1_T0,
|
||||||
|
gen_op_cmovw_ESI_T1_T0,
|
||||||
|
gen_op_cmovw_EDI_T1_T0,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
gen_op_cmovl_EAX_T1_T0,
|
||||||
|
gen_op_cmovl_ECX_T1_T0,
|
||||||
|
gen_op_cmovl_EDX_T1_T0,
|
||||||
|
gen_op_cmovl_EBX_T1_T0,
|
||||||
|
gen_op_cmovl_ESP_T1_T0,
|
||||||
|
gen_op_cmovl_EBP_T1_T0,
|
||||||
|
gen_op_cmovl_ESI_T1_T0,
|
||||||
|
gen_op_cmovl_EDI_T1_T0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
|
static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
|
||||||
gen_op_addl_T0_T1_cc,
|
gen_op_addl_T0_T1_cc,
|
||||||
gen_op_orl_T0_T1_cc,
|
gen_op_orl_T0_T1_cc,
|
||||||
@ -2586,12 +2596,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
s->is_jmp = 1;
|
s->is_jmp = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x190 ... 0x19f:
|
case 0x190 ... 0x19f: /* setcc Gv */
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub(s->pc++);
|
||||||
gen_setcc(s, b);
|
gen_setcc(s, b);
|
||||||
gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
|
gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
|
||||||
break;
|
break;
|
||||||
|
case 0x140 ... 0x14f: /* cmov Gv, Ev */
|
||||||
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
modrm = ldub(s->pc++);
|
||||||
|
reg = (modrm >> 3) & 7;
|
||||||
|
mod = (modrm >> 6) & 3;
|
||||||
|
gen_setcc(s, b);
|
||||||
|
if (mod != 3) {
|
||||||
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||||
|
gen_op_ld_T1_A0[ot]();
|
||||||
|
} else {
|
||||||
|
rm = modrm & 7;
|
||||||
|
gen_op_mov_TN_reg[ot][1][rm]();
|
||||||
|
}
|
||||||
|
gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
|
||||||
|
break;
|
||||||
|
|
||||||
/************************/
|
/************************/
|
||||||
/* flags */
|
/* flags */
|
||||||
case 0x9c: /* pushf */
|
case 0x9c: /* pushf */
|
||||||
@ -2801,7 +2826,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
|
gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
|
||||||
s->is_jmp = 1;
|
s->is_jmp = 1;
|
||||||
break;
|
break;
|
||||||
case 0x1a2: /* rdtsc */
|
case 0x131: /* rdtsc */
|
||||||
gen_op_rdtsc();
|
gen_op_rdtsc();
|
||||||
break;
|
break;
|
||||||
#if 0
|
#if 0
|
||||||
@ -2841,8 +2866,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
|
|||||||
do {
|
do {
|
||||||
ret = disas_insn(dc, pc_ptr);
|
ret = disas_insn(dc, pc_ptr);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
error("unknown instruction at PC=0x%x B=%02x %02x %02x",
|
fprintf(stderr, "unknown instruction at PC=0x%08lx B=%02x %02x %02x",
|
||||||
pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
|
(long)pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
pc_ptr = (void *)ret;
|
pc_ptr = (void *)ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user