diff --git a/op_string.h b/op_string.h new file mode 100644 index 0000000000..9d0b454c30 --- /dev/null +++ b/op_string.h @@ -0,0 +1,245 @@ + +void OPPROTO glue(glue(op_movs, SUFFIX), STRING_SUFFIX)(void) +{ + int v, inc; + inc = (DF << SHIFT); + v = glue(ldu, SUFFIX)(SI_ADDR); + glue(st, SUFFIX)(DI_ADDR, v); + inc = (DF << SHIFT); + INC_SI(); + INC_DI(); +} + +void OPPROTO glue(glue(op_rep_movs, SUFFIX), STRING_SUFFIX)(void) +{ + int v, inc; + inc = (DF << SHIFT); + while (CX != 0) { + v = glue(ldu, SUFFIX)(SI_ADDR); + glue(st, SUFFIX)(DI_ADDR, v); + INC_SI(); + INC_DI(); + DEC_CX(); + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_stos, SUFFIX), STRING_SUFFIX)(void) +{ + int inc; + glue(st, SUFFIX)(DI_ADDR, EAX); + inc = (DF << SHIFT); + INC_DI(); +} + +void OPPROTO glue(glue(op_rep_stos, SUFFIX), STRING_SUFFIX)(void) +{ + int inc; + inc = (DF << SHIFT); + while (CX != 0) { + glue(st, SUFFIX)(DI_ADDR, EAX); + INC_DI(); + DEC_CX(); + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_lods, SUFFIX), STRING_SUFFIX)(void) +{ + int v, inc; + v = glue(ldu, SUFFIX)(SI_ADDR); +#if SHIFT == 0 + EAX = (EAX & ~0xff) | v; +#elif SHIFT == 1 + EAX = (EAX & ~0xffff) | v; +#else + EAX = v; +#endif + inc = (DF << SHIFT); + INC_SI(); +} + +/* don't know if it is used */ +void OPPROTO glue(glue(op_rep_lods, SUFFIX), STRING_SUFFIX)(void) +{ + int v, inc; + inc = (DF << SHIFT); + while (CX != 0) { + v = glue(ldu, SUFFIX)(SI_ADDR); +#if SHIFT == 0 + EAX = (EAX & ~0xff) | v; +#elif SHIFT == 1 + EAX = (EAX & ~0xffff) | v; +#else + EAX = v; +#endif + INC_SI(); + DEC_CX(); + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_scas, SUFFIX), STRING_SUFFIX)(void) +{ + int v, inc; + + v = glue(ldu, SUFFIX)(DI_ADDR); + inc = (DF << SHIFT); + INC_DI(); + CC_SRC = EAX; + CC_DST = EAX - v; +} + +void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void) +{ + int v1, v2, inc; + + if (CX != 0) { + /* NOTE: the flags are not modified if CX == 0 */ + v1 = EAX & DATA_MASK; + inc = (DF << SHIFT); + do { + v2 = glue(ldu, SUFFIX)(DI_ADDR); + INC_DI(); + DEC_CX(); + if (v1 != v2) + break; + } while (CX != 0); + CC_SRC = v1; + CC_DST = v1 - v2; + CC_OP = CC_OP_SUBB + SHIFT; + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void) +{ + int v1, v2, inc; + + if (CX != 0) { + /* NOTE: the flags are not modified if CX == 0 */ + v1 = EAX & DATA_MASK; + inc = (DF << SHIFT); + do { + v2 = glue(ldu, SUFFIX)(DI_ADDR); + INC_DI(); + DEC_CX(); + if (v1 == v2) + break; + } while (CX != 0); + CC_SRC = v1; + CC_DST = v1 - v2; + CC_OP = CC_OP_SUBB + SHIFT; + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_cmps, SUFFIX), STRING_SUFFIX)(void) +{ + int v1, v2, inc; + v1 = glue(ldu, SUFFIX)(SI_ADDR); + v2 = glue(ldu, SUFFIX)(DI_ADDR); + inc = (DF << SHIFT); + INC_SI(); + INC_DI(); + CC_SRC = v1; + CC_DST = v1 - v2; +} + +void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void) +{ + int v1, v2, inc; + if (CX != 0) { + inc = (DF << SHIFT); + do { + v1 = glue(ldu, SUFFIX)(SI_ADDR); + v2 = glue(ldu, SUFFIX)(DI_ADDR); + INC_SI(); + INC_DI(); + DEC_CX(); + if (v1 != v2) + break; + } while (CX != 0); + CC_SRC = v1; + CC_DST = v1 - v2; + CC_OP = CC_OP_SUBB + SHIFT; + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void) +{ + int v1, v2, inc; + if (CX != 0) { + inc = (DF << SHIFT); + do { + v1 = glue(ldu, SUFFIX)(SI_ADDR); + v2 = glue(ldu, SUFFIX)(DI_ADDR); + INC_SI(); + INC_DI(); + DEC_CX(); + if (v1 == v2) + break; + } while (CX != 0); + CC_SRC = v1; + CC_DST = v1 - v2; + CC_OP = CC_OP_SUBB + SHIFT; + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_outs, SUFFIX), STRING_SUFFIX)(void) +{ + int v, dx, inc; + dx = EDX & 0xffff; + v = glue(ldu, SUFFIX)(SI_ADDR); + glue(cpu_x86_out, SUFFIX)(dx, v); + inc = (DF << SHIFT); + INC_SI(); +} + +void OPPROTO glue(glue(op_rep_outs, SUFFIX), STRING_SUFFIX)(void) +{ + int v, dx, inc; + inc = (DF << SHIFT); + dx = EDX & 0xffff; + while (CX != 0) { + v = glue(ldu, SUFFIX)(SI_ADDR); + glue(cpu_x86_out, SUFFIX)(dx, v); + INC_SI(); + DEC_CX(); + } + FORCE_RET(); +} + +void OPPROTO glue(glue(op_ins, SUFFIX), STRING_SUFFIX)(void) +{ + int v, dx, inc; + dx = EDX & 0xffff; + v = glue(cpu_x86_in, SUFFIX)(dx); + glue(st, SUFFIX)(DI_ADDR, v); + inc = (DF << SHIFT); + INC_DI(); +} + +void OPPROTO glue(glue(op_rep_ins, SUFFIX), STRING_SUFFIX)(void) +{ + int v, dx, inc; + inc = (DF << SHIFT); + dx = EDX & 0xffff; + while (CX != 0) { + v = glue(cpu_x86_in, SUFFIX)(dx); + glue(st, SUFFIX)(DI_ADDR, v); + INC_DI(); + DEC_CX(); + } + FORCE_RET(); +} + +#undef STRING_SUFFIX +#undef SI_ADDR +#undef DI_ADDR +#undef INC_SI +#undef INC_DI +#undef CX +#undef DEC_CX diff --git a/ops_template.h b/ops_template.h index 34f10cdf93..60223fb2ff 100644 --- a/ops_template.h +++ b/ops_template.h @@ -806,238 +806,37 @@ void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void) #endif /* string operations */ -/* XXX: maybe use lower level instructions to ease exception handling */ +/* XXX: maybe use lower level instructions to ease 16 bit / segment handling */ -void OPPROTO glue(op_movs, SUFFIX)(void) -{ - int v; - v = glue(ldu, SUFFIX)((void *)ESI); - glue(st, SUFFIX)((void *)EDI, v); - ESI += (DF << SHIFT); - EDI += (DF << SHIFT); -} +#define STRING_SUFFIX _fast +#define SI_ADDR (void *)ESI +#define DI_ADDR (void *)EDI +#define INC_SI() ESI += inc +#define INC_DI() EDI += inc +#define CX ECX +#define DEC_CX() ECX-- +#include "op_string.h" -void OPPROTO glue(op_rep_movs, SUFFIX)(void) -{ - int v, inc; - inc = (DF << SHIFT); - while (ECX != 0) { - v = glue(ldu, SUFFIX)((void *)ESI); - glue(st, SUFFIX)((void *)EDI, v); - ESI += inc; - EDI += inc; - ECX--; - } - FORCE_RET(); -} +#define STRING_SUFFIX _a32 +#define SI_ADDR (uint8_t *)A0 + ESI +#define DI_ADDR env->seg_cache[R_ES].base + EDI +#define INC_SI() ESI += inc +#define INC_DI() EDI += inc +#define CX ECX +#define DEC_CX() ECX-- +#include "op_string.h" -void OPPROTO glue(op_stos, SUFFIX)(void) -{ - glue(st, SUFFIX)((void *)EDI, EAX); - EDI += (DF << SHIFT); -} - -void OPPROTO glue(op_rep_stos, SUFFIX)(void) -{ - int inc; - inc = (DF << SHIFT); - while (ECX != 0) { - glue(st, SUFFIX)((void *)EDI, EAX); - EDI += inc; - ECX--; - } - FORCE_RET(); -} - -void OPPROTO glue(op_lods, SUFFIX)(void) -{ - int v; - v = glue(ldu, SUFFIX)((void *)ESI); -#if SHIFT == 0 - EAX = (EAX & ~0xff) | v; -#elif SHIFT == 1 - EAX = (EAX & ~0xffff) | v; -#else - EAX = v; -#endif - ESI += (DF << SHIFT); -} - -/* don't know if it is used */ -void OPPROTO glue(op_rep_lods, SUFFIX)(void) -{ - int v, inc; - inc = (DF << SHIFT); - while (ECX != 0) { - v = glue(ldu, SUFFIX)((void *)ESI); -#if SHIFT == 0 - EAX = (EAX & ~0xff) | v; -#elif SHIFT == 1 - EAX = (EAX & ~0xffff) | v; -#else - EAX = v; -#endif - ESI += inc; - ECX--; - } - FORCE_RET(); -} - -void OPPROTO glue(op_scas, SUFFIX)(void) -{ - int v; - - v = glue(ldu, SUFFIX)((void *)EDI); - EDI += (DF << SHIFT); - CC_SRC = EAX; - CC_DST = EAX - v; -} - -void OPPROTO glue(op_repz_scas, SUFFIX)(void) -{ - int v1, v2, inc; - - if (ECX != 0) { - /* NOTE: the flags are not modified if ECX == 0 */ - v1 = EAX & DATA_MASK; - inc = (DF << SHIFT); - do { - v2 = glue(ldu, SUFFIX)((void *)EDI); - EDI += inc; - ECX--; - if (v1 != v2) - break; - } while (ECX != 0); - CC_SRC = v1; - CC_DST = v1 - v2; - CC_OP = CC_OP_SUBB + SHIFT; - } - FORCE_RET(); -} - -void OPPROTO glue(op_repnz_scas, SUFFIX)(void) -{ - int v1, v2, inc; - - if (ECX != 0) { - /* NOTE: the flags are not modified if ECX == 0 */ - v1 = EAX & DATA_MASK; - inc = (DF << SHIFT); - do { - v2 = glue(ldu, SUFFIX)((void *)EDI); - EDI += inc; - ECX--; - if (v1 == v2) - break; - } while (ECX != 0); - CC_SRC = v1; - CC_DST = v1 - v2; - CC_OP = CC_OP_SUBB + SHIFT; - } - FORCE_RET(); -} - -void OPPROTO glue(op_cmps, SUFFIX)(void) -{ - int v1, v2; - v1 = glue(ldu, SUFFIX)((void *)ESI); - v2 = glue(ldu, SUFFIX)((void *)EDI); - ESI += (DF << SHIFT); - EDI += (DF << SHIFT); - CC_SRC = v1; - CC_DST = v1 - v2; -} - -void OPPROTO glue(op_repz_cmps, SUFFIX)(void) -{ - int v1, v2, inc; - if (ECX != 0) { - inc = (DF << SHIFT); - do { - v1 = glue(ldu, SUFFIX)((void *)ESI); - v2 = glue(ldu, SUFFIX)((void *)EDI); - ESI += inc; - EDI += inc; - ECX--; - if (v1 != v2) - break; - } while (ECX != 0); - CC_SRC = v1; - CC_DST = v1 - v2; - CC_OP = CC_OP_SUBB + SHIFT; - } - FORCE_RET(); -} - -void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) -{ - int v1, v2, inc; - if (ECX != 0) { - inc = (DF << SHIFT); - do { - v1 = glue(ldu, SUFFIX)((void *)ESI); - v2 = glue(ldu, SUFFIX)((void *)EDI); - ESI += inc; - EDI += inc; - ECX--; - if (v1 == v2) - break; - } while (ECX != 0); - CC_SRC = v1; - CC_DST = v1 - v2; - CC_OP = CC_OP_SUBB + SHIFT; - } - FORCE_RET(); -} +#define STRING_SUFFIX _a16 +#define SI_ADDR (uint8_t *)A0 + (ESI & 0xffff) +#define DI_ADDR env->seg_cache[R_ES].base + (EDI & 0xffff) +#define INC_SI() ESI = (ESI & ~0xffff) | ((ESI + inc) & 0xffff) +#define INC_DI() EDI = (EDI & ~0xffff) | ((EDI + inc) & 0xffff) +#define CX (ECX & 0xffff) +#define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff) +#include "op_string.h" /* port I/O */ -void OPPROTO glue(op_outs, SUFFIX)(void) -{ - int v, dx; - dx = EDX & 0xffff; - v = glue(ldu, SUFFIX)((void *)ESI); - glue(cpu_x86_out, SUFFIX)(dx, v); - ESI += (DF << SHIFT); -} - -void OPPROTO glue(op_rep_outs, SUFFIX)(void) -{ - int v, dx, inc; - inc = (DF << SHIFT); - dx = EDX & 0xffff; - while (ECX != 0) { - v = glue(ldu, SUFFIX)((void *)ESI); - glue(cpu_x86_out, SUFFIX)(dx, v); - ESI += inc; - ECX--; - } - FORCE_RET(); -} - -void OPPROTO glue(op_ins, SUFFIX)(void) -{ - int v, dx; - dx = EDX & 0xffff; - v = glue(cpu_x86_in, SUFFIX)(dx); - glue(st, SUFFIX)((void *)EDI, v); - EDI += (DF << SHIFT); -} - -void OPPROTO glue(op_rep_ins, SUFFIX)(void) -{ - int v, dx, inc; - inc = (DF << SHIFT); - dx = EDX & 0xffff; - while (ECX != 0) { - v = glue(cpu_x86_in, SUFFIX)(dx); - glue(st, SUFFIX)((void *)EDI, v); - EDI += (DF << SHIFT); - ECX--; - } - FORCE_RET(); -} - void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void) { glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);