105b261ecSmrg/**************************************************************************** 205b261ecSmrg* 305b261ecSmrg* Realmode X86 Emulator Library 405b261ecSmrg* 505b261ecSmrg* Copyright (C) 1996-1999 SciTech Software, Inc. 605b261ecSmrg* Copyright (C) David Mosberger-Tang 705b261ecSmrg* Copyright (C) 1999 Egbert Eich 805b261ecSmrg* 905b261ecSmrg* ======================================================================== 1005b261ecSmrg* 1105b261ecSmrg* Permission to use, copy, modify, distribute, and sell this software and 1205b261ecSmrg* its documentation for any purpose is hereby granted without fee, 1305b261ecSmrg* provided that the above copyright notice appear in all copies and that 1405b261ecSmrg* both that copyright notice and this permission notice appear in 1505b261ecSmrg* supporting documentation, and that the name of the authors not be used 1605b261ecSmrg* in advertising or publicity pertaining to distribution of the software 1705b261ecSmrg* without specific, written prior permission. The authors makes no 1805b261ecSmrg* representations about the suitability of this software for any purpose. 1905b261ecSmrg* It is provided "as is" without express or implied warranty. 2005b261ecSmrg* 2105b261ecSmrg* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 2205b261ecSmrg* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 2305b261ecSmrg* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 2405b261ecSmrg* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 2505b261ecSmrg* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 2605b261ecSmrg* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2705b261ecSmrg* PERFORMANCE OF THIS SOFTWARE. 2805b261ecSmrg* 2905b261ecSmrg* ======================================================================== 3005b261ecSmrg* 3105b261ecSmrg* Language: ANSI C 3205b261ecSmrg* Environment: Any 3305b261ecSmrg* Developer: Kendall Bennett 3405b261ecSmrg* 3505b261ecSmrg* Description: This file contains the code to implement the primitive 3605b261ecSmrg* machine operations used by the emulation code in ops.c 3705b261ecSmrg* 3805b261ecSmrg* Carry Chain Calculation 3905b261ecSmrg* 4005b261ecSmrg* This represents a somewhat expensive calculation which is 4105b261ecSmrg* apparently required to emulate the setting of the OF and AF flag. 4205b261ecSmrg* The latter is not so important, but the former is. The overflow 4305b261ecSmrg* flag is the XOR of the top two bits of the carry chain for an 4405b261ecSmrg* addition (similar for subtraction). Since we do not want to 4505b261ecSmrg* simulate the addition in a bitwise manner, we try to calculate the 4605b261ecSmrg* carry chain given the two operands and the result. 4705b261ecSmrg* 4805b261ecSmrg* So, given the following table, which represents the addition of two 4905b261ecSmrg* bits, we can derive a formula for the carry chain. 5005b261ecSmrg* 5105b261ecSmrg* a b cin r cout 5205b261ecSmrg* 0 0 0 0 0 5305b261ecSmrg* 0 0 1 1 0 5405b261ecSmrg* 0 1 0 1 0 5505b261ecSmrg* 0 1 1 0 1 5605b261ecSmrg* 1 0 0 1 0 5705b261ecSmrg* 1 0 1 0 1 5805b261ecSmrg* 1 1 0 0 1 5905b261ecSmrg* 1 1 1 1 1 6005b261ecSmrg* 6105b261ecSmrg* Construction of table for cout: 6205b261ecSmrg* 6305b261ecSmrg* ab 6405b261ecSmrg* r \ 00 01 11 10 6505b261ecSmrg* |------------------ 6605b261ecSmrg* 0 | 0 1 1 1 6705b261ecSmrg* 1 | 0 0 1 0 6805b261ecSmrg* 6905b261ecSmrg* By inspection, one gets: cc = ab + r'(a + b) 7005b261ecSmrg* 715a112b11Smrg* That represents a lot of operations, but NO CHOICE.... 7205b261ecSmrg* 7305b261ecSmrg* Borrow Chain Calculation. 7405b261ecSmrg* 7505b261ecSmrg* The following table represents the subtraction of two bits, from 7605b261ecSmrg* which we can derive a formula for the borrow chain. 7705b261ecSmrg* 7805b261ecSmrg* a b bin r bout 7905b261ecSmrg* 0 0 0 0 0 8005b261ecSmrg* 0 0 1 1 1 8105b261ecSmrg* 0 1 0 1 1 8205b261ecSmrg* 0 1 1 0 1 8305b261ecSmrg* 1 0 0 1 0 8405b261ecSmrg* 1 0 1 0 0 8505b261ecSmrg* 1 1 0 0 0 8605b261ecSmrg* 1 1 1 1 1 8705b261ecSmrg* 8805b261ecSmrg* Construction of table for cout: 8905b261ecSmrg* 9005b261ecSmrg* ab 9105b261ecSmrg* r \ 00 01 11 10 9205b261ecSmrg* |------------------ 9305b261ecSmrg* 0 | 0 1 0 0 9405b261ecSmrg* 1 | 1 1 1 0 9505b261ecSmrg* 9605b261ecSmrg* By inspection, one gets: bc = a'b + r(a' + b) 9705b261ecSmrg* 9805b261ecSmrg****************************************************************************/ 9905b261ecSmrg 10005b261ecSmrg#include <stdlib.h> 10105b261ecSmrg 10205b261ecSmrg#define PRIM_OPS_NO_REDEFINE_ASM 10305b261ecSmrg#include "x86emu/x86emui.h" 10405b261ecSmrg 1054642e01fSmrg#if defined(__GNUC__) 106f7df2e56Smrg#if defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__amd64__) 107f7df2e56Smrg#include "x86emu/prim_x86_gcc.h" 108f7df2e56Smrg#endif 1094642e01fSmrg#endif 1104642e01fSmrg 11105b261ecSmrg/*------------------------- Global Variables ------------------------------*/ 11205b261ecSmrg 113f7df2e56Smrgstatic u32 x86emu_parity_tab[8] = { 114f7df2e56Smrg 0x96696996, 115f7df2e56Smrg 0x69969669, 116f7df2e56Smrg 0x69969669, 117f7df2e56Smrg 0x96696996, 118f7df2e56Smrg 0x69969669, 119f7df2e56Smrg 0x96696996, 120f7df2e56Smrg 0x96696996, 121f7df2e56Smrg 0x69969669, 12205b261ecSmrg}; 12305b261ecSmrg 12405b261ecSmrg#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) 12505b261ecSmrg#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) 12605b261ecSmrg 12705b261ecSmrg/*----------------------------- Implementation ----------------------------*/ 12805b261ecSmrg 12905b261ecSmrg/**************************************************************************** 13005b261ecSmrgREMARKS: 13105b261ecSmrgImplements the AAA instruction and side effects. 13205b261ecSmrg****************************************************************************/ 133f7df2e56Smrgu16 134f7df2e56Smrgaaa_word(u16 d) 13505b261ecSmrg{ 136f7df2e56Smrg u16 res; 137f7df2e56Smrg 138f7df2e56Smrg if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 139f7df2e56Smrg d += 0x6; 140f7df2e56Smrg d += 0x100; 141f7df2e56Smrg SET_FLAG(F_AF); 142f7df2e56Smrg SET_FLAG(F_CF); 143f7df2e56Smrg } 144f7df2e56Smrg else { 145f7df2e56Smrg CLEAR_FLAG(F_CF); 146f7df2e56Smrg CLEAR_FLAG(F_AF); 147f7df2e56Smrg } 148f7df2e56Smrg res = (u16) (d & 0xFF0F); 149f7df2e56Smrg CLEAR_FLAG(F_SF); 150f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 151f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 152f7df2e56Smrg return res; 15305b261ecSmrg} 15405b261ecSmrg 15505b261ecSmrg/**************************************************************************** 15605b261ecSmrgREMARKS: 15705b261ecSmrgImplements the AAA instruction and side effects. 15805b261ecSmrg****************************************************************************/ 159f7df2e56Smrgu16 160f7df2e56Smrgaas_word(u16 d) 16105b261ecSmrg{ 162f7df2e56Smrg u16 res; 163f7df2e56Smrg 164f7df2e56Smrg if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 165f7df2e56Smrg d -= 0x6; 166f7df2e56Smrg d -= 0x100; 167f7df2e56Smrg SET_FLAG(F_AF); 168f7df2e56Smrg SET_FLAG(F_CF); 169f7df2e56Smrg } 170f7df2e56Smrg else { 171f7df2e56Smrg CLEAR_FLAG(F_CF); 172f7df2e56Smrg CLEAR_FLAG(F_AF); 173f7df2e56Smrg } 174f7df2e56Smrg res = (u16) (d & 0xFF0F); 175f7df2e56Smrg CLEAR_FLAG(F_SF); 176f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 177f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 178f7df2e56Smrg return res; 17905b261ecSmrg} 18005b261ecSmrg 18105b261ecSmrg/**************************************************************************** 18205b261ecSmrgREMARKS: 18305b261ecSmrgImplements the AAD instruction and side effects. 18405b261ecSmrg****************************************************************************/ 185f7df2e56Smrgu16 186f7df2e56Smrgaad_word(u16 d) 18705b261ecSmrg{ 188f7df2e56Smrg u16 l; 189f7df2e56Smrg u8 hb, lb; 19005b261ecSmrg 191f7df2e56Smrg hb = (u8) ((d >> 8) & 0xff); 192f7df2e56Smrg lb = (u8) ((d & 0xff)); 193f7df2e56Smrg l = (u16) ((lb + 10 * hb) & 0xFF); 19405b261ecSmrg 195f7df2e56Smrg CLEAR_FLAG(F_CF); 196f7df2e56Smrg CLEAR_FLAG(F_AF); 197f7df2e56Smrg CLEAR_FLAG(F_OF); 198f7df2e56Smrg CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 199f7df2e56Smrg CONDITIONAL_SET_FLAG(l == 0, F_ZF); 200f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 201f7df2e56Smrg return l; 20205b261ecSmrg} 20305b261ecSmrg 20405b261ecSmrg/**************************************************************************** 20505b261ecSmrgREMARKS: 20605b261ecSmrgImplements the AAM instruction and side effects. 20705b261ecSmrg****************************************************************************/ 208f7df2e56Smrgu16 209f7df2e56Smrgaam_word(u8 d) 21005b261ecSmrg{ 21105b261ecSmrg u16 h, l; 21205b261ecSmrg 213f7df2e56Smrg h = (u16) (d / 10); 214f7df2e56Smrg l = (u16) (d % 10); 215f7df2e56Smrg l |= (u16) (h << 8); 21605b261ecSmrg 217f7df2e56Smrg CLEAR_FLAG(F_CF); 218f7df2e56Smrg CLEAR_FLAG(F_AF); 219f7df2e56Smrg CLEAR_FLAG(F_OF); 220f7df2e56Smrg CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 221f7df2e56Smrg CONDITIONAL_SET_FLAG(l == 0, F_ZF); 222f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 22305b261ecSmrg return l; 22405b261ecSmrg} 22505b261ecSmrg 22605b261ecSmrg/**************************************************************************** 22705b261ecSmrgREMARKS: 22805b261ecSmrgImplements the ADC instruction and side effects. 22905b261ecSmrg****************************************************************************/ 230f7df2e56Smrgu8 231f7df2e56Smrgadc_byte(u8 d, u8 s) 23205b261ecSmrg{ 233f7df2e56Smrg register u32 res; /* all operands in native machine order */ 234f7df2e56Smrg register u32 cc; 23505b261ecSmrg 236f7df2e56Smrg if (ACCESS_FLAG(F_CF)) 237f7df2e56Smrg res = 1 + d + s; 238f7df2e56Smrg else 239f7df2e56Smrg res = d + s; 24005b261ecSmrg 241f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 242f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 243f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 244f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 24505b261ecSmrg 246f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 247f7df2e56Smrg cc = (s & d) | ((~res) & (s | d)); 248f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 249f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 250f7df2e56Smrg return (u8) res; 25105b261ecSmrg} 25205b261ecSmrg 25305b261ecSmrg/**************************************************************************** 25405b261ecSmrgREMARKS: 25505b261ecSmrgImplements the ADC instruction and side effects. 25605b261ecSmrg****************************************************************************/ 257f7df2e56Smrgu16 258f7df2e56Smrgadc_word(u16 d, u16 s) 25905b261ecSmrg{ 260f7df2e56Smrg register u32 res; /* all operands in native machine order */ 261f7df2e56Smrg register u32 cc; 26205b261ecSmrg 263f7df2e56Smrg if (ACCESS_FLAG(F_CF)) 264f7df2e56Smrg res = 1 + d + s; 265f7df2e56Smrg else 266f7df2e56Smrg res = d + s; 26705b261ecSmrg 268f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 269f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 270f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 271f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 27205b261ecSmrg 273f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 274f7df2e56Smrg cc = (s & d) | ((~res) & (s | d)); 275f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 276f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 277f7df2e56Smrg return (u16) res; 27805b261ecSmrg} 27905b261ecSmrg 28005b261ecSmrg/**************************************************************************** 28105b261ecSmrgREMARKS: 28205b261ecSmrgImplements the ADC instruction and side effects. 28305b261ecSmrg****************************************************************************/ 284f7df2e56Smrgu32 285f7df2e56Smrgadc_long(u32 d, u32 s) 28605b261ecSmrg{ 287f7df2e56Smrg register u32 lo; /* all operands in native machine order */ 288f7df2e56Smrg register u32 hi; 289f7df2e56Smrg register u32 res; 290f7df2e56Smrg register u32 cc; 29105b261ecSmrg 292f7df2e56Smrg if (ACCESS_FLAG(F_CF)) { 293f7df2e56Smrg lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); 294f7df2e56Smrg res = 1 + d + s; 295f7df2e56Smrg } 296f7df2e56Smrg else { 297f7df2e56Smrg lo = (d & 0xFFFF) + (s & 0xFFFF); 298f7df2e56Smrg res = d + s; 299f7df2e56Smrg } 300f7df2e56Smrg hi = (lo >> 16) + (d >> 16) + (s >> 16); 30105b261ecSmrg 302f7df2e56Smrg CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 303f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 304f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 305f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 30605b261ecSmrg 307f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 308f7df2e56Smrg cc = (s & d) | ((~res) & (s | d)); 309f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 310f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 311f7df2e56Smrg return res; 31205b261ecSmrg} 31305b261ecSmrg 31405b261ecSmrg/**************************************************************************** 31505b261ecSmrgREMARKS: 31605b261ecSmrgImplements the ADD instruction and side effects. 31705b261ecSmrg****************************************************************************/ 318f7df2e56Smrgu8 319f7df2e56Smrgadd_byte(u8 d, u8 s) 32005b261ecSmrg{ 321f7df2e56Smrg register u32 res; /* all operands in native machine order */ 322f7df2e56Smrg register u32 cc; 32305b261ecSmrg 324f7df2e56Smrg res = d + s; 325f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 326f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 327f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 328f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 32905b261ecSmrg 330f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 331f7df2e56Smrg cc = (s & d) | ((~res) & (s | d)); 332f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 333f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 334f7df2e56Smrg return (u8) res; 33505b261ecSmrg} 33605b261ecSmrg 33705b261ecSmrg/**************************************************************************** 33805b261ecSmrgREMARKS: 33905b261ecSmrgImplements the ADD instruction and side effects. 34005b261ecSmrg****************************************************************************/ 341f7df2e56Smrgu16 342f7df2e56Smrgadd_word(u16 d, u16 s) 34305b261ecSmrg{ 344f7df2e56Smrg register u32 res; /* all operands in native machine order */ 345f7df2e56Smrg register u32 cc; 34605b261ecSmrg 347f7df2e56Smrg res = d + s; 348f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 349f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 350f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 351f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 35205b261ecSmrg 353f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 354f7df2e56Smrg cc = (s & d) | ((~res) & (s | d)); 355f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 356f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 357f7df2e56Smrg return (u16) res; 35805b261ecSmrg} 35905b261ecSmrg 36005b261ecSmrg/**************************************************************************** 36105b261ecSmrgREMARKS: 36205b261ecSmrgImplements the ADD instruction and side effects. 36305b261ecSmrg****************************************************************************/ 364f7df2e56Smrgu32 365f7df2e56Smrgadd_long(u32 d, u32 s) 36605b261ecSmrg{ 367f7df2e56Smrg register u32 lo; /* all operands in native machine order */ 368f7df2e56Smrg register u32 hi; 369f7df2e56Smrg register u32 res; 370f7df2e56Smrg register u32 cc; 37105b261ecSmrg 372f7df2e56Smrg lo = (d & 0xFFFF) + (s & 0xFFFF); 373f7df2e56Smrg res = d + s; 374f7df2e56Smrg hi = (lo >> 16) + (d >> 16) + (s >> 16); 37505b261ecSmrg 376f7df2e56Smrg CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 377f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 378f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 379f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 38005b261ecSmrg 38105b261ecSmrg /* calculate the carry chain SEE NOTE AT TOP. */ 38205b261ecSmrg cc = (s & d) | ((~res) & (s | d)); 383f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 384f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 38505b261ecSmrg 38605b261ecSmrg return res; 38705b261ecSmrg} 38805b261ecSmrg 38905b261ecSmrg/**************************************************************************** 39005b261ecSmrgREMARKS: 39105b261ecSmrgImplements the AND instruction and side effects. 39205b261ecSmrg****************************************************************************/ 393f7df2e56Smrgu8 394f7df2e56Smrgand_byte(u8 d, u8 s) 39505b261ecSmrg{ 396f7df2e56Smrg register u8 res; /* all operands in native machine order */ 39705b261ecSmrg 398f7df2e56Smrg res = d & s; 39905b261ecSmrg 400f7df2e56Smrg /* set the flags */ 401f7df2e56Smrg CLEAR_FLAG(F_OF); 402f7df2e56Smrg CLEAR_FLAG(F_CF); 403f7df2e56Smrg CLEAR_FLAG(F_AF); 404f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 405f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 406f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 407f7df2e56Smrg return res; 40805b261ecSmrg} 40905b261ecSmrg 41005b261ecSmrg/**************************************************************************** 41105b261ecSmrgREMARKS: 41205b261ecSmrgImplements the AND instruction and side effects. 41305b261ecSmrg****************************************************************************/ 414f7df2e56Smrgu16 415f7df2e56Smrgand_word(u16 d, u16 s) 41605b261ecSmrg{ 417f7df2e56Smrg register u16 res; /* all operands in native machine order */ 41805b261ecSmrg 41905b261ecSmrg res = d & s; 42005b261ecSmrg 42105b261ecSmrg /* set the flags */ 422f7df2e56Smrg CLEAR_FLAG(F_OF); 423f7df2e56Smrg CLEAR_FLAG(F_CF); 424f7df2e56Smrg CLEAR_FLAG(F_AF); 425f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 426f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 427f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 42805b261ecSmrg return res; 42905b261ecSmrg} 43005b261ecSmrg 43105b261ecSmrg/**************************************************************************** 43205b261ecSmrgREMARKS: 43305b261ecSmrgImplements the AND instruction and side effects. 43405b261ecSmrg****************************************************************************/ 435f7df2e56Smrgu32 436f7df2e56Smrgand_long(u32 d, u32 s) 43705b261ecSmrg{ 438f7df2e56Smrg register u32 res; /* all operands in native machine order */ 43905b261ecSmrg 440f7df2e56Smrg res = d & s; 44105b261ecSmrg 442f7df2e56Smrg /* set the flags */ 443f7df2e56Smrg CLEAR_FLAG(F_OF); 444f7df2e56Smrg CLEAR_FLAG(F_CF); 445f7df2e56Smrg CLEAR_FLAG(F_AF); 446f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 447f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 448f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 449f7df2e56Smrg return res; 45005b261ecSmrg} 45105b261ecSmrg 45205b261ecSmrg/**************************************************************************** 45305b261ecSmrgREMARKS: 45405b261ecSmrgImplements the CMP instruction and side effects. 45505b261ecSmrg****************************************************************************/ 456f7df2e56Smrgu8 457f7df2e56Smrgcmp_byte(u8 d, u8 s) 45805b261ecSmrg{ 459f7df2e56Smrg register u32 res; /* all operands in native machine order */ 460f7df2e56Smrg register u32 bc; 46105b261ecSmrg 462f7df2e56Smrg res = d - s; 463f7df2e56Smrg CLEAR_FLAG(F_CF); 464f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 465f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 466f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 46705b261ecSmrg 468f7df2e56Smrg /* calculate the borrow chain. See note at top */ 469f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 470f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 471f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 472f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 473f7df2e56Smrg return d; 47405b261ecSmrg} 47505b261ecSmrg 47605b261ecSmrg/**************************************************************************** 47705b261ecSmrgREMARKS: 47805b261ecSmrgImplements the CMP instruction and side effects. 47905b261ecSmrg****************************************************************************/ 480f7df2e56Smrgu16 481f7df2e56Smrgcmp_word(u16 d, u16 s) 48205b261ecSmrg{ 483f7df2e56Smrg register u32 res; /* all operands in native machine order */ 484f7df2e56Smrg register u32 bc; 48505b261ecSmrg 486f7df2e56Smrg res = d - s; 487f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 488f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 489f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 49005b261ecSmrg 491f7df2e56Smrg /* calculate the borrow chain. See note at top */ 49205b261ecSmrg bc = (res & (~d | s)) | (~d & s); 493f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 494f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 495f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 496f7df2e56Smrg return d; 49705b261ecSmrg} 49805b261ecSmrg 49905b261ecSmrg/**************************************************************************** 50005b261ecSmrgREMARKS: 50105b261ecSmrgImplements the CMP instruction and side effects. 50205b261ecSmrg****************************************************************************/ 503f7df2e56Smrgu32 504f7df2e56Smrgcmp_long(u32 d, u32 s) 50505b261ecSmrg{ 506f7df2e56Smrg register u32 res; /* all operands in native machine order */ 507f7df2e56Smrg register u32 bc; 50805b261ecSmrg 509f7df2e56Smrg res = d - s; 510f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 511f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 512f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 51305b261ecSmrg 514f7df2e56Smrg /* calculate the borrow chain. See note at top */ 515f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 516f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 517f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 518f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 519f7df2e56Smrg return d; 52005b261ecSmrg} 52105b261ecSmrg 52205b261ecSmrg/**************************************************************************** 52305b261ecSmrgREMARKS: 52405b261ecSmrgImplements the DAA instruction and side effects. 52505b261ecSmrg****************************************************************************/ 526f7df2e56Smrgu8 527f7df2e56Smrgdaa_byte(u8 d) 52805b261ecSmrg{ 529f7df2e56Smrg u32 res = d; 530f7df2e56Smrg 531f7df2e56Smrg if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 532f7df2e56Smrg res += 6; 533f7df2e56Smrg SET_FLAG(F_AF); 534f7df2e56Smrg } 535f7df2e56Smrg if (res > 0x9F || ACCESS_FLAG(F_CF)) { 536f7df2e56Smrg res += 0x60; 537f7df2e56Smrg SET_FLAG(F_CF); 538f7df2e56Smrg } 539f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 540f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); 541f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 542f7df2e56Smrg return (u8) res; 54305b261ecSmrg} 54405b261ecSmrg 54505b261ecSmrg/**************************************************************************** 54605b261ecSmrgREMARKS: 54705b261ecSmrgImplements the DAS instruction and side effects. 54805b261ecSmrg****************************************************************************/ 549f7df2e56Smrgu8 550f7df2e56Smrgdas_byte(u8 d) 55105b261ecSmrg{ 552f7df2e56Smrg if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 553f7df2e56Smrg d -= 6; 554f7df2e56Smrg SET_FLAG(F_AF); 555f7df2e56Smrg } 556f7df2e56Smrg if (d > 0x9F || ACCESS_FLAG(F_CF)) { 557f7df2e56Smrg d -= 0x60; 558f7df2e56Smrg SET_FLAG(F_CF); 559f7df2e56Smrg } 560f7df2e56Smrg CONDITIONAL_SET_FLAG(d & 0x80, F_SF); 561f7df2e56Smrg CONDITIONAL_SET_FLAG(d == 0, F_ZF); 562f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); 563f7df2e56Smrg return d; 56405b261ecSmrg} 56505b261ecSmrg 56605b261ecSmrg/**************************************************************************** 56705b261ecSmrgREMARKS: 56805b261ecSmrgImplements the DEC instruction and side effects. 56905b261ecSmrg****************************************************************************/ 570f7df2e56Smrgu8 571f7df2e56Smrgdec_byte(u8 d) 57205b261ecSmrg{ 573f7df2e56Smrg register u32 res; /* all operands in native machine order */ 57405b261ecSmrg register u32 bc; 57505b261ecSmrg 57605b261ecSmrg res = d - 1; 577f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 578f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 579f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 58005b261ecSmrg 581f7df2e56Smrg /* calculate the borrow chain. See note at top */ 582f7df2e56Smrg /* based on sub_byte, uses s==1. */ 583f7df2e56Smrg bc = (res & (~d | 1)) | (~d & 1); 584f7df2e56Smrg /* carry flag unchanged */ 585f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 586f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 587f7df2e56Smrg return (u8) res; 58805b261ecSmrg} 58905b261ecSmrg 59005b261ecSmrg/**************************************************************************** 59105b261ecSmrgREMARKS: 59205b261ecSmrgImplements the DEC instruction and side effects. 59305b261ecSmrg****************************************************************************/ 594f7df2e56Smrgu16 595f7df2e56Smrgdec_word(u16 d) 59605b261ecSmrg{ 597f7df2e56Smrg register u32 res; /* all operands in native machine order */ 59805b261ecSmrg register u32 bc; 59905b261ecSmrg 60005b261ecSmrg res = d - 1; 601f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 602f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 603f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 60405b261ecSmrg 60505b261ecSmrg /* calculate the borrow chain. See note at top */ 60605b261ecSmrg /* based on the sub_byte routine, with s==1 */ 60705b261ecSmrg bc = (res & (~d | 1)) | (~d & 1); 60805b261ecSmrg /* carry flag unchanged */ 609f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 610f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 611f7df2e56Smrg return (u16) res; 61205b261ecSmrg} 61305b261ecSmrg 61405b261ecSmrg/**************************************************************************** 61505b261ecSmrgREMARKS: 61605b261ecSmrgImplements the DEC instruction and side effects. 61705b261ecSmrg****************************************************************************/ 618f7df2e56Smrgu32 619f7df2e56Smrgdec_long(u32 d) 62005b261ecSmrg{ 621f7df2e56Smrg register u32 res; /* all operands in native machine order */ 62205b261ecSmrg register u32 bc; 62305b261ecSmrg 62405b261ecSmrg res = d - 1; 62505b261ecSmrg 626f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 627f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 628f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 62905b261ecSmrg 63005b261ecSmrg /* calculate the borrow chain. See note at top */ 631f7df2e56Smrg bc = (res & (~d | 1)) | (~d & 1); 632f7df2e56Smrg /* carry flag unchanged */ 633f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 634f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 635f7df2e56Smrg return res; 63605b261ecSmrg} 63705b261ecSmrg 63805b261ecSmrg/**************************************************************************** 63905b261ecSmrgREMARKS: 64005b261ecSmrgImplements the INC instruction and side effects. 64105b261ecSmrg****************************************************************************/ 642f7df2e56Smrgu8 643f7df2e56Smrginc_byte(u8 d) 64405b261ecSmrg{ 645f7df2e56Smrg register u32 res; /* all operands in native machine order */ 646f7df2e56Smrg register u32 cc; 64705b261ecSmrg 648f7df2e56Smrg res = d + 1; 649f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 650f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 651f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 65205b261ecSmrg 653f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 654f7df2e56Smrg cc = ((1 & d) | (~res)) & (1 | d); 655f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 656f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 657f7df2e56Smrg return (u8) res; 65805b261ecSmrg} 65905b261ecSmrg 66005b261ecSmrg/**************************************************************************** 66105b261ecSmrgREMARKS: 66205b261ecSmrgImplements the INC instruction and side effects. 66305b261ecSmrg****************************************************************************/ 664f7df2e56Smrgu16 665f7df2e56Smrginc_word(u16 d) 66605b261ecSmrg{ 667f7df2e56Smrg register u32 res; /* all operands in native machine order */ 668f7df2e56Smrg register u32 cc; 66905b261ecSmrg 670f7df2e56Smrg res = d + 1; 671f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 672f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 673f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 67405b261ecSmrg 675f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 676f7df2e56Smrg cc = (1 & d) | ((~res) & (1 | d)); 677f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 678f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 679f7df2e56Smrg return (u16) res; 68005b261ecSmrg} 68105b261ecSmrg 68205b261ecSmrg/**************************************************************************** 68305b261ecSmrgREMARKS: 68405b261ecSmrgImplements the INC instruction and side effects. 68505b261ecSmrg****************************************************************************/ 686f7df2e56Smrgu32 687f7df2e56Smrginc_long(u32 d) 68805b261ecSmrg{ 689f7df2e56Smrg register u32 res; /* all operands in native machine order */ 690f7df2e56Smrg register u32 cc; 69105b261ecSmrg 692f7df2e56Smrg res = d + 1; 693f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 694f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 695f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 69605b261ecSmrg 697f7df2e56Smrg /* calculate the carry chain SEE NOTE AT TOP. */ 698f7df2e56Smrg cc = (1 & d) | ((~res) & (1 | d)); 699f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 700f7df2e56Smrg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 701f7df2e56Smrg return res; 70205b261ecSmrg} 70305b261ecSmrg 70405b261ecSmrg/**************************************************************************** 70505b261ecSmrgREMARKS: 70605b261ecSmrgImplements the OR instruction and side effects. 70705b261ecSmrg****************************************************************************/ 708f7df2e56Smrgu8 709f7df2e56Smrgor_byte(u8 d, u8 s) 71005b261ecSmrg{ 711f7df2e56Smrg register u8 res; /* all operands in native machine order */ 71205b261ecSmrg 713f7df2e56Smrg res = d | s; 714f7df2e56Smrg CLEAR_FLAG(F_OF); 715f7df2e56Smrg CLEAR_FLAG(F_CF); 716f7df2e56Smrg CLEAR_FLAG(F_AF); 717f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 718f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 719f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 720f7df2e56Smrg return res; 72105b261ecSmrg} 72205b261ecSmrg 72305b261ecSmrg/**************************************************************************** 72405b261ecSmrgREMARKS: 72505b261ecSmrgImplements the OR instruction and side effects. 72605b261ecSmrg****************************************************************************/ 727f7df2e56Smrgu16 728f7df2e56Smrgor_word(u16 d, u16 s) 72905b261ecSmrg{ 730f7df2e56Smrg register u16 res; /* all operands in native machine order */ 73105b261ecSmrg 732f7df2e56Smrg res = d | s; 733f7df2e56Smrg /* set the carry flag to be bit 8 */ 734f7df2e56Smrg CLEAR_FLAG(F_OF); 735f7df2e56Smrg CLEAR_FLAG(F_CF); 736f7df2e56Smrg CLEAR_FLAG(F_AF); 737f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 738f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 739f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 740f7df2e56Smrg return res; 74105b261ecSmrg} 74205b261ecSmrg 74305b261ecSmrg/**************************************************************************** 74405b261ecSmrgREMARKS: 74505b261ecSmrgImplements the OR instruction and side effects. 74605b261ecSmrg****************************************************************************/ 747f7df2e56Smrgu32 748f7df2e56Smrgor_long(u32 d, u32 s) 74905b261ecSmrg{ 750f7df2e56Smrg register u32 res; /* all operands in native machine order */ 75105b261ecSmrg 752f7df2e56Smrg res = d | s; 75305b261ecSmrg 754f7df2e56Smrg /* set the carry flag to be bit 8 */ 755f7df2e56Smrg CLEAR_FLAG(F_OF); 756f7df2e56Smrg CLEAR_FLAG(F_CF); 757f7df2e56Smrg CLEAR_FLAG(F_AF); 758f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 759f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 760f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 761f7df2e56Smrg return res; 76205b261ecSmrg} 76305b261ecSmrg 76405b261ecSmrg/**************************************************************************** 76505b261ecSmrgREMARKS: 76605b261ecSmrgImplements the OR instruction and side effects. 76705b261ecSmrg****************************************************************************/ 768f7df2e56Smrgu8 769f7df2e56Smrgneg_byte(u8 s) 77005b261ecSmrg{ 77105b261ecSmrg register u8 res; 77205b261ecSmrg register u8 bc; 77305b261ecSmrg 774f7df2e56Smrg CONDITIONAL_SET_FLAG(s != 0, F_CF); 775f7df2e56Smrg res = (u8) - s; 776f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 777f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 778f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 779f7df2e56Smrg /* calculate the borrow chain --- modified such that d=0. 780f7df2e56Smrg substitutiing d=0 into bc= res&(~d|s)|(~d&s); 781f7df2e56Smrg (the one used for sub) and simplifying, since ~d=0xff..., 782f7df2e56Smrg ~d|s == 0xffff..., and res&0xfff... == res. Similarly 783f7df2e56Smrg ~d&s == s. So the simplified result is: */ 784f7df2e56Smrg bc = res | s; 785f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 786f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 787f7df2e56Smrg return res; 78805b261ecSmrg} 78905b261ecSmrg 79005b261ecSmrg/**************************************************************************** 79105b261ecSmrgREMARKS: 79205b261ecSmrgImplements the OR instruction and side effects. 79305b261ecSmrg****************************************************************************/ 794f7df2e56Smrgu16 795f7df2e56Smrgneg_word(u16 s) 796f7df2e56Smrg{ 797f7df2e56Smrg register u16 res; 798f7df2e56Smrg register u16 bc; 799f7df2e56Smrg 800f7df2e56Smrg CONDITIONAL_SET_FLAG(s != 0, F_CF); 801f7df2e56Smrg res = (u16) - s; 802f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 803f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 804f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 805f7df2e56Smrg 806f7df2e56Smrg /* calculate the borrow chain --- modified such that d=0. 807f7df2e56Smrg substitutiing d=0 into bc= res&(~d|s)|(~d&s); 808f7df2e56Smrg (the one used for sub) and simplifying, since ~d=0xff..., 809f7df2e56Smrg ~d|s == 0xffff..., and res&0xfff... == res. Similarly 810f7df2e56Smrg ~d&s == s. So the simplified result is: */ 811f7df2e56Smrg bc = res | s; 812f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 813f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 814f7df2e56Smrg return res; 81505b261ecSmrg} 81605b261ecSmrg 81705b261ecSmrg/**************************************************************************** 81805b261ecSmrgREMARKS: 81905b261ecSmrgImplements the OR instruction and side effects. 82005b261ecSmrg****************************************************************************/ 821f7df2e56Smrgu32 822f7df2e56Smrgneg_long(u32 s) 82305b261ecSmrg{ 824f7df2e56Smrg register u32 res; 825f7df2e56Smrg register u32 bc; 82605b261ecSmrg 827f7df2e56Smrg CONDITIONAL_SET_FLAG(s != 0, F_CF); 828f7df2e56Smrg res = (u32) - s; 829f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 830f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 831f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 832f7df2e56Smrg 833f7df2e56Smrg /* calculate the borrow chain --- modified such that d=0. 834f7df2e56Smrg substitutiing d=0 into bc= res&(~d|s)|(~d&s); 835f7df2e56Smrg (the one used for sub) and simplifying, since ~d=0xff..., 836f7df2e56Smrg ~d|s == 0xffff..., and res&0xfff... == res. Similarly 837f7df2e56Smrg ~d&s == s. So the simplified result is: */ 838f7df2e56Smrg bc = res | s; 839f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 840f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 841f7df2e56Smrg return res; 84205b261ecSmrg} 84305b261ecSmrg 84405b261ecSmrg/**************************************************************************** 84505b261ecSmrgREMARKS: 84605b261ecSmrgImplements the NOT instruction and side effects. 84705b261ecSmrg****************************************************************************/ 848f7df2e56Smrgu8 849f7df2e56Smrgnot_byte(u8 s) 85005b261ecSmrg{ 851f7df2e56Smrg return ~s; 85205b261ecSmrg} 85305b261ecSmrg 85405b261ecSmrg/**************************************************************************** 85505b261ecSmrgREMARKS: 85605b261ecSmrgImplements the NOT instruction and side effects. 85705b261ecSmrg****************************************************************************/ 858f7df2e56Smrgu16 859f7df2e56Smrgnot_word(u16 s) 86005b261ecSmrg{ 861f7df2e56Smrg return ~s; 86205b261ecSmrg} 86305b261ecSmrg 86405b261ecSmrg/**************************************************************************** 86505b261ecSmrgREMARKS: 86605b261ecSmrgImplements the NOT instruction and side effects. 86705b261ecSmrg****************************************************************************/ 868f7df2e56Smrgu32 869f7df2e56Smrgnot_long(u32 s) 87005b261ecSmrg{ 871f7df2e56Smrg return ~s; 87205b261ecSmrg} 87305b261ecSmrg 87405b261ecSmrg/**************************************************************************** 87505b261ecSmrgREMARKS: 87605b261ecSmrgImplements the RCL instruction and side effects. 87705b261ecSmrg****************************************************************************/ 878f7df2e56Smrgu8 879f7df2e56Smrgrcl_byte(u8 d, u8 s) 88005b261ecSmrg{ 88105b261ecSmrg register unsigned int res, cnt, mask, cf; 88205b261ecSmrg 88305b261ecSmrg /* s is the rotate distance. It varies from 0 - 8. */ 884f7df2e56Smrg /* have 88505b261ecSmrg 886f7df2e56Smrg CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 88705b261ecSmrg 888f7df2e56Smrg want to rotate through the carry by "s" bits. We could 88905b261ecSmrg loop, but that's inefficient. So the width is 9, 89005b261ecSmrg and we split into three parts: 89105b261ecSmrg 89205b261ecSmrg The new carry flag (was B_n) 89305b261ecSmrg the stuff in B_n-1 .. B_0 89405b261ecSmrg the stuff in B_7 .. B_n+1 89505b261ecSmrg 89605b261ecSmrg The new rotate is done mod 9, and given this, 89705b261ecSmrg for a rotation of n bits (mod 9) the new carry flag is 898f7df2e56Smrg then located n bits from the MSB. The low part is 89905b261ecSmrg then shifted up cnt bits, and the high part is or'd 900f7df2e56Smrg in. Using CAPS for new values, and lowercase for the 90105b261ecSmrg original values, this can be expressed as: 90205b261ecSmrg 903f7df2e56Smrg IF n > 0 90405b261ecSmrg 1) CF <- b_(8-n) 90505b261ecSmrg 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 90605b261ecSmrg 3) B_(n-1) <- cf 90705b261ecSmrg 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) 908f7df2e56Smrg */ 909f7df2e56Smrg res = d; 910f7df2e56Smrg if ((cnt = s % 9) != 0) { 91105b261ecSmrg /* extract the new CARRY FLAG. */ 91205b261ecSmrg /* CF <- b_(8-n) */ 91305b261ecSmrg cf = (d >> (8 - cnt)) & 0x1; 91405b261ecSmrg 915f7df2e56Smrg /* get the low stuff which rotated 91605b261ecSmrg into the range B_7 .. B_cnt */ 91705b261ecSmrg /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ 91805b261ecSmrg /* note that the right hand side done by the mask */ 919f7df2e56Smrg res = (d << cnt) & 0xff; 92005b261ecSmrg 921f7df2e56Smrg /* now the high stuff which rotated around 92205b261ecSmrg into the positions B_cnt-2 .. B_0 */ 92305b261ecSmrg /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 924f7df2e56Smrg /* shift it downward, 7-(n-2) = 9-n positions. 925f7df2e56Smrg and mask off the result before or'ing in. 92605b261ecSmrg */ 92705b261ecSmrg mask = (1 << (cnt - 1)) - 1; 92805b261ecSmrg res |= (d >> (9 - cnt)) & mask; 92905b261ecSmrg 93005b261ecSmrg /* if the carry flag was set, or it in. */ 931f7df2e56Smrg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 93205b261ecSmrg /* B_(n-1) <- cf */ 93305b261ecSmrg res |= 1 << (cnt - 1); 93405b261ecSmrg } 93505b261ecSmrg /* set the new carry flag, based on the variable "cf" */ 936f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 937f7df2e56Smrg /* OVERFLOW is set *IFF* cnt==1, then it is the 93805b261ecSmrg xor of CF and the most significant bit. Blecck. */ 93905b261ecSmrg /* parenthesized this expression since it appears to 94005b261ecSmrg be causing OF to be misset */ 941f7df2e56Smrg CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), F_OF); 94205b261ecSmrg 94305b261ecSmrg } 944f7df2e56Smrg return (u8) res; 94505b261ecSmrg} 94605b261ecSmrg 94705b261ecSmrg/**************************************************************************** 94805b261ecSmrgREMARKS: 94905b261ecSmrgImplements the RCL instruction and side effects. 95005b261ecSmrg****************************************************************************/ 951f7df2e56Smrgu16 952f7df2e56Smrgrcl_word(u16 d, u8 s) 95305b261ecSmrg{ 954f7df2e56Smrg register unsigned int res, cnt, mask, cf; 95505b261ecSmrg 956f7df2e56Smrg res = d; 957f7df2e56Smrg if ((cnt = s % 17) != 0) { 958f7df2e56Smrg cf = (d >> (16 - cnt)) & 0x1; 959f7df2e56Smrg res = (d << cnt) & 0xffff; 960f7df2e56Smrg mask = (1 << (cnt - 1)) - 1; 961f7df2e56Smrg res |= (d >> (17 - cnt)) & mask; 962f7df2e56Smrg if (ACCESS_FLAG(F_CF)) { 963f7df2e56Smrg res |= 1 << (cnt - 1); 964f7df2e56Smrg } 965f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 966f7df2e56Smrg CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), F_OF); 967f7df2e56Smrg } 968f7df2e56Smrg return (u16) res; 96905b261ecSmrg} 97005b261ecSmrg 97105b261ecSmrg/**************************************************************************** 97205b261ecSmrgREMARKS: 97305b261ecSmrgImplements the RCL instruction and side effects. 97405b261ecSmrg****************************************************************************/ 975f7df2e56Smrgu32 976f7df2e56Smrgrcl_long(u32 d, u8 s) 97705b261ecSmrg{ 978f7df2e56Smrg register u32 res, cnt, mask, cf; 97905b261ecSmrg 980f7df2e56Smrg res = d; 981f7df2e56Smrg if ((cnt = s % 33) != 0) { 982f7df2e56Smrg cf = (d >> (32 - cnt)) & 0x1; 983f7df2e56Smrg res = (d << cnt) & 0xffffffff; 984f7df2e56Smrg mask = (1 << (cnt - 1)) - 1; 985f7df2e56Smrg res |= (d >> (33 - cnt)) & mask; 986f7df2e56Smrg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 987f7df2e56Smrg res |= 1 << (cnt - 1); 988f7df2e56Smrg } 989f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 990f7df2e56Smrg CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), F_OF); 991f7df2e56Smrg } 992f7df2e56Smrg return res; 99305b261ecSmrg} 99405b261ecSmrg 99505b261ecSmrg/**************************************************************************** 99605b261ecSmrgREMARKS: 99705b261ecSmrgImplements the RCR instruction and side effects. 99805b261ecSmrg****************************************************************************/ 999f7df2e56Smrgu8 1000f7df2e56Smrgrcr_byte(u8 d, u8 s) 100105b261ecSmrg{ 1002f7df2e56Smrg u32 res, cnt; 1003f7df2e56Smrg u32 mask, cf, ocf = 0; 100405b261ecSmrg 1005f7df2e56Smrg /* rotate right through carry */ 1006f7df2e56Smrg /* 100705b261ecSmrg s is the rotate distance. It varies from 0 - 8. 1008f7df2e56Smrg d is the byte object rotated. 100905b261ecSmrg 1010f7df2e56Smrg have 101105b261ecSmrg 1012f7df2e56Smrg CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 101305b261ecSmrg 101405b261ecSmrg The new rotate is done mod 9, and given this, 101505b261ecSmrg for a rotation of n bits (mod 9) the new carry flag is 1016f7df2e56Smrg then located n bits from the LSB. The low part is 101705b261ecSmrg then shifted up cnt bits, and the high part is or'd 1018f7df2e56Smrg in. Using CAPS for new values, and lowercase for the 101905b261ecSmrg original values, this can be expressed as: 102005b261ecSmrg 1021f7df2e56Smrg IF n > 0 102205b261ecSmrg 1) CF <- b_(n-1) 102305b261ecSmrg 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 102405b261ecSmrg 3) B_(8-n) <- cf 102505b261ecSmrg 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) 1026f7df2e56Smrg */ 1027f7df2e56Smrg res = d; 1028f7df2e56Smrg if ((cnt = s % 9) != 0) { 102905b261ecSmrg /* extract the new CARRY FLAG. */ 103005b261ecSmrg /* CF <- b_(n-1) */ 103105b261ecSmrg if (cnt == 1) { 103205b261ecSmrg cf = d & 0x1; 103305b261ecSmrg /* note hackery here. Access_flag(..) evaluates to either 103405b261ecSmrg 0 if flag not set 103505b261ecSmrg non-zero if flag is set. 1036f7df2e56Smrg doing access_flag(..) != 0 casts that into either 1037f7df2e56Smrg 0..1 in any representation of the flags register 103805b261ecSmrg (i.e. packed bit array or unpacked.) 103905b261ecSmrg */ 1040f7df2e56Smrg ocf = ACCESS_FLAG(F_CF) != 0; 1041f7df2e56Smrg } 1042f7df2e56Smrg else 104305b261ecSmrg cf = (d >> (cnt - 1)) & 0x1; 104405b261ecSmrg 104505b261ecSmrg /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ 104605b261ecSmrg /* note that the right hand side done by the mask 1047f7df2e56Smrg This is effectively done by shifting the 104805b261ecSmrg object to the right. The result must be masked, 1049f7df2e56Smrg in case the object came in and was treated 105005b261ecSmrg as a negative number. Needed??? */ 105105b261ecSmrg 105205b261ecSmrg mask = (1 << (8 - cnt)) - 1; 105305b261ecSmrg res = (d >> cnt) & mask; 105405b261ecSmrg 1055f7df2e56Smrg /* now the high stuff which rotated around 105605b261ecSmrg into the positions B_cnt-2 .. B_0 */ 105705b261ecSmrg /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 1058f7df2e56Smrg /* shift it downward, 7-(n-2) = 9-n positions. 1059f7df2e56Smrg and mask off the result before or'ing in. 106005b261ecSmrg */ 106105b261ecSmrg res |= (d << (9 - cnt)); 106205b261ecSmrg 106305b261ecSmrg /* if the carry flag was set, or it in. */ 1064f7df2e56Smrg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 106505b261ecSmrg /* B_(8-n) <- cf */ 106605b261ecSmrg res |= 1 << (8 - cnt); 106705b261ecSmrg } 106805b261ecSmrg /* set the new carry flag, based on the variable "cf" */ 1069f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1070f7df2e56Smrg /* OVERFLOW is set *IFF* cnt==1, then it is the 107105b261ecSmrg xor of CF and the most significant bit. Blecck. */ 107205b261ecSmrg /* parenthesized... */ 1073f7df2e56Smrg if (cnt == 1) { 1074f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), F_OF); 1075f7df2e56Smrg } 1076f7df2e56Smrg } 1077f7df2e56Smrg return (u8) res; 107805b261ecSmrg} 107905b261ecSmrg 108005b261ecSmrg/**************************************************************************** 108105b261ecSmrgREMARKS: 108205b261ecSmrgImplements the RCR instruction and side effects. 108305b261ecSmrg****************************************************************************/ 1084f7df2e56Smrgu16 1085f7df2e56Smrgrcr_word(u16 d, u8 s) 108605b261ecSmrg{ 1087f7df2e56Smrg u32 res, cnt; 1088f7df2e56Smrg u32 mask, cf, ocf = 0; 108905b261ecSmrg 1090f7df2e56Smrg /* rotate right through carry */ 1091f7df2e56Smrg res = d; 1092f7df2e56Smrg if ((cnt = s % 17) != 0) { 1093f7df2e56Smrg if (cnt == 1) { 1094f7df2e56Smrg cf = d & 0x1; 1095f7df2e56Smrg ocf = ACCESS_FLAG(F_CF) != 0; 1096f7df2e56Smrg } 1097f7df2e56Smrg else 1098f7df2e56Smrg cf = (d >> (cnt - 1)) & 0x1; 1099f7df2e56Smrg mask = (1 << (16 - cnt)) - 1; 1100f7df2e56Smrg res = (d >> cnt) & mask; 1101f7df2e56Smrg res |= (d << (17 - cnt)); 1102f7df2e56Smrg if (ACCESS_FLAG(F_CF)) { 1103f7df2e56Smrg res |= 1 << (16 - cnt); 1104f7df2e56Smrg } 1105f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1106f7df2e56Smrg if (cnt == 1) { 1107f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), F_OF); 1108f7df2e56Smrg } 1109f7df2e56Smrg } 1110f7df2e56Smrg return (u16) res; 111105b261ecSmrg} 111205b261ecSmrg 111305b261ecSmrg/**************************************************************************** 111405b261ecSmrgREMARKS: 111505b261ecSmrgImplements the RCR instruction and side effects. 111605b261ecSmrg****************************************************************************/ 1117f7df2e56Smrgu32 1118f7df2e56Smrgrcr_long(u32 d, u8 s) 1119f7df2e56Smrg{ 1120f7df2e56Smrg u32 res, cnt; 1121f7df2e56Smrg u32 mask, cf, ocf = 0; 1122f7df2e56Smrg 1123f7df2e56Smrg /* rotate right through carry */ 1124f7df2e56Smrg res = d; 1125f7df2e56Smrg if ((cnt = s % 33) != 0) { 1126f7df2e56Smrg if (cnt == 1) { 1127f7df2e56Smrg cf = d & 0x1; 1128f7df2e56Smrg ocf = ACCESS_FLAG(F_CF) != 0; 1129f7df2e56Smrg } 1130f7df2e56Smrg else 1131f7df2e56Smrg cf = (d >> (cnt - 1)) & 0x1; 1132f7df2e56Smrg mask = (1 << (32 - cnt)) - 1; 1133f7df2e56Smrg res = (d >> cnt) & mask; 1134f7df2e56Smrg if (cnt != 1) 1135f7df2e56Smrg res |= (d << (33 - cnt)); 1136f7df2e56Smrg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 1137f7df2e56Smrg res |= 1 << (32 - cnt); 1138f7df2e56Smrg } 1139f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1140f7df2e56Smrg if (cnt == 1) { 1141f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), F_OF); 1142f7df2e56Smrg } 1143f7df2e56Smrg } 1144f7df2e56Smrg return res; 114505b261ecSmrg} 114605b261ecSmrg 114705b261ecSmrg/**************************************************************************** 114805b261ecSmrgREMARKS: 114905b261ecSmrgImplements the ROL instruction and side effects. 115005b261ecSmrg****************************************************************************/ 1151f7df2e56Smrgu8 1152f7df2e56Smrgrol_byte(u8 d, u8 s) 115305b261ecSmrg{ 115405b261ecSmrg register unsigned int res, cnt, mask; 115505b261ecSmrg 115605b261ecSmrg /* rotate left */ 1157f7df2e56Smrg /* 115805b261ecSmrg s is the rotate distance. It varies from 0 - 8. 1159f7df2e56Smrg d is the byte object rotated. 116005b261ecSmrg 1161f7df2e56Smrg have 116205b261ecSmrg 1163f7df2e56Smrg CF B_7 ... B_0 116405b261ecSmrg 116505b261ecSmrg The new rotate is done mod 8. 116605b261ecSmrg Much simpler than the "rcl" or "rcr" operations. 116705b261ecSmrg 1168f7df2e56Smrg IF n > 0 116905b261ecSmrg 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 117005b261ecSmrg 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) 1171f7df2e56Smrg */ 117205b261ecSmrg res = d; 1173f7df2e56Smrg if ((cnt = s % 8) != 0) { 1174f7df2e56Smrg /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ 1175f7df2e56Smrg res = (d << cnt); 117605b261ecSmrg 1177f7df2e56Smrg /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ 1178f7df2e56Smrg mask = (1 << cnt) - 1; 1179f7df2e56Smrg res |= (d >> (8 - cnt)) & mask; 118005b261ecSmrg 1181f7df2e56Smrg /* set the new carry flag, Note that it is the low order 1182f7df2e56Smrg bit of the result!!! */ 1183f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 1184f7df2e56Smrg /* OVERFLOW is set *IFF* s==1, then it is the 1185f7df2e56Smrg xor of CF and the most significant bit. Blecck. */ 1186f7df2e56Smrg CONDITIONAL_SET_FLAG(s == 1 && 1187f7df2e56Smrg XOR2((res & 0x1) + ((res >> 6) & 0x2)), F_OF); 1188f7df2e56Smrg } 1189f7df2e56Smrg if (s != 0) { 1190f7df2e56Smrg /* set the new carry flag, Note that it is the low order 1191f7df2e56Smrg bit of the result!!! */ 1192f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 1193f7df2e56Smrg } 1194f7df2e56Smrg return (u8) res; 119505b261ecSmrg} 119605b261ecSmrg 119705b261ecSmrg/**************************************************************************** 119805b261ecSmrgREMARKS: 119905b261ecSmrgImplements the ROL instruction and side effects. 120005b261ecSmrg****************************************************************************/ 1201f7df2e56Smrgu16 1202f7df2e56Smrgrol_word(u16 d, u8 s) 120305b261ecSmrg{ 120405b261ecSmrg register unsigned int res, cnt, mask; 120505b261ecSmrg 1206f7df2e56Smrg res = d; 1207f7df2e56Smrg if ((cnt = s % 16) != 0) { 1208f7df2e56Smrg res = (d << cnt); 1209f7df2e56Smrg mask = (1 << cnt) - 1; 1210f7df2e56Smrg res |= (d >> (16 - cnt)) & mask; 1211f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 1212f7df2e56Smrg CONDITIONAL_SET_FLAG(s == 1 && 1213f7df2e56Smrg XOR2((res & 0x1) + ((res >> 14) & 0x2)), F_OF); 1214f7df2e56Smrg } 1215f7df2e56Smrg if (s != 0) { 1216f7df2e56Smrg /* set the new carry flag, Note that it is the low order 1217f7df2e56Smrg bit of the result!!! */ 1218f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 1219f7df2e56Smrg } 1220f7df2e56Smrg return (u16) res; 122105b261ecSmrg} 122205b261ecSmrg 122305b261ecSmrg/**************************************************************************** 122405b261ecSmrgREMARKS: 122505b261ecSmrgImplements the ROL instruction and side effects. 122605b261ecSmrg****************************************************************************/ 1227f7df2e56Smrgu32 1228f7df2e56Smrgrol_long(u32 d, u8 s) 122905b261ecSmrg{ 123005b261ecSmrg register u32 res, cnt, mask; 123105b261ecSmrg 1232f7df2e56Smrg res = d; 1233f7df2e56Smrg if ((cnt = s % 32) != 0) { 1234f7df2e56Smrg res = (d << cnt); 1235f7df2e56Smrg mask = (1 << cnt) - 1; 1236f7df2e56Smrg res |= (d >> (32 - cnt)) & mask; 1237f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 1238f7df2e56Smrg CONDITIONAL_SET_FLAG(s == 1 && 1239f7df2e56Smrg XOR2((res & 0x1) + ((res >> 30) & 0x2)), F_OF); 1240f7df2e56Smrg } 1241f7df2e56Smrg if (s != 0) { 1242f7df2e56Smrg /* set the new carry flag, Note that it is the low order 1243f7df2e56Smrg bit of the result!!! */ 1244f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 1245f7df2e56Smrg } 1246f7df2e56Smrg return res; 124705b261ecSmrg} 124805b261ecSmrg 124905b261ecSmrg/**************************************************************************** 125005b261ecSmrgREMARKS: 125105b261ecSmrgImplements the ROR instruction and side effects. 125205b261ecSmrg****************************************************************************/ 1253f7df2e56Smrgu8 1254f7df2e56Smrgror_byte(u8 d, u8 s) 125505b261ecSmrg{ 125605b261ecSmrg register unsigned int res, cnt, mask; 125705b261ecSmrg 125805b261ecSmrg /* rotate right */ 1259f7df2e56Smrg /* 126005b261ecSmrg s is the rotate distance. It varies from 0 - 8. 1261f7df2e56Smrg d is the byte object rotated. 126205b261ecSmrg 1263f7df2e56Smrg have 126405b261ecSmrg 1265f7df2e56Smrg B_7 ... B_0 126605b261ecSmrg 126705b261ecSmrg The rotate is done mod 8. 126805b261ecSmrg 1269f7df2e56Smrg IF n > 0 127005b261ecSmrg 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 127105b261ecSmrg 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) 1272f7df2e56Smrg */ 1273f7df2e56Smrg res = d; 1274f7df2e56Smrg if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ 127505b261ecSmrg /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ 127605b261ecSmrg res = (d << (8 - cnt)); 127705b261ecSmrg 127805b261ecSmrg /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ 127905b261ecSmrg mask = (1 << (8 - cnt)) - 1; 128005b261ecSmrg res |= (d >> (cnt)) & mask; 128105b261ecSmrg 1282f7df2e56Smrg /* set the new carry flag, Note that it is the low order 128305b261ecSmrg bit of the result!!! */ 1284f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 1285f7df2e56Smrg /* OVERFLOW is set *IFF* s==1, then it is the 128605b261ecSmrg xor of the two most significant bits. Blecck. */ 1287f7df2e56Smrg CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); 1288f7df2e56Smrg } 1289f7df2e56Smrg else if (s != 0) { 1290f7df2e56Smrg /* set the new carry flag, Note that it is the low order 1291f7df2e56Smrg bit of the result!!! */ 1292f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 1293f7df2e56Smrg } 1294f7df2e56Smrg return (u8) res; 129505b261ecSmrg} 129605b261ecSmrg 129705b261ecSmrg/**************************************************************************** 129805b261ecSmrgREMARKS: 129905b261ecSmrgImplements the ROR instruction and side effects. 130005b261ecSmrg****************************************************************************/ 1301f7df2e56Smrgu16 1302f7df2e56Smrgror_word(u16 d, u8 s) 130305b261ecSmrg{ 130405b261ecSmrg register unsigned int res, cnt, mask; 130505b261ecSmrg 1306f7df2e56Smrg res = d; 1307f7df2e56Smrg if ((cnt = s % 16) != 0) { 1308f7df2e56Smrg res = (d << (16 - cnt)); 1309f7df2e56Smrg mask = (1 << (16 - cnt)) - 1; 1310f7df2e56Smrg res |= (d >> (cnt)) & mask; 1311f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 1312f7df2e56Smrg CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); 1313f7df2e56Smrg } 1314f7df2e56Smrg else if (s != 0) { 1315f7df2e56Smrg /* set the new carry flag, Note that it is the low order 1316f7df2e56Smrg bit of the result!!! */ 1317f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 1318f7df2e56Smrg } 1319f7df2e56Smrg return (u16) res; 132005b261ecSmrg} 132105b261ecSmrg 132205b261ecSmrg/**************************************************************************** 132305b261ecSmrgREMARKS: 132405b261ecSmrgImplements the ROR instruction and side effects. 132505b261ecSmrg****************************************************************************/ 1326f7df2e56Smrgu32 1327f7df2e56Smrgror_long(u32 d, u8 s) 132805b261ecSmrg{ 1329f7df2e56Smrg register u32 res, cnt, mask; 133005b261ecSmrg 1331f7df2e56Smrg res = d; 1332f7df2e56Smrg if ((cnt = s % 32) != 0) { 1333f7df2e56Smrg res = (d << (32 - cnt)); 1334f7df2e56Smrg mask = (1 << (32 - cnt)) - 1; 1335f7df2e56Smrg res |= (d >> (cnt)) & mask; 1336f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 1337f7df2e56Smrg CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); 1338f7df2e56Smrg } 1339f7df2e56Smrg else if (s != 0) { 1340f7df2e56Smrg /* set the new carry flag, Note that it is the low order 1341f7df2e56Smrg bit of the result!!! */ 1342f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 1343f7df2e56Smrg } 1344f7df2e56Smrg return res; 134505b261ecSmrg} 134605b261ecSmrg 134705b261ecSmrg/**************************************************************************** 134805b261ecSmrgREMARKS: 134905b261ecSmrgImplements the SHL instruction and side effects. 135005b261ecSmrg****************************************************************************/ 1351f7df2e56Smrgu8 1352f7df2e56Smrgshl_byte(u8 d, u8 s) 135305b261ecSmrg{ 1354f7df2e56Smrg unsigned int cnt, res, cf; 135505b261ecSmrg 1356f7df2e56Smrg if (s < 8) { 1357f7df2e56Smrg cnt = s % 8; 1358f7df2e56Smrg 1359f7df2e56Smrg /* last bit shifted out goes into carry flag */ 1360f7df2e56Smrg if (cnt > 0) { 1361f7df2e56Smrg res = d << cnt; 1362f7df2e56Smrg cf = d & (1 << (8 - cnt)); 1363f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1364f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 1365f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 1366f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1367f7df2e56Smrg } 1368f7df2e56Smrg else { 1369f7df2e56Smrg res = (u8) d; 1370f7df2e56Smrg } 137105b261ecSmrg 1372f7df2e56Smrg if (cnt == 1) { 1373f7df2e56Smrg /* Needs simplification. */ 1374f7df2e56Smrg CONDITIONAL_SET_FLAG((((res & 0x80) == 0x80) ^ 1375f7df2e56Smrg (ACCESS_FLAG(F_CF) != 0)), 1376f7df2e56Smrg /* was (M.x86.R_FLG&F_CF)==F_CF)), */ 1377f7df2e56Smrg F_OF); 1378f7df2e56Smrg } 1379f7df2e56Smrg else { 1380f7df2e56Smrg CLEAR_FLAG(F_OF); 1381f7df2e56Smrg } 138205b261ecSmrg } 1383f7df2e56Smrg else { 1384f7df2e56Smrg res = 0; 1385f7df2e56Smrg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF); 1386f7df2e56Smrg CLEAR_FLAG(F_OF); 1387f7df2e56Smrg CLEAR_FLAG(F_SF); 1388f7df2e56Smrg SET_FLAG(F_PF); 1389f7df2e56Smrg SET_FLAG(F_ZF); 1390f7df2e56Smrg } 1391f7df2e56Smrg return (u8) res; 139205b261ecSmrg} 139305b261ecSmrg 139405b261ecSmrg/**************************************************************************** 139505b261ecSmrgREMARKS: 139605b261ecSmrgImplements the SHL instruction and side effects. 139705b261ecSmrg****************************************************************************/ 1398f7df2e56Smrgu16 1399f7df2e56Smrgshl_word(u16 d, u8 s) 140005b261ecSmrg{ 140105b261ecSmrg unsigned int cnt, res, cf; 140205b261ecSmrg 1403f7df2e56Smrg if (s < 16) { 1404f7df2e56Smrg cnt = s % 16; 1405f7df2e56Smrg if (cnt > 0) { 1406f7df2e56Smrg res = d << cnt; 1407f7df2e56Smrg cf = d & (1 << (16 - cnt)); 1408f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1409f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 1410f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 1411f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1412f7df2e56Smrg } 1413f7df2e56Smrg else { 1414f7df2e56Smrg res = (u16) d; 1415f7df2e56Smrg } 1416f7df2e56Smrg 1417f7df2e56Smrg if (cnt == 1) { 1418f7df2e56Smrg CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ 1419f7df2e56Smrg (ACCESS_FLAG(F_CF) != 0)), F_OF); 1420f7df2e56Smrg } 1421f7df2e56Smrg else { 1422f7df2e56Smrg CLEAR_FLAG(F_OF); 1423f7df2e56Smrg } 1424f7df2e56Smrg } 1425f7df2e56Smrg else { 1426f7df2e56Smrg res = 0; 1427f7df2e56Smrg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 1428f7df2e56Smrg CLEAR_FLAG(F_OF); 1429f7df2e56Smrg CLEAR_FLAG(F_SF); 1430f7df2e56Smrg SET_FLAG(F_PF); 1431f7df2e56Smrg SET_FLAG(F_ZF); 1432f7df2e56Smrg } 1433f7df2e56Smrg return (u16) res; 143405b261ecSmrg} 143505b261ecSmrg 143605b261ecSmrg/**************************************************************************** 143705b261ecSmrgREMARKS: 143805b261ecSmrgImplements the SHL instruction and side effects. 143905b261ecSmrg****************************************************************************/ 1440f7df2e56Smrgu32 1441f7df2e56Smrgshl_long(u32 d, u8 s) 1442f7df2e56Smrg{ 1443f7df2e56Smrg unsigned int cnt, res, cf; 1444f7df2e56Smrg 1445f7df2e56Smrg if (s < 32) { 1446f7df2e56Smrg cnt = s % 32; 1447f7df2e56Smrg if (cnt > 0) { 1448f7df2e56Smrg res = d << cnt; 1449f7df2e56Smrg cf = d & (1 << (32 - cnt)); 1450f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1451f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 1452f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 1453f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1454f7df2e56Smrg } 1455f7df2e56Smrg else { 1456f7df2e56Smrg res = d; 1457f7df2e56Smrg } 1458f7df2e56Smrg if (cnt == 1) { 1459f7df2e56Smrg CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 1460f7df2e56Smrg (ACCESS_FLAG(F_CF) != 0)), F_OF); 1461f7df2e56Smrg } 1462f7df2e56Smrg else { 1463f7df2e56Smrg CLEAR_FLAG(F_OF); 1464f7df2e56Smrg } 1465f7df2e56Smrg } 1466f7df2e56Smrg else { 1467f7df2e56Smrg res = 0; 1468f7df2e56Smrg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 1469f7df2e56Smrg CLEAR_FLAG(F_OF); 1470f7df2e56Smrg CLEAR_FLAG(F_SF); 1471f7df2e56Smrg SET_FLAG(F_PF); 1472f7df2e56Smrg SET_FLAG(F_ZF); 1473f7df2e56Smrg } 1474f7df2e56Smrg return res; 147505b261ecSmrg} 147605b261ecSmrg 147705b261ecSmrg/**************************************************************************** 147805b261ecSmrgREMARKS: 147905b261ecSmrgImplements the SHR instruction and side effects. 148005b261ecSmrg****************************************************************************/ 1481f7df2e56Smrgu8 1482f7df2e56Smrgshr_byte(u8 d, u8 s) 1483f7df2e56Smrg{ 1484f7df2e56Smrg unsigned int cnt, res, cf; 1485f7df2e56Smrg 1486f7df2e56Smrg if (s < 8) { 1487f7df2e56Smrg cnt = s % 8; 1488f7df2e56Smrg if (cnt > 0) { 1489f7df2e56Smrg cf = d & (1 << (cnt - 1)); 1490f7df2e56Smrg res = d >> cnt; 1491f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1492f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 1493f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 1494f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1495f7df2e56Smrg } 1496f7df2e56Smrg else { 1497f7df2e56Smrg res = (u8) d; 1498f7df2e56Smrg } 1499f7df2e56Smrg 1500f7df2e56Smrg if (cnt == 1) { 1501f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); 1502f7df2e56Smrg } 1503f7df2e56Smrg else { 1504f7df2e56Smrg CLEAR_FLAG(F_OF); 1505f7df2e56Smrg } 1506f7df2e56Smrg } 1507f7df2e56Smrg else { 1508f7df2e56Smrg res = 0; 1509f7df2e56Smrg CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF); 1510f7df2e56Smrg CLEAR_FLAG(F_OF); 1511f7df2e56Smrg CLEAR_FLAG(F_SF); 1512f7df2e56Smrg SET_FLAG(F_PF); 1513f7df2e56Smrg SET_FLAG(F_ZF); 1514f7df2e56Smrg } 1515f7df2e56Smrg return (u8) res; 151605b261ecSmrg} 151705b261ecSmrg 151805b261ecSmrg/**************************************************************************** 151905b261ecSmrgREMARKS: 152005b261ecSmrgImplements the SHR instruction and side effects. 152105b261ecSmrg****************************************************************************/ 1522f7df2e56Smrgu16 1523f7df2e56Smrgshr_word(u16 d, u8 s) 152405b261ecSmrg{ 1525f7df2e56Smrg unsigned int cnt, res, cf; 152605b261ecSmrg 1527f7df2e56Smrg if (s < 16) { 1528f7df2e56Smrg cnt = s % 16; 1529f7df2e56Smrg if (cnt > 0) { 1530f7df2e56Smrg cf = d & (1 << (cnt - 1)); 1531f7df2e56Smrg res = d >> cnt; 1532f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1533f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 1534f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 1535f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1536f7df2e56Smrg } 1537f7df2e56Smrg else { 1538f7df2e56Smrg res = d; 1539f7df2e56Smrg } 154005b261ecSmrg 1541f7df2e56Smrg if (cnt == 1) { 1542f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 154305b261ecSmrg } 1544f7df2e56Smrg else { 1545f7df2e56Smrg CLEAR_FLAG(F_OF); 1546f7df2e56Smrg } 1547f7df2e56Smrg } 1548f7df2e56Smrg else { 1549f7df2e56Smrg res = 0; 1550f7df2e56Smrg CLEAR_FLAG(F_CF); 1551f7df2e56Smrg CLEAR_FLAG(F_OF); 1552f7df2e56Smrg SET_FLAG(F_ZF); 1553f7df2e56Smrg CLEAR_FLAG(F_SF); 1554f7df2e56Smrg CLEAR_FLAG(F_PF); 155505b261ecSmrg } 1556f7df2e56Smrg return (u16) res; 155705b261ecSmrg} 155805b261ecSmrg 155905b261ecSmrg/**************************************************************************** 156005b261ecSmrgREMARKS: 156105b261ecSmrgImplements the SHR instruction and side effects. 156205b261ecSmrg****************************************************************************/ 1563f7df2e56Smrgu32 1564f7df2e56Smrgshr_long(u32 d, u8 s) 156505b261ecSmrg{ 1566f7df2e56Smrg unsigned int cnt, res, cf; 156705b261ecSmrg 1568f7df2e56Smrg if (s < 32) { 1569f7df2e56Smrg cnt = s % 32; 1570f7df2e56Smrg if (cnt > 0) { 1571f7df2e56Smrg cf = d & (1 << (cnt - 1)); 1572f7df2e56Smrg res = d >> cnt; 1573f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1574f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 1575f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 1576f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1577f7df2e56Smrg } 1578f7df2e56Smrg else { 157905b261ecSmrg res = d; 158005b261ecSmrg } 158105b261ecSmrg if (cnt == 1) { 1582f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 1583f7df2e56Smrg } 1584f7df2e56Smrg else { 1585f7df2e56Smrg CLEAR_FLAG(F_OF); 158605b261ecSmrg } 1587f7df2e56Smrg } 1588f7df2e56Smrg else { 158905b261ecSmrg res = 0; 1590f7df2e56Smrg CLEAR_FLAG(F_CF); 1591f7df2e56Smrg CLEAR_FLAG(F_OF); 1592f7df2e56Smrg SET_FLAG(F_ZF); 1593f7df2e56Smrg CLEAR_FLAG(F_SF); 1594f7df2e56Smrg CLEAR_FLAG(F_PF); 159505b261ecSmrg } 159605b261ecSmrg return res; 159705b261ecSmrg} 159805b261ecSmrg 159905b261ecSmrg/**************************************************************************** 160005b261ecSmrgREMARKS: 160105b261ecSmrgImplements the SAR instruction and side effects. 160205b261ecSmrg****************************************************************************/ 1603f7df2e56Smrgu8 1604f7df2e56Smrgsar_byte(u8 d, u8 s) 160505b261ecSmrg{ 1606f7df2e56Smrg unsigned int cnt, res, cf, mask, sf; 160705b261ecSmrg 1608f7df2e56Smrg res = d; 1609f7df2e56Smrg sf = d & 0x80; 161005b261ecSmrg cnt = s % 8; 1611f7df2e56Smrg if (cnt > 0 && cnt < 8) { 1612f7df2e56Smrg mask = (1 << (8 - cnt)) - 1; 1613f7df2e56Smrg cf = d & (1 << (cnt - 1)); 1614f7df2e56Smrg res = (d >> cnt) & mask; 1615f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1616f7df2e56Smrg if (sf) { 1617f7df2e56Smrg res |= ~mask; 1618f7df2e56Smrg } 1619f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 1620f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1621f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 1622f7df2e56Smrg } 1623f7df2e56Smrg else if (cnt >= 8) { 162405b261ecSmrg if (sf) { 162505b261ecSmrg res = 0xff; 1626f7df2e56Smrg SET_FLAG(F_CF); 1627f7df2e56Smrg CLEAR_FLAG(F_ZF); 1628f7df2e56Smrg SET_FLAG(F_SF); 1629f7df2e56Smrg SET_FLAG(F_PF); 1630f7df2e56Smrg } 1631f7df2e56Smrg else { 1632f7df2e56Smrg res = 0; 1633f7df2e56Smrg CLEAR_FLAG(F_CF); 1634f7df2e56Smrg SET_FLAG(F_ZF); 1635f7df2e56Smrg CLEAR_FLAG(F_SF); 1636f7df2e56Smrg CLEAR_FLAG(F_PF); 1637f7df2e56Smrg } 1638f7df2e56Smrg } 1639f7df2e56Smrg return (u8) res; 164005b261ecSmrg} 164105b261ecSmrg 164205b261ecSmrg/**************************************************************************** 164305b261ecSmrgREMARKS: 164405b261ecSmrgImplements the SAR instruction and side effects. 164505b261ecSmrg****************************************************************************/ 1646f7df2e56Smrgu16 1647f7df2e56Smrgsar_word(u16 d, u8 s) 164805b261ecSmrg{ 164905b261ecSmrg unsigned int cnt, res, cf, mask, sf; 165005b261ecSmrg 165105b261ecSmrg sf = d & 0x8000; 165205b261ecSmrg cnt = s % 16; 1653f7df2e56Smrg res = d; 1654f7df2e56Smrg if (cnt > 0 && cnt < 16) { 165505b261ecSmrg mask = (1 << (16 - cnt)) - 1; 165605b261ecSmrg cf = d & (1 << (cnt - 1)); 165705b261ecSmrg res = (d >> cnt) & mask; 1658f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 165905b261ecSmrg if (sf) { 166005b261ecSmrg res |= ~mask; 166105b261ecSmrg } 1662f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 1663f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 1664f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1665f7df2e56Smrg } 1666f7df2e56Smrg else if (cnt >= 16) { 166705b261ecSmrg if (sf) { 166805b261ecSmrg res = 0xffff; 1669f7df2e56Smrg SET_FLAG(F_CF); 1670f7df2e56Smrg CLEAR_FLAG(F_ZF); 1671f7df2e56Smrg SET_FLAG(F_SF); 1672f7df2e56Smrg SET_FLAG(F_PF); 1673f7df2e56Smrg } 1674f7df2e56Smrg else { 167505b261ecSmrg res = 0; 1676f7df2e56Smrg CLEAR_FLAG(F_CF); 1677f7df2e56Smrg SET_FLAG(F_ZF); 1678f7df2e56Smrg CLEAR_FLAG(F_SF); 1679f7df2e56Smrg CLEAR_FLAG(F_PF); 168005b261ecSmrg } 168105b261ecSmrg } 1682f7df2e56Smrg return (u16) res; 168305b261ecSmrg} 168405b261ecSmrg 168505b261ecSmrg/**************************************************************************** 168605b261ecSmrgREMARKS: 168705b261ecSmrgImplements the SAR instruction and side effects. 168805b261ecSmrg****************************************************************************/ 1689f7df2e56Smrgu32 1690f7df2e56Smrgsar_long(u32 d, u8 s) 169105b261ecSmrg{ 169205b261ecSmrg u32 cnt, res, cf, mask, sf; 169305b261ecSmrg 169405b261ecSmrg sf = d & 0x80000000; 169505b261ecSmrg cnt = s % 32; 1696f7df2e56Smrg res = d; 1697f7df2e56Smrg if (cnt > 0 && cnt < 32) { 169805b261ecSmrg mask = (1 << (32 - cnt)) - 1; 1699f7df2e56Smrg cf = d & (1 << (cnt - 1)); 170005b261ecSmrg res = (d >> cnt) & mask; 1701f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 170205b261ecSmrg if (sf) { 170305b261ecSmrg res |= ~mask; 170405b261ecSmrg } 1705f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 1706f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 1707f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1708f7df2e56Smrg } 1709f7df2e56Smrg else if (cnt >= 32) { 171005b261ecSmrg if (sf) { 171105b261ecSmrg res = 0xffffffff; 1712f7df2e56Smrg SET_FLAG(F_CF); 1713f7df2e56Smrg CLEAR_FLAG(F_ZF); 1714f7df2e56Smrg SET_FLAG(F_SF); 1715f7df2e56Smrg SET_FLAG(F_PF); 1716f7df2e56Smrg } 1717f7df2e56Smrg else { 1718f7df2e56Smrg res = 0; 1719f7df2e56Smrg CLEAR_FLAG(F_CF); 1720f7df2e56Smrg SET_FLAG(F_ZF); 1721f7df2e56Smrg CLEAR_FLAG(F_SF); 1722f7df2e56Smrg CLEAR_FLAG(F_PF); 1723f7df2e56Smrg } 1724f7df2e56Smrg } 1725f7df2e56Smrg return res; 172605b261ecSmrg} 172705b261ecSmrg 172805b261ecSmrg/**************************************************************************** 172905b261ecSmrgREMARKS: 173005b261ecSmrgImplements the SHLD instruction and side effects. 173105b261ecSmrg****************************************************************************/ 1732f7df2e56Smrgu16 1733f7df2e56Smrgshld_word(u16 d, u16 fill, u8 s) 1734f7df2e56Smrg{ 1735f7df2e56Smrg unsigned int cnt, res, cf; 1736f7df2e56Smrg 1737f7df2e56Smrg if (s < 16) { 1738f7df2e56Smrg cnt = s % 16; 1739f7df2e56Smrg if (cnt > 0) { 1740f7df2e56Smrg res = (d << cnt) | (fill >> (16 - cnt)); 1741f7df2e56Smrg cf = d & (1 << (16 - cnt)); 1742f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1743f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 1744f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 1745f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1746f7df2e56Smrg } 1747f7df2e56Smrg else { 1748f7df2e56Smrg res = d; 1749f7df2e56Smrg } 1750f7df2e56Smrg if (cnt == 1) { 1751f7df2e56Smrg CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ 1752f7df2e56Smrg (ACCESS_FLAG(F_CF) != 0)), F_OF); 1753f7df2e56Smrg } 1754f7df2e56Smrg else { 1755f7df2e56Smrg CLEAR_FLAG(F_OF); 1756f7df2e56Smrg } 1757f7df2e56Smrg } 1758f7df2e56Smrg else { 1759f7df2e56Smrg res = 0; 1760f7df2e56Smrg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 1761f7df2e56Smrg CLEAR_FLAG(F_OF); 1762f7df2e56Smrg CLEAR_FLAG(F_SF); 1763f7df2e56Smrg SET_FLAG(F_PF); 1764f7df2e56Smrg SET_FLAG(F_ZF); 1765f7df2e56Smrg } 1766f7df2e56Smrg return (u16) res; 176705b261ecSmrg} 176805b261ecSmrg 176905b261ecSmrg/**************************************************************************** 177005b261ecSmrgREMARKS: 177105b261ecSmrgImplements the SHLD instruction and side effects. 177205b261ecSmrg****************************************************************************/ 1773f7df2e56Smrgu32 1774f7df2e56Smrgshld_long(u32 d, u32 fill, u8 s) 1775f7df2e56Smrg{ 1776f7df2e56Smrg unsigned int cnt, res, cf; 1777f7df2e56Smrg 1778f7df2e56Smrg if (s < 32) { 1779f7df2e56Smrg cnt = s % 32; 1780f7df2e56Smrg if (cnt > 0) { 1781f7df2e56Smrg res = (d << cnt) | (fill >> (32 - cnt)); 1782f7df2e56Smrg cf = d & (1 << (32 - cnt)); 1783f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1784f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 1785f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 1786f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1787f7df2e56Smrg } 1788f7df2e56Smrg else { 1789f7df2e56Smrg res = d; 1790f7df2e56Smrg } 1791f7df2e56Smrg if (cnt == 1) { 1792f7df2e56Smrg CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 1793f7df2e56Smrg (ACCESS_FLAG(F_CF) != 0)), F_OF); 1794f7df2e56Smrg } 1795f7df2e56Smrg else { 1796f7df2e56Smrg CLEAR_FLAG(F_OF); 1797f7df2e56Smrg } 1798f7df2e56Smrg } 1799f7df2e56Smrg else { 1800f7df2e56Smrg res = 0; 1801f7df2e56Smrg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 1802f7df2e56Smrg CLEAR_FLAG(F_OF); 1803f7df2e56Smrg CLEAR_FLAG(F_SF); 1804f7df2e56Smrg SET_FLAG(F_PF); 1805f7df2e56Smrg SET_FLAG(F_ZF); 1806f7df2e56Smrg } 1807f7df2e56Smrg return res; 180805b261ecSmrg} 180905b261ecSmrg 181005b261ecSmrg/**************************************************************************** 181105b261ecSmrgREMARKS: 181205b261ecSmrgImplements the SHRD instruction and side effects. 181305b261ecSmrg****************************************************************************/ 1814f7df2e56Smrgu16 1815f7df2e56Smrgshrd_word(u16 d, u16 fill, u8 s) 181605b261ecSmrg{ 1817f7df2e56Smrg unsigned int cnt, res, cf; 181805b261ecSmrg 1819f7df2e56Smrg if (s < 16) { 1820f7df2e56Smrg cnt = s % 16; 1821f7df2e56Smrg if (cnt > 0) { 1822f7df2e56Smrg cf = d & (1 << (cnt - 1)); 1823f7df2e56Smrg res = (d >> cnt) | (fill << (16 - cnt)); 1824f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1825f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 1826f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 1827f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 1828f7df2e56Smrg } 1829f7df2e56Smrg else { 1830f7df2e56Smrg res = d; 1831f7df2e56Smrg } 183205b261ecSmrg 1833f7df2e56Smrg if (cnt == 1) { 1834f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 1835f7df2e56Smrg } 1836f7df2e56Smrg else { 1837f7df2e56Smrg CLEAR_FLAG(F_OF); 183805b261ecSmrg } 183905b261ecSmrg } 1840f7df2e56Smrg else { 1841f7df2e56Smrg res = 0; 1842f7df2e56Smrg CLEAR_FLAG(F_CF); 1843f7df2e56Smrg CLEAR_FLAG(F_OF); 1844f7df2e56Smrg SET_FLAG(F_ZF); 1845f7df2e56Smrg CLEAR_FLAG(F_SF); 1846f7df2e56Smrg CLEAR_FLAG(F_PF); 1847f7df2e56Smrg } 1848f7df2e56Smrg return (u16) res; 184905b261ecSmrg} 185005b261ecSmrg 185105b261ecSmrg/**************************************************************************** 185205b261ecSmrgREMARKS: 185305b261ecSmrgImplements the SHRD instruction and side effects. 185405b261ecSmrg****************************************************************************/ 1855f7df2e56Smrgu32 1856f7df2e56Smrgshrd_long(u32 d, u32 fill, u8 s) 185705b261ecSmrg{ 1858f7df2e56Smrg unsigned int cnt, res, cf; 185905b261ecSmrg 1860f7df2e56Smrg if (s < 32) { 1861f7df2e56Smrg cnt = s % 32; 1862f7df2e56Smrg if (cnt > 0) { 1863f7df2e56Smrg cf = d & (1 << (cnt - 1)); 1864f7df2e56Smrg res = (d >> cnt) | (fill << (32 - cnt)); 1865f7df2e56Smrg CONDITIONAL_SET_FLAG(cf, F_CF); 1866f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 1867f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 1868f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 186905b261ecSmrg } 1870f7df2e56Smrg else { 1871f7df2e56Smrg res = d; 1872f7df2e56Smrg } 1873f7df2e56Smrg if (cnt == 1) { 1874f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 1875f7df2e56Smrg } 1876f7df2e56Smrg else { 1877f7df2e56Smrg CLEAR_FLAG(F_OF); 1878f7df2e56Smrg } 1879f7df2e56Smrg } 1880f7df2e56Smrg else { 1881f7df2e56Smrg res = 0; 1882f7df2e56Smrg CLEAR_FLAG(F_CF); 1883f7df2e56Smrg CLEAR_FLAG(F_OF); 1884f7df2e56Smrg SET_FLAG(F_ZF); 1885f7df2e56Smrg CLEAR_FLAG(F_SF); 1886f7df2e56Smrg CLEAR_FLAG(F_PF); 188705b261ecSmrg } 1888f7df2e56Smrg return res; 188905b261ecSmrg} 189005b261ecSmrg 189105b261ecSmrg/**************************************************************************** 189205b261ecSmrgREMARKS: 189305b261ecSmrgImplements the SBB instruction and side effects. 189405b261ecSmrg****************************************************************************/ 1895f7df2e56Smrgu8 1896f7df2e56Smrgsbb_byte(u8 d, u8 s) 189705b261ecSmrg{ 1898f7df2e56Smrg register u32 res; /* all operands in native machine order */ 189905b261ecSmrg register u32 bc; 190005b261ecSmrg 1901f7df2e56Smrg if (ACCESS_FLAG(F_CF)) 1902f7df2e56Smrg res = d - s - 1; 1903f7df2e56Smrg else 1904f7df2e56Smrg res = d - s; 1905f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 1906f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 1907f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 190805b261ecSmrg 1909f7df2e56Smrg /* calculate the borrow chain. See note at top */ 1910f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 1911f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 1912f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 1913f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 1914f7df2e56Smrg return (u8) res; 191505b261ecSmrg} 191605b261ecSmrg 191705b261ecSmrg/**************************************************************************** 191805b261ecSmrgREMARKS: 191905b261ecSmrgImplements the SBB instruction and side effects. 192005b261ecSmrg****************************************************************************/ 1921f7df2e56Smrgu16 1922f7df2e56Smrgsbb_word(u16 d, u16 s) 192305b261ecSmrg{ 1924f7df2e56Smrg register u32 res; /* all operands in native machine order */ 192505b261ecSmrg register u32 bc; 192605b261ecSmrg 1927f7df2e56Smrg if (ACCESS_FLAG(F_CF)) 192805b261ecSmrg res = d - s - 1; 192905b261ecSmrg else 193005b261ecSmrg res = d - s; 1931f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 1932f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 1933f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 193405b261ecSmrg 1935f7df2e56Smrg /* calculate the borrow chain. See note at top */ 1936f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 1937f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 1938f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 1939f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 1940f7df2e56Smrg return (u16) res; 194105b261ecSmrg} 194205b261ecSmrg 194305b261ecSmrg/**************************************************************************** 194405b261ecSmrgREMARKS: 194505b261ecSmrgImplements the SBB instruction and side effects. 194605b261ecSmrg****************************************************************************/ 1947f7df2e56Smrgu32 1948f7df2e56Smrgsbb_long(u32 d, u32 s) 194905b261ecSmrg{ 1950f7df2e56Smrg register u32 res; /* all operands in native machine order */ 1951f7df2e56Smrg register u32 bc; 195205b261ecSmrg 1953f7df2e56Smrg if (ACCESS_FLAG(F_CF)) 195405b261ecSmrg res = d - s - 1; 195505b261ecSmrg else 195605b261ecSmrg res = d - s; 1957f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 1958f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 1959f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 196005b261ecSmrg 1961f7df2e56Smrg /* calculate the borrow chain. See note at top */ 1962f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 1963f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 1964f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 1965f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 1966f7df2e56Smrg return res; 196705b261ecSmrg} 196805b261ecSmrg 196905b261ecSmrg/**************************************************************************** 197005b261ecSmrgREMARKS: 197105b261ecSmrgImplements the SUB instruction and side effects. 197205b261ecSmrg****************************************************************************/ 1973f7df2e56Smrgu8 1974f7df2e56Smrgsub_byte(u8 d, u8 s) 197505b261ecSmrg{ 1976f7df2e56Smrg register u32 res; /* all operands in native machine order */ 1977f7df2e56Smrg register u32 bc; 197805b261ecSmrg 1979f7df2e56Smrg res = d - s; 1980f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 1981f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 1982f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 198305b261ecSmrg 1984f7df2e56Smrg /* calculate the borrow chain. See note at top */ 1985f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 1986f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 1987f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 1988f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 1989f7df2e56Smrg return (u8) res; 199005b261ecSmrg} 199105b261ecSmrg 199205b261ecSmrg/**************************************************************************** 199305b261ecSmrgREMARKS: 199405b261ecSmrgImplements the SUB instruction and side effects. 199505b261ecSmrg****************************************************************************/ 1996f7df2e56Smrgu16 1997f7df2e56Smrgsub_word(u16 d, u16 s) 199805b261ecSmrg{ 1999f7df2e56Smrg register u32 res; /* all operands in native machine order */ 200005b261ecSmrg register u32 bc; 200105b261ecSmrg 200205b261ecSmrg res = d - s; 2003f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 2004f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 2005f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 200605b261ecSmrg 2007f7df2e56Smrg /* calculate the borrow chain. See note at top */ 2008f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 2009f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 2010f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 2011f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 2012f7df2e56Smrg return (u16) res; 201305b261ecSmrg} 201405b261ecSmrg 201505b261ecSmrg/**************************************************************************** 201605b261ecSmrgREMARKS: 201705b261ecSmrgImplements the SUB instruction and side effects. 201805b261ecSmrg****************************************************************************/ 2019f7df2e56Smrgu32 2020f7df2e56Smrgsub_long(u32 d, u32 s) 202105b261ecSmrg{ 2022f7df2e56Smrg register u32 res; /* all operands in native machine order */ 2023f7df2e56Smrg register u32 bc; 202405b261ecSmrg 2025f7df2e56Smrg res = d - s; 2026f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 2027f7df2e56Smrg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 2028f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 202905b261ecSmrg 2030f7df2e56Smrg /* calculate the borrow chain. See note at top */ 2031f7df2e56Smrg bc = (res & (~d | s)) | (~d & s); 2032f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 2033f7df2e56Smrg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 2034f7df2e56Smrg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 2035f7df2e56Smrg return res; 203605b261ecSmrg} 203705b261ecSmrg 203805b261ecSmrg/**************************************************************************** 203905b261ecSmrgREMARKS: 204005b261ecSmrgImplements the TEST instruction and side effects. 204105b261ecSmrg****************************************************************************/ 2042f7df2e56Smrgvoid 2043f7df2e56Smrgtest_byte(u8 d, u8 s) 204405b261ecSmrg{ 2045f7df2e56Smrg register u32 res; /* all operands in native machine order */ 204605b261ecSmrg 204705b261ecSmrg res = d & s; 204805b261ecSmrg 2049f7df2e56Smrg CLEAR_FLAG(F_OF); 2050f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 2051f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 2052f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 20535a112b11Smrg /* AF == don't care */ 2054f7df2e56Smrg CLEAR_FLAG(F_CF); 205505b261ecSmrg} 205605b261ecSmrg 205705b261ecSmrg/**************************************************************************** 205805b261ecSmrgREMARKS: 205905b261ecSmrgImplements the TEST instruction and side effects. 206005b261ecSmrg****************************************************************************/ 2061f7df2e56Smrgvoid 2062f7df2e56Smrgtest_word(u16 d, u16 s) 206305b261ecSmrg{ 2064f7df2e56Smrg register u32 res; /* all operands in native machine order */ 206505b261ecSmrg 2066f7df2e56Smrg res = d & s; 206705b261ecSmrg 2068f7df2e56Smrg CLEAR_FLAG(F_OF); 2069f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 2070f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 2071f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 20725a112b11Smrg /* AF == don't care */ 2073f7df2e56Smrg CLEAR_FLAG(F_CF); 207405b261ecSmrg} 207505b261ecSmrg 207605b261ecSmrg/**************************************************************************** 207705b261ecSmrgREMARKS: 207805b261ecSmrgImplements the TEST instruction and side effects. 207905b261ecSmrg****************************************************************************/ 2080f7df2e56Smrgvoid 2081f7df2e56Smrgtest_long(u32 d, u32 s) 208205b261ecSmrg{ 2083f7df2e56Smrg register u32 res; /* all operands in native machine order */ 208405b261ecSmrg 2085f7df2e56Smrg res = d & s; 208605b261ecSmrg 2087f7df2e56Smrg CLEAR_FLAG(F_OF); 2088f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 2089f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 2090f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 20915a112b11Smrg /* AF == don't care */ 2092f7df2e56Smrg CLEAR_FLAG(F_CF); 209305b261ecSmrg} 209405b261ecSmrg 209505b261ecSmrg/**************************************************************************** 209605b261ecSmrgREMARKS: 209705b261ecSmrgImplements the XOR instruction and side effects. 209805b261ecSmrg****************************************************************************/ 2099f7df2e56Smrgu8 2100f7df2e56Smrgxor_byte(u8 d, u8 s) 210105b261ecSmrg{ 2102f7df2e56Smrg register u8 res; /* all operands in native machine order */ 210305b261ecSmrg 2104f7df2e56Smrg res = d ^ s; 2105f7df2e56Smrg CLEAR_FLAG(F_OF); 2106f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 2107f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 2108f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 2109f7df2e56Smrg CLEAR_FLAG(F_CF); 2110f7df2e56Smrg CLEAR_FLAG(F_AF); 2111f7df2e56Smrg return res; 211205b261ecSmrg} 211305b261ecSmrg 211405b261ecSmrg/**************************************************************************** 211505b261ecSmrgREMARKS: 211605b261ecSmrgImplements the XOR instruction and side effects. 211705b261ecSmrg****************************************************************************/ 2118f7df2e56Smrgu16 2119f7df2e56Smrgxor_word(u16 d, u16 s) 212005b261ecSmrg{ 2121f7df2e56Smrg register u16 res; /* all operands in native machine order */ 212205b261ecSmrg 2123f7df2e56Smrg res = d ^ s; 2124f7df2e56Smrg CLEAR_FLAG(F_OF); 2125f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 2126f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 2127f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 2128f7df2e56Smrg CLEAR_FLAG(F_CF); 2129f7df2e56Smrg CLEAR_FLAG(F_AF); 2130f7df2e56Smrg return res; 213105b261ecSmrg} 213205b261ecSmrg 213305b261ecSmrg/**************************************************************************** 213405b261ecSmrgREMARKS: 213505b261ecSmrgImplements the XOR instruction and side effects. 213605b261ecSmrg****************************************************************************/ 2137f7df2e56Smrgu32 2138f7df2e56Smrgxor_long(u32 d, u32 s) 213905b261ecSmrg{ 2140f7df2e56Smrg register u32 res; /* all operands in native machine order */ 214105b261ecSmrg 2142f7df2e56Smrg res = d ^ s; 2143f7df2e56Smrg CLEAR_FLAG(F_OF); 2144f7df2e56Smrg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 2145f7df2e56Smrg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 2146f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 2147f7df2e56Smrg CLEAR_FLAG(F_CF); 2148f7df2e56Smrg CLEAR_FLAG(F_AF); 2149f7df2e56Smrg return res; 215005b261ecSmrg} 215105b261ecSmrg 215205b261ecSmrg/**************************************************************************** 215305b261ecSmrgREMARKS: 215405b261ecSmrgImplements the IMUL instruction and side effects. 215505b261ecSmrg****************************************************************************/ 2156f7df2e56Smrgvoid 2157f7df2e56Smrgimul_byte(u8 s) 215805b261ecSmrg{ 2159f7df2e56Smrg s16 res = (s16) ((s8) M.x86.R_AL * (s8) s); 216005b261ecSmrg 2161f7df2e56Smrg M.x86.R_AX = res; 2162f7df2e56Smrg if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) || 2163f7df2e56Smrg ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) { 2164f7df2e56Smrg CLEAR_FLAG(F_CF); 2165f7df2e56Smrg CLEAR_FLAG(F_OF); 2166f7df2e56Smrg } 2167f7df2e56Smrg else { 2168f7df2e56Smrg SET_FLAG(F_CF); 2169f7df2e56Smrg SET_FLAG(F_OF); 2170f7df2e56Smrg } 217105b261ecSmrg} 217205b261ecSmrg 217305b261ecSmrg/**************************************************************************** 217405b261ecSmrgREMARKS: 217505b261ecSmrgImplements the IMUL instruction and side effects. 217605b261ecSmrg****************************************************************************/ 2177f7df2e56Smrgvoid 2178f7df2e56Smrgimul_word(u16 s) 217905b261ecSmrg{ 2180f7df2e56Smrg s32 res = (s16) M.x86.R_AX * (s16) s; 218105b261ecSmrg 2182f7df2e56Smrg M.x86.R_AX = (u16) res; 2183f7df2e56Smrg M.x86.R_DX = (u16) (res >> 16); 2184f7df2e56Smrg if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) || 2185f7df2e56Smrg ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) { 2186f7df2e56Smrg CLEAR_FLAG(F_CF); 2187f7df2e56Smrg CLEAR_FLAG(F_OF); 2188f7df2e56Smrg } 2189f7df2e56Smrg else { 2190f7df2e56Smrg SET_FLAG(F_CF); 2191f7df2e56Smrg SET_FLAG(F_OF); 2192f7df2e56Smrg } 219305b261ecSmrg} 219405b261ecSmrg 219505b261ecSmrg/**************************************************************************** 219605b261ecSmrgREMARKS: 219705b261ecSmrgImplements the IMUL instruction and side effects. 219805b261ecSmrg****************************************************************************/ 2199f7df2e56Smrgvoid 2200f7df2e56Smrgimul_long_direct(u32 * res_lo, u32 * res_hi, u32 d, u32 s) 220105b261ecSmrg{ 220205b261ecSmrg#ifdef __HAS_LONG_LONG__ 2203f7df2e56Smrg s64 res = (s64) (s32) d * (s32) s; 220405b261ecSmrg 2205f7df2e56Smrg *res_lo = (u32) res; 2206f7df2e56Smrg *res_hi = (u32) (res >> 32); 220705b261ecSmrg#else 2208f7df2e56Smrg u32 d_lo, d_hi, d_sign; 2209f7df2e56Smrg u32 s_lo, s_hi, s_sign; 2210f7df2e56Smrg u32 rlo_lo, rlo_hi, rhi_lo; 2211f7df2e56Smrg 2212f7df2e56Smrg if ((d_sign = d & 0x80000000) != 0) 2213f7df2e56Smrg d = -d; 2214f7df2e56Smrg d_lo = d & 0xFFFF; 2215f7df2e56Smrg d_hi = d >> 16; 2216f7df2e56Smrg if ((s_sign = s & 0x80000000) != 0) 2217f7df2e56Smrg s = -s; 2218f7df2e56Smrg s_lo = s & 0xFFFF; 2219f7df2e56Smrg s_hi = s >> 16; 2220f7df2e56Smrg rlo_lo = d_lo * s_lo; 2221f7df2e56Smrg rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16); 2222f7df2e56Smrg rhi_lo = d_hi * s_hi + (rlo_hi >> 16); 2223f7df2e56Smrg *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF); 2224f7df2e56Smrg *res_hi = rhi_lo; 2225f7df2e56Smrg if (d_sign != s_sign) { 2226f7df2e56Smrg d = ~*res_lo; 2227f7df2e56Smrg s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16); 2228f7df2e56Smrg *res_lo = ~*res_lo + 1; 2229f7df2e56Smrg *res_hi = ~*res_hi + (s >> 16); 2230f7df2e56Smrg } 223105b261ecSmrg#endif 223205b261ecSmrg} 223305b261ecSmrg 223405b261ecSmrg/**************************************************************************** 223505b261ecSmrgREMARKS: 223605b261ecSmrgImplements the IMUL instruction and side effects. 223705b261ecSmrg****************************************************************************/ 2238f7df2e56Smrgvoid 2239f7df2e56Smrgimul_long(u32 s) 224005b261ecSmrg{ 2241f7df2e56Smrg imul_long_direct(&M.x86.R_EAX, &M.x86.R_EDX, M.x86.R_EAX, s); 2242f7df2e56Smrg if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) || 2243f7df2e56Smrg ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) { 2244f7df2e56Smrg CLEAR_FLAG(F_CF); 2245f7df2e56Smrg CLEAR_FLAG(F_OF); 2246f7df2e56Smrg } 2247f7df2e56Smrg else { 2248f7df2e56Smrg SET_FLAG(F_CF); 2249f7df2e56Smrg SET_FLAG(F_OF); 2250f7df2e56Smrg } 225105b261ecSmrg} 225205b261ecSmrg 225305b261ecSmrg/**************************************************************************** 225405b261ecSmrgREMARKS: 225505b261ecSmrgImplements the MUL instruction and side effects. 225605b261ecSmrg****************************************************************************/ 2257f7df2e56Smrgvoid 2258f7df2e56Smrgmul_byte(u8 s) 225905b261ecSmrg{ 2260f7df2e56Smrg u16 res = (u16) (M.x86.R_AL * s); 226105b261ecSmrg 2262f7df2e56Smrg M.x86.R_AX = res; 2263f7df2e56Smrg if (M.x86.R_AH == 0) { 2264f7df2e56Smrg CLEAR_FLAG(F_CF); 2265f7df2e56Smrg CLEAR_FLAG(F_OF); 2266f7df2e56Smrg } 2267f7df2e56Smrg else { 2268f7df2e56Smrg SET_FLAG(F_CF); 2269f7df2e56Smrg SET_FLAG(F_OF); 2270f7df2e56Smrg } 227105b261ecSmrg} 227205b261ecSmrg 227305b261ecSmrg/**************************************************************************** 227405b261ecSmrgREMARKS: 227505b261ecSmrgImplements the MUL instruction and side effects. 227605b261ecSmrg****************************************************************************/ 2277f7df2e56Smrgvoid 2278f7df2e56Smrgmul_word(u16 s) 227905b261ecSmrg{ 2280f7df2e56Smrg u32 res = M.x86.R_AX * s; 228105b261ecSmrg 2282f7df2e56Smrg M.x86.R_AX = (u16) res; 2283f7df2e56Smrg M.x86.R_DX = (u16) (res >> 16); 2284f7df2e56Smrg if (M.x86.R_DX == 0) { 2285f7df2e56Smrg CLEAR_FLAG(F_CF); 2286f7df2e56Smrg CLEAR_FLAG(F_OF); 2287f7df2e56Smrg } 2288f7df2e56Smrg else { 2289f7df2e56Smrg SET_FLAG(F_CF); 2290f7df2e56Smrg SET_FLAG(F_OF); 229105b261ecSmrg } 229205b261ecSmrg} 229305b261ecSmrg 229405b261ecSmrg/**************************************************************************** 229505b261ecSmrgREMARKS: 229605b261ecSmrgImplements the MUL instruction and side effects. 229705b261ecSmrg****************************************************************************/ 2298f7df2e56Smrgvoid 2299f7df2e56Smrgmul_long(u32 s) 230005b261ecSmrg{ 230105b261ecSmrg#ifdef __HAS_LONG_LONG__ 2302f7df2e56Smrg u64 res = (u64) M.x86.R_EAX * s; 230305b261ecSmrg 2304f7df2e56Smrg M.x86.R_EAX = (u32) res; 2305f7df2e56Smrg M.x86.R_EDX = (u32) (res >> 32); 230605b261ecSmrg#else 2307f7df2e56Smrg u32 a, a_lo, a_hi; 2308f7df2e56Smrg u32 s_lo, s_hi; 2309f7df2e56Smrg u32 rlo_lo, rlo_hi, rhi_lo; 2310f7df2e56Smrg 2311f7df2e56Smrg a = M.x86.R_EAX; 2312f7df2e56Smrg a_lo = a & 0xFFFF; 2313f7df2e56Smrg a_hi = a >> 16; 2314f7df2e56Smrg s_lo = s & 0xFFFF; 2315f7df2e56Smrg s_hi = s >> 16; 2316f7df2e56Smrg rlo_lo = a_lo * s_lo; 2317f7df2e56Smrg rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16); 2318f7df2e56Smrg rhi_lo = a_hi * s_hi + (rlo_hi >> 16); 2319f7df2e56Smrg M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF); 2320f7df2e56Smrg M.x86.R_EDX = rhi_lo; 232105b261ecSmrg#endif 232205b261ecSmrg 2323f7df2e56Smrg if (M.x86.R_EDX == 0) { 2324f7df2e56Smrg CLEAR_FLAG(F_CF); 2325f7df2e56Smrg CLEAR_FLAG(F_OF); 2326f7df2e56Smrg } 2327f7df2e56Smrg else { 2328f7df2e56Smrg SET_FLAG(F_CF); 2329f7df2e56Smrg SET_FLAG(F_OF); 233005b261ecSmrg } 233105b261ecSmrg} 233205b261ecSmrg 233305b261ecSmrg/**************************************************************************** 233405b261ecSmrgREMARKS: 233505b261ecSmrgImplements the IDIV instruction and side effects. 233605b261ecSmrg****************************************************************************/ 2337f7df2e56Smrgvoid 2338f7df2e56Smrgidiv_byte(u8 s) 233905b261ecSmrg{ 234005b261ecSmrg s32 dvd, div, mod; 234105b261ecSmrg 2342f7df2e56Smrg dvd = (s16) M.x86.R_AX; 2343f7df2e56Smrg if (s == 0) { 2344f7df2e56Smrg x86emu_intr_raise(0); 2345f7df2e56Smrg return; 2346f7df2e56Smrg } 2347f7df2e56Smrg div = dvd / (s8) s; 2348f7df2e56Smrg mod = dvd % (s8) s; 2349f7df2e56Smrg if (abs(div) > 0x7f) { 2350f7df2e56Smrg x86emu_intr_raise(0); 235105b261ecSmrg return; 2352f7df2e56Smrg } 2353f7df2e56Smrg M.x86.R_AL = (s8) div; 2354f7df2e56Smrg M.x86.R_AH = (s8) mod; 235505b261ecSmrg} 235605b261ecSmrg 235705b261ecSmrg/**************************************************************************** 235805b261ecSmrgREMARKS: 235905b261ecSmrgImplements the IDIV instruction and side effects. 236005b261ecSmrg****************************************************************************/ 2361f7df2e56Smrgvoid 2362f7df2e56Smrgidiv_word(u16 s) 236305b261ecSmrg{ 2364f7df2e56Smrg s32 dvd, div, mod; 236505b261ecSmrg 2366f7df2e56Smrg dvd = (((s32) M.x86.R_DX) << 16) | M.x86.R_AX; 2367f7df2e56Smrg if (s == 0) { 2368f7df2e56Smrg x86emu_intr_raise(0); 2369f7df2e56Smrg return; 2370f7df2e56Smrg } 2371f7df2e56Smrg div = dvd / (s16) s; 2372f7df2e56Smrg mod = dvd % (s16) s; 2373f7df2e56Smrg if (abs(div) > 0x7fff) { 2374f7df2e56Smrg x86emu_intr_raise(0); 2375f7df2e56Smrg return; 2376f7df2e56Smrg } 2377f7df2e56Smrg CLEAR_FLAG(F_CF); 2378f7df2e56Smrg CLEAR_FLAG(F_SF); 2379f7df2e56Smrg CONDITIONAL_SET_FLAG(div == 0, F_ZF); 2380f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 238105b261ecSmrg 2382f7df2e56Smrg M.x86.R_AX = (u16) div; 2383f7df2e56Smrg M.x86.R_DX = (u16) mod; 238405b261ecSmrg} 238505b261ecSmrg 238605b261ecSmrg/**************************************************************************** 238705b261ecSmrgREMARKS: 238805b261ecSmrgImplements the IDIV instruction and side effects. 238905b261ecSmrg****************************************************************************/ 2390f7df2e56Smrgvoid 2391f7df2e56Smrgidiv_long(u32 s) 239205b261ecSmrg{ 239305b261ecSmrg#ifdef __HAS_LONG_LONG__ 2394f7df2e56Smrg s64 dvd, div, mod; 2395f7df2e56Smrg 2396f7df2e56Smrg dvd = (((s64) M.x86.R_EDX) << 32) | M.x86.R_EAX; 2397f7df2e56Smrg if (s == 0) { 2398f7df2e56Smrg x86emu_intr_raise(0); 2399f7df2e56Smrg return; 2400f7df2e56Smrg } 2401f7df2e56Smrg div = dvd / (s32) s; 2402f7df2e56Smrg mod = dvd % (s32) s; 2403f7df2e56Smrg if (abs(div) > 0x7fffffff) { 2404f7df2e56Smrg x86emu_intr_raise(0); 2405f7df2e56Smrg return; 2406f7df2e56Smrg } 240705b261ecSmrg#else 2408f7df2e56Smrg s32 div = 0, mod; 2409f7df2e56Smrg s32 h_dvd = M.x86.R_EDX; 2410f7df2e56Smrg u32 l_dvd = M.x86.R_EAX; 2411f7df2e56Smrg u32 abs_s = s & 0x7FFFFFFF; 2412f7df2e56Smrg u32 abs_h_dvd = h_dvd & 0x7FFFFFFF; 2413f7df2e56Smrg u32 h_s = abs_s >> 1; 2414f7df2e56Smrg u32 l_s = abs_s << 31; 2415f7df2e56Smrg int counter = 31; 2416f7df2e56Smrg int carry; 2417f7df2e56Smrg 2418f7df2e56Smrg if (s == 0) { 2419f7df2e56Smrg x86emu_intr_raise(0); 2420f7df2e56Smrg return; 2421f7df2e56Smrg } 2422f7df2e56Smrg do { 2423f7df2e56Smrg div <<= 1; 2424f7df2e56Smrg carry = (l_dvd >= l_s) ? 0 : 1; 2425f7df2e56Smrg 2426f7df2e56Smrg if (abs_h_dvd < (h_s + carry)) { 2427f7df2e56Smrg h_s >>= 1; 2428f7df2e56Smrg l_s = abs_s << (--counter); 2429f7df2e56Smrg continue; 2430f7df2e56Smrg } 2431f7df2e56Smrg else { 2432f7df2e56Smrg abs_h_dvd -= (h_s + carry); 2433f7df2e56Smrg l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) 2434f7df2e56Smrg : (l_dvd - l_s); 2435f7df2e56Smrg h_s >>= 1; 2436f7df2e56Smrg l_s = abs_s << (--counter); 2437f7df2e56Smrg div |= 1; 2438f7df2e56Smrg continue; 2439f7df2e56Smrg } 2440f7df2e56Smrg 2441f7df2e56Smrg } while (counter > -1); 2442f7df2e56Smrg /* overflow */ 2443f7df2e56Smrg if (abs_h_dvd || (l_dvd > abs_s)) { 2444f7df2e56Smrg x86emu_intr_raise(0); 2445f7df2e56Smrg return; 2446f7df2e56Smrg } 2447f7df2e56Smrg /* sign */ 2448f7df2e56Smrg div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000)); 2449f7df2e56Smrg mod = l_dvd; 245005b261ecSmrg 245105b261ecSmrg#endif 2452f7df2e56Smrg CLEAR_FLAG(F_CF); 2453f7df2e56Smrg CLEAR_FLAG(F_AF); 2454f7df2e56Smrg CLEAR_FLAG(F_SF); 2455f7df2e56Smrg SET_FLAG(F_ZF); 2456f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 245705b261ecSmrg 2458f7df2e56Smrg M.x86.R_EAX = (u32) div; 2459f7df2e56Smrg M.x86.R_EDX = (u32) mod; 246005b261ecSmrg} 246105b261ecSmrg 246205b261ecSmrg/**************************************************************************** 246305b261ecSmrgREMARKS: 246405b261ecSmrgImplements the DIV instruction and side effects. 246505b261ecSmrg****************************************************************************/ 2466f7df2e56Smrgvoid 2467f7df2e56Smrgdiv_byte(u8 s) 246805b261ecSmrg{ 2469f7df2e56Smrg u32 dvd, div, mod; 247005b261ecSmrg 2471f7df2e56Smrg dvd = M.x86.R_AX; 247205b261ecSmrg if (s == 0) { 2473f7df2e56Smrg x86emu_intr_raise(0); 247405b261ecSmrg return; 247505b261ecSmrg } 2476f7df2e56Smrg div = dvd / (u8) s; 2477f7df2e56Smrg mod = dvd % (u8) s; 2478f7df2e56Smrg if (div > 0xff) { 2479f7df2e56Smrg x86emu_intr_raise(0); 248005b261ecSmrg return; 2481f7df2e56Smrg } 2482f7df2e56Smrg M.x86.R_AL = (u8) div; 2483f7df2e56Smrg M.x86.R_AH = (u8) mod; 248405b261ecSmrg} 248505b261ecSmrg 248605b261ecSmrg/**************************************************************************** 248705b261ecSmrgREMARKS: 248805b261ecSmrgImplements the DIV instruction and side effects. 248905b261ecSmrg****************************************************************************/ 2490f7df2e56Smrgvoid 2491f7df2e56Smrgdiv_word(u16 s) 249205b261ecSmrg{ 2493f7df2e56Smrg u32 dvd, div, mod; 249405b261ecSmrg 2495f7df2e56Smrg dvd = (((u32) M.x86.R_DX) << 16) | M.x86.R_AX; 2496f7df2e56Smrg if (s == 0) { 2497f7df2e56Smrg x86emu_intr_raise(0); 249805b261ecSmrg return; 249905b261ecSmrg } 2500f7df2e56Smrg div = dvd / (u16) s; 2501f7df2e56Smrg mod = dvd % (u16) s; 2502f7df2e56Smrg if (div > 0xffff) { 2503f7df2e56Smrg x86emu_intr_raise(0); 2504f7df2e56Smrg return; 2505f7df2e56Smrg } 2506f7df2e56Smrg CLEAR_FLAG(F_CF); 2507f7df2e56Smrg CLEAR_FLAG(F_SF); 2508f7df2e56Smrg CONDITIONAL_SET_FLAG(div == 0, F_ZF); 2509f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 251005b261ecSmrg 2511f7df2e56Smrg M.x86.R_AX = (u16) div; 2512f7df2e56Smrg M.x86.R_DX = (u16) mod; 251305b261ecSmrg} 251405b261ecSmrg 251505b261ecSmrg/**************************************************************************** 251605b261ecSmrgREMARKS: 251705b261ecSmrgImplements the DIV instruction and side effects. 251805b261ecSmrg****************************************************************************/ 2519f7df2e56Smrgvoid 2520f7df2e56Smrgdiv_long(u32 s) 252105b261ecSmrg{ 252205b261ecSmrg#ifdef __HAS_LONG_LONG__ 2523f7df2e56Smrg u64 dvd, div, mod; 2524f7df2e56Smrg 2525f7df2e56Smrg dvd = (((u64) M.x86.R_EDX) << 32) | M.x86.R_EAX; 2526f7df2e56Smrg if (s == 0) { 2527f7df2e56Smrg x86emu_intr_raise(0); 2528f7df2e56Smrg return; 2529f7df2e56Smrg } 2530f7df2e56Smrg div = dvd / (u32) s; 2531f7df2e56Smrg mod = dvd % (u32) s; 2532f7df2e56Smrg if (abs(div) > 0xffffffff) { 2533f7df2e56Smrg x86emu_intr_raise(0); 2534f7df2e56Smrg return; 2535f7df2e56Smrg } 253605b261ecSmrg#else 2537f7df2e56Smrg s32 div = 0, mod; 2538f7df2e56Smrg s32 h_dvd = M.x86.R_EDX; 2539f7df2e56Smrg u32 l_dvd = M.x86.R_EAX; 2540f7df2e56Smrg 2541f7df2e56Smrg u32 h_s = s; 2542f7df2e56Smrg u32 l_s = 0; 2543f7df2e56Smrg int counter = 32; 2544f7df2e56Smrg int carry; 2545f7df2e56Smrg 2546f7df2e56Smrg if (s == 0) { 2547f7df2e56Smrg x86emu_intr_raise(0); 2548f7df2e56Smrg return; 2549f7df2e56Smrg } 2550f7df2e56Smrg do { 2551f7df2e56Smrg div <<= 1; 2552f7df2e56Smrg carry = (l_dvd >= l_s) ? 0 : 1; 2553f7df2e56Smrg 2554f7df2e56Smrg if (h_dvd < (h_s + carry)) { 2555f7df2e56Smrg h_s >>= 1; 2556f7df2e56Smrg l_s = s << (--counter); 2557f7df2e56Smrg continue; 2558f7df2e56Smrg } 2559f7df2e56Smrg else { 2560f7df2e56Smrg h_dvd -= (h_s + carry); 2561f7df2e56Smrg l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) 2562f7df2e56Smrg : (l_dvd - l_s); 2563f7df2e56Smrg h_s >>= 1; 2564f7df2e56Smrg l_s = s << (--counter); 2565f7df2e56Smrg div |= 1; 2566f7df2e56Smrg continue; 2567f7df2e56Smrg } 2568f7df2e56Smrg 2569f7df2e56Smrg } while (counter > -1); 2570f7df2e56Smrg /* overflow */ 2571f7df2e56Smrg if (h_dvd || (l_dvd > s)) { 2572f7df2e56Smrg x86emu_intr_raise(0); 2573f7df2e56Smrg return; 2574f7df2e56Smrg } 2575f7df2e56Smrg mod = l_dvd; 257605b261ecSmrg#endif 2577f7df2e56Smrg CLEAR_FLAG(F_CF); 2578f7df2e56Smrg CLEAR_FLAG(F_AF); 2579f7df2e56Smrg CLEAR_FLAG(F_SF); 2580f7df2e56Smrg SET_FLAG(F_ZF); 2581f7df2e56Smrg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 258205b261ecSmrg 2583f7df2e56Smrg M.x86.R_EAX = (u32) div; 2584f7df2e56Smrg M.x86.R_EDX = (u32) mod; 258505b261ecSmrg} 258605b261ecSmrg 258705b261ecSmrg/**************************************************************************** 258805b261ecSmrgREMARKS: 258905b261ecSmrgImplements the IN string instruction and side effects. 259005b261ecSmrg****************************************************************************/ 2591f7df2e56Smrgvoid 2592f7df2e56Smrgins(int size) 259305b261ecSmrg{ 2594f7df2e56Smrg int inc = size; 259505b261ecSmrg 2596f7df2e56Smrg if (ACCESS_FLAG(F_DF)) { 2597f7df2e56Smrg inc = -size; 2598f7df2e56Smrg } 2599f7df2e56Smrg if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 26005a112b11Smrg /* don't care whether REPE or REPNE */ 260105b261ecSmrg /* in until CX is ZERO. */ 2602f7df2e56Smrg u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? 2603f7df2e56Smrg M.x86.R_ECX : M.x86.R_CX); 260405b261ecSmrg switch (size) { 2605f7df2e56Smrg case 1: 260605b261ecSmrg while (count--) { 2607f7df2e56Smrg store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, 2608f7df2e56Smrg (*sys_inb) (M.x86.R_DX)); 2609f7df2e56Smrg M.x86.R_DI += inc; 261005b261ecSmrg } 261105b261ecSmrg break; 261205b261ecSmrg 2613f7df2e56Smrg case 2: 261405b261ecSmrg while (count--) { 2615f7df2e56Smrg store_data_word_abs(M.x86.R_ES, M.x86.R_DI, 2616f7df2e56Smrg (*sys_inw) (M.x86.R_DX)); 2617f7df2e56Smrg M.x86.R_DI += inc; 261805b261ecSmrg } 261905b261ecSmrg break; 2620f7df2e56Smrg case 4: 262105b261ecSmrg while (count--) { 2622f7df2e56Smrg store_data_long_abs(M.x86.R_ES, M.x86.R_DI, 2623f7df2e56Smrg (*sys_inl) (M.x86.R_DX)); 2624f7df2e56Smrg M.x86.R_DI += inc; 262505b261ecSmrg break; 262605b261ecSmrg } 262705b261ecSmrg } 2628f7df2e56Smrg M.x86.R_CX = 0; 2629f7df2e56Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2630f7df2e56Smrg M.x86.R_ECX = 0; 263105b261ecSmrg } 2632f7df2e56Smrg M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2633f7df2e56Smrg } 2634f7df2e56Smrg else { 263505b261ecSmrg switch (size) { 2636f7df2e56Smrg case 1: 2637f7df2e56Smrg store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, 2638f7df2e56Smrg (*sys_inb) (M.x86.R_DX)); 263905b261ecSmrg break; 2640f7df2e56Smrg case 2: 2641f7df2e56Smrg store_data_word_abs(M.x86.R_ES, M.x86.R_DI, 2642f7df2e56Smrg (*sys_inw) (M.x86.R_DX)); 264305b261ecSmrg break; 2644f7df2e56Smrg case 4: 2645f7df2e56Smrg store_data_long_abs(M.x86.R_ES, M.x86.R_DI, 2646f7df2e56Smrg (*sys_inl) (M.x86.R_DX)); 264705b261ecSmrg break; 264805b261ecSmrg } 2649f7df2e56Smrg M.x86.R_DI += inc; 265005b261ecSmrg } 265105b261ecSmrg} 265205b261ecSmrg 265305b261ecSmrg/**************************************************************************** 265405b261ecSmrgREMARKS: 265505b261ecSmrgImplements the OUT string instruction and side effects. 265605b261ecSmrg****************************************************************************/ 2657f7df2e56Smrgvoid 2658f7df2e56Smrgouts(int size) 265905b261ecSmrg{ 266005b261ecSmrg int inc = size; 266105b261ecSmrg 2662f7df2e56Smrg if (ACCESS_FLAG(F_DF)) { 266305b261ecSmrg inc = -size; 266405b261ecSmrg } 2665f7df2e56Smrg if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 26665a112b11Smrg /* don't care whether REPE or REPNE */ 266705b261ecSmrg /* out until CX is ZERO. */ 2668f7df2e56Smrg u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? 2669f7df2e56Smrg M.x86.R_ECX : M.x86.R_CX); 267005b261ecSmrg switch (size) { 2671f7df2e56Smrg case 1: 267205b261ecSmrg while (count--) { 2673f7df2e56Smrg (*sys_outb) (M.x86.R_DX, 2674f7df2e56Smrg fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI)); 2675f7df2e56Smrg M.x86.R_SI += inc; 267605b261ecSmrg } 267705b261ecSmrg break; 267805b261ecSmrg 2679f7df2e56Smrg case 2: 268005b261ecSmrg while (count--) { 2681f7df2e56Smrg (*sys_outw) (M.x86.R_DX, 2682f7df2e56Smrg fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI)); 2683f7df2e56Smrg M.x86.R_SI += inc; 268405b261ecSmrg } 268505b261ecSmrg break; 2686f7df2e56Smrg case 4: 268705b261ecSmrg while (count--) { 2688f7df2e56Smrg (*sys_outl) (M.x86.R_DX, 2689f7df2e56Smrg fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI)); 2690f7df2e56Smrg M.x86.R_SI += inc; 269105b261ecSmrg break; 269205b261ecSmrg } 269305b261ecSmrg } 2694f7df2e56Smrg M.x86.R_CX = 0; 2695f7df2e56Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2696f7df2e56Smrg M.x86.R_ECX = 0; 269705b261ecSmrg } 2698f7df2e56Smrg M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2699f7df2e56Smrg } 2700f7df2e56Smrg else { 270105b261ecSmrg switch (size) { 2702f7df2e56Smrg case 1: 2703f7df2e56Smrg (*sys_outb) (M.x86.R_DX, 2704f7df2e56Smrg fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI)); 270505b261ecSmrg break; 2706f7df2e56Smrg case 2: 2707f7df2e56Smrg (*sys_outw) (M.x86.R_DX, 2708f7df2e56Smrg fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI)); 270905b261ecSmrg break; 2710f7df2e56Smrg case 4: 2711f7df2e56Smrg (*sys_outl) (M.x86.R_DX, 2712f7df2e56Smrg fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI)); 271305b261ecSmrg break; 271405b261ecSmrg } 2715f7df2e56Smrg M.x86.R_SI += inc; 271605b261ecSmrg } 271705b261ecSmrg} 271805b261ecSmrg 271905b261ecSmrg/**************************************************************************** 272005b261ecSmrgPARAMETERS: 272105b261ecSmrgaddr - Address to fetch word from 272205b261ecSmrg 272305b261ecSmrgREMARKS: 272405b261ecSmrgFetches a word from emulator memory using an absolute address. 272505b261ecSmrg****************************************************************************/ 2726f7df2e56Smrgu16 2727f7df2e56Smrgmem_access_word(int addr) 272805b261ecSmrg{ 2729f7df2e56Smrg DB(if (CHECK_MEM_ACCESS()) 2730f7df2e56Smrg x86emu_check_mem_access(addr);) 2731f7df2e56Smrg return (*sys_rdw) (addr); 273205b261ecSmrg} 273305b261ecSmrg 273405b261ecSmrg/**************************************************************************** 273505b261ecSmrgREMARKS: 273605b261ecSmrgPushes a word onto the stack. 273705b261ecSmrg 273805b261ecSmrgNOTE: Do not inline this, as (*sys_wrX) is already inline! 273905b261ecSmrg****************************************************************************/ 2740f7df2e56Smrgvoid 2741f7df2e56Smrgpush_word(u16 w) 274205b261ecSmrg{ 2743f7df2e56Smrg DB(if (CHECK_SP_ACCESS()) 2744f7df2e56Smrg x86emu_check_sp_access();) 2745f7df2e56Smrg M.x86.R_SP -= 2; 2746f7df2e56Smrg (*sys_wrw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w); 274705b261ecSmrg} 274805b261ecSmrg 274905b261ecSmrg/**************************************************************************** 275005b261ecSmrgREMARKS: 275105b261ecSmrgPushes a long onto the stack. 275205b261ecSmrg 275305b261ecSmrgNOTE: Do not inline this, as (*sys_wrX) is already inline! 275405b261ecSmrg****************************************************************************/ 2755f7df2e56Smrgvoid 2756f7df2e56Smrgpush_long(u32 w) 275705b261ecSmrg{ 2758f7df2e56Smrg DB(if (CHECK_SP_ACCESS()) 2759f7df2e56Smrg x86emu_check_sp_access();) 2760f7df2e56Smrg M.x86.R_SP -= 4; 2761f7df2e56Smrg (*sys_wrl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w); 276205b261ecSmrg} 276305b261ecSmrg 276405b261ecSmrg/**************************************************************************** 276505b261ecSmrgREMARKS: 276605b261ecSmrgPops a word from the stack. 276705b261ecSmrg 276805b261ecSmrgNOTE: Do not inline this, as (*sys_rdX) is already inline! 276905b261ecSmrg****************************************************************************/ 2770f7df2e56Smrgu16 2771f7df2e56Smrgpop_word(void) 277205b261ecSmrg{ 2773f7df2e56Smrg register u16 res; 277405b261ecSmrg 2775f7df2e56Smrg DB(if (CHECK_SP_ACCESS()) 2776f7df2e56Smrg x86emu_check_sp_access();) 2777f7df2e56Smrg res = (*sys_rdw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP); 2778f7df2e56Smrg M.x86.R_SP += 2; 2779f7df2e56Smrg return res; 278005b261ecSmrg} 278105b261ecSmrg 278205b261ecSmrg/**************************************************************************** 278305b261ecSmrgREMARKS: 278405b261ecSmrgPops a long from the stack. 278505b261ecSmrg 278605b261ecSmrgNOTE: Do not inline this, as (*sys_rdX) is already inline! 278705b261ecSmrg****************************************************************************/ 2788f7df2e56Smrgu32 2789f7df2e56Smrgpop_long(void) 279005b261ecSmrg{ 279105b261ecSmrg register u32 res; 279205b261ecSmrg 2793f7df2e56Smrg DB(if (CHECK_SP_ACCESS()) 2794f7df2e56Smrg x86emu_check_sp_access();) 2795f7df2e56Smrg res = (*sys_rdl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP); 2796f7df2e56Smrg M.x86.R_SP += 4; 279705b261ecSmrg return res; 279805b261ecSmrg} 279905b261ecSmrg 28004642e01fSmrg/**************************************************************************** 28014642e01fSmrgREMARKS: 28024642e01fSmrgCPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output 28034642e01fSmrg****************************************************************************/ 2804f7df2e56Smrgvoid 2805f7df2e56Smrgcpuid(void) 28064642e01fSmrg{ 28074642e01fSmrg u32 feature = M.x86.R_EAX; 28084642e01fSmrg 28094642e01fSmrg#ifdef X86EMU_HAS_HW_CPUID 28104642e01fSmrg /* If the platform allows it, we will base our values on the real 28114642e01fSmrg * results from the CPUID instruction. We limit support to the 28124642e01fSmrg * first two features, and the results of those are sanitized. 28134642e01fSmrg */ 28144642e01fSmrg if (feature <= 1) 2815f7df2e56Smrg hw_cpuid(&M.x86.R_EAX, &M.x86.R_EBX, &M.x86.R_ECX, &M.x86.R_EDX); 28164642e01fSmrg#endif 28174642e01fSmrg 28184642e01fSmrg switch (feature) { 28194642e01fSmrg case 0: 28204642e01fSmrg /* Regardless if we have real data from the hardware, the emulator 28215a112b11Smrg * will only support up to feature 1, which we set in register EAX. 2822f7df2e56Smrg * Registers EBX:EDX:ECX contain a string identifying the CPU. 2823f7df2e56Smrg */ 28244642e01fSmrg M.x86.R_EAX = 1; 28254642e01fSmrg#ifndef X86EMU_HAS_HW_CPUID 28264642e01fSmrg /* EBX:EDX:ECX = "GenuineIntel" */ 28274642e01fSmrg M.x86.R_EBX = 0x756e6547; 28284642e01fSmrg M.x86.R_EDX = 0x49656e69; 28294642e01fSmrg M.x86.R_ECX = 0x6c65746e; 28304642e01fSmrg#endif 28314642e01fSmrg break; 28324642e01fSmrg case 1: 28334642e01fSmrg#ifndef X86EMU_HAS_HW_CPUID 28344642e01fSmrg /* If we don't have x86 compatible hardware, we return values from an 2835f7df2e56Smrg * Intel 486dx4; which was one of the first processors to have CPUID. 2836f7df2e56Smrg */ 28374642e01fSmrg M.x86.R_EAX = 0x00000480; 28384642e01fSmrg M.x86.R_EBX = 0x00000000; 28394642e01fSmrg M.x86.R_ECX = 0x00000000; 2840f7df2e56Smrg M.x86.R_EDX = 0x00000002; /* VME */ 28414642e01fSmrg#else 28424642e01fSmrg /* In the case that we have hardware CPUID instruction, we make sure 2843f7df2e56Smrg * that the features reported are limited to TSC and VME. 2844f7df2e56Smrg */ 28454642e01fSmrg M.x86.R_EDX &= 0x00000012; 28464642e01fSmrg#endif 28474642e01fSmrg break; 28484642e01fSmrg default: 28494642e01fSmrg /* Finally, we don't support any additional features. Most CPUs 2850f7df2e56Smrg * return all zeros when queried for invalid or unsupported feature 2851f7df2e56Smrg * numbers. 2852f7df2e56Smrg */ 28534642e01fSmrg M.x86.R_EAX = 0; 28544642e01fSmrg M.x86.R_EBX = 0; 28554642e01fSmrg M.x86.R_ECX = 0; 28564642e01fSmrg M.x86.R_EDX = 0; 28574642e01fSmrg break; 28584642e01fSmrg } 28594642e01fSmrg} 2860