correct eflags evaluation order for all operations - fixed important CPU state restoring bug in some exception cases - disabled unsafe inc flags optimisation

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@303 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-06-30 23:36:57 +00:00
parent b118d61e55
commit e477b8b81b
5 changed files with 636 additions and 339 deletions

View File

@ -174,7 +174,7 @@ op-$(TARGET_ARCH).o: op-$(TARGET_ARCH).c
helper-$(TARGET_ARCH).o: helper-$(TARGET_ARCH).c
$(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
op-i386.o: op-i386.c opreg_template.h ops_template.h
op-i386.o: op-i386.c opreg_template.h ops_template.h ops_template_mem.h
op-arm.o: op-arm.c op-arm-template.h

View File

@ -1200,11 +1200,11 @@ int load_elf(const char *filename, FILE *outfile, int out_type)
}
if (out_type == OUT_INDEX_OP) {
fprintf(outfile, "DEF(nop1, 0, 0)\n");
fprintf(outfile, "DEF(nop2, 0, 0)\n");
fprintf(outfile, "DEF(nop3, 0, 0)\n");
fprintf(outfile, "DEF(nop, 0, 0)\n");
fprintf(outfile, "DEF(end, 0, 0)\n");
fprintf(outfile, "DEF(nop, 0, 0)\n");
fprintf(outfile, "DEF(nop1, 1, 0)\n");
fprintf(outfile, "DEF(nop2, 2, 0)\n");
fprintf(outfile, "DEF(nop3, 3, 0)\n");
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name, *p;
name = strtab + sym->st_name;

View File

@ -406,127 +406,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
/* shifts */
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & SHIFT_MASK;
if (count) {
CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
src = T0;
T0 &= DATA_MASK;
T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
(T0 & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1)(void)
{
int count;
count = T1 & SHIFT_MASK;
if (count) {
T0 &= DATA_MASK;
T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
}
FORCE_RET();
}
void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & SHIFT_MASK;
if (count) {
CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
src = T0;
T0 &= DATA_MASK;
T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
((T0 >> (DATA_BITS - 1)) & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1)(void)
{
int count;
count = T1 & SHIFT_MASK;
if (count) {
T0 &= DATA_MASK;
T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
}
FORCE_RET();
}
void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
{
int count, res, eflags;
unsigned int src;
count = T1 & 0x1f;
#if DATA_BITS == 16
count = rclw_table[count];
#elif DATA_BITS == 8
count = rclb_table[count];
#endif
if (count) {
eflags = cc_table[CC_OP].compute_all();
T0 &= DATA_MASK;
src = T0;
res = (T0 << count) | ((eflags & CC_C) << (count - 1));
if (count > 1)
res |= T0 >> (DATA_BITS + 1 - count);
T0 = res;
CC_SRC = (eflags & ~(CC_C | CC_O)) |
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
((src >> (DATA_BITS - count)) & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
{
int count, res, eflags;
unsigned int src;
count = T1 & 0x1f;
#if DATA_BITS == 16
count = rclw_table[count];
#elif DATA_BITS == 8
count = rclb_table[count];
#endif
if (count) {
eflags = cc_table[CC_OP].compute_all();
T0 &= DATA_MASK;
src = T0;
res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
if (count > 1)
res |= T0 << (DATA_BITS + 1 - count);
T0 = res;
CC_SRC = (eflags & ~(CC_C | CC_O)) |
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
((src >> (count - 1)) & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
{
int count;
count = T1 & 0x1f;
if (count) {
CC_SRC = (DATA_TYPE)T0 << (count - 1);
T0 = T0 << count;
CC_DST = T0;
CC_OP = CC_OP_SHLB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
{
int count;
@ -535,20 +414,6 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
FORCE_RET();
}
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
{
int count;
count = T1 & 0x1f;
if (count) {
T0 &= DATA_MASK;
CC_SRC = T0 >> (count - 1);
T0 = T0 >> count;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
{
int count;
@ -558,20 +423,6 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
FORCE_RET();
}
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & 0x1f;
if (count) {
src = (DATA_STYPE)T0;
CC_SRC = src >> (count - 1);
T0 = src >> count;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
{
int count, src;
@ -581,162 +432,11 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
FORCE_RET();
}
#if DATA_BITS == 16
/* XXX: overflow flag might be incorrect in some cases in shldw */
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
{
int count;
unsigned int res;
count = PARAM1;
T1 &= 0xffff;
res = T1 | (T0 << 16);
CC_SRC = res >> (32 - count);
res <<= count;
if (count > 16)
res |= T1 << (count - 16);
T0 = res >> 16;
CC_DST = T0;
}
#undef MEM_WRITE
#include "ops_template_mem.h"
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
{
int count;
unsigned int res;
count = ECX & 0x1f;
if (count) {
T1 &= 0xffff;
res = T1 | (T0 << 16);
CC_SRC = res >> (32 - count);
res <<= count;
if (count > 16)
res |= T1 << (count - 16);
T0 = res >> 16;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
{
int count;
unsigned int res;
count = PARAM1;
res = (T0 & 0xffff) | (T1 << 16);
CC_SRC = res >> (count - 1);
res >>= count;
if (count > 16)
res |= T1 << (32 - count);
T0 = res;
CC_DST = T0;
}
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
{
int count;
unsigned int res;
count = ECX & 0x1f;
if (count) {
res = (T0 & 0xffff) | (T1 << 16);
CC_SRC = res >> (count - 1);
res >>= count;
if (count > 16)
res |= T1 << (32 - count);
T0 = res;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
#endif
#if DATA_BITS == 32
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
{
int count;
count = PARAM1;
T0 &= DATA_MASK;
T1 &= DATA_MASK;
CC_SRC = T0 << (count - 1);
T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
CC_DST = T0;
}
void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
{
int count;
count = ECX & 0x1f;
if (count) {
T0 &= DATA_MASK;
T1 &= DATA_MASK;
CC_SRC = T0 << (count - 1);
T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
CC_DST = T0;
CC_OP = CC_OP_SHLB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
{
int count;
count = PARAM1;
T0 &= DATA_MASK;
T1 &= DATA_MASK;
CC_SRC = T0 >> (count - 1);
T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
CC_DST = T0;
}
void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
{
int count;
count = ECX & 0x1f;
if (count) {
T0 &= DATA_MASK;
T1 &= DATA_MASK;
CC_SRC = T0 >> (count - 1);
T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
#endif
/* carry add/sub (we only need to set CC_OP differently) */
void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
{
int cf;
cf = cc_table[CC_OP].compute_c();
T0 = T0 + T1 + cf;
CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
}
void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
{
int cf;
cf = cc_table[CC_OP].compute_c();
T0 = T0 - T1 - cf;
CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
}
void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
{
CC_SRC = T0;
CC_DST = EAX - T0;
if ((DATA_TYPE)CC_DST == 0) {
T0 = T1;
} else {
EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
}
FORCE_RET();
}
#define MEM_WRITE
#include "ops_template_mem.h"
/* bit operations */
#if DATA_BITS >= 16
@ -752,7 +452,7 @@ void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
{
int count;
count = T1 & SHIFT_MASK;
CC_SRC = T0 >> count;
T1 = T0 >> count;
T0 |= (1 << count);
}
@ -760,7 +460,7 @@ void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
{
int count;
count = T1 & SHIFT_MASK;
CC_SRC = T0 >> count;
T1 = T0 >> count;
T0 &= ~(1 << count);
}
@ -768,7 +468,7 @@ void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
{
int count;
count = T1 & SHIFT_MASK;
CC_SRC = T0 >> count;
T1 = T0 >> count;
T0 ^= (1 << count);
}
@ -810,6 +510,13 @@ void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
#endif
#if DATA_BITS == 32
void OPPROTO op_update_bt_cc(void)
{
CC_SRC = T1;
}
#endif
/* string operations */
/* XXX: maybe use lower level instructions to ease 16 bit / segment handling */

423
ops_template_mem.h Normal file
View File

@ -0,0 +1,423 @@
/*
* i386 micro operations (included several times to generate
* different operand sizes)
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef MEM_WRITE
#if DATA_BITS == 8
#define MEM_SUFFIX b_mem
#elif DATA_BITS == 16
#define MEM_SUFFIX w_mem
#elif DATA_BITS == 32
#define MEM_SUFFIX l_mem
#endif
#else
#define MEM_SUFFIX SUFFIX
#endif
void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & SHIFT_MASK;
if (count) {
src = T0;
T0 &= DATA_MASK;
T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
(T0 & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & SHIFT_MASK;
if (count) {
src = T0;
T0 &= DATA_MASK;
T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
((T0 >> (DATA_BITS - 1)) & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void)
{
int count;
count = T1 & SHIFT_MASK;
if (count) {
T0 &= DATA_MASK;
T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
}
FORCE_RET();
}
void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void)
{
int count;
count = T1 & SHIFT_MASK;
if (count) {
T0 &= DATA_MASK;
T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
}
FORCE_RET();
}
void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void)
{
int count, res, eflags;
unsigned int src;
count = T1 & 0x1f;
#if DATA_BITS == 16
count = rclw_table[count];
#elif DATA_BITS == 8
count = rclb_table[count];
#endif
if (count) {
eflags = cc_table[CC_OP].compute_all();
T0 &= DATA_MASK;
src = T0;
res = (T0 << count) | ((eflags & CC_C) << (count - 1));
if (count > 1)
res |= T0 >> (DATA_BITS + 1 - count);
T0 = res;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = (eflags & ~(CC_C | CC_O)) |
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
((src >> (DATA_BITS - count)) & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void)
{
int count, res, eflags;
unsigned int src;
count = T1 & 0x1f;
#if DATA_BITS == 16
count = rclw_table[count];
#elif DATA_BITS == 8
count = rclb_table[count];
#endif
if (count) {
eflags = cc_table[CC_OP].compute_all();
T0 &= DATA_MASK;
src = T0;
res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
if (count > 1)
res |= T0 << (DATA_BITS + 1 - count);
T0 = res;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = (eflags & ~(CC_C | CC_O)) |
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
((src >> (count - 1)) & CC_C);
CC_OP = CC_OP_EFLAGS;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & 0x1f;
if (count) {
src = (DATA_TYPE)T0 << (count - 1);
T0 = T0 << count;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = src;
CC_DST = T0;
CC_OP = CC_OP_SHLB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & 0x1f;
if (count) {
T0 &= DATA_MASK;
src = T0 >> (count - 1);
T0 = T0 >> count;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = src;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void)
{
int count, src;
count = T1 & 0x1f;
if (count) {
src = (DATA_STYPE)T0;
T0 = src >> count;
src = src >> (count - 1);
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = src;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
#if DATA_BITS == 16
/* XXX: overflow flag might be incorrect in some cases in shldw */
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
{
int count;
unsigned int res, tmp;
count = PARAM1;
T1 &= 0xffff;
res = T1 | (T0 << 16);
tmp = res >> (32 - count);
res <<= count;
if (count > 16)
res |= T1 << (count - 16);
T0 = res >> 16;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
}
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
{
int count;
unsigned int res, tmp;
count = ECX & 0x1f;
if (count) {
T1 &= 0xffff;
res = T1 | (T0 << 16);
tmp = res >> (32 - count);
res <<= count;
if (count > 16)
res |= T1 << (count - 16);
T0 = res >> 16;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
{
int count;
unsigned int res, tmp;
count = PARAM1;
res = (T0 & 0xffff) | (T1 << 16);
tmp = res >> (count - 1);
res >>= count;
if (count > 16)
res |= T1 << (32 - count);
T0 = res;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
}
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
{
int count;
unsigned int res, tmp;
count = ECX & 0x1f;
if (count) {
res = (T0 & 0xffff) | (T1 << 16);
tmp = res >> (count - 1);
res >>= count;
if (count > 16)
res |= T1 << (32 - count);
T0 = res;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
#endif
#if DATA_BITS == 32
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
{
int count, tmp;
count = PARAM1;
T0 &= DATA_MASK;
T1 &= DATA_MASK;
tmp = T0 << (count - 1);
T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
}
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
{
int count, tmp;
count = ECX & 0x1f;
if (count) {
T0 &= DATA_MASK;
T1 &= DATA_MASK;
tmp = T0 << (count - 1);
T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
CC_OP = CC_OP_SHLB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
{
int count, tmp;
count = PARAM1;
T0 &= DATA_MASK;
T1 &= DATA_MASK;
tmp = T0 >> (count - 1);
T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
}
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
{
int count, tmp;
count = ECX & 0x1f;
if (count) {
T0 &= DATA_MASK;
T1 &= DATA_MASK;
tmp = T0 >> (count - 1);
T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = tmp;
CC_DST = T0;
CC_OP = CC_OP_SARB + SHIFT;
}
FORCE_RET();
}
#endif
/* carry add/sub (we only need to set CC_OP differently) */
void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void)
{
int cf;
cf = cc_table[CC_OP].compute_c();
T0 = T0 + T1 + cf;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = T1;
CC_DST = T0;
CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
}
void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void)
{
int cf;
cf = cc_table[CC_OP].compute_c();
T0 = T0 - T1 - cf;
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = T1;
CC_DST = T0;
CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
}
void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void)
{
unsigned int src, dst;
src = T0;
dst = EAX - T0;
if ((DATA_TYPE)dst == 0) {
T0 = T1;
} else {
EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
}
#ifdef MEM_WRITE
glue(st, SUFFIX)((uint8_t *)A0, T0);
#endif
CC_SRC = src;
CC_DST = dst;
FORCE_RET();
}
#undef MEM_SUFFIX
#undef MEM_WRITE

View File

@ -390,6 +390,21 @@ static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
},
};
static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3][2] = {
[OT_BYTE] = {
gen_op_adcb_mem_T0_T1_cc,
gen_op_sbbb_mem_T0_T1_cc,
},
[OT_WORD] = {
gen_op_adcw_mem_T0_T1_cc,
gen_op_sbbw_mem_T0_T1_cc,
},
[OT_LONG] = {
gen_op_adcl_mem_T0_T1_cc,
gen_op_sbbl_mem_T0_T1_cc,
},
};
static const int cc_op_arithb[8] = {
CC_OP_ADDB,
CC_OP_LOGICB,
@ -407,6 +422,12 @@ static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
gen_op_cmpxchgl_T0_T1_EAX_cc,
};
static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3] = {
gen_op_cmpxchgb_mem_T0_T1_EAX_cc,
gen_op_cmpxchgw_mem_T0_T1_EAX_cc,
gen_op_cmpxchgl_mem_T0_T1_EAX_cc,
};
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
[OT_BYTE] = {
gen_op_rolb_T0_T1_cc,
@ -440,6 +461,39 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
},
};
static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3][8] = {
[OT_BYTE] = {
gen_op_rolb_mem_T0_T1_cc,
gen_op_rorb_mem_T0_T1_cc,
gen_op_rclb_mem_T0_T1_cc,
gen_op_rcrb_mem_T0_T1_cc,
gen_op_shlb_mem_T0_T1_cc,
gen_op_shrb_mem_T0_T1_cc,
gen_op_shlb_mem_T0_T1_cc,
gen_op_sarb_mem_T0_T1_cc,
},
[OT_WORD] = {
gen_op_rolw_mem_T0_T1_cc,
gen_op_rorw_mem_T0_T1_cc,
gen_op_rclw_mem_T0_T1_cc,
gen_op_rcrw_mem_T0_T1_cc,
gen_op_shlw_mem_T0_T1_cc,
gen_op_shrw_mem_T0_T1_cc,
gen_op_shlw_mem_T0_T1_cc,
gen_op_sarw_mem_T0_T1_cc,
},
[OT_LONG] = {
gen_op_roll_mem_T0_T1_cc,
gen_op_rorl_mem_T0_T1_cc,
gen_op_rcll_mem_T0_T1_cc,
gen_op_rcrl_mem_T0_T1_cc,
gen_op_shll_mem_T0_T1_cc,
gen_op_shrl_mem_T0_T1_cc,
gen_op_shll_mem_T0_T1_cc,
gen_op_sarl_mem_T0_T1_cc,
},
};
static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
[0] = {
gen_op_shldw_T0_T1_im_cc,
@ -462,6 +516,28 @@ static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
},
};
static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[2][2] = {
[0] = {
gen_op_shldw_mem_T0_T1_im_cc,
gen_op_shrdw_mem_T0_T1_im_cc,
},
[1] = {
gen_op_shldl_mem_T0_T1_im_cc,
gen_op_shrdl_mem_T0_T1_im_cc,
},
};
static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[2][2] = {
[0] = {
gen_op_shldw_mem_T0_T1_ECX_cc,
gen_op_shrdw_mem_T0_T1_ECX_cc,
},
[1] = {
gen_op_shldl_mem_T0_T1_ECX_cc,
gen_op_shrdl_mem_T0_T1_ECX_cc,
},
};
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
[0] = {
gen_op_btw_T0_T1_cc,
@ -763,11 +839,14 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
case OP_SBBL:
if (s1->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s1->cc_op);
gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
if (d != OR_TMP0) {
gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
gen_op_mov_reg_T0[ot][d]();
} else {
gen_op_arithc_mem_T0_T1_cc[ot][op - OP_ADCL]();
}
s1->cc_op = CC_OP_DYNAMIC;
/* XXX: incorrect: CC_OP must also be modified AFTER memory access */
gen_update_cc = gen_op_update2_cc;
break;
goto the_end;
case OP_ADDL:
gen_op_addl_T0_T1();
s1->cc_op = CC_OP_ADDB + ot;
@ -802,6 +881,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
exception support) */
if (gen_update_cc)
gen_update_cc();
the_end: ;
}
/* if d == OR_TMP0, it means memory operand (address in A0) */
@ -831,14 +911,18 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
{
if (d != OR_TMP0)
gen_op_mov_TN_reg[ot][0][d]();
else
gen_op_ld_T0_A0[ot]();
if (s != OR_TMP1)
gen_op_mov_TN_reg[ot][1][s]();
/* for zero counts, flags are not updated, so must do it dynamically */
if (s1->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s1->cc_op);
gen_op_shift_T0_T1_cc[ot][op]();
if (d != OR_TMP0)
gen_op_shift_T0_T1_cc[ot][op]();
else
gen_op_shift_mem_T0_T1_cc[ot][op]();
if (d != OR_TMP0)
gen_op_mov_reg_T0[ot][d]();
s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
@ -1885,8 +1969,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
} else {
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_op_ld_T0_A0[ot]();
gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
gen_op_st_T0_A0[ot]();
gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot]();
}
s->cc_op = CC_OP_SUBB + ot;
break;
@ -2264,7 +2347,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
if (mod != 3) {
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_op_ld_T0_A0[ot]();
opreg = OR_TMP0;
} else {
opreg = rm + OR_EAX;
@ -2279,10 +2361,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
}
gen_shifti(s, op, ot, opreg, shift);
}
if (mod != 3) {
gen_op_st_T0_A0[ot]();
}
}
break;
case 0xd0:
@ -2330,7 +2408,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
val = ldub(s->pc++);
val &= 0x1f;
if (val) {
gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
if (mod == 3)
gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
else
gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val);
if (op == 0 && ot != OT_WORD)
s->cc_op = CC_OP_SHLB + ot;
else
@ -2339,12 +2420,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
} else {
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
if (mod == 3)
gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
else
gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op]();
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
}
if (mod != 3) {
gen_op_st_T0_A0[ot]();
} else {
if (mod == 3) {
gen_op_mov_reg_T0[ot][rm]();
}
break;
@ -3202,6 +3284,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_st_T0_A0[ot]();
else
gen_op_mov_reg_T0[ot][rm]();
gen_op_update_bt_cc();
}
break;
case 0x1a3: /* bt Gv, Ev */
@ -3240,6 +3323,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_st_T0_A0[ot]();
else
gen_op_mov_reg_T0[ot][rm]();
gen_op_update_bt_cc();
}
break;
case 0x1bc: /* bsf */
@ -3640,6 +3724,13 @@ static uint16_t opc_read_flags[NB_OPS] = {
[INDEX_op_sbbw_T0_T1_cc] = CC_C,
[INDEX_op_sbbl_T0_T1_cc] = CC_C,
[INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
[INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
[INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
[INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
[INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
[INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
/* subtle: due to the incl/decl implementation, C is used */
[INDEX_op_update_inc_cc] = CC_C,
@ -3717,23 +3808,38 @@ static uint16_t opc_read_flags[NB_OPS] = {
[INDEX_op_rcrb_T0_T1_cc] = CC_C,
[INDEX_op_rcrw_T0_T1_cc] = CC_C,
[INDEX_op_rcrl_T0_T1_cc] = CC_C,
[INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
[INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
[INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
[INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
[INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
[INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
};
/* flags written by an operation */
static uint16_t opc_write_flags[NB_OPS] = {
[INDEX_op_update2_cc] = CC_OSZAPC,
[INDEX_op_update1_cc] = CC_OSZAPC,
[INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_update_neg_cc] = CC_OSZAPC,
/* subtle: due to the incl/decl implementation, C is used */
[INDEX_op_update_inc_cc] = CC_OSZAPC,
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_update_neg_cc] = CC_OSZAPC,
/* subtle: due to the incl/decl implementation, C is used */
[INDEX_op_update_inc_cc] = CC_OSZAPC,
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_mulb_AL_T0] = CC_OSZAPC,
[INDEX_op_imulb_AL_T0] = CC_OSZAPC,
@ -3795,6 +3901,42 @@ static uint16_t opc_write_flags[NB_OPS] = {
[INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
[INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
[INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
[INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
[INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
[INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
[INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
[INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
[INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
[INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
[INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
[INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
@ -3832,6 +3974,10 @@ static uint16_t opc_write_flags[NB_OPS] = {
[INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchg8b] = CC_Z,
[INDEX_op_lar] = CC_Z,
[INDEX_op_lsl] = CC_Z,
@ -3844,8 +3990,10 @@ static uint16_t opc_simpler[NB_OPS] = {
[INDEX_op_update2_cc] = INDEX_op_nop,
[INDEX_op_update1_cc] = INDEX_op_nop,
[INDEX_op_update_neg_cc] = INDEX_op_nop,
#if 0
/* broken: CC_OP logic must be rewritten */
[INDEX_op_update_inc_cc] = INDEX_op_nop,
#endif
[INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
[INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
[INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
@ -3854,6 +4002,14 @@ static uint16_t opc_simpler[NB_OPS] = {
[INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
[INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
[INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
[INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
[INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
[INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
[INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
[INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
[INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
[INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
[INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
@ -3971,6 +4127,10 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
break;
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
(pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
gen_jmp(dc, ret - (unsigned long)dc->cs_base);
}
/* we must store the eflags state if it is not already done */
if (dc->is_jmp != DISAS_TB_JUMP) {
if (dc->cc_op != CC_OP_DYNAMIC)
@ -3983,12 +4143,19 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
if (dc->tf) {
gen_op_raise_exception(EXCP01_SSTP);
}
if (dc->is_jmp != 3) {
if (dc->is_jmp != DISAS_TB_JUMP) {
/* indicate that the hash table must be used to find the next TB */
gen_op_movl_T0_0();
}
*gen_opc_ptr = INDEX_op_end;
/* we don't forget to fill the last values */
if (search_pc) {
j = gen_opc_ptr - gen_opc_buf;
lj++;
while (lj <= j)
gen_opc_instr_start[lj++] = 0;
}
#ifdef DEBUG_DISAS
if (loglevel) {
fprintf(logfile, "----------------\n");