/*
* Copyright (c) 2004 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IA32_CPU_ARITH_MCR__
#define IA32_CPU_ARITH_MCR__
/* args == 1 */
#define ARITH_INSTRUCTION_1(inst) \
static UINT32 CPUCALL \
inst##1(UINT32 dst, void *arg) \
{ \
BYTE_##inst(dst); \
return dst; \
} \
static UINT32 CPUCALL \
inst##2(UINT32 dst, void *arg) \
{ \
WORD_##inst(dst); \
return dst; \
} \
static UINT32 CPUCALL \
inst##4(UINT32 dst, void *arg) \
{ \
DWORD_##inst(dst); \
return dst; \
} \
\
void CPUCALL \
inst##_Eb(UINT32 op) \
{ \
UINT8 *out; \
UINT32 dst, madr; \
\
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg8_b20[op]; \
dst = *out; \
BYTE_##inst(dst); \
*out = (UINT8)dst; \
} else { \
CPU_WORKCLOCK(5); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, 0); \
} \
} \
\
void CPUCALL \
inst##_Ew(UINT32 op) \
{ \
UINT16 *out; \
UINT32 dst, madr; \
\
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg16_b20[op]; \
dst = *out; \
WORD_##inst(dst); \
*out = (UINT16)dst; \
} else { \
CPU_WORKCLOCK(5); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, 0); \
} \
} \
\
void CPUCALL \
inst##_Ed(UINT32 op) \
{ \
UINT32 *out; \
UINT32 dst, madr; \
\
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg32_b20[op]; \
dst = *out; \
DWORD_##inst(dst); \
*out = dst; \
} else { \
CPU_WORKCLOCK(5); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, 0); \
} \
}
/* args == 2 */
#define ARITH_INSTRUCTION_2(inst) \
static UINT32 CPUCALL \
inst##1(UINT32 dst, void *arg) \
{ \
UINT32 src = PTR_TO_UINT32(arg); \
BYTE_##inst(dst, src); \
return dst; \
} \
static UINT32 CPUCALL \
inst##2(UINT32 dst, void *arg) \
{ \
UINT32 src = PTR_TO_UINT32(arg); \
WORD_##inst(dst, src); \
return dst; \
} \
static UINT32 CPUCALL \
inst##4(UINT32 dst, void *arg) \
{ \
UINT32 src = PTR_TO_UINT32(arg); \
DWORD_##inst(dst, src); \
return dst; \
} \
\
void \
inst##_EbGb(void) \
{ \
UINT8 *out; \
UINT32 op, src, dst, madr; \
\
PREPART_EA_REG8(op, src); \
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg8_b20[op]; \
dst = *out; \
BYTE_##inst(dst, src); \
*out = (UINT8)dst; \
} else { \
CPU_WORKCLOCK(7); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \
} \
} \
\
void \
inst##_EwGw(void) \
{ \
UINT16 *out; \
UINT32 op, src, dst, madr; \
\
PREPART_EA_REG16(op, src); \
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg16_b20[op]; \
dst = *out; \
WORD_##inst(dst, src); \
*out = (UINT16)dst; \
} else { \
CPU_WORKCLOCK(7); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \
} \
} \
\
void \
inst##_EdGd(void) \
{ \
UINT32 *out; \
UINT32 op, src, dst, madr; \
\
PREPART_EA_REG32(op, src); \
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg32_b20[op]; \
dst = *out; \
DWORD_##inst(dst, src); \
*out = dst; \
} else { \
CPU_WORKCLOCK(7); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \
} \
} \
\
void \
inst##_GbEb(void) \
{ \
UINT8 *out; \
UINT32 op, src, dst; \
\
PREPART_REG8_EA(op, src, out, 2, 7); \
dst = *out; \
BYTE_##inst(dst, src); \
*out = (UINT8)dst; \
} \
\
void \
inst##_GwEw(void) \
{ \
UINT16 *out; \
UINT32 op, src, dst; \
\
PREPART_REG16_EA(op, src, out, 2, 7); \
dst = *out; \
WORD_##inst(dst, src); \
*out = (UINT16)dst; \
} \
\
void \
inst##_GdEd(void) \
{ \
UINT32 *out; \
UINT32 op, src, dst; \
\
PREPART_REG32_EA(op, src, out, 2, 7); \
dst = *out; \
DWORD_##inst(dst, src); \
*out = dst; \
} \
\
void \
inst##_ALIb(void) \
{ \
UINT32 src, dst; \
\
CPU_WORKCLOCK(3); \
GET_PCBYTE(src); \
dst = CPU_AL; \
BYTE_##inst(dst, src); \
CPU_AL = (UINT8)dst; \
} \
\
void \
inst##_AXIw(void) \
{ \
UINT32 src, dst; \
\
CPU_WORKCLOCK(3); \
GET_PCWORD(src); \
dst = CPU_AX; \
WORD_##inst(dst, src); \
CPU_AX = (UINT16)dst; \
} \
\
void \
inst##_EAXId(void) \
{ \
UINT32 src, dst; \
\
CPU_WORKCLOCK(3); \
GET_PCDWORD(src); \
dst = CPU_EAX; \
DWORD_##inst(dst, src); \
CPU_EAX = dst; \
} \
\
void CPUCALL \
inst##_EbIb(UINT8 *regp, UINT32 src) \
{ \
UINT32 dst; \
\
dst = *regp; \
BYTE_##inst(dst, src); \
*regp = (UINT8)dst; \
} \
\
void CPUCALL \
inst##_EbIb_ext(UINT32 madr, UINT32 src) \
{ \
\
cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \
} \
\
void CPUCALL \
inst##_EwIx(UINT16 *regp, UINT32 src) \
{ \
UINT32 dst; \
\
dst = *regp; \
WORD_##inst(dst, src); \
*regp = (UINT16)dst; \
} \
\
void CPUCALL \
inst##_EwIx_ext(UINT32 madr, UINT32 src) \
{ \
\
cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \
} \
\
void CPUCALL \
inst##_EdIx(UINT32 *regp, UINT32 src) \
{ \
UINT32 dst; \
\
dst = *regp; \
DWORD_##inst(dst, src); \
*regp = dst; \
} \
\
void CPUCALL \
inst##_EdIx_ext(UINT32 madr, UINT32 src) \
{ \
\
cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \
}
/* args == 3 */
#define ARITH_INSTRUCTION_3(inst) \
static UINT32 CPUCALL \
inst##1(UINT32 dst, void *arg) \
{ \
UINT32 src = PTR_TO_UINT32(arg); \
UINT32 res; \
BYTE_##inst(res, dst, src); \
return res; \
} \
static UINT32 CPUCALL \
inst##2(UINT32 dst, void *arg) \
{ \
UINT32 src = PTR_TO_UINT32(arg); \
UINT32 res; \
WORD_##inst(res, dst, src); \
return res; \
} \
static UINT32 CPUCALL \
inst##4(UINT32 dst, void *arg) \
{ \
UINT32 src = PTR_TO_UINT32(arg); \
UINT32 res; \
DWORD_##inst(res, dst, src); \
return res; \
} \
\
void \
inst##_EbGb(void) \
{ \
UINT8 *out; \
UINT32 op, src, dst, res, madr; \
\
PREPART_EA_REG8(op, src); \
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg8_b20[op]; \
dst = *out; \
BYTE_##inst(res, dst, src); \
*out = (UINT8)res; \
} else { \
CPU_WORKCLOCK(7); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \
} \
} \
\
void \
inst##_EwGw(void) \
{ \
UINT16 *out; \
UINT32 op, src, dst, res, madr; \
\
PREPART_EA_REG16(op, src); \
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg16_b20[op]; \
dst = *out; \
WORD_##inst(res, dst, src); \
*out = (UINT16)res; \
} else { \
CPU_WORKCLOCK(7); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \
} \
} \
\
void \
inst##_EdGd(void) \
{ \
UINT32 *out; \
UINT32 op, src, dst, res, madr; \
\
PREPART_EA_REG32(op, src); \
if (op >= 0xc0) { \
CPU_WORKCLOCK(2); \
out = reg32_b20[op]; \
dst = *out; \
DWORD_##inst(res, dst, src); \
*out = res; \
} else { \
CPU_WORKCLOCK(7); \
madr = calc_ea_dst(op); \
cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \
} \
} \
\
void \
inst##_GbEb(void) \
{ \
UINT8 *out; \
UINT32 op, src, dst, res; \
\
PREPART_REG8_EA(op, src, out, 2, 7); \
dst = *out; \
BYTE_##inst(res, dst, src); \
*out = (UINT8)res; \
} \
\
void \
inst##_GwEw(void) \
{ \
UINT16 *out; \
UINT32 op, src, dst, res; \
\
PREPART_REG16_EA(op, src, out, 2, 7); \
dst = *out; \
WORD_##inst(res, dst, src); \
*out = (UINT16)res; \
} \
\
void \
inst##_GdEd(void) \
{ \
UINT32 *out; \
UINT32 op, src, dst, res; \
\
PREPART_REG32_EA(op, src, out, 2, 7); \
dst = *out; \
DWORD_##inst(res, dst, src); \
*out = res; \
} \
\
void \
inst##_ALIb(void) \
{ \
UINT32 src, dst, res; \
\
CPU_WORKCLOCK(2); \
GET_PCBYTE(src); \
dst = CPU_AL; \
BYTE_##inst(res, dst, src); \
CPU_AL = (UINT8)res; \
} \
\
void \
inst##_AXIw(void) \
{ \
UINT32 src, dst, res; \
\
CPU_WORKCLOCK(2); \
GET_PCWORD(src); \
dst = CPU_AX; \
WORD_##inst(res, dst, src); \
CPU_AX = (UINT16)res; \
} \
\
void \
inst##_EAXId(void) \
{ \
UINT32 src, dst, res; \
\
CPU_WORKCLOCK(2); \
GET_PCDWORD(src); \
dst = CPU_EAX; \
DWORD_##inst(res, dst, src); \
CPU_EAX = res; \
} \
\
void CPUCALL \
inst##_EbIb(UINT8 *regp, UINT32 src) \
{ \
UINT32 dst, res; \
\
dst = *regp; \
BYTE_##inst(res, dst, src); \
*regp = (UINT8)res; \
} \
\
void CPUCALL \
inst##_EbIb_ext(UINT32 madr, UINT32 src) \
{ \
\
cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \
} \
\
void CPUCALL \
inst##_EwIx(UINT16 *regp, UINT32 src) \
{ \
UINT32 dst, res; \
\
dst = *regp; \
WORD_##inst(res, dst, src); \
*regp = (UINT16)res; \
} \
\
void CPUCALL \
inst##_EwIx_ext(UINT32 madr, UINT32 src) \
{ \
\
cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \
} \
\
void CPUCALL \
inst##_EdIx(UINT32 *regp, UINT32 src) \
{ \
UINT32 dst, res; \
\
dst = *regp; \
DWORD_##inst(res, dst, src); \
*regp = res; \
} \
\
void CPUCALL \
inst##_EdIx_ext(UINT32 madr, UINT32 src) \
{ \
\
cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \
}
#endif /* IA32_CPU_ARITH_MCR__ */
RetroPC.NET-CVS <cvs@retropc.net>