aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-01-31 18:54:23 +0000
committermarha <marha@users.sourceforge.net>2010-01-31 18:54:23 +0000
commit62d24022ec725850c6635118b5cd372ae47d63d9 (patch)
tree1393d83c103303ade89e34444c1bf4fdf81b7d5f /xorg-server/hw/xfree86
parentfe6927d79e02d01cce20ecf56c8721fcadc2d278 (diff)
parent007385f704a99ab49dab0789f9c330a1a3a455be (diff)
downloadvcxsrv-62d24022ec725850c6635118b5cd372ae47d63d9.tar.gz
vcxsrv-62d24022ec725850c6635118b5cd372ae47d63d9.tar.bz2
vcxsrv-62d24022ec725850c6635118b5cd372ae47d63d9.zip
svn merge ^/branches/released
Diffstat (limited to 'xorg-server/hw/xfree86')
-rw-r--r--xorg-server/hw/xfree86/common/xf86Events.c1487
-rw-r--r--xorg-server/hw/xfree86/common/xf86VGAarbiter.c2291
-rw-r--r--xorg-server/hw/xfree86/common/xf86cmap.c2335
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.c1826
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.h527
-rw-r--r--xorg-server/hw/xfree86/modes/xf86Crtc.c6396
-rw-r--r--xorg-server/hw/xfree86/os-support/bsd/bsd_VTsw.c197
-rw-r--r--xorg-server/hw/xfree86/os-support/sco/VTsw_sco.c244
-rw-r--r--xorg-server/hw/xfree86/os-support/shared/VTsw_noop.c114
-rw-r--r--xorg-server/hw/xfree86/os-support/shared/VTsw_usl.c191
-rw-r--r--xorg-server/hw/xfree86/os-support/solaris/sun_VTsw.c241
-rw-r--r--xorg-server/hw/xfree86/os-support/solaris/sun_init.c727
-rw-r--r--xorg-server/hw/xfree86/os-support/xf86_OSproc.h439
-rw-r--r--xorg-server/hw/xfree86/x86emu/ops.c23414
14 files changed, 20255 insertions, 20174 deletions
diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c
index 8cd765a1c..ee4835233 100644
--- a/xorg-server/hw/xfree86/common/xf86Events.c
+++ b/xorg-server/hw/xfree86/common/xf86Events.c
@@ -1,747 +1,740 @@
-/*
- * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Thomas Roell not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Thomas Roell makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-/*
- * Copyright (c) 1994-2003 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-/* [JCH-96/01/21] Extended std reverse map to four buttons. */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xpoll.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "compiler.h"
-#include "xf86.h"
-#include "xf86Priv.h"
-#define XF86_OS_PRIVS
-#include "xf86_OSlib.h"
-#include <X11/keysym.h>
-
-#ifdef XFreeXDGA
-#include "dgaproc.h"
-#endif
-
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "inputstr.h"
-#include "xf86Xinput.h"
-
-#include "mi.h"
-#include "mipointer.h"
-
-#include "xkbsrv.h"
-#include "xkbstr.h"
-
-#ifdef DPMSExtension
-#include <X11/extensions/dpmsconst.h>
-#include "dpmsproc.h"
-#endif
-
-/*
- * This is a toggling variable:
- * FALSE = No VT switching keys have been pressed last time around
- * TRUE = Possible VT switch Pending
- * (DWH - 12/2/93)
- *
- * This has been generalised to work with Linux and *BSD+syscons (DHD)
- */
-
-Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for
- *BSD and for avoiding VT
- switches when using the DRI
- automatic full screen mode.*/
-
-extern fd_set EnabledDevices;
-
-#ifdef XF86PM
-extern void (*xf86OSPMClose)(void);
-#endif
-
-static void xf86VTSwitch(void);
-
-/*
- * Allow arbitrary drivers or other XFree86 code to register with our main
- * Wakeup handler.
- */
-typedef struct x_IHRec {
- int fd;
- InputHandlerProc ihproc;
- pointer data;
- Bool enabled;
- struct x_IHRec * next;
-} IHRec, *IHPtr;
-
-static IHPtr InputHandlers = NULL;
-
-
-Bool
-LegalModifier(unsigned int key, DeviceIntPtr pDev)
-{
- return TRUE;
-}
-
-/*
- * TimeSinceLastInputEvent --
- * Function used for screensaver purposes by the os module. Returns the
- * time in milliseconds since there last was any input.
- */
-int
-TimeSinceLastInputEvent(void)
-{
- if (xf86Info.lastEventTime == 0) {
- xf86Info.lastEventTime = GetTimeInMillis();
- }
- return GetTimeInMillis() - xf86Info.lastEventTime;
-}
-
-/*
- * SetTimeSinceLastInputEvent --
- * Set the lastEventTime to now.
- */
-void
-SetTimeSinceLastInputEvent(void)
-{
- xf86Info.lastEventTime = GetTimeInMillis();
-}
-
-/*
- * ProcessInputEvents --
- * Retrieve all waiting input events and pass them to DIX in their
- * correct chronological order. Only reads from the system pointer
- * and keyboard.
- */
-void
-ProcessInputEvents (void)
-{
- int x, y;
-
- mieqProcessInputEvents();
-
- /* FIXME: This is a problem if we have multiple pointers */
- miPointerGetPosition(inputInfo.pointer, &x, &y);
- xf86SetViewport(xf86Info.currentScreen, x, y);
-}
-
-/*
- * Handle keyboard events that cause some kind of "action"
- * (i.e., server termination, video mode changes, VT switches, etc.)
- */
-void
-xf86ProcessActionEvent(ActionEvent action, void *arg)
-{
- DebugF("ProcessActionEvent(%d,%x)\n", (int) action, arg);
- switch (action) {
- case ACTION_TERMINATE:
- if (!xf86Info.dontZap) {
-#ifdef XFreeXDGA
- DGAShutdown();
-#endif
- GiveUp(0);
- }
- break;
- case ACTION_NEXT_MODE:
- if (!xf86Info.dontZoom)
- xf86ZoomViewport(xf86Info.currentScreen, 1);
- break;
- case ACTION_PREV_MODE:
- if (!xf86Info.dontZoom)
- xf86ZoomViewport(xf86Info.currentScreen, -1);
- break;
-#if defined(VT_ACTIVATE)
- case ACTION_SWITCHSCREEN:
- if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) {
- int vtno = *((int *) arg);
-#if defined(__SCO__) || defined(__UNIXWARE__)
- vtno--;
-#endif
-#if defined(sun)
- if (vtno == xf86Info.vtno)
- break;
-
- xf86Info.vtRequestsPending = TRUE;
- xf86Info.vtPendingNum = vtno;
-#else
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vtno) < 0)
- ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
-#endif
- }
- break;
- case ACTION_SWITCHSCREEN_NEXT:
- if (VTSwitchEnabled && !xf86Info.dontVTSwitch) {
-#if defined(__SCO__) || defined(__UNIXWARE__)
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) < 0)
-#else
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1) < 0)
-#endif
-#if defined (__SCO__) || (defined(sun) && defined (__i386__) && defined (SVR4)) || defined(__UNIXWARE__)
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0)
-#else
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) < 0)
-#endif
- ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
- }
- break;
- case ACTION_SWITCHSCREEN_PREV:
- if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) {
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno - 1) < 0)
- ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
- }
- break;
-#endif
- default:
- break;
- }
-}
-
-/*
- * xf86Wakeup --
- * Os wakeup handler.
- */
-
-/* ARGSUSED */
-void
-xf86Wakeup(pointer blockData, int err, pointer pReadmask)
-{
- fd_set* LastSelectMask = (fd_set*)pReadmask;
- fd_set devicesWithInput;
- InputInfoPtr pInfo;
-
- if (err >= 0) {
-
- XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices);
- if (XFD_ANYSET(&devicesWithInput)) {
- pInfo = xf86InputDevs;
- while (pInfo) {
- if (pInfo->read_input && pInfo->fd >= 0 &&
- (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) {
- int sigstate = xf86BlockSIGIO();
-
- /*
- * Remove the descriptior from the set because more than one
- * device may share the same file descriptor.
- */
- FD_CLR(pInfo->fd, &devicesWithInput);
-
- pInfo->read_input(pInfo);
- xf86UnblockSIGIO(sigstate);
- }
- pInfo = pInfo->next;
- }
- }
- }
-
- if (err >= 0) { /* we don't want the handlers called if select() */
- IHPtr ih; /* returned with an error condition, do we? */
-
- for (ih = InputHandlers; ih; ih = ih->next) {
- if (ih->enabled && ih->fd >= 0 && ih->ihproc &&
- (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) {
- ih->ihproc(ih->fd, ih->data);
- }
- }
- }
-
- if (xf86VTSwitchPending()) xf86VTSwitch();
-}
-
-
-/*
- * xf86SigioReadInput --
- * signal handler for the SIGIO signal.
- */
-static void
-xf86SigioReadInput(int fd, void *closure)
-{
- int errno_save = errno;
- InputInfoPtr pInfo = closure;
-
- pInfo->read_input(pInfo);
-
- errno = errno_save;
-}
-
-/*
- * xf86AddEnabledDevice --
- *
- */
-void
-xf86AddEnabledDevice(InputInfoPtr pInfo)
-{
- if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) {
- AddEnabledDevice(pInfo->fd);
- }
-}
-
-/*
- * xf86RemoveEnabledDevice --
- *
- */
-void
-xf86RemoveEnabledDevice(InputInfoPtr pInfo)
-{
- if (!xf86RemoveSIGIOHandler (pInfo->fd)) {
- RemoveEnabledDevice(pInfo->fd);
- }
-}
-
-static int *xf86SignalIntercept = NULL;
-
-void
-xf86InterceptSignals(int *signo)
-{
- if ((xf86SignalIntercept = signo))
- *signo = -1;
-}
-
-static void (*xf86SigIllHandler)(void) = NULL;
-
-void
-xf86InterceptSigIll(void (*sigillhandler)(void))
-{
- xf86SigIllHandler = sigillhandler;
-}
-
-/*
- * xf86SigWrapper --
- * Catch unexpected signals and exit or continue cleanly.
- */
-int
-xf86SigWrapper(int signo)
-{
- if ((signo == SIGILL) && xf86SigIllHandler) {
- (*xf86SigIllHandler)();
- return 0; /* continue */
- }
-
- if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) {
- *xf86SignalIntercept = signo;
- return 0; /* continue */
- }
-
- xf86Info.caughtSignal = TRUE;
- return 1; /* abort */
-}
-
-/*
- * xf86PrintBacktrace --
- * Print a stack backtrace for debugging purposes.
- */
-void
-xf86PrintBacktrace(void)
-{
- xorg_backtrace();
-}
-
-#define KeyPressed(k) (keyc->postdown[k >> 3] & (1 << (k & 7)))
-
-static void
-xf86ReleaseKeys(DeviceIntPtr pDev)
-{
- KeyClassPtr keyc;
- int i, j, nevents, sigstate;
-
- if (!pDev || !pDev->key)
- return;
-
- keyc = pDev->key;
-
- /*
- * Hmm... here is the biggest hack of every time !
- * It may be possible that a switch-vt procedure has finished BEFORE
- * you released all keys neccessary to do this. That peculiar behavior
- * can fool the X-server pretty much, cause it assumes that some keys
- * were not released. TWM may stuck alsmost completly....
- * OK, what we are doing here is after returning from the vt-switch
- * exeplicitely unrelease all keyboard keys before the input-devices
- * are reenabled.
- */
-
- for (i = keyc->xkbInfo->desc->min_key_code;
- i < keyc->xkbInfo->desc->max_key_code;
- i++) {
- if (KeyPressed(i)) {
- sigstate = xf86BlockSIGIO ();
- nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i);
- for (j = 0; j < nevents; j++)
- mieqEnqueue(pDev, (InternalEvent*)(xf86Events + j)->event);
- xf86UnblockSIGIO(sigstate);
- }
- }
-}
-
-/*
- * xf86VTSwitch --
- * Handle requests for switching the vt.
- */
-static void
-xf86VTSwitch(void)
-{
- int i, prevSIGIO;
- InputInfoPtr pInfo;
- IHPtr ih;
-
- DebugF("xf86VTSwitch()\n");
-
-#ifdef XFreeXDGA
- if(!DGAVTSwitch())
- return;
-#endif
-
- /*
- * Since all screens are currently all in the same state it is sufficient
- * check the first. This might change in future.
- */
- if (xf86Screens[0]->vtSema) {
-
- DebugF("xf86VTSwitch: Leaving, xf86Exiting is %s\n",
- BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE));
-#ifdef DPMSExtension
- if (DPMSPowerLevel != DPMSModeOn)
- DPMSSet(serverClient, DPMSModeOn);
-#endif
- for (i = 0; i < xf86NumScreens; i++) {
- if (!(dispatchException & DE_TERMINATE))
- if (xf86Screens[i]->EnableDisableFBAccess)
- (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE);
- }
-
- /*
- * Keep the order: Disable Device > LeaveVT
- * EnterVT > EnableDevice
- */
- for (ih = InputHandlers; ih; ih = ih->next)
- xf86DisableInputHandler(ih);
- for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) {
- if (pInfo->dev) {
- xf86ReleaseKeys(pInfo->dev);
- ProcessInputEvents();
- DisableDevice(pInfo->dev, TRUE);
- }
- }
- xf86EnterServerState(SETUP);
- for (i = 0; i < xf86NumScreens; i++)
- xf86Screens[i]->LeaveVT(i, 0);
-
- xf86AccessLeave(); /* We need this here, otherwise */
-
- if (!xf86VTSwitchAway()) {
- /*
- * switch failed
- */
-
- DebugF("xf86VTSwitch: Leave failed\n");
- prevSIGIO = xf86BlockSIGIO();
- xf86AccessEnter();
- xf86EnterServerState(SETUP);
- for (i = 0; i < xf86NumScreens; i++) {
- if (!xf86Screens[i]->EnterVT(i, 0))
- FatalError("EnterVT failed for screen %d\n", i);
- }
- xf86EnterServerState(OPERATING);
- if (!(dispatchException & DE_TERMINATE)) {
- for (i = 0; i < xf86NumScreens; i++) {
- if (xf86Screens[i]->EnableDisableFBAccess)
- (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE);
- }
- }
- dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
-
- pInfo = xf86InputDevs;
- while (pInfo) {
- if (pInfo->dev)
- EnableDevice(pInfo->dev, TRUE);
- pInfo = pInfo->next;
- }
- for (ih = InputHandlers; ih; ih = ih->next)
- xf86EnableInputHandler(ih);
-
- xf86UnblockSIGIO(prevSIGIO);
-
- } else {
-#ifdef XF86PM
- if (xf86OSPMClose)
- xf86OSPMClose();
- xf86OSPMClose = NULL;
-#endif
-
- for (i = 0; i < xf86NumScreens; i++) {
- /*
- * zero all access functions to
- * trap calls when switched away.
- */
- xf86Screens[i]->vtSema = FALSE;
- }
- if (xorgHWAccess)
- xf86DisableIO();
- }
- } else {
-
- DebugF("xf86VTSwitch: Entering\n");
- if (!xf86VTSwitchTo()) return;
-
- prevSIGIO = xf86BlockSIGIO();
-#ifdef XF86PM
- xf86OSPMClose = xf86OSPMOpen();
-#endif
-
- if (xorgHWAccess)
- xf86EnableIO();
- xf86AccessEnter();
- xf86EnterServerState(SETUP);
- for (i = 0; i < xf86NumScreens; i++) {
- xf86Screens[i]->vtSema = TRUE;
- if (!xf86Screens[i]->EnterVT(i, 0))
- FatalError("EnterVT failed for screen %d\n", i);
- }
- xf86EnterServerState(OPERATING);
- for (i = 0; i < xf86NumScreens; i++) {
- if (xf86Screens[i]->EnableDisableFBAccess)
- (*xf86Screens[i]->EnableDisableFBAccess)(i, TRUE);
- }
-
- /* Turn screen saver off when switching back */
- dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
-
- pInfo = xf86InputDevs;
- while (pInfo) {
- if (pInfo->dev)
- EnableDevice(pInfo->dev, TRUE);
- pInfo = pInfo->next;
- }
-
- for (ih = InputHandlers; ih; ih = ih->next)
- xf86EnableInputHandler(ih);
-
- xf86UnblockSIGIO(prevSIGIO);
- }
-}
-
-
-/* Input handler registration */
-
-static pointer
-addInputHandler(int fd, InputHandlerProc proc, pointer data)
-{
- IHPtr ih;
-
- if (fd < 0 || !proc)
- return NULL;
-
- ih = xcalloc(sizeof(*ih), 1);
- if (!ih)
- return NULL;
-
- ih->fd = fd;
- ih->ihproc = proc;
- ih->data = data;
- ih->enabled = TRUE;
-
- ih->next = InputHandlers;
- InputHandlers = ih;
-
- return ih;
-}
-
-pointer
-xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data)
-{
- IHPtr ih = addInputHandler(fd, proc, data);
-
- if (ih)
- AddEnabledDevice(fd);
- return ih;
-}
-
-pointer
-xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data)
-{
- IHPtr ih = addInputHandler(fd, proc, data);
-
- if (ih)
- AddGeneralSocket(fd);
- return ih;
-}
-
-static void
-removeInputHandler(IHPtr ih)
-{
- IHPtr p;
-
- if (ih == InputHandlers)
- InputHandlers = ih->next;
- else {
- p = InputHandlers;
- while (p && p->next != ih)
- p = p->next;
- if (ih)
- p->next = ih->next;
- }
- xfree(ih);
-}
-
-int
-xf86RemoveInputHandler(pointer handler)
-{
- IHPtr ih;
- int fd;
-
- if (!handler)
- return -1;
-
- ih = handler;
- fd = ih->fd;
-
- if (ih->fd >= 0)
- RemoveEnabledDevice(ih->fd);
- removeInputHandler(ih);
-
- return fd;
-}
-
-int
-xf86RemoveGeneralHandler(pointer handler)
-{
- IHPtr ih;
- int fd;
-
- if (!handler)
- return -1;
-
- ih = handler;
- fd = ih->fd;
-
- if (ih->fd >= 0)
- RemoveGeneralSocket(ih->fd);
- removeInputHandler(ih);
-
- return fd;
-}
-
-void
-xf86DisableInputHandler(pointer handler)
-{
- IHPtr ih;
-
- if (!handler)
- return;
-
- ih = handler;
- ih->enabled = FALSE;
- if (ih->fd >= 0)
- RemoveEnabledDevice(ih->fd);
-}
-
-void
-xf86DisableGeneralHandler(pointer handler)
-{
- IHPtr ih;
-
- if (!handler)
- return;
-
- ih = handler;
- ih->enabled = FALSE;
- if (ih->fd >= 0)
- RemoveGeneralSocket(ih->fd);
-}
-
-void
-xf86EnableInputHandler(pointer handler)
-{
- IHPtr ih;
-
- if (!handler)
- return;
-
- ih = handler;
- ih->enabled = TRUE;
- if (ih->fd >= 0)
- AddEnabledDevice(ih->fd);
-}
-
-void
-xf86EnableGeneralHandler(pointer handler)
-{
- IHPtr ih;
-
- if (!handler)
- return;
-
- ih = handler;
- ih->enabled = TRUE;
- if (ih->fd >= 0)
- AddGeneralSocket(ih->fd);
-}
-
-/*
- * As used currently by the DRI, the return value is ignored.
- */
-Bool
-xf86EnableVTSwitch(Bool new)
-{
- static Bool def = TRUE;
- Bool old;
-
- old = VTSwitchEnabled;
- if (!new) {
- /* Disable VT switching */
- def = VTSwitchEnabled;
- VTSwitchEnabled = FALSE;
- } else {
- /* Restore VT switching to default */
- VTSwitchEnabled = def;
- }
- return old;
-}
-
-void
-DDXRingBell(int volume, int pitch, int duration) {
- xf86OSRingBell(volume, pitch, duration);
-}
+/*
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Thomas Roell not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Thomas Roell makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * Copyright (c) 1994-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+/* [JCH-96/01/21] Extended std reverse map to four buttons. */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xpoll.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "compiler.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#define XF86_OS_PRIVS
+#include "xf86_OSlib.h"
+#include <X11/keysym.h>
+
+#ifdef XFreeXDGA
+#include "dgaproc.h"
+#endif
+
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "inputstr.h"
+#include "xf86Xinput.h"
+
+#include "mi.h"
+#include "mipointer.h"
+
+#include "xkbsrv.h"
+#include "xkbstr.h"
+
+#ifdef DPMSExtension
+#include <X11/extensions/dpmsconst.h>
+#include "dpmsproc.h"
+#endif
+
+/*
+ * This is a toggling variable:
+ * FALSE = No VT switching keys have been pressed last time around
+ * TRUE = Possible VT switch Pending
+ * (DWH - 12/2/93)
+ *
+ * This has been generalised to work with Linux and *BSD+syscons (DHD)
+ */
+
+Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for
+ *BSD and for avoiding VT
+ switches when using the DRI
+ automatic full screen mode.*/
+
+extern fd_set EnabledDevices;
+
+#ifdef XF86PM
+extern void (*xf86OSPMClose)(void);
+#endif
+
+static void xf86VTSwitch(void);
+
+/*
+ * Allow arbitrary drivers or other XFree86 code to register with our main
+ * Wakeup handler.
+ */
+typedef struct x_IHRec {
+ int fd;
+ InputHandlerProc ihproc;
+ pointer data;
+ Bool enabled;
+ struct x_IHRec * next;
+} IHRec, *IHPtr;
+
+static IHPtr InputHandlers = NULL;
+
+
+Bool
+LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+ return TRUE;
+}
+
+/*
+ * TimeSinceLastInputEvent --
+ * Function used for screensaver purposes by the os module. Returns the
+ * time in milliseconds since there last was any input.
+ */
+int
+TimeSinceLastInputEvent(void)
+{
+ if (xf86Info.lastEventTime == 0) {
+ xf86Info.lastEventTime = GetTimeInMillis();
+ }
+ return GetTimeInMillis() - xf86Info.lastEventTime;
+}
+
+/*
+ * SetTimeSinceLastInputEvent --
+ * Set the lastEventTime to now.
+ */
+void
+SetTimeSinceLastInputEvent(void)
+{
+ xf86Info.lastEventTime = GetTimeInMillis();
+}
+
+/*
+ * ProcessInputEvents --
+ * Retrieve all waiting input events and pass them to DIX in their
+ * correct chronological order. Only reads from the system pointer
+ * and keyboard.
+ */
+void
+ProcessInputEvents (void)
+{
+ int x, y;
+
+ mieqProcessInputEvents();
+
+ /* FIXME: This is a problem if we have multiple pointers */
+ miPointerGetPosition(inputInfo.pointer, &x, &y);
+ xf86SetViewport(xf86Info.currentScreen, x, y);
+}
+
+/*
+ * Handle keyboard events that cause some kind of "action"
+ * (i.e., server termination, video mode changes, VT switches, etc.)
+ */
+void
+xf86ProcessActionEvent(ActionEvent action, void *arg)
+{
+ DebugF("ProcessActionEvent(%d,%x)\n", (int) action, arg);
+ switch (action) {
+ case ACTION_TERMINATE:
+ if (!xf86Info.dontZap) {
+#ifdef XFreeXDGA
+ DGAShutdown();
+#endif
+ GiveUp(0);
+ }
+ break;
+ case ACTION_NEXT_MODE:
+ if (!xf86Info.dontZoom)
+ xf86ZoomViewport(xf86Info.currentScreen, 1);
+ break;
+ case ACTION_PREV_MODE:
+ if (!xf86Info.dontZoom)
+ xf86ZoomViewport(xf86Info.currentScreen, -1);
+ break;
+ case ACTION_SWITCHSCREEN:
+ if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) {
+ int vtno = *((int *) arg);
+
+ if (vtno != xf86Info.vtno) {
+ if (!xf86VTActivate(vtno)) {
+ ErrorF("Failed to switch from vt%02d to vt%02d: %s\n",
+ xf86Info.vtno, vtno, strerror(errno));
+ }
+ }
+ }
+ break;
+ case ACTION_SWITCHSCREEN_NEXT:
+ if (VTSwitchEnabled && !xf86Info.dontVTSwitch) {
+ if (!xf86VTActivate(xf86Info.vtno + 1)) {
+ /* If first try failed, assume this is the last VT and
+ * try wrapping around to the first vt.
+ */
+ if (!xf86VTActivate(1)) {
+ ErrorF("Failed to switch from vt%02d to next vt: %s\n",
+ xf86Info.vtno, strerror(errno));
+ }
+ }
+ }
+ break;
+ case ACTION_SWITCHSCREEN_PREV:
+ if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) {
+ if (!xf86VTActivate(xf86Info.vtno - 1)) {
+ /* Don't know what the maximum VT is, so can't wrap around */
+ ErrorF("Failed to switch from vt%02d to previous vt: %s\n",
+ xf86Info.vtno, strerror(errno));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * xf86Wakeup --
+ * Os wakeup handler.
+ */
+
+/* ARGSUSED */
+void
+xf86Wakeup(pointer blockData, int err, pointer pReadmask)
+{
+ fd_set* LastSelectMask = (fd_set*)pReadmask;
+ fd_set devicesWithInput;
+ InputInfoPtr pInfo;
+
+ if (err >= 0) {
+
+ XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices);
+ if (XFD_ANYSET(&devicesWithInput)) {
+ pInfo = xf86InputDevs;
+ while (pInfo) {
+ if (pInfo->read_input && pInfo->fd >= 0 &&
+ (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) {
+ int sigstate = xf86BlockSIGIO();
+
+ /*
+ * Remove the descriptior from the set because more than one
+ * device may share the same file descriptor.
+ */
+ FD_CLR(pInfo->fd, &devicesWithInput);
+
+ pInfo->read_input(pInfo);
+ xf86UnblockSIGIO(sigstate);
+ }
+ pInfo = pInfo->next;
+ }
+ }
+ }
+
+ if (err >= 0) { /* we don't want the handlers called if select() */
+ IHPtr ih; /* returned with an error condition, do we? */
+
+ for (ih = InputHandlers; ih; ih = ih->next) {
+ if (ih->enabled && ih->fd >= 0 && ih->ihproc &&
+ (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) {
+ ih->ihproc(ih->fd, ih->data);
+ }
+ }
+ }
+
+ if (xf86VTSwitchPending()) xf86VTSwitch();
+}
+
+
+/*
+ * xf86SigioReadInput --
+ * signal handler for the SIGIO signal.
+ */
+static void
+xf86SigioReadInput(int fd, void *closure)
+{
+ int errno_save = errno;
+ InputInfoPtr pInfo = closure;
+
+ pInfo->read_input(pInfo);
+
+ errno = errno_save;
+}
+
+/*
+ * xf86AddEnabledDevice --
+ *
+ */
+void
+xf86AddEnabledDevice(InputInfoPtr pInfo)
+{
+ if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) {
+ AddEnabledDevice(pInfo->fd);
+ }
+}
+
+/*
+ * xf86RemoveEnabledDevice --
+ *
+ */
+void
+xf86RemoveEnabledDevice(InputInfoPtr pInfo)
+{
+ if (!xf86RemoveSIGIOHandler (pInfo->fd)) {
+ RemoveEnabledDevice(pInfo->fd);
+ }
+}
+
+static int *xf86SignalIntercept = NULL;
+
+void
+xf86InterceptSignals(int *signo)
+{
+ if ((xf86SignalIntercept = signo))
+ *signo = -1;
+}
+
+static void (*xf86SigIllHandler)(void) = NULL;
+
+void
+xf86InterceptSigIll(void (*sigillhandler)(void))
+{
+ xf86SigIllHandler = sigillhandler;
+}
+
+/*
+ * xf86SigWrapper --
+ * Catch unexpected signals and exit or continue cleanly.
+ */
+int
+xf86SigWrapper(int signo)
+{
+ if ((signo == SIGILL) && xf86SigIllHandler) {
+ (*xf86SigIllHandler)();
+ return 0; /* continue */
+ }
+
+ if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) {
+ *xf86SignalIntercept = signo;
+ return 0; /* continue */
+ }
+
+ xf86Info.caughtSignal = TRUE;
+ return 1; /* abort */
+}
+
+/*
+ * xf86PrintBacktrace --
+ * Print a stack backtrace for debugging purposes.
+ */
+void
+xf86PrintBacktrace(void)
+{
+ xorg_backtrace();
+}
+
+#define KeyPressed(k) (keyc->postdown[k >> 3] & (1 << (k & 7)))
+
+static void
+xf86ReleaseKeys(DeviceIntPtr pDev)
+{
+ KeyClassPtr keyc;
+ int i, j, nevents, sigstate;
+
+ if (!pDev || !pDev->key)
+ return;
+
+ keyc = pDev->key;
+
+ /*
+ * Hmm... here is the biggest hack of every time !
+ * It may be possible that a switch-vt procedure has finished BEFORE
+ * you released all keys neccessary to do this. That peculiar behavior
+ * can fool the X-server pretty much, cause it assumes that some keys
+ * were not released. TWM may stuck alsmost completly....
+ * OK, what we are doing here is after returning from the vt-switch
+ * exeplicitely unrelease all keyboard keys before the input-devices
+ * are reenabled.
+ */
+
+ for (i = keyc->xkbInfo->desc->min_key_code;
+ i < keyc->xkbInfo->desc->max_key_code;
+ i++) {
+ if (KeyPressed(i)) {
+ sigstate = xf86BlockSIGIO ();
+ nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i);
+ for (j = 0; j < nevents; j++)
+ mieqEnqueue(pDev, (InternalEvent*)(xf86Events + j)->event);
+ xf86UnblockSIGIO(sigstate);
+ }
+ }
+}
+
+/*
+ * xf86VTSwitch --
+ * Handle requests for switching the vt.
+ */
+static void
+xf86VTSwitch(void)
+{
+ int i, prevSIGIO;
+ InputInfoPtr pInfo;
+ IHPtr ih;
+
+ DebugF("xf86VTSwitch()\n");
+
+#ifdef XFreeXDGA
+ if(!DGAVTSwitch())
+ return;
+#endif
+
+ /*
+ * Since all screens are currently all in the same state it is sufficient
+ * check the first. This might change in future.
+ */
+ if (xf86Screens[0]->vtSema) {
+
+ DebugF("xf86VTSwitch: Leaving, xf86Exiting is %s\n",
+ BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE));
+#ifdef DPMSExtension
+ if (DPMSPowerLevel != DPMSModeOn)
+ DPMSSet(serverClient, DPMSModeOn);
+#endif
+ for (i = 0; i < xf86NumScreens; i++) {
+ if (!(dispatchException & DE_TERMINATE))
+ if (xf86Screens[i]->EnableDisableFBAccess)
+ (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE);
+ }
+
+ /*
+ * Keep the order: Disable Device > LeaveVT
+ * EnterVT > EnableDevice
+ */
+ for (ih = InputHandlers; ih; ih = ih->next)
+ xf86DisableInputHandler(ih);
+ for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) {
+ if (pInfo->dev) {
+ xf86ReleaseKeys(pInfo->dev);
+ ProcessInputEvents();
+ DisableDevice(pInfo->dev, TRUE);
+ }
+ }
+ xf86EnterServerState(SETUP);
+ for (i = 0; i < xf86NumScreens; i++)
+ xf86Screens[i]->LeaveVT(i, 0);
+
+ xf86AccessLeave(); /* We need this here, otherwise */
+
+ if (!xf86VTSwitchAway()) {
+ /*
+ * switch failed
+ */
+
+ DebugF("xf86VTSwitch: Leave failed\n");
+ prevSIGIO = xf86BlockSIGIO();
+ xf86AccessEnter();
+ xf86EnterServerState(SETUP);
+ for (i = 0; i < xf86NumScreens; i++) {
+ if (!xf86Screens[i]->EnterVT(i, 0))
+ FatalError("EnterVT failed for screen %d\n", i);
+ }
+ xf86EnterServerState(OPERATING);
+ if (!(dispatchException & DE_TERMINATE)) {
+ for (i = 0; i < xf86NumScreens; i++) {
+ if (xf86Screens[i]->EnableDisableFBAccess)
+ (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE);
+ }
+ }
+ dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
+
+ pInfo = xf86InputDevs;
+ while (pInfo) {
+ if (pInfo->dev)
+ EnableDevice(pInfo->dev, TRUE);
+ pInfo = pInfo->next;
+ }
+ for (ih = InputHandlers; ih; ih = ih->next)
+ xf86EnableInputHandler(ih);
+
+ xf86UnblockSIGIO(prevSIGIO);
+
+ } else {
+#ifdef XF86PM
+ if (xf86OSPMClose)
+ xf86OSPMClose();
+ xf86OSPMClose = NULL;
+#endif
+
+ for (i = 0; i < xf86NumScreens; i++) {
+ /*
+ * zero all access functions to
+ * trap calls when switched away.
+ */
+ xf86Screens[i]->vtSema = FALSE;
+ }
+ if (xorgHWAccess)
+ xf86DisableIO();
+ }
+ } else {
+
+ DebugF("xf86VTSwitch: Entering\n");
+ if (!xf86VTSwitchTo()) return;
+
+ prevSIGIO = xf86BlockSIGIO();
+#ifdef XF86PM
+ xf86OSPMClose = xf86OSPMOpen();
+#endif
+
+ if (xorgHWAccess)
+ xf86EnableIO();
+ xf86AccessEnter();
+ xf86EnterServerState(SETUP);
+ for (i = 0; i < xf86NumScreens; i++) {
+ xf86Screens[i]->vtSema = TRUE;
+ if (!xf86Screens[i]->EnterVT(i, 0))
+ FatalError("EnterVT failed for screen %d\n", i);
+ }
+ xf86EnterServerState(OPERATING);
+ for (i = 0; i < xf86NumScreens; i++) {
+ if (xf86Screens[i]->EnableDisableFBAccess)
+ (*xf86Screens[i]->EnableDisableFBAccess)(i, TRUE);
+ }
+
+ /* Turn screen saver off when switching back */
+ dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
+
+ pInfo = xf86InputDevs;
+ while (pInfo) {
+ if (pInfo->dev)
+ EnableDevice(pInfo->dev, TRUE);
+ pInfo = pInfo->next;
+ }
+
+ for (ih = InputHandlers; ih; ih = ih->next)
+ xf86EnableInputHandler(ih);
+
+ xf86UnblockSIGIO(prevSIGIO);
+ }
+}
+
+
+/* Input handler registration */
+
+static pointer
+addInputHandler(int fd, InputHandlerProc proc, pointer data)
+{
+ IHPtr ih;
+
+ if (fd < 0 || !proc)
+ return NULL;
+
+ ih = xcalloc(sizeof(*ih), 1);
+ if (!ih)
+ return NULL;
+
+ ih->fd = fd;
+ ih->ihproc = proc;
+ ih->data = data;
+ ih->enabled = TRUE;
+
+ ih->next = InputHandlers;
+ InputHandlers = ih;
+
+ return ih;
+}
+
+pointer
+xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data)
+{
+ IHPtr ih = addInputHandler(fd, proc, data);
+
+ if (ih)
+ AddEnabledDevice(fd);
+ return ih;
+}
+
+pointer
+xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data)
+{
+ IHPtr ih = addInputHandler(fd, proc, data);
+
+ if (ih)
+ AddGeneralSocket(fd);
+ return ih;
+}
+
+static void
+removeInputHandler(IHPtr ih)
+{
+ IHPtr p;
+
+ if (ih == InputHandlers)
+ InputHandlers = ih->next;
+ else {
+ p = InputHandlers;
+ while (p && p->next != ih)
+ p = p->next;
+ if (ih)
+ p->next = ih->next;
+ }
+ xfree(ih);
+}
+
+int
+xf86RemoveInputHandler(pointer handler)
+{
+ IHPtr ih;
+ int fd;
+
+ if (!handler)
+ return -1;
+
+ ih = handler;
+ fd = ih->fd;
+
+ if (ih->fd >= 0)
+ RemoveEnabledDevice(ih->fd);
+ removeInputHandler(ih);
+
+ return fd;
+}
+
+int
+xf86RemoveGeneralHandler(pointer handler)
+{
+ IHPtr ih;
+ int fd;
+
+ if (!handler)
+ return -1;
+
+ ih = handler;
+ fd = ih->fd;
+
+ if (ih->fd >= 0)
+ RemoveGeneralSocket(ih->fd);
+ removeInputHandler(ih);
+
+ return fd;
+}
+
+void
+xf86DisableInputHandler(pointer handler)
+{
+ IHPtr ih;
+
+ if (!handler)
+ return;
+
+ ih = handler;
+ ih->enabled = FALSE;
+ if (ih->fd >= 0)
+ RemoveEnabledDevice(ih->fd);
+}
+
+void
+xf86DisableGeneralHandler(pointer handler)
+{
+ IHPtr ih;
+
+ if (!handler)
+ return;
+
+ ih = handler;
+ ih->enabled = FALSE;
+ if (ih->fd >= 0)
+ RemoveGeneralSocket(ih->fd);
+}
+
+void
+xf86EnableInputHandler(pointer handler)
+{
+ IHPtr ih;
+
+ if (!handler)
+ return;
+
+ ih = handler;
+ ih->enabled = TRUE;
+ if (ih->fd >= 0)
+ AddEnabledDevice(ih->fd);
+}
+
+void
+xf86EnableGeneralHandler(pointer handler)
+{
+ IHPtr ih;
+
+ if (!handler)
+ return;
+
+ ih = handler;
+ ih->enabled = TRUE;
+ if (ih->fd >= 0)
+ AddGeneralSocket(ih->fd);
+}
+
+/*
+ * As used currently by the DRI, the return value is ignored.
+ */
+Bool
+xf86EnableVTSwitch(Bool new)
+{
+ static Bool def = TRUE;
+ Bool old;
+
+ old = VTSwitchEnabled;
+ if (!new) {
+ /* Disable VT switching */
+ def = VTSwitchEnabled;
+ VTSwitchEnabled = FALSE;
+ } else {
+ /* Restore VT switching to default */
+ VTSwitchEnabled = def;
+ }
+ return old;
+}
+
+void
+DDXRingBell(int volume, int pitch, int duration) {
+ xf86OSRingBell(volume, pitch, duration);
+}
diff --git a/xorg-server/hw/xfree86/common/xf86VGAarbiter.c b/xorg-server/hw/xfree86/common/xf86VGAarbiter.c
index b24099811..a3eccdfff 100644
--- a/xorg-server/hw/xfree86/common/xf86VGAarbiter.c
+++ b/xorg-server/hw/xfree86/common/xf86VGAarbiter.c
@@ -1,1178 +1,1113 @@
-/*
- * This code was stolen from RAC and adapted to control the legacy vga
- * interface.
- *
- *
- * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "xorg-config.h"
-
-#include "xf86VGAarbiter.h"
-
-#ifdef HAVE_PCI_DEVICE_VGAARB_INIT
-#include "xf86VGAarbiterPriv.h"
-#include "xf86Bus.h"
-#include "xf86Priv.h"
-#include "pciaccess.h"
-
-#ifdef DEBUG
-#error "no, really, you dont want to do this"
-#define DPRINT_S(x,y) ErrorF(x ": %i\n",y);
-#define DPRINT(x) ErrorF(x "\n");
-#else
-#define DPRINT_S(x,y)
-#define DPRINT(x)
-#endif
-
-static GCFuncs VGAarbiterGCFuncs = {
- VGAarbiterValidateGC, VGAarbiterChangeGC, VGAarbiterCopyGC,
- VGAarbiterDestroyGC, VGAarbiterChangeClip, VGAarbiterDestroyClip,
- VGAarbiterCopyClip
-};
-
-static GCOps VGAarbiterGCOps = {
- VGAarbiterFillSpans, VGAarbiterSetSpans, VGAarbiterPutImage,
- VGAarbiterCopyArea, VGAarbiterCopyPlane, VGAarbiterPolyPoint,
- VGAarbiterPolylines, VGAarbiterPolySegment, VGAarbiterPolyRectangle,
- VGAarbiterPolyArc, VGAarbiterFillPolygon, VGAarbiterPolyFillRect,
- VGAarbiterPolyFillArc, VGAarbiterPolyText8, VGAarbiterPolyText16,
- VGAarbiterImageText8, VGAarbiterImageText16, VGAarbiterImageGlyphBlt,
- VGAarbiterPolyGlyphBlt, VGAarbiterPushPixels,
- {NULL} /* devPrivate */
-};
-
-static miPointerSpriteFuncRec VGAarbiterSpriteFuncs = {
- VGAarbiterSpriteRealizeCursor, VGAarbiterSpriteUnrealizeCursor,
- VGAarbiterSpriteSetCursor, VGAarbiterSpriteMoveCursor,
- VGAarbiterDeviceCursorInitialize, VGAarbiterDeviceCursorCleanup
-};
-
-static int VGAarbiterKeyIndex;
-static DevPrivateKey VGAarbiterScreenKey = &VGAarbiterKeyIndex;
-static int VGAarbiterGCIndex;
-static DevPrivateKey VGAarbiterGCKey = &VGAarbiterGCIndex;
-
-static int vga_no_arb = 0;
-void
-xf86VGAarbiterInit(void)
-{
- if (pci_device_vgaarb_init() != 0) {
- vga_no_arb = 1;
- xf86Msg(X_WARNING, "VGA arbiter: cannot open kernel arbiter, no multi-card support\n");
- }
-}
-
-void
-xf86VGAarbiterFini(void)
-{
- if (vga_no_arb)
- return;
- pci_device_vgaarb_fini();
-}
-
-void
-xf86VGAarbiterLock(ScrnInfoPtr pScrn)
-{
- if (vga_no_arb)
- return;
- pci_device_vgaarb_set_target(pScrn->vgaDev);
- pci_device_vgaarb_lock();
-}
-
-void
-xf86VGAarbiterUnlock(ScrnInfoPtr pScrn)
-{
- if (vga_no_arb)
- return;
- pci_device_vgaarb_unlock();
-}
-
-Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen)
-{
- int vga_count;
- int rsrc_decodes;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-
- if (vga_no_arb)
- return TRUE;
-
- pci_device_vgaarb_get_info(pScrn->vgaDev, &vga_count, &rsrc_decodes);
- if (vga_count > 1) {
- if (rsrc_decodes) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-void
-xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn)
-{
- struct pci_device *dev;
- EntityPtr pEnt;
-
- if (vga_no_arb)
- return;
-
- pEnt = xf86Entities[pScrn->entityList[0]];
- if (pEnt->bus.type != BUS_PCI)
- return;
-
- dev = pEnt->bus.id.pci;
- pScrn->vgaDev = dev;
-}
-
-void
-xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn)
-{
- if (vga_no_arb)
- return;
- pci_device_vgaarb_decodes(VGA_ARB_RSRC_LEGACY_MEM | VGA_ARB_RSRC_LEGACY_IO);
-}
-
-Bool
-xf86VGAarbiterWrapFunctions(void)
-{
- ScrnInfoPtr pScrn;
- VGAarbiterScreenPtr pScreenPriv;
- miPointerScreenPtr PointPriv;
-#ifdef RENDER
- PictureScreenPtr ps;
-#endif
- ScreenPtr pScreen;
- int vga_count, i;
-
- if (vga_no_arb)
- return FALSE;
-
- /*
- * we need to wrap the arbiter if we have more than
- * one VGA card - hotplug cries.
- */
- pci_device_vgaarb_get_info(NULL, &vga_count, NULL);
- if (vga_count < 2 || !xf86Screens)
- return FALSE;
-
- xf86Msg(X_INFO,"Found %d VGA devices: arbiter wrapping enabled\n",
- vga_count);
-
- for (i = 0; i < xf86NumScreens; i++) {
- pScreen = xf86Screens[i]->pScreen;
-#ifdef RENDER
- ps = GetPictureScreenIfSet(pScreen);
-#endif
- pScrn = xf86Screens[pScreen->myNum];
- PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
-
- DPRINT_S("VGAarbiterWrapFunctions",pScreen->myNum);
-
- if (!dixRequestPrivate(VGAarbiterGCKey, sizeof(VGAarbiterGCRec)))
- return FALSE;
-
- if (!(pScreenPriv = xalloc(sizeof(VGAarbiterScreenRec))))
- return FALSE;
-
- dixSetPrivate(&pScreen->devPrivates, VGAarbiterScreenKey, pScreenPriv);
-
- WRAP_SCREEN(CloseScreen, VGAarbiterCloseScreen);
- WRAP_SCREEN(SaveScreen, VGAarbiterSaveScreen);
- WRAP_SCREEN(WakeupHandler, VGAarbiterWakeupHandler);
- WRAP_SCREEN(BlockHandler, VGAarbiterBlockHandler);
- WRAP_SCREEN(CreateGC, VGAarbiterCreateGC);
- WRAP_SCREEN(GetImage, VGAarbiterGetImage);
- WRAP_SCREEN(GetSpans, VGAarbiterGetSpans);
- WRAP_SCREEN(SourceValidate, VGAarbiterSourceValidate);
- WRAP_SCREEN(CopyWindow, VGAarbiterCopyWindow);
- WRAP_SCREEN(ClearToBackground, VGAarbiterClearToBackground);
- WRAP_SCREEN(CreatePixmap, VGAarbiterCreatePixmap);
- WRAP_SCREEN(StoreColors, VGAarbiterStoreColors);
- WRAP_SCREEN(DisplayCursor, VGAarbiterDisplayCursor);
- WRAP_SCREEN(RealizeCursor, VGAarbiterRealizeCursor);
- WRAP_SCREEN(UnrealizeCursor, VGAarbiterUnrealizeCursor);
- WRAP_SCREEN(RecolorCursor, VGAarbiterRecolorCursor);
- WRAP_SCREEN(SetCursorPosition, VGAarbiterSetCursorPosition);
-#ifdef RENDER
- WRAP_PICT(Composite,VGAarbiterComposite);
- WRAP_PICT(Glyphs,VGAarbiterGlyphs);
- WRAP_PICT(CompositeRects,VGAarbiterCompositeRects);
-#endif
- WRAP_SCREEN_INFO(AdjustFrame, VGAarbiterAdjustFrame);
- WRAP_SCREEN_INFO(SwitchMode, VGAarbiterSwitchMode);
- WRAP_SCREEN_INFO(EnterVT, VGAarbiterEnterVT);
- WRAP_SCREEN_INFO(LeaveVT, VGAarbiterLeaveVT);
- WRAP_SCREEN_INFO(FreeScreen, VGAarbiterFreeScreen);
- WRAP_SPRITE;
- }
-
- return TRUE;
-}
-
-/* Screen funcs */
-static Bool
-VGAarbiterCloseScreen (int i, ScreenPtr pScreen)
-{
- Bool val;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, VGAarbiterScreenKey);
- miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, miPointerScreenKey);
-#ifdef RENDER
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
-#endif
-
- DPRINT_S("VGAarbiterCloseScreen",pScreen->myNum);
- UNWRAP_SCREEN(CreateGC);
- UNWRAP_SCREEN(CloseScreen);
- UNWRAP_SCREEN(GetImage);
- UNWRAP_SCREEN(GetSpans);
- UNWRAP_SCREEN(SourceValidate);
- UNWRAP_SCREEN(CopyWindow);
- UNWRAP_SCREEN(ClearToBackground);
- UNWRAP_SCREEN(SaveScreen);
- UNWRAP_SCREEN(StoreColors);
- UNWRAP_SCREEN(DisplayCursor);
- UNWRAP_SCREEN(RealizeCursor);
- UNWRAP_SCREEN(UnrealizeCursor);
- UNWRAP_SCREEN(RecolorCursor);
- UNWRAP_SCREEN(SetCursorPosition);
-#ifdef RENDER
- UNWRAP_PICT(Composite);
- UNWRAP_PICT(Glyphs);
- UNWRAP_PICT(CompositeRects);
-#endif
- UNWRAP_SCREEN_INFO(AdjustFrame);
- UNWRAP_SCREEN_INFO(SwitchMode);
- UNWRAP_SCREEN_INFO(EnterVT);
- UNWRAP_SCREEN_INFO(LeaveVT);
- UNWRAP_SCREEN_INFO(FreeScreen);
- UNWRAP_SPRITE;
-
- xfree ((pointer) pScreenPriv);
- xf86VGAarbiterLock(xf86Screens[i]);
- val = (*pScreen->CloseScreen) (i, pScreen);
- xf86VGAarbiterUnlock(xf86Screens[i]);
- return val;
-}
-
-static void
-VGAarbiterBlockHandler(int i,
- pointer blockData, pointer pTimeout, pointer pReadmask)
-{
- ScreenPtr pScreen = screenInfo.screens[i];
- SCREEN_PROLOG(BlockHandler);
- VGAGet();
- pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
- VGAPut();
- SCREEN_EPILOG(BlockHandler, VGAarbiterBlockHandler);
-}
-
-static void
-VGAarbiterWakeupHandler(int i, pointer blockData, unsigned long result, pointer pReadmask)
-{
- ScreenPtr pScreen = screenInfo.screens[i];
- SCREEN_PROLOG(WakeupHandler);
- VGAGet();
- pScreen->WakeupHandler(i, blockData, result, pReadmask);
- VGAPut();
- SCREEN_EPILOG(WakeupHandler, VGAarbiterWakeupHandler);
-}
-
-static void
-VGAarbiterGetImage (
- DrawablePtr pDrawable,
- int sx, int sy, int w, int h,
- unsigned int format,
- unsigned long planemask,
- char *pdstLine
- )
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DPRINT_S("VGAarbiterGetImage",pScreen->myNum);
- SCREEN_PROLOG(GetImage);
-// if (xf86Screens[pScreen->myNum]->vtSema) {
- VGAGet();
-// }
- (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
- format, planemask, pdstLine);
- VGAPut();
- SCREEN_EPILOG (GetImage, VGAarbiterGetImage);
-}
-
-static void
-VGAarbiterGetSpans (
- DrawablePtr pDrawable,
- int wMax,
- DDXPointPtr ppt,
- int *pwidth,
- int nspans,
- char *pdstStart
- )
-{
- ScreenPtr pScreen = pDrawable->pScreen;
-
- DPRINT_S("VGAarbiterGetSpans",pScreen->myNum);
- SCREEN_PROLOG (GetSpans);
- VGAGet();
- (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
- VGAPut();
- SCREEN_EPILOG (GetSpans, VGAarbiterGetSpans);
-}
-
-static void
-VGAarbiterSourceValidate (
- DrawablePtr pDrawable,
- int x, int y, int width, int height )
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DPRINT_S("VGAarbiterSourceValidate",pScreen->myNum);
- SCREEN_PROLOG (SourceValidate);
- VGAGet();
- if (pScreen->SourceValidate)
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
- VGAPut();
- SCREEN_EPILOG (SourceValidate, VGAarbiterSourceValidate);
-}
-
-static void
-VGAarbiterCopyWindow(
- WindowPtr pWin,
- DDXPointRec ptOldOrg,
- RegionPtr prgnSrc )
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- DPRINT_S("VGAarbiterCopyWindow",pScreen->myNum);
- SCREEN_PROLOG (CopyWindow);
- VGAGet();
- (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
- VGAPut();
- SCREEN_EPILOG (CopyWindow, VGAarbiterCopyWindow);
-}
-
-static void
-VGAarbiterClearToBackground (
- WindowPtr pWin,
- int x, int y,
- int w, int h,
- Bool generateExposures )
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- DPRINT_S("VGAarbiterClearToBackground",pScreen->myNum);
- SCREEN_PROLOG ( ClearToBackground);
- VGAGet();
- (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
- VGAPut();
- SCREEN_EPILOG (ClearToBackground, VGAarbiterClearToBackground);
-}
-
-static PixmapPtr
-VGAarbiterCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint)
-{
- PixmapPtr pPix;
-
- DPRINT_S("VGAarbiterCreatePixmap",pScreen->myNum);
- SCREEN_PROLOG ( CreatePixmap);
- VGAGet();
- pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint);
- VGAPut();
- SCREEN_EPILOG (CreatePixmap, VGAarbiterCreatePixmap);
-
- return pPix;
-}
-
-static Bool
-VGAarbiterSaveScreen(ScreenPtr pScreen, Bool unblank)
-{
- Bool val;
-
- DPRINT_S("VGAarbiterSaveScreen",pScreen->myNum);
- SCREEN_PROLOG (SaveScreen);
- VGAGet();
- val = (*pScreen->SaveScreen) (pScreen, unblank);
- VGAPut();
- SCREEN_EPILOG (SaveScreen, VGAarbiterSaveScreen);
-
- return val;
-}
-
-static void
-VGAarbiterStoreColors (
- ColormapPtr pmap,
- int ndef,
- xColorItem *pdefs)
-{
- ScreenPtr pScreen = pmap->pScreen;
-
- DPRINT_S("VGAarbiterStoreColors",pScreen->myNum);
- SCREEN_PROLOG (StoreColors);
- VGAGet();
- (*pScreen->StoreColors) (pmap,ndef,pdefs);
- VGAPut();
- SCREEN_EPILOG ( StoreColors, VGAarbiterStoreColors);
-}
-
-static void
-VGAarbiterRecolorCursor (
- DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCurs,
- Bool displayed
- )
-{
- DPRINT_S("VGAarbiterRecolorCursor",pScreen->myNum);
- SCREEN_PROLOG (RecolorCursor);
- VGAGet();
- (*pScreen->RecolorCursor) (pDev, pScreen, pCurs, displayed);
- VGAPut();
- SCREEN_EPILOG ( RecolorCursor, VGAarbiterRecolorCursor);
-}
-
-static Bool
-VGAarbiterRealizeCursor (
- DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor
- )
-{
- Bool val;
-
- DPRINT_S("VGAarbiterRealizeCursor",pScreen->myNum);
- SCREEN_PROLOG (RealizeCursor);
- VGAGet();
- val = (*pScreen->RealizeCursor) (pDev, pScreen,pCursor);
- VGAPut();
- SCREEN_EPILOG ( RealizeCursor, VGAarbiterRealizeCursor);
- return val;
-}
-
-static Bool
-VGAarbiterUnrealizeCursor (
- DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor
- )
-{
- Bool val;
-
- DPRINT_S("VGAarbiterUnrealizeCursor",pScreen->myNum);
- SCREEN_PROLOG (UnrealizeCursor);
- VGAGet();
- val = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor);
- VGAPut();
- SCREEN_EPILOG ( UnrealizeCursor, VGAarbiterUnrealizeCursor);
- return val;
-}
-
-static Bool
-VGAarbiterDisplayCursor (
- DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor
- )
-{
- Bool val;
-
- DPRINT_S("VGAarbiterDisplayCursor",pScreen->myNum);
- SCREEN_PROLOG (DisplayCursor);
- VGAGet();
- val = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
- VGAPut();
- SCREEN_EPILOG ( DisplayCursor, VGAarbiterDisplayCursor);
- return val;
-}
-
-static Bool
-VGAarbiterSetCursorPosition (
- DeviceIntPtr pDev,
- ScreenPtr pScreen,
- int x, int y,
- Bool generateEvent)
-{
- Bool val;
-
- DPRINT_S("VGAarbiterSetCursorPosition",pScreen->myNum);
- SCREEN_PROLOG (SetCursorPosition);
- VGAGet();
- val = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
- VGAPut();
- SCREEN_EPILOG ( SetCursorPosition, VGAarbiterSetCursorPosition);
- return val;
-}
-
-static void
-VGAarbiterAdjustFrame(int index, int x, int y, int flags)
-{
- ScreenPtr pScreen = screenInfo.screens[index];
- VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, VGAarbiterScreenKey);
-
- DPRINT_S("VGAarbiterAdjustFrame",index);
- VGAGet();
- (*pScreenPriv->AdjustFrame)(index, x, y, flags);
- VGAPut();
-}
-
-static Bool
-VGAarbiterSwitchMode(int index, DisplayModePtr mode, int flags)
-{
- Bool val;
- ScreenPtr pScreen = screenInfo.screens[index];
- VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, VGAarbiterScreenKey);
-
- DPRINT_S("VGAarbiterSwitchMode",index);
- VGAGet();
- val = (*pScreenPriv->SwitchMode)(index, mode, flags);
- VGAPut();
- return val;
-}
-
-static Bool
-VGAarbiterEnterVT(int index, int flags)
-{
- Bool val;
- ScreenPtr pScreen = screenInfo.screens[index];
- VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, VGAarbiterScreenKey);
-
- DPRINT_S("VGAarbiterEnterVT",index);
- VGAGet();
- val = (*pScreenPriv->EnterVT)(index, flags);
- VGAPut();
- return val;
-}
-
-static void
-VGAarbiterLeaveVT(int index, int flags)
-{
- ScreenPtr pScreen = screenInfo.screens[index];
- VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, VGAarbiterScreenKey);
-
- DPRINT_S("VGAarbiterLeaveVT",index);
-
- VGAGet();
- (*pScreenPriv->LeaveVT)(index, flags);
- VGAPut();
-}
-
-static void
-VGAarbiterFreeScreen(int index, int flags)
-{
- ScreenPtr pScreen = screenInfo.screens[index];
- VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, VGAarbiterScreenKey);
-
- DPRINT_S("VGAarbiterFreeScreen",index);
-
- VGAGet();
- (*pScreenPriv->FreeScreen)(index, flags);
- VGAPut();
-}
-
-static Bool
-VGAarbiterCreateGC(GCPtr pGC)
-{
- ScreenPtr pScreen = pGC->pScreen;
- VGAarbiterGCPtr pGCPriv = (VGAarbiterGCPtr)dixLookupPrivate(&pGC->devPrivates, VGAarbiterGCKey);
- Bool ret;
-
- DPRINT_S("VGAarbiterCreateGC",pScreen->myNum);
- SCREEN_PROLOG(CreateGC);
- VGAGet();
- ret = (*pScreen->CreateGC)(pGC);
- VGAPut();
- GC_WRAP(pGC);
- SCREEN_EPILOG(CreateGC,VGAarbiterCreateGC);
-
- return ret;
-}
-
-/* GC funcs */
-static void
-VGAarbiterValidateGC(
- GCPtr pGC,
- unsigned long changes,
- DrawablePtr pDraw )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterValidateGC");
- (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
- GC_WRAP(pGC);
-}
-
-
-static void
-VGAarbiterDestroyGC(GCPtr pGC)
-{
- GC_UNWRAP (pGC);
- DPRINT("VGAarbiterDestroyGC");
- (*pGC->funcs->DestroyGC)(pGC);
- GC_WRAP (pGC);
-}
-
-static void
-VGAarbiterChangeGC (
- GCPtr pGC,
- unsigned long mask)
-{
- GC_UNWRAP (pGC);
- DPRINT("VGAarbiterChangeGC");
- (*pGC->funcs->ChangeGC) (pGC, mask);
- GC_WRAP (pGC);
-}
-
-static void
-VGAarbiterCopyGC (
- GCPtr pGCSrc,
- unsigned long mask,
- GCPtr pGCDst)
-{
- GC_UNWRAP (pGCDst);
- DPRINT("VGAarbiterCopyGC");
- (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
- GC_WRAP (pGCDst);
-}
-
-static void
-VGAarbiterChangeClip (
- GCPtr pGC,
- int type,
- pointer pvalue,
- int nrects )
-{
- GC_UNWRAP (pGC);
- DPRINT("VGAarbiterChangeClip");
- (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
- GC_WRAP (pGC);
-}
-
-static void
-VGAarbiterCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
-{
- GC_UNWRAP (pgcDst);
- DPRINT("VGAarbiterCopyClip");
- (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
- GC_WRAP (pgcDst);
-}
-
-static void
-VGAarbiterDestroyClip(GCPtr pGC)
-{
- GC_UNWRAP (pGC);
- DPRINT("VGAarbiterDestroyClip");
- (* pGC->funcs->DestroyClip)(pGC);
- GC_WRAP (pGC);
-}
-
-/* GC Ops */
-static void
-VGAarbiterFillSpans(
- DrawablePtr pDraw,
- GC *pGC,
- int nInit,
- DDXPointPtr pptInit,
- int *pwidthInit,
- int fSorted )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterFillSpans");
- VGAGet_GC();
- (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterSetSpans(
- DrawablePtr pDraw,
- GCPtr pGC,
- char *pcharsrc,
- register DDXPointPtr ppt,
- int *pwidth,
- int nspans,
- int fSorted )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterSetSpans");
- VGAGet_GC();
- (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPutImage(
- DrawablePtr pDraw,
- GCPtr pGC,
- int depth,
- int x, int y, int w, int h,
- int leftPad,
- int format,
- char *pImage )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPutImage");
- VGAGet_GC();
- (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h,
- leftPad, format, pImage);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static RegionPtr
-VGAarbiterCopyArea(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GC *pGC,
- int srcx, int srcy,
- int width, int height,
- int dstx, int dsty )
-{
- RegionPtr ret;
-
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterCopyArea");
- VGAGet_GC();
- ret = (*pGC->ops->CopyArea)(pSrc, pDst,
- pGC, srcx, srcy, width, height, dstx, dsty);
- VGAPut_GC();
- GC_WRAP(pGC);
- return ret;
-}
-
-static RegionPtr
-VGAarbiterCopyPlane(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx, int srcy,
- int width, int height,
- int dstx, int dsty,
- unsigned long bitPlane )
-{
- RegionPtr ret;
-
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterCopyPlane");
- VGAGet_GC();
- ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, srcx, srcy,
- width, height, dstx, dsty, bitPlane);
- VGAPut_GC();
- GC_WRAP(pGC);
- return ret;
-}
-
-static void
-VGAarbiterPolyPoint(
- DrawablePtr pDraw,
- GCPtr pGC,
- int mode,
- int npt,
- xPoint *pptInit )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyPoint");
- VGAGet_GC();
- (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-
-static void
-VGAarbiterPolylines(
- DrawablePtr pDraw,
- GCPtr pGC,
- int mode,
- int npt,
- DDXPointPtr pptInit )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolylines");
- VGAGet_GC();
- (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPolySegment(
- DrawablePtr pDraw,
- GCPtr pGC,
- int nseg,
- xSegment *pSeg )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolySegment");
- VGAGet_GC();
- (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPolyRectangle(
- DrawablePtr pDraw,
- GCPtr pGC,
- int nRectsInit,
- xRectangle *pRectsInit )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyRectangle");
- VGAGet_GC();
- (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPolyArc(
- DrawablePtr pDraw,
- GCPtr pGC,
- int narcs,
- xArc *parcs )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyArc");
- VGAGet_GC();
- (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterFillPolygon(
- DrawablePtr pDraw,
- GCPtr pGC,
- int shape,
- int mode,
- int count,
- DDXPointPtr ptsIn )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterFillPolygon");
- VGAGet_GC();
- (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPolyFillRect(
- DrawablePtr pDraw,
- GCPtr pGC,
- int nrectFill,
- xRectangle *prectInit)
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyFillRect");
- VGAGet_GC();
- (*pGC->ops->PolyFillRect)(pDraw, pGC, nrectFill, prectInit);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPolyFillArc(
- DrawablePtr pDraw,
- GCPtr pGC,
- int narcs,
- xArc *parcs )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyFillArc");
- VGAGet_GC();
- (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static int
-VGAarbiterPolyText8(
- DrawablePtr pDraw,
- GCPtr pGC,
- int x,
- int y,
- int count,
- char *chars )
-{
- int ret;
-
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyText8");
- VGAGet_GC();
- ret = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
- VGAPut_GC();
- GC_WRAP(pGC);
- return ret;
-}
-
-static int
-VGAarbiterPolyText16(
- DrawablePtr pDraw,
- GCPtr pGC,
- int x,
- int y,
- int count,
- unsigned short *chars )
-{
- int ret;
-
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyText16");
- VGAGet_GC();
- ret = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
- VGAPut_GC();
- GC_WRAP(pGC);
- return ret;
-}
-
-static void
-VGAarbiterImageText8(
- DrawablePtr pDraw,
- GCPtr pGC,
- int x,
- int y,
- int count,
- char *chars )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterImageText8");
- VGAGet_GC();
- (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterImageText16(
- DrawablePtr pDraw,
- GCPtr pGC,
- int x,
- int y,
- int count,
- unsigned short *chars )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterImageText16");
- VGAGet_GC();
- (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-
-static void
-VGAarbiterImageGlyphBlt(
- DrawablePtr pDraw,
- GCPtr pGC,
- int xInit, int yInit,
- unsigned int nglyph,
- CharInfoPtr *ppci,
- pointer pglyphBase )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterImageGlyphBlt");
- VGAGet_GC();
- (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, xInit, yInit,
- nglyph, ppci, pglyphBase);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPolyGlyphBlt(
- DrawablePtr pDraw,
- GCPtr pGC,
- int xInit, int yInit,
- unsigned int nglyph,
- CharInfoPtr *ppci,
- pointer pglyphBase )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPolyGlyphBlt");
- VGAGet_GC();
- (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, xInit, yInit,
- nglyph, ppci, pglyphBase);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-static void
-VGAarbiterPushPixels(
- GCPtr pGC,
- PixmapPtr pBitMap,
- DrawablePtr pDraw,
- int dx, int dy, int xOrg, int yOrg )
-{
- GC_UNWRAP(pGC);
- DPRINT("VGAarbiterPushPixels");
- VGAGet_GC();
- (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
- VGAPut_GC();
- GC_WRAP(pGC);
-}
-
-
-/* miSpriteFuncs */
-static Bool
-VGAarbiterSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur)
-{
- Bool val;
- SPRITE_PROLOG;
- DPRINT_S("VGAarbiterSpriteRealizeCursor",pScreen->myNum);
- VGAGet();
- val = PointPriv->spriteFuncs->RealizeCursor(pDev, pScreen, pCur);
- VGAPut();
- SPRITE_EPILOG;
- return val;
-}
-
-static Bool
-VGAarbiterSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur)
-{
- Bool val;
- SPRITE_PROLOG;
- DPRINT_S("VGAarbiterSpriteUnrealizeCursor",pScreen->myNum);
- VGAGet();
- val = PointPriv->spriteFuncs->UnrealizeCursor(pDev, pScreen, pCur);
- VGAPut();
- SPRITE_EPILOG;
- return val;
-}
-
-static void
-VGAarbiterSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur, int x, int y)
-{
- SPRITE_PROLOG;
- DPRINT_S("VGAarbiterSpriteSetCursor",pScreen->myNum);
- VGAGet();
- PointPriv->spriteFuncs->SetCursor(pDev, pScreen, pCur, x, y);
- VGAPut();
- SPRITE_EPILOG;
-}
-
-static void
-VGAarbiterSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- SPRITE_PROLOG;
- DPRINT_S("VGAarbiterSpriteMoveCursor",pScreen->myNum);
- VGAGet();
- PointPriv->spriteFuncs->MoveCursor(pDev, pScreen, x, y);
- VGAPut();
- SPRITE_EPILOG;
-}
-
-static Bool
-VGAarbiterDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- Bool val;
- SPRITE_PROLOG;
- DPRINT_S("VGAarbiterDeviceCursorInitialize",pScreen->myNum);
- VGAGet();
- val = PointPriv->spriteFuncs->DeviceCursorInitialize(pDev, pScreen);
- VGAPut();
- SPRITE_EPILOG;
- return val;
-}
-
-static void
-VGAarbiterDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- SPRITE_PROLOG;
- DPRINT_S("VGAarbiterDeviceCursorCleanup",pScreen->myNum);
- VGAGet();
- PointPriv->spriteFuncs->DeviceCursorCleanup(pDev, pScreen);
- VGAPut();
- SPRITE_EPILOG;
-}
-
-#ifdef RENDER
-static void
-VGAarbiterComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
- PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
- INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width,
- CARD16 height)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
-
- PICTURE_PROLOGUE(Composite);
-
- VGAGet();
- (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst,
- yDst, width, height);
- VGAPut();
- PICTURE_EPILOGUE(Composite, VGAarbiterComposite);
-}
-
-static void
-VGAarbiterGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
- GlyphListPtr list, GlyphPtr *glyphs)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
-
- PICTURE_PROLOGUE(Glyphs);
-
- VGAGet();
- (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
- VGAPut();
- PICTURE_EPILOGUE (Glyphs, VGAarbiterGlyphs);
-}
-
-static void
-VGAarbiterCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, int nRect,
- xRectangle *rects)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
-
- PICTURE_PROLOGUE(CompositeRects);
-
- VGAGet();
- (*ps->CompositeRects)(op, pDst, color, nRect, rects);
- VGAPut();
- PICTURE_EPILOGUE (CompositeRects, VGAarbiterCompositeRects);
-}
-#endif
-#else
-/* dummy functions */
-void xf86VGAarbiterInit(void) {}
-void xf86VGAarbiterFini(void) {}
-
-void xf86VGAarbiterLock(ScrnInfoPtr pScrn) {}
-void xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) {}
-Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) { return TRUE; }
-void xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) {}
-void xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn) {}
-Bool xf86VGAarbiterWrapFunctions(void) { return FALSE; }
-
-#endif
+/*
+ * This code was stolen from RAC and adapted to control the legacy vga
+ * interface.
+ *
+ *
+ * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "xorg-config.h"
+
+#include "xf86VGAarbiter.h"
+
+#ifdef HAVE_PCI_DEVICE_VGAARB_INIT
+#include "xf86VGAarbiterPriv.h"
+#include "xf86Bus.h"
+#include "xf86Priv.h"
+#include "pciaccess.h"
+
+
+static GCFuncs VGAarbiterGCFuncs = {
+ VGAarbiterValidateGC, VGAarbiterChangeGC, VGAarbiterCopyGC,
+ VGAarbiterDestroyGC, VGAarbiterChangeClip, VGAarbiterDestroyClip,
+ VGAarbiterCopyClip
+};
+
+static GCOps VGAarbiterGCOps = {
+ VGAarbiterFillSpans, VGAarbiterSetSpans, VGAarbiterPutImage,
+ VGAarbiterCopyArea, VGAarbiterCopyPlane, VGAarbiterPolyPoint,
+ VGAarbiterPolylines, VGAarbiterPolySegment, VGAarbiterPolyRectangle,
+ VGAarbiterPolyArc, VGAarbiterFillPolygon, VGAarbiterPolyFillRect,
+ VGAarbiterPolyFillArc, VGAarbiterPolyText8, VGAarbiterPolyText16,
+ VGAarbiterImageText8, VGAarbiterImageText16, VGAarbiterImageGlyphBlt,
+ VGAarbiterPolyGlyphBlt, VGAarbiterPushPixels,
+ {NULL} /* devPrivate */
+};
+
+static miPointerSpriteFuncRec VGAarbiterSpriteFuncs = {
+ VGAarbiterSpriteRealizeCursor, VGAarbiterSpriteUnrealizeCursor,
+ VGAarbiterSpriteSetCursor, VGAarbiterSpriteMoveCursor,
+ VGAarbiterDeviceCursorInitialize, VGAarbiterDeviceCursorCleanup
+};
+
+static int VGAarbiterKeyIndex;
+static DevPrivateKey VGAarbiterScreenKey = &VGAarbiterKeyIndex;
+static int VGAarbiterGCIndex;
+static DevPrivateKey VGAarbiterGCKey = &VGAarbiterGCIndex;
+
+static int vga_no_arb = 0;
+void
+xf86VGAarbiterInit(void)
+{
+ if (pci_device_vgaarb_init() != 0) {
+ vga_no_arb = 1;
+ xf86Msg(X_WARNING, "VGA arbiter: cannot open kernel arbiter, no multi-card support\n");
+ }
+}
+
+void
+xf86VGAarbiterFini(void)
+{
+ if (vga_no_arb)
+ return;
+ pci_device_vgaarb_fini();
+}
+
+void
+xf86VGAarbiterLock(ScrnInfoPtr pScrn)
+{
+ if (vga_no_arb)
+ return;
+ pci_device_vgaarb_set_target(pScrn->vgaDev);
+ pci_device_vgaarb_lock();
+}
+
+void
+xf86VGAarbiterUnlock(ScrnInfoPtr pScrn)
+{
+ if (vga_no_arb)
+ return;
+ pci_device_vgaarb_unlock();
+}
+
+Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen)
+{
+ int vga_count;
+ int rsrc_decodes;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (vga_no_arb)
+ return TRUE;
+
+ pci_device_vgaarb_get_info(pScrn->vgaDev, &vga_count, &rsrc_decodes);
+ if (vga_count > 1) {
+ if (rsrc_decodes) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void
+xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn)
+{
+ struct pci_device *dev;
+ EntityPtr pEnt;
+
+ if (vga_no_arb)
+ return;
+
+ pEnt = xf86Entities[pScrn->entityList[0]];
+ if (pEnt->bus.type != BUS_PCI)
+ return;
+
+ dev = pEnt->bus.id.pci;
+ pScrn->vgaDev = dev;
+}
+
+void
+xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn)
+{
+ if (vga_no_arb)
+ return;
+ pci_device_vgaarb_decodes(VGA_ARB_RSRC_LEGACY_MEM | VGA_ARB_RSRC_LEGACY_IO);
+}
+
+Bool
+xf86VGAarbiterWrapFunctions(void)
+{
+ ScrnInfoPtr pScrn;
+ VGAarbiterScreenPtr pScreenPriv;
+ miPointerScreenPtr PointPriv;
+#ifdef RENDER
+ PictureScreenPtr ps;
+#endif
+ ScreenPtr pScreen;
+ int vga_count, i;
+
+ if (vga_no_arb)
+ return FALSE;
+
+ /*
+ * we need to wrap the arbiter if we have more than
+ * one VGA card - hotplug cries.
+ */
+ pci_device_vgaarb_get_info(NULL, &vga_count, NULL);
+ if (vga_count < 2 || !xf86Screens)
+ return FALSE;
+
+ xf86Msg(X_INFO,"Found %d VGA devices: arbiter wrapping enabled\n",
+ vga_count);
+
+ for (i = 0; i < xf86NumScreens; i++) {
+ pScreen = xf86Screens[i]->pScreen;
+#ifdef RENDER
+ ps = GetPictureScreenIfSet(pScreen);
+#endif
+ pScrn = xf86Screens[pScreen->myNum];
+ PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
+
+ if (!dixRequestPrivate(VGAarbiterGCKey, sizeof(VGAarbiterGCRec)))
+ return FALSE;
+
+ if (!(pScreenPriv = xalloc(sizeof(VGAarbiterScreenRec))))
+ return FALSE;
+
+ dixSetPrivate(&pScreen->devPrivates, VGAarbiterScreenKey, pScreenPriv);
+
+ WRAP_SCREEN(CloseScreen, VGAarbiterCloseScreen);
+ WRAP_SCREEN(SaveScreen, VGAarbiterSaveScreen);
+ WRAP_SCREEN(WakeupHandler, VGAarbiterWakeupHandler);
+ WRAP_SCREEN(BlockHandler, VGAarbiterBlockHandler);
+ WRAP_SCREEN(CreateGC, VGAarbiterCreateGC);
+ WRAP_SCREEN(GetImage, VGAarbiterGetImage);
+ WRAP_SCREEN(GetSpans, VGAarbiterGetSpans);
+ WRAP_SCREEN(SourceValidate, VGAarbiterSourceValidate);
+ WRAP_SCREEN(CopyWindow, VGAarbiterCopyWindow);
+ WRAP_SCREEN(ClearToBackground, VGAarbiterClearToBackground);
+ WRAP_SCREEN(CreatePixmap, VGAarbiterCreatePixmap);
+ WRAP_SCREEN(StoreColors, VGAarbiterStoreColors);
+ WRAP_SCREEN(DisplayCursor, VGAarbiterDisplayCursor);
+ WRAP_SCREEN(RealizeCursor, VGAarbiterRealizeCursor);
+ WRAP_SCREEN(UnrealizeCursor, VGAarbiterUnrealizeCursor);
+ WRAP_SCREEN(RecolorCursor, VGAarbiterRecolorCursor);
+ WRAP_SCREEN(SetCursorPosition, VGAarbiterSetCursorPosition);
+#ifdef RENDER
+ WRAP_PICT(Composite,VGAarbiterComposite);
+ WRAP_PICT(Glyphs,VGAarbiterGlyphs);
+ WRAP_PICT(CompositeRects,VGAarbiterCompositeRects);
+#endif
+ WRAP_SCREEN_INFO(AdjustFrame, VGAarbiterAdjustFrame);
+ WRAP_SCREEN_INFO(SwitchMode, VGAarbiterSwitchMode);
+ WRAP_SCREEN_INFO(EnterVT, VGAarbiterEnterVT);
+ WRAP_SCREEN_INFO(LeaveVT, VGAarbiterLeaveVT);
+ WRAP_SCREEN_INFO(FreeScreen, VGAarbiterFreeScreen);
+ WRAP_SPRITE;
+ }
+
+ return TRUE;
+}
+
+/* Screen funcs */
+static Bool
+VGAarbiterCloseScreen (int i, ScreenPtr pScreen)
+{
+ Bool val;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, VGAarbiterScreenKey);
+ miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, miPointerScreenKey);
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ UNWRAP_SCREEN(CreateGC);
+ UNWRAP_SCREEN(CloseScreen);
+ UNWRAP_SCREEN(GetImage);
+ UNWRAP_SCREEN(GetSpans);
+ UNWRAP_SCREEN(SourceValidate);
+ UNWRAP_SCREEN(CopyWindow);
+ UNWRAP_SCREEN(ClearToBackground);
+ UNWRAP_SCREEN(SaveScreen);
+ UNWRAP_SCREEN(StoreColors);
+ UNWRAP_SCREEN(DisplayCursor);
+ UNWRAP_SCREEN(RealizeCursor);
+ UNWRAP_SCREEN(UnrealizeCursor);
+ UNWRAP_SCREEN(RecolorCursor);
+ UNWRAP_SCREEN(SetCursorPosition);
+#ifdef RENDER
+ UNWRAP_PICT(Composite);
+ UNWRAP_PICT(Glyphs);
+ UNWRAP_PICT(CompositeRects);
+#endif
+ UNWRAP_SCREEN_INFO(AdjustFrame);
+ UNWRAP_SCREEN_INFO(SwitchMode);
+ UNWRAP_SCREEN_INFO(EnterVT);
+ UNWRAP_SCREEN_INFO(LeaveVT);
+ UNWRAP_SCREEN_INFO(FreeScreen);
+ UNWRAP_SPRITE;
+
+ xfree ((pointer) pScreenPriv);
+ xf86VGAarbiterLock(xf86Screens[i]);
+ val = (*pScreen->CloseScreen) (i, pScreen);
+ xf86VGAarbiterUnlock(xf86Screens[i]);
+ return val;
+}
+
+static void
+VGAarbiterBlockHandler(int i,
+ pointer blockData, pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ SCREEN_PROLOG(BlockHandler);
+ VGAGet();
+ pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
+ VGAPut();
+ SCREEN_EPILOG(BlockHandler, VGAarbiterBlockHandler);
+}
+
+static void
+VGAarbiterWakeupHandler(int i, pointer blockData, unsigned long result, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ SCREEN_PROLOG(WakeupHandler);
+ VGAGet();
+ pScreen->WakeupHandler(i, blockData, result, pReadmask);
+ VGAPut();
+ SCREEN_EPILOG(WakeupHandler, VGAarbiterWakeupHandler);
+}
+
+static void
+VGAarbiterGetImage (
+ DrawablePtr pDrawable,
+ int sx, int sy, int w, int h,
+ unsigned int format,
+ unsigned long planemask,
+ char *pdstLine
+ )
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ SCREEN_PROLOG(GetImage);
+// if (xf86Screens[pScreen->myNum]->vtSema) {
+ VGAGet();
+// }
+ (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
+ format, planemask, pdstLine);
+ VGAPut();
+ SCREEN_EPILOG (GetImage, VGAarbiterGetImage);
+}
+
+static void
+VGAarbiterGetSpans (
+ DrawablePtr pDrawable,
+ int wMax,
+ DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ char *pdstStart
+ )
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+
+ SCREEN_PROLOG (GetSpans);
+ VGAGet();
+ (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+ VGAPut();
+ SCREEN_EPILOG (GetSpans, VGAarbiterGetSpans);
+}
+
+static void
+VGAarbiterSourceValidate (
+ DrawablePtr pDrawable,
+ int x, int y, int width, int height )
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ SCREEN_PROLOG (SourceValidate);
+ VGAGet();
+ if (pScreen->SourceValidate)
+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
+ VGAPut();
+ SCREEN_EPILOG (SourceValidate, VGAarbiterSourceValidate);
+}
+
+static void
+VGAarbiterCopyWindow(
+ WindowPtr pWin,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc )
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ SCREEN_PROLOG (CopyWindow);
+ VGAGet();
+ (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
+ VGAPut();
+ SCREEN_EPILOG (CopyWindow, VGAarbiterCopyWindow);
+}
+
+static void
+VGAarbiterClearToBackground (
+ WindowPtr pWin,
+ int x, int y,
+ int w, int h,
+ Bool generateExposures )
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ SCREEN_PROLOG ( ClearToBackground);
+ VGAGet();
+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
+ VGAPut();
+ SCREEN_EPILOG (ClearToBackground, VGAarbiterClearToBackground);
+}
+
+static PixmapPtr
+VGAarbiterCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint)
+{
+ PixmapPtr pPix;
+
+ SCREEN_PROLOG ( CreatePixmap);
+ VGAGet();
+ pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint);
+ VGAPut();
+ SCREEN_EPILOG (CreatePixmap, VGAarbiterCreatePixmap);
+
+ return pPix;
+}
+
+static Bool
+VGAarbiterSaveScreen(ScreenPtr pScreen, Bool unblank)
+{
+ Bool val;
+
+ SCREEN_PROLOG (SaveScreen);
+ VGAGet();
+ val = (*pScreen->SaveScreen) (pScreen, unblank);
+ VGAPut();
+ SCREEN_EPILOG (SaveScreen, VGAarbiterSaveScreen);
+
+ return val;
+}
+
+static void
+VGAarbiterStoreColors (
+ ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+
+ SCREEN_PROLOG (StoreColors);
+ VGAGet();
+ (*pScreen->StoreColors) (pmap,ndef,pdefs);
+ VGAPut();
+ SCREEN_EPILOG ( StoreColors, VGAarbiterStoreColors);
+}
+
+static void
+VGAarbiterRecolorCursor (
+ DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCurs,
+ Bool displayed
+ )
+{
+ SCREEN_PROLOG (RecolorCursor);
+ VGAGet();
+ (*pScreen->RecolorCursor) (pDev, pScreen, pCurs, displayed);
+ VGAPut();
+ SCREEN_EPILOG ( RecolorCursor, VGAarbiterRecolorCursor);
+}
+
+static Bool
+VGAarbiterRealizeCursor (
+ DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor
+ )
+{
+ Bool val;
+
+ SCREEN_PROLOG (RealizeCursor);
+ VGAGet();
+ val = (*pScreen->RealizeCursor) (pDev, pScreen,pCursor);
+ VGAPut();
+ SCREEN_EPILOG ( RealizeCursor, VGAarbiterRealizeCursor);
+ return val;
+}
+
+static Bool
+VGAarbiterUnrealizeCursor (
+ DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor
+ )
+{
+ Bool val;
+
+ SCREEN_PROLOG (UnrealizeCursor);
+ VGAGet();
+ val = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor);
+ VGAPut();
+ SCREEN_EPILOG ( UnrealizeCursor, VGAarbiterUnrealizeCursor);
+ return val;
+}
+
+static Bool
+VGAarbiterDisplayCursor (
+ DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor
+ )
+{
+ Bool val;
+
+ SCREEN_PROLOG (DisplayCursor);
+ VGAGet();
+ val = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
+ VGAPut();
+ SCREEN_EPILOG ( DisplayCursor, VGAarbiterDisplayCursor);
+ return val;
+}
+
+static Bool
+VGAarbiterSetCursorPosition (
+ DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ int x, int y,
+ Bool generateEvent)
+{
+ Bool val;
+
+ SCREEN_PROLOG (SetCursorPosition);
+ VGAGet();
+ val = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
+ VGAPut();
+ SCREEN_EPILOG ( SetCursorPosition, VGAarbiterSetCursorPosition);
+ return val;
+}
+
+static void
+VGAarbiterAdjustFrame(int index, int x, int y, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, VGAarbiterScreenKey);
+
+ VGAGet();
+ (*pScreenPriv->AdjustFrame)(index, x, y, flags);
+ VGAPut();
+}
+
+static Bool
+VGAarbiterSwitchMode(int index, DisplayModePtr mode, int flags)
+{
+ Bool val;
+ ScreenPtr pScreen = screenInfo.screens[index];
+ VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, VGAarbiterScreenKey);
+
+ VGAGet();
+ val = (*pScreenPriv->SwitchMode)(index, mode, flags);
+ VGAPut();
+ return val;
+}
+
+static Bool
+VGAarbiterEnterVT(int index, int flags)
+{
+ Bool val;
+ ScreenPtr pScreen = screenInfo.screens[index];
+ VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, VGAarbiterScreenKey);
+
+ VGAGet();
+ val = (*pScreenPriv->EnterVT)(index, flags);
+ VGAPut();
+ return val;
+}
+
+static void
+VGAarbiterLeaveVT(int index, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, VGAarbiterScreenKey);
+
+ VGAGet();
+ (*pScreenPriv->LeaveVT)(index, flags);
+ VGAPut();
+}
+
+static void
+VGAarbiterFreeScreen(int index, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, VGAarbiterScreenKey);
+
+ VGAGet();
+ (*pScreenPriv->FreeScreen)(index, flags);
+ VGAPut();
+}
+
+static Bool
+VGAarbiterCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ VGAarbiterGCPtr pGCPriv = (VGAarbiterGCPtr)dixLookupPrivate(&pGC->devPrivates, VGAarbiterGCKey);
+ Bool ret;
+
+ SCREEN_PROLOG(CreateGC);
+ VGAGet();
+ ret = (*pScreen->CreateGC)(pGC);
+ VGAPut();
+ GC_WRAP(pGC);
+ SCREEN_EPILOG(CreateGC,VGAarbiterCreateGC);
+
+ return ret;
+}
+
+/* GC funcs */
+static void
+VGAarbiterValidateGC(
+ GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDraw )
+{
+ GC_UNWRAP(pGC);
+ (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
+ GC_WRAP(pGC);
+}
+
+
+static void
+VGAarbiterDestroyGC(GCPtr pGC)
+{
+ GC_UNWRAP (pGC);
+ (*pGC->funcs->DestroyGC)(pGC);
+ GC_WRAP (pGC);
+}
+
+static void
+VGAarbiterChangeGC (
+ GCPtr pGC,
+ unsigned long mask)
+{
+ GC_UNWRAP (pGC);
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ GC_WRAP (pGC);
+}
+
+static void
+VGAarbiterCopyGC (
+ GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst)
+{
+ GC_UNWRAP (pGCDst);
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ GC_WRAP (pGCDst);
+}
+
+static void
+VGAarbiterChangeClip (
+ GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects )
+{
+ GC_UNWRAP (pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ GC_WRAP (pGC);
+}
+
+static void
+VGAarbiterCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ GC_UNWRAP (pgcDst);
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+ GC_WRAP (pgcDst);
+}
+
+static void
+VGAarbiterDestroyClip(GCPtr pGC)
+{
+ GC_UNWRAP (pGC);
+ (* pGC->funcs->DestroyClip)(pGC);
+ GC_WRAP (pGC);
+}
+
+/* GC Ops */
+static void
+VGAarbiterFillSpans(
+ DrawablePtr pDraw,
+ GC *pGC,
+ int nInit,
+ DDXPointPtr pptInit,
+ int *pwidthInit,
+ int fSorted )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterSetSpans(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ char *pcharsrc,
+ register DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ int fSorted )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPutImage(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int depth,
+ int x, int y, int w, int h,
+ int leftPad,
+ int format,
+ char *pImage )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h,
+ leftPad, format, pImage);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static RegionPtr
+VGAarbiterCopyArea(
+ DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GC *pGC,
+ int srcx, int srcy,
+ int width, int height,
+ int dstx, int dsty )
+{
+ RegionPtr ret;
+
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ ret = (*pGC->ops->CopyArea)(pSrc, pDst,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+ return ret;
+}
+
+static RegionPtr
+VGAarbiterCopyPlane(
+ DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GCPtr pGC,
+ int srcx, int srcy,
+ int width, int height,
+ int dstx, int dsty,
+ unsigned long bitPlane )
+{
+ RegionPtr ret;
+
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, srcx, srcy,
+ width, height, dstx, dsty, bitPlane);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+ return ret;
+}
+
+static void
+VGAarbiterPolyPoint(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ xPoint *pptInit )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+
+static void
+VGAarbiterPolylines(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ DDXPointPtr pptInit )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPolySegment(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nseg,
+ xSegment *pSeg )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPolyRectangle(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nRectsInit,
+ xRectangle *pRectsInit )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPolyArc(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int narcs,
+ xArc *parcs )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterFillPolygon(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int shape,
+ int mode,
+ int count,
+ DDXPointPtr ptsIn )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPolyFillRect(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nrectFill,
+ xRectangle *prectInit)
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PolyFillRect)(pDraw, pGC, nrectFill, prectInit);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPolyFillArc(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int narcs,
+ xArc *parcs )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static int
+VGAarbiterPolyText8(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars )
+{
+ int ret;
+
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ ret = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+ return ret;
+}
+
+static int
+VGAarbiterPolyText16(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars )
+{
+ int ret;
+
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ ret = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+ return ret;
+}
+
+static void
+VGAarbiterImageText8(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterImageText16(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+
+static void
+VGAarbiterImageGlyphBlt(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int xInit, int yInit,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, xInit, yInit,
+ nglyph, ppci, pglyphBase);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPolyGlyphBlt(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int xInit, int yInit,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, xInit, yInit,
+ nglyph, ppci, pglyphBase);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+static void
+VGAarbiterPushPixels(
+ GCPtr pGC,
+ PixmapPtr pBitMap,
+ DrawablePtr pDraw,
+ int dx, int dy, int xOrg, int yOrg )
+{
+ GC_UNWRAP(pGC);
+ VGAGet_GC();
+ (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
+ VGAPut_GC();
+ GC_WRAP(pGC);
+}
+
+
+/* miSpriteFuncs */
+static Bool
+VGAarbiterSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur)
+{
+ Bool val;
+ SPRITE_PROLOG;
+ VGAGet();
+ val = PointPriv->spriteFuncs->RealizeCursor(pDev, pScreen, pCur);
+ VGAPut();
+ SPRITE_EPILOG;
+ return val;
+}
+
+static Bool
+VGAarbiterSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur)
+{
+ Bool val;
+ SPRITE_PROLOG;
+ VGAGet();
+ val = PointPriv->spriteFuncs->UnrealizeCursor(pDev, pScreen, pCur);
+ VGAPut();
+ SPRITE_EPILOG;
+ return val;
+}
+
+static void
+VGAarbiterSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur, int x, int y)
+{
+ SPRITE_PROLOG;
+ VGAGet();
+ PointPriv->spriteFuncs->SetCursor(pDev, pScreen, pCur, x, y);
+ VGAPut();
+ SPRITE_EPILOG;
+}
+
+static void
+VGAarbiterSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+ SPRITE_PROLOG;
+ VGAGet();
+ PointPriv->spriteFuncs->MoveCursor(pDev, pScreen, x, y);
+ VGAPut();
+ SPRITE_EPILOG;
+}
+
+static Bool
+VGAarbiterDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ Bool val;
+ SPRITE_PROLOG;
+ VGAGet();
+ val = PointPriv->spriteFuncs->DeviceCursorInitialize(pDev, pScreen);
+ VGAPut();
+ SPRITE_EPILOG;
+ return val;
+}
+
+static void
+VGAarbiterDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ SPRITE_PROLOG;
+ VGAGet();
+ PointPriv->spriteFuncs->DeviceCursorCleanup(pDev, pScreen);
+ VGAPut();
+ SPRITE_EPILOG;
+}
+
+#ifdef RENDER
+static void
+VGAarbiterComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
+ PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
+ INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width,
+ CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ PICTURE_PROLOGUE(Composite);
+
+ VGAGet();
+ (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst,
+ yDst, width, height);
+ VGAPut();
+ PICTURE_EPILOGUE(Composite, VGAarbiterComposite);
+}
+
+static void
+VGAarbiterGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
+ GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ PICTURE_PROLOGUE(Glyphs);
+
+ VGAGet();
+ (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+ VGAPut();
+ PICTURE_EPILOGUE (Glyphs, VGAarbiterGlyphs);
+}
+
+static void
+VGAarbiterCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, int nRect,
+ xRectangle *rects)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ PICTURE_PROLOGUE(CompositeRects);
+
+ VGAGet();
+ (*ps->CompositeRects)(op, pDst, color, nRect, rects);
+ VGAPut();
+ PICTURE_EPILOGUE (CompositeRects, VGAarbiterCompositeRects);
+}
+#endif
+#else
+/* dummy functions */
+void xf86VGAarbiterInit(void) {}
+void xf86VGAarbiterFini(void) {}
+
+void xf86VGAarbiterLock(ScrnInfoPtr pScrn) {}
+void xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) {}
+Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) { return TRUE; }
+void xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) {}
+void xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn) {}
+Bool xf86VGAarbiterWrapFunctions(void) { return FALSE; }
+
+#endif
diff --git a/xorg-server/hw/xfree86/common/xf86cmap.c b/xorg-server/hw/xfree86/common/xf86cmap.c
index 08f557ccd..4cab8b3eb 100644
--- a/xorg-server/hw/xfree86/common/xf86cmap.c
+++ b/xorg-server/hw/xfree86/common/xf86cmap.c
@@ -1,1165 +1,1170 @@
-/*
- * Copyright (c) 1998-2001 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4)
-#include <math.h>
-#else
-#define _XOPEN_SOURCE /* to get prototype for pow on some systems */
-#include <math.h>
-#undef _XOPEN_SOURCE
-#endif
-
-#include <X11/X.h>
-#include "misc.h"
-#include <X11/Xproto.h>
-#include "colormapst.h"
-#include "scrnintstr.h"
-
-#include "resource.h"
-
-#include "xf86.h"
-#include "xf86_OSproc.h"
-#include "xf86str.h"
-#include "micmap.h"
-#include "xf86Crtc.h"
-
-#ifdef XFreeXDGA
-#include <X11/extensions/xf86dgaproto.h>
-#include "dgaproc.h"
-#endif
-
-#include "xf86cmap.h"
-
-#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
- ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field)
-#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
- ((pScreen)->field = wrapper)
-
-#define LOAD_PALETTE(pmap, index) \
- ((pmap == miInstalledMaps[index]) && \
- ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \
- xf86Screens[index]->vtSema || pScreenPriv->isDGAmode))
-
-
-typedef struct _CMapLink {
- ColormapPtr cmap;
- struct _CMapLink *next;
-} CMapLink, *CMapLinkPtr;
-
-typedef struct {
- ScrnInfoPtr pScrn;
- CloseScreenProcPtr CloseScreen;
- CreateColormapProcPtr CreateColormap;
- DestroyColormapProcPtr DestroyColormap;
- InstallColormapProcPtr InstallColormap;
- StoreColorsProcPtr StoreColors;
- Bool (*EnterVT)(int, int);
- Bool (*SwitchMode)(int, DisplayModePtr, int);
- int (*SetDGAMode)(int, int, DGADevicePtr);
- xf86ChangeGammaProc *ChangeGamma;
- int maxColors;
- int sigRGBbits;
- int gammaElements;
- LOCO *gamma;
- int *PreAllocIndices;
- CMapLinkPtr maps;
- unsigned int flags;
- Bool isDGAmode;
-} CMapScreenRec, *CMapScreenPtr;
-
-typedef struct {
- int numColors;
- LOCO *colors;
- Bool recalculate;
- int overscan;
-} CMapColormapRec, *CMapColormapPtr;
-
-static int CMapScreenKeyIndex;
-static DevPrivateKey CMapScreenKey;
-static int CMapColormapKeyIndex;
-static DevPrivateKey CMapColormapKey = &CMapColormapKeyIndex;
-
-static void CMapInstallColormap(ColormapPtr);
-static void CMapStoreColors(ColormapPtr, int, xColorItem *);
-static Bool CMapCloseScreen (int, ScreenPtr);
-static Bool CMapCreateColormap (ColormapPtr);
-static void CMapDestroyColormap (ColormapPtr);
-
-static Bool CMapEnterVT(int, int);
-static Bool CMapSwitchMode(int, DisplayModePtr, int);
-#ifdef XFreeXDGA
-static int CMapSetDGAMode(int, int, DGADevicePtr);
-#endif
-static int CMapChangeGamma(int, Gamma);
-
-static void ComputeGamma(CMapScreenPtr);
-static Bool CMapAllocateColormapPrivate(ColormapPtr);
-static void CMapRefreshColors(ColormapPtr, int, int*);
-static void CMapSetOverscan(ColormapPtr, int, int *);
-static void CMapReinstallMap(ColormapPtr);
-static void CMapUnwrapScreen(ScreenPtr pScreen);
-
-
-
-Bool xf86HandleColormaps(
- ScreenPtr pScreen,
- int maxColors,
- int sigRGBbits,
- xf86LoadPaletteProc *loadPalette,
- xf86SetOverscanProc *setOverscan,
- unsigned int flags
-){
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- ColormapPtr pDefMap = NULL;
- CMapScreenPtr pScreenPriv;
- LOCO *gamma;
- int *indices;
- int elements;
-
- /* If we support a better colormap system, then pretend we succeeded. */
- if (xf86_crtc_supports_gamma(pScrn))
- return TRUE;
-
- if(!maxColors || !sigRGBbits || !loadPalette)
- return FALSE;
-
- CMapScreenKey = &CMapScreenKeyIndex;
-
- elements = 1 << sigRGBbits;
-
- if(!(gamma = xalloc(elements * sizeof(LOCO))))
- return FALSE;
-
- if(!(indices = xalloc(maxColors * sizeof(int)))) {
- xfree(gamma);
- return FALSE;
- }
-
- if(!(pScreenPriv = xalloc(sizeof(CMapScreenRec)))) {
- xfree(gamma);
- xfree(indices);
- return FALSE;
- }
-
- dixSetPrivate(&pScreen->devPrivates, CMapScreenKey, pScreenPriv);
-
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreenPriv->CreateColormap = pScreen->CreateColormap;
- pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
- pScreenPriv->InstallColormap = pScreen->InstallColormap;
- pScreenPriv->StoreColors = pScreen->StoreColors;
- pScreen->CloseScreen = CMapCloseScreen;
- pScreen->CreateColormap = CMapCreateColormap;
- pScreen->DestroyColormap = CMapDestroyColormap;
- pScreen->InstallColormap = CMapInstallColormap;
- pScreen->StoreColors = CMapStoreColors;
-
- pScreenPriv->pScrn = pScrn;
- pScrn->LoadPalette = loadPalette;
- pScrn->SetOverscan = setOverscan;
- pScreenPriv->maxColors = maxColors;
- pScreenPriv->sigRGBbits = sigRGBbits;
- pScreenPriv->gammaElements = elements;
- pScreenPriv->gamma = gamma;
- pScreenPriv->PreAllocIndices = indices;
- pScreenPriv->maps = NULL;
- pScreenPriv->flags = flags;
- pScreenPriv->isDGAmode = FALSE;
-
- pScreenPriv->EnterVT = pScrn->EnterVT;
- pScreenPriv->SwitchMode = pScrn->SwitchMode;
- pScreenPriv->SetDGAMode = pScrn->SetDGAMode;
- pScreenPriv->ChangeGamma = pScrn->ChangeGamma;
-
- if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) {
- pScrn->EnterVT = CMapEnterVT;
- if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode)
- pScrn->SwitchMode = CMapSwitchMode;
- }
-#ifdef XFreeXDGA
- pScrn->SetDGAMode = CMapSetDGAMode;
-#endif
- pScrn->ChangeGamma = CMapChangeGamma;
-
- ComputeGamma(pScreenPriv);
-
- /* get the default map */
- dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap,
- RT_COLORMAP, serverClient, DixInstallAccess);
-
- if(!CMapAllocateColormapPrivate(pDefMap)) {
- CMapUnwrapScreen(pScreen);
- return FALSE;
- }
-
- /* Force the initial map to be loaded */
- miInstalledMaps[pScreen->myNum] = NULL;
- CMapInstallColormap(pDefMap);
- return TRUE;
-}
-
-
-/**** Screen functions ****/
-
-
-static Bool
-CMapCloseScreen (int i, ScreenPtr pScreen)
-{
- CMapUnwrapScreen(pScreen);
-
- return (*pScreen->CloseScreen) (i, pScreen);
-}
-
-static Bool
-CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv)
-{
- if (pVisual->nplanes > 16)
- return TRUE;
- return ((1 << pVisual->nplanes) > pScreenPriv->maxColors);
-}
-
-static Bool
-CMapAllocateColormapPrivate(ColormapPtr pmap)
-{
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pmap->pScreen->devPrivates, CMapScreenKey);
- CMapColormapPtr pColPriv;
- CMapLinkPtr pLink;
- int numColors;
- LOCO *colors;
-
- if (CMapColormapUseMax(pmap->pVisual, pScreenPriv))
- numColors = pmap->pVisual->ColormapEntries;
- else
- numColors = 1 << pmap->pVisual->nplanes;
-
- if(!(colors = xalloc(numColors * sizeof(LOCO))))
- return FALSE;
-
- if(!(pColPriv = xalloc(sizeof(CMapColormapRec)))) {
- xfree(colors);
- return FALSE;
- }
-
- dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv);
-
- pColPriv->numColors = numColors;
- pColPriv->colors = colors;
- pColPriv->recalculate = TRUE;
- pColPriv->overscan = -1;
-
- /* add map to list */
- pLink = xalloc(sizeof(CMapLink));
- if(pLink) {
- pLink->cmap = pmap;
- pLink->next = pScreenPriv->maps;
- pScreenPriv->maps = pLink;
- }
-
- return TRUE;
-}
-
-static Bool
-CMapCreateColormap (ColormapPtr pmap)
-{
- ScreenPtr pScreen = pmap->pScreen;
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
- Bool ret = FALSE;
-
- pScreen->CreateColormap = pScreenPriv->CreateColormap;
- if((*pScreen->CreateColormap)(pmap)) {
- if(CMapAllocateColormapPrivate(pmap))
- ret = TRUE;
- }
- pScreen->CreateColormap = CMapCreateColormap;
-
- return ret;
-}
-
-static void
-CMapDestroyColormap (ColormapPtr cmap)
-{
- ScreenPtr pScreen = cmap->pScreen;
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
- CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
- &cmap->devPrivates, CMapColormapKey);
- CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps;
-
- if(pColPriv) {
- if(pColPriv->colors) xfree(pColPriv->colors);
- xfree(pColPriv);
- }
-
- /* remove map from list */
- while(pLink) {
- if(pLink->cmap == cmap) {
- if(prevLink)
- prevLink->next = pLink->next;
- else
- pScreenPriv->maps = pLink->next;
- xfree(pLink);
- break;
- }
- prevLink = pLink;
- pLink = pLink->next;
- }
-
- if(pScreenPriv->DestroyColormap) {
- pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
- (*pScreen->DestroyColormap)(cmap);
- pScreen->DestroyColormap = CMapDestroyColormap;
- }
-}
-
-
-
-static void
-CMapStoreColors(
- ColormapPtr pmap,
- int ndef,
- xColorItem *pdefs
-){
- ScreenPtr pScreen = pmap->pScreen;
- VisualPtr pVisual = pmap->pVisual;
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
- int *indices = pScreenPriv->PreAllocIndices;
- int num = ndef;
-
- /* At the moment this isn't necessary since there's nobody below us */
- pScreen->StoreColors = pScreenPriv->StoreColors;
- (*pScreen->StoreColors)(pmap, ndef, pdefs);
- pScreen->StoreColors = CMapStoreColors;
-
- /* should never get here for these */
- if( (pVisual->class == TrueColor) ||
- (pVisual->class == StaticColor) ||
- (pVisual->class == StaticGray))
- return;
-
- if(pVisual->class == DirectColor) {
- CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
- &pmap->devPrivates, CMapColormapKey);
- int i;
-
- if (CMapColormapUseMax(pVisual, pScreenPriv)) {
- int index;
-
- num = 0;
- while(ndef--) {
- if(pdefs[ndef].flags & DoRed) {
- index = (pdefs[ndef].pixel & pVisual->redMask) >>
- pVisual->offsetRed;
- i = num;
- while(i--)
- if(indices[i] == index) break;
- if(i == -1)
- indices[num++] = index;
- }
- if(pdefs[ndef].flags & DoGreen) {
- index = (pdefs[ndef].pixel & pVisual->greenMask) >>
- pVisual->offsetGreen;
- i = num;
- while(i--)
- if(indices[i] == index) break;
- if(i == -1)
- indices[num++] = index;
- }
- if(pdefs[ndef].flags & DoBlue) {
- index = (pdefs[ndef].pixel & pVisual->blueMask) >>
- pVisual->offsetBlue;
- i = num;
- while(i--)
- if(indices[i] == index) break;
- if(i == -1)
- indices[num++] = index;
- }
- }
-
- } else {
- /* not really as overkill as it seems */
- num = pColPriv->numColors;
- for(i = 0; i < pColPriv->numColors; i++)
- indices[i] = i;
- }
- } else {
- while(ndef--)
- indices[ndef] = pdefs[ndef].pixel;
- }
-
- CMapRefreshColors(pmap, num, indices);
-}
-
-
-static void
-CMapInstallColormap(ColormapPtr pmap)
-{
- ScreenPtr pScreen = pmap->pScreen;
- int index = pScreen->myNum;
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
-
- if (pmap == miInstalledMaps[index])
- return;
-
- pScreen->InstallColormap = pScreenPriv->InstallColormap;
- (*pScreen->InstallColormap)(pmap);
- pScreen->InstallColormap = CMapInstallColormap;
-
- /* Important. We let the lower layers, namely DGA,
- overwrite the choice of Colormap to install */
- if (miInstalledMaps[index])
- pmap = miInstalledMaps[index];
-
- if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
- (pmap->pVisual->class == TrueColor) &&
- CMapColormapUseMax(pmap->pVisual, pScreenPriv))
- return;
-
- if(LOAD_PALETTE(pmap, index))
- CMapReinstallMap(pmap);
-}
-
-
-/**** ScrnInfoRec functions ****/
-
-static Bool
-CMapEnterVT(int index, int flags)
-{
- ScreenPtr pScreen = screenInfo.screens[index];
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
-
- if((*pScreenPriv->EnterVT)(index, flags)) {
- if(miInstalledMaps[index])
- CMapReinstallMap(miInstalledMaps[index]);
- return TRUE;
- }
- return FALSE;
-}
-
-
-static Bool
-CMapSwitchMode(int index, DisplayModePtr mode, int flags)
-{
- ScreenPtr pScreen = screenInfo.screens[index];
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
-
- if((*pScreenPriv->SwitchMode)(index, mode, flags)) {
- if(miInstalledMaps[index])
- CMapReinstallMap(miInstalledMaps[index]);
- return TRUE;
- }
- return FALSE;
-}
-
-#ifdef XFreeXDGA
-static int
-CMapSetDGAMode(int index, int num, DGADevicePtr dev)
-{
- ScreenPtr pScreen = screenInfo.screens[index];
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
- int ret;
-
- ret = (*pScreenPriv->SetDGAMode)(index, num, dev);
-
- pScreenPriv->isDGAmode = DGAActive(index);
-
- if(!pScreenPriv->isDGAmode && miInstalledMaps[index]
- && xf86Screens[pScreen->myNum]->vtSema)
- CMapReinstallMap(miInstalledMaps[index]);
-
- return ret;
-}
-#endif
-
-
-/**** Utilities ****/
-
-static void
-CMapReinstallMap(ColormapPtr pmap)
-{
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pmap->pScreen->devPrivates, CMapScreenKey);
- CMapColormapPtr cmapPriv = (CMapColormapPtr)dixLookupPrivate(
- &pmap->devPrivates, CMapColormapKey);
- ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum];
- int i = cmapPriv->numColors;
- int *indices = pScreenPriv->PreAllocIndices;
-
- while(i--)
- indices[i] = i;
-
- if(cmapPriv->recalculate)
- CMapRefreshColors(pmap, cmapPriv->numColors, indices);
- else {
- (*pScrn->LoadPalette)(pScrn, cmapPriv->numColors,
- indices, cmapPriv->colors, pmap->pVisual);
- if (pScrn->SetOverscan) {
-#ifdef DEBUGOVERSCAN
- ErrorF("SetOverscan() called from CMapReinstallMap\n");
-#endif
- pScrn->SetOverscan(pScrn, cmapPriv->overscan);
- }
- }
-
- cmapPriv->recalculate = FALSE;
-}
-
-
-static void
-CMapRefreshColors(ColormapPtr pmap, int defs, int* indices)
-{
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pmap->pScreen->devPrivates, CMapScreenKey);
- CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
- &pmap->devPrivates, CMapColormapKey);
- VisualPtr pVisual = pmap->pVisual;
- ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum];
- int numColors, i;
- LOCO *gamma, *colors;
- EntryPtr entry;
- int reds, greens, blues, maxValue, index, shift;
-
- numColors = pColPriv->numColors;
- shift = 16 - pScreenPriv->sigRGBbits;
- maxValue = (1 << pScreenPriv->sigRGBbits) - 1;
- gamma = pScreenPriv->gamma;
- colors = pColPriv->colors;
-
- reds = pVisual->redMask >> pVisual->offsetRed;
- greens = pVisual->greenMask >> pVisual->offsetGreen;
- blues = pVisual->blueMask >> pVisual->offsetBlue;
-
- switch(pVisual->class) {
- case StaticGray:
- for(i = 0; i < numColors; i++) {
- index = (i+1) * maxValue / numColors;
- colors[i].red = gamma[index].red;
- colors[i].green = gamma[index].green;
- colors[i].blue = gamma[index].blue;
- }
- break;
- case TrueColor:
- if (CMapColormapUseMax(pVisual, pScreenPriv)) {
- for(i = 0; i <= reds; i++)
- colors[i].red = gamma[i * maxValue / reds].red;
- for(i = 0; i <= greens; i++)
- colors[i].green = gamma[i * maxValue / greens].green;
- for(i = 0; i <= blues; i++)
- colors[i].blue = gamma[i * maxValue / blues].blue;
- break;
- }
- for(i = 0; i < numColors; i++) {
- colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) *
- maxValue / reds].red;
- colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) *
- maxValue / greens].green;
- colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) *
- maxValue / blues].blue;
- }
- break;
- case StaticColor:
- case PseudoColor:
- case GrayScale:
- for(i = 0; i < defs; i++) {
- index = indices[i];
- entry = (EntryPtr)&pmap->red[index];
-
- if(entry->fShared) {
- colors[index].red =
- gamma[entry->co.shco.red->color >> shift].red;
- colors[index].green =
- gamma[entry->co.shco.green->color >> shift].green;
- colors[index].blue =
- gamma[entry->co.shco.blue->color >> shift].blue;
- } else {
- colors[index].red =
- gamma[entry->co.local.red >> shift].red;
- colors[index].green =
- gamma[entry->co.local.green >> shift].green;
- colors[index].blue =
- gamma[entry->co.local.blue >> shift].blue;
- }
- }
- break;
- case DirectColor:
- if (CMapColormapUseMax(pVisual, pScreenPriv)) {
- for(i = 0; i < defs; i++) {
- index = indices[i];
- if(index <= reds)
- colors[index].red =
- gamma[pmap->red[index].co.local.red >> shift].red;
- if(index <= greens)
- colors[index].green =
- gamma[pmap->green[index].co.local.green >> shift].green;
- if(index <= blues)
- colors[index].blue =
- gamma[pmap->blue[index].co.local.blue >> shift].blue;
-
- }
- break;
- }
- for(i = 0; i < defs; i++) {
- index = indices[i];
-
- colors[index].red = gamma[pmap->red[
- (index >> pVisual->offsetRed) & reds
- ].co.local.red >> shift].red;
- colors[index].green = gamma[pmap->green[
- (index >> pVisual->offsetGreen) & greens
- ].co.local.green >> shift].green;
- colors[index].blue = gamma[pmap->blue[
- (index >> pVisual->offsetBlue) & blues
- ].co.local.blue >> shift].blue;
- }
- break;
- }
-
-
- if(LOAD_PALETTE(pmap, pmap->pScreen->myNum))
- (*pScrn->LoadPalette)(pScreenPriv->pScrn, defs, indices,
- colors, pmap->pVisual);
-
- if (pScrn->SetOverscan)
- CMapSetOverscan(pmap, defs, indices);
-
-}
-
-static Bool
-CMapCompareColors(LOCO *color1, LOCO *color2)
-{
- /* return TRUE if the color1 is "closer" to black than color2 */
-#ifdef DEBUGOVERSCAN
- ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n",
- color1->red, color1->green, color1->blue,
- color2->red, color2->green, color2->blue,
- color1->red + color1->green + color1->blue,
- color2->red + color2->green + color2->blue);
-#endif
- return (color1->red + color1->green + color1->blue <
- color2->red + color2->green + color2->blue);
-}
-
-static void
-CMapSetOverscan(ColormapPtr pmap, int defs, int *indices)
-{
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pmap->pScreen->devPrivates, CMapScreenKey);
- CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
- &pmap->devPrivates, CMapColormapKey);
- ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum];
- VisualPtr pVisual = pmap->pVisual;
- int i;
- LOCO *colors;
- int index;
- Bool newOverscan = FALSE;
- int overscan, tmpOverscan;
-
- colors = pColPriv->colors;
- overscan = pColPriv->overscan;
-
- /*
- * Search for a new overscan index in the following cases:
- *
- * - The index hasn't yet been initialised.  In this case search
- * for an index that is black or a close match to black.
- *
- * - The colour of the old index is changed. In this case search
- * all indices for a black or close match to black.
- *
- * - The colour of the old index wasn't black. In this case only
- * search the indices that were changed for a better match to black.
- */
-
- switch (pVisual->class) {
- case StaticGray:
- case TrueColor:
- /* Should only come here once. Initialise the overscan index to 0 */
- overscan = 0;
- newOverscan = TRUE;
- break;
- case StaticColor:
- /*
- * Only come here once, but search for the overscan in the same way
- * as for the other cases.
- */
- case DirectColor:
- case PseudoColor:
- case GrayScale:
- if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) {
- /* Uninitialised */
- newOverscan = TRUE;
- } else {
- /* Check if the overscan was changed */
- for (i = 0; i < defs; i++) {
- index = indices[i];
- if (index == overscan) {
- newOverscan = TRUE;
- break;
- }
- }
- }
- if (newOverscan) {
- /* The overscan is either uninitialised or it has been changed */
-
- if (overscan < 0 || overscan > pScreenPriv->maxColors - 1)
- tmpOverscan = pScreenPriv->maxColors - 1;
- else
- tmpOverscan = overscan;
-
- /* search all entries for a close match to black */
- for (i = pScreenPriv->maxColors - 1; i >= 0; i--) {
- if (colors[i].red == 0 && colors[i].green == 0 &&
- colors[i].blue == 0) {
- overscan = i;
-#ifdef DEBUGOVERSCAN
- ErrorF("Black found at index 0x%02x\n", i);
-#endif
- break;
- } else {
-#ifdef DEBUGOVERSCAN
- ErrorF("0x%02x: ", i);
-#endif
- if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) {
- tmpOverscan = i;
-#ifdef DEBUGOVERSCAN
- ErrorF("possible \"Black\" at index 0x%02x\n", i);
-#endif
- }
- }
- }
- if (i < 0)
- overscan = tmpOverscan;
- } else {
- /* Check of the old overscan wasn't black */
- if (colors[overscan].red != 0 || colors[overscan].green != 0 ||
- colors[overscan].blue != 0) {
- int oldOverscan = tmpOverscan = overscan;
- /* See of there is now a better match */
- for (i = 0; i < defs; i++) {
- index = indices[i];
- if (colors[index].red == 0 && colors[index].green == 0 &&
- colors[index].blue == 0) {
- overscan = index;
-#ifdef DEBUGOVERSCAN
- ErrorF("Black found at index 0x%02x\n", index);
-#endif
- break;
- } else {
-#ifdef DEBUGOVERSCAN
- ErrorF("0x%02x: ", index);
-#endif
- if (CMapCompareColors(&colors[index],
- &colors[tmpOverscan])) {
- tmpOverscan = index;
-#ifdef DEBUGOVERSCAN
- ErrorF("possible \"Black\" at index 0x%02x\n",
- index);
-#endif
- }
- }
- }
- if (i == defs)
- overscan = tmpOverscan;
- if (overscan != oldOverscan)
- newOverscan = TRUE;
- }
- }
- break;
- }
- if (newOverscan) {
- pColPriv->overscan = overscan;
- if (LOAD_PALETTE(pmap, pmap->pScreen->myNum)) {
-#ifdef DEBUGOVERSCAN
- ErrorF("SetOverscan() called from CmapSetOverscan\n");
-#endif
- pScrn->SetOverscan(pScreenPriv->pScrn, overscan);
- }
- }
-}
-
-static void
-CMapUnwrapScreen(ScreenPtr pScreen)
-{
- CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, CMapScreenKey);
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- pScreen->CreateColormap = pScreenPriv->CreateColormap;
- pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
- pScreen->InstallColormap = pScreenPriv->InstallColormap;
- pScreen->StoreColors = pScreenPriv->StoreColors;
-
- pScrn->EnterVT = pScreenPriv->EnterVT;
- pScrn->SwitchMode = pScreenPriv->SwitchMode;
- pScrn->SetDGAMode = pScreenPriv->SetDGAMode;
- pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
-
- xfree(pScreenPriv->gamma);
- xfree(pScreenPriv->PreAllocIndices);
- xfree(pScreenPriv);
-}
-
-
-static void
-ComputeGamma(CMapScreenPtr priv)
-{
- int elements = priv->gammaElements - 1;
- double RedGamma, GreenGamma, BlueGamma;
- int i;
-
-#ifndef DONT_CHECK_GAMMA
- /* This check is to catch drivers that are not initialising pScrn->gamma */
- if (priv->pScrn->gamma.red < GAMMA_MIN ||
- priv->pScrn->gamma.red > GAMMA_MAX ||
- priv->pScrn->gamma.green < GAMMA_MIN ||
- priv->pScrn->gamma.green > GAMMA_MAX ||
- priv->pScrn->gamma.blue < GAMMA_MIN ||
- priv->pScrn->gamma.blue > GAMMA_MAX) {
-
- xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0,
- "The %s driver didn't call xf86SetGamma() to initialise\n"
- "\tthe gamma values.\n", priv->pScrn->driverName);
- xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0,
- "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName);
- priv->pScrn->gamma.red = 1.0;
- priv->pScrn->gamma.green = 1.0;
- priv->pScrn->gamma.blue = 1.0;
- }
-#endif
-
- RedGamma = 1.0 / (double)priv->pScrn->gamma.red;
- GreenGamma = 1.0 / (double)priv->pScrn->gamma.green;
- BlueGamma = 1.0 / (double)priv->pScrn->gamma.blue;
-
- for(i = 0; i <= elements; i++) {
- if(RedGamma == 1.0)
- priv->gamma[i].red = i;
- else
- priv->gamma[i].red = (CARD16)(pow((double)i/(double)elements,
- RedGamma) * (double)elements + 0.5);
-
- if(GreenGamma == 1.0)
- priv->gamma[i].green = i;
- else
- priv->gamma[i].green = (CARD16)(pow((double)i/(double)elements,
- GreenGamma) * (double)elements + 0.5);
-
- if(BlueGamma == 1.0)
- priv->gamma[i].blue = i;
- else
- priv->gamma[i].blue = (CARD16)(pow((double)i/(double)elements,
- BlueGamma) * (double)elements + 0.5);
- }
-}
-
-
-int
-CMapChangeGamma(
- int index,
- Gamma gamma
-){
- int ret = Success;
- ScrnInfoPtr pScrn = xf86Screens[index];
- ScreenPtr pScreen = pScrn->pScreen;
- CMapColormapPtr pColPriv;
- CMapScreenPtr pScreenPriv;
- CMapLinkPtr pLink;
-
- /* Is this sufficient checking ? */
- if(CMapScreenKey == NULL)
- return BadImplementation;
-
- pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- CMapScreenKey);
- if(!pScreenPriv)
- return BadImplementation;
-
- if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX ||
- gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX ||
- gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX)
- return BadValue;
-
- pScrn->gamma.red = gamma.red;
- pScrn->gamma.green = gamma.green;
- pScrn->gamma.blue = gamma.blue;
-
- ComputeGamma(pScreenPriv);
-
- /* mark all colormaps on this screen */
- pLink = pScreenPriv->maps;
- while(pLink) {
- pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates,
- CMapColormapKey);
- pColPriv->recalculate = TRUE;
- pLink = pLink->next;
- }
-
- if(miInstalledMaps[pScreen->myNum] &&
- ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
- pScrn->vtSema || pScreenPriv->isDGAmode)) {
- ColormapPtr pMap = miInstalledMaps[pScreen->myNum];
-
- if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
- (pMap->pVisual->class == TrueColor) &&
- CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
-
- /* if the current map doesn't have a palette look
- for another map to change the gamma on. */
-
- pLink = pScreenPriv->maps;
- while(pLink) {
- if(pLink->cmap->pVisual->class == PseudoColor)
- break;
- pLink = pLink->next;
- }
-
- if(pLink) {
- /* need to trick CMapRefreshColors() into thinking
- this is the currently installed map */
- miInstalledMaps[pScreen->myNum] = pLink->cmap;
- CMapReinstallMap(pLink->cmap);
- miInstalledMaps[pScreen->myNum] = pMap;
- }
- } else
- CMapReinstallMap(pMap);
- }
-
- pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
- if (pScrn->ChangeGamma)
- ret = pScrn->ChangeGamma(index, gamma);
- pScrn->ChangeGamma = CMapChangeGamma;
-
- return ret;
-}
-
-
-static void
-ComputeGammaRamp (
- CMapScreenPtr priv,
- unsigned short *red,
- unsigned short *green,
- unsigned short *blue
-){
- int elements = priv->gammaElements;
- LOCO *entry = priv->gamma;
- int shift = 16 - priv->sigRGBbits;
-
- while(elements--) {
- entry->red = *(red++) >> shift;
- entry->green = *(green++) >> shift;
- entry->blue = *(blue++) >> shift;
- entry++;
- }
-}
-
-int
-xf86ChangeGammaRamp(
- ScreenPtr pScreen,
- int size,
- unsigned short *red,
- unsigned short *green,
- unsigned short *blue
-){
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- CMapColormapPtr pColPriv;
- CMapScreenPtr pScreenPriv;
- CMapLinkPtr pLink;
-
- if (xf86_crtc_supports_gamma(pScrn)) {
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
- RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc;
-
- if (crtc->gammaSize != size)
- return BadValue;
-
- RRCrtcGammaSet(crtc, red, green, blue);
-
- return Success;
- }
-
- if(CMapScreenKey == NULL)
- return BadImplementation;
-
- pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- CMapScreenKey);
- if(!pScreenPriv)
- return BadImplementation;
-
- if(pScreenPriv->gammaElements != size)
- return BadValue;
-
- ComputeGammaRamp(pScreenPriv, red, green, blue);
-
- /* mark all colormaps on this screen */
- pLink = pScreenPriv->maps;
- while(pLink) {
- pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates,
- CMapColormapKey);
- pColPriv->recalculate = TRUE;
- pLink = pLink->next;
- }
-
- if(miInstalledMaps[pScreen->myNum] &&
- ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
- pScrn->vtSema || pScreenPriv->isDGAmode)) {
- ColormapPtr pMap = miInstalledMaps[pScreen->myNum];
-
- if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
- (pMap->pVisual->class == TrueColor) &&
- CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
-
- /* if the current map doesn't have a palette look
- for another map to change the gamma on. */
-
- pLink = pScreenPriv->maps;
- while(pLink) {
- if(pLink->cmap->pVisual->class == PseudoColor)
- break;
- pLink = pLink->next;
- }
-
- if(pLink) {
- /* need to trick CMapRefreshColors() into thinking
- this is the currently installed map */
- miInstalledMaps[pScreen->myNum] = pLink->cmap;
- CMapReinstallMap(pLink->cmap);
- miInstalledMaps[pScreen->myNum] = pMap;
- }
- } else
- CMapReinstallMap(pMap);
- }
-
- return Success;
-}
-
-int
-xf86GetGammaRampSize(ScreenPtr pScreen)
-{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- CMapScreenPtr pScreenPriv;
-
- if (xf86_crtc_supports_gamma(pScrn)) {
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
- RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc;
-
- return crtc->gammaSize;
- }
-
- if(CMapScreenKey == NULL) return 0;
-
- pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- CMapScreenKey);
- if(!pScreenPriv) return 0;
-
- return pScreenPriv->gammaElements;
-}
-
-int
-xf86GetGammaRamp(
- ScreenPtr pScreen,
- int size,
- unsigned short *red,
- unsigned short *green,
- unsigned short *blue
-){
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- CMapScreenPtr pScreenPriv;
- LOCO *entry;
- int shift, sigbits;
-
- if (xf86_crtc_supports_gamma(pScrn)) {
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
- RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc;
-
- if (crtc->gammaSize < size)
- return BadValue;
-
- if (!RRCrtcGammaGet(crtc))
- return BadImplementation;
-
- memcpy(red, crtc->gammaRed, size * sizeof(*red));
- memcpy(green, crtc->gammaGreen, size * sizeof(*green));
- memcpy(blue, crtc->gammaBlue, size * sizeof(*blue));
-
- return Success;
- }
-
- if(CMapScreenKey == NULL)
- return BadImplementation;
-
- pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- CMapScreenKey);
- if(!pScreenPriv)
- return BadImplementation;
-
- if(size > pScreenPriv->gammaElements)
- return BadValue;
-
- entry = pScreenPriv->gamma;
- sigbits = pScreenPriv->sigRGBbits;
-
- while(size--) {
- *red = entry->red << (16 - sigbits);
- *green = entry->green << (16 - sigbits);
- *blue = entry->blue << (16 - sigbits);
- shift = sigbits;
- while(shift < 16) {
- *red |= *red >> shift;
- *green |= *green >> shift;
- *blue |= *blue >> shift;
- shift += sigbits;
- }
- red++; green++; blue++;
- entry++;
- }
-
- return Success;
-}
-
-int
-xf86ChangeGamma(
- ScreenPtr pScreen,
- Gamma gamma
-){
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-
- if(pScrn->ChangeGamma)
- return (*pScrn->ChangeGamma)(pScreen->myNum, gamma);
-
- return BadImplementation;
-}
+/*
+ * Copyright (c) 1998-2001 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4)
+#include <math.h>
+#else
+#define _XOPEN_SOURCE /* to get prototype for pow on some systems */
+#include <math.h>
+#undef _XOPEN_SOURCE
+#endif
+
+#include <X11/X.h>
+#include "misc.h"
+#include <X11/Xproto.h>
+#include "colormapst.h"
+#include "scrnintstr.h"
+
+#include "resource.h"
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86str.h"
+#include "micmap.h"
+#include "xf86Crtc.h"
+
+#ifdef XFreeXDGA
+#include <X11/extensions/xf86dgaproto.h>
+#include "dgaproc.h"
+#endif
+
+#include "xf86cmap.h"
+
+#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
+ ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field)
+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
+ ((pScreen)->field = wrapper)
+
+#define LOAD_PALETTE(pmap, index) \
+ ((pmap == miInstalledMaps[index]) && \
+ ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \
+ xf86Screens[index]->vtSema || pScreenPriv->isDGAmode))
+
+
+typedef struct _CMapLink {
+ ColormapPtr cmap;
+ struct _CMapLink *next;
+} CMapLink, *CMapLinkPtr;
+
+typedef struct {
+ ScrnInfoPtr pScrn;
+ CloseScreenProcPtr CloseScreen;
+ CreateColormapProcPtr CreateColormap;
+ DestroyColormapProcPtr DestroyColormap;
+ InstallColormapProcPtr InstallColormap;
+ StoreColorsProcPtr StoreColors;
+ Bool (*EnterVT)(int, int);
+ Bool (*SwitchMode)(int, DisplayModePtr, int);
+ int (*SetDGAMode)(int, int, DGADevicePtr);
+ xf86ChangeGammaProc *ChangeGamma;
+ int maxColors;
+ int sigRGBbits;
+ int gammaElements;
+ LOCO *gamma;
+ int *PreAllocIndices;
+ CMapLinkPtr maps;
+ unsigned int flags;
+ Bool isDGAmode;
+} CMapScreenRec, *CMapScreenPtr;
+
+typedef struct {
+ int numColors;
+ LOCO *colors;
+ Bool recalculate;
+ int overscan;
+} CMapColormapRec, *CMapColormapPtr;
+
+static int CMapScreenKeyIndex;
+static DevPrivateKey CMapScreenKey;
+static int CMapColormapKeyIndex;
+static DevPrivateKey CMapColormapKey = &CMapColormapKeyIndex;
+
+static void CMapInstallColormap(ColormapPtr);
+static void CMapStoreColors(ColormapPtr, int, xColorItem *);
+static Bool CMapCloseScreen (int, ScreenPtr);
+static Bool CMapCreateColormap (ColormapPtr);
+static void CMapDestroyColormap (ColormapPtr);
+
+static Bool CMapEnterVT(int, int);
+static Bool CMapSwitchMode(int, DisplayModePtr, int);
+#ifdef XFreeXDGA
+static int CMapSetDGAMode(int, int, DGADevicePtr);
+#endif
+static int CMapChangeGamma(int, Gamma);
+
+static void ComputeGamma(CMapScreenPtr);
+static Bool CMapAllocateColormapPrivate(ColormapPtr);
+static void CMapRefreshColors(ColormapPtr, int, int*);
+static void CMapSetOverscan(ColormapPtr, int, int *);
+static void CMapReinstallMap(ColormapPtr);
+static void CMapUnwrapScreen(ScreenPtr pScreen);
+
+
+
+Bool xf86HandleColormaps(
+ ScreenPtr pScreen,
+ int maxColors,
+ int sigRGBbits,
+ xf86LoadPaletteProc *loadPalette,
+ xf86SetOverscanProc *setOverscan,
+ unsigned int flags
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ ColormapPtr pDefMap = NULL;
+ CMapScreenPtr pScreenPriv;
+ LOCO *gamma;
+ int *indices;
+ int elements;
+
+ /* If we support a better colormap system, then pretend we succeeded. */
+ if (xf86_crtc_supports_gamma(pScrn))
+ return TRUE;
+
+ if(!maxColors || !sigRGBbits || !loadPalette)
+ return FALSE;
+
+ CMapScreenKey = &CMapScreenKeyIndex;
+
+ elements = 1 << sigRGBbits;
+
+ if(!(gamma = xalloc(elements * sizeof(LOCO))))
+ return FALSE;
+
+ if(!(indices = xalloc(maxColors * sizeof(int)))) {
+ xfree(gamma);
+ return FALSE;
+ }
+
+ if(!(pScreenPriv = xalloc(sizeof(CMapScreenRec)))) {
+ xfree(gamma);
+ xfree(indices);
+ return FALSE;
+ }
+
+ dixSetPrivate(&pScreen->devPrivates, CMapScreenKey, pScreenPriv);
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreenPriv->CreateColormap = pScreen->CreateColormap;
+ pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
+ pScreenPriv->InstallColormap = pScreen->InstallColormap;
+ pScreenPriv->StoreColors = pScreen->StoreColors;
+ pScreen->CloseScreen = CMapCloseScreen;
+ pScreen->CreateColormap = CMapCreateColormap;
+ pScreen->DestroyColormap = CMapDestroyColormap;
+ pScreen->InstallColormap = CMapInstallColormap;
+ pScreen->StoreColors = CMapStoreColors;
+
+ pScreenPriv->pScrn = pScrn;
+ pScrn->LoadPalette = loadPalette;
+ pScrn->SetOverscan = setOverscan;
+ pScreenPriv->maxColors = maxColors;
+ pScreenPriv->sigRGBbits = sigRGBbits;
+ pScreenPriv->gammaElements = elements;
+ pScreenPriv->gamma = gamma;
+ pScreenPriv->PreAllocIndices = indices;
+ pScreenPriv->maps = NULL;
+ pScreenPriv->flags = flags;
+ pScreenPriv->isDGAmode = FALSE;
+
+ pScreenPriv->EnterVT = pScrn->EnterVT;
+ pScreenPriv->SwitchMode = pScrn->SwitchMode;
+ pScreenPriv->SetDGAMode = pScrn->SetDGAMode;
+ pScreenPriv->ChangeGamma = pScrn->ChangeGamma;
+
+ if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) {
+ pScrn->EnterVT = CMapEnterVT;
+ if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode)
+ pScrn->SwitchMode = CMapSwitchMode;
+ }
+#ifdef XFreeXDGA
+ pScrn->SetDGAMode = CMapSetDGAMode;
+#endif
+ pScrn->ChangeGamma = CMapChangeGamma;
+
+ ComputeGamma(pScreenPriv);
+
+ /* get the default map */
+ dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap,
+ RT_COLORMAP, serverClient, DixInstallAccess);
+
+ if(!CMapAllocateColormapPrivate(pDefMap)) {
+ CMapUnwrapScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Force the initial map to be loaded */
+ miInstalledMaps[pScreen->myNum] = NULL;
+ CMapInstallColormap(pDefMap);
+ return TRUE;
+}
+
+
+/**** Screen functions ****/
+
+
+static Bool
+CMapCloseScreen (int i, ScreenPtr pScreen)
+{
+ CMapUnwrapScreen(pScreen);
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static Bool
+CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv)
+{
+ if (pVisual->nplanes > 16)
+ return TRUE;
+ return ((1 << pVisual->nplanes) > pScreenPriv->maxColors);
+}
+
+static Bool
+CMapAllocateColormapPrivate(ColormapPtr pmap)
+{
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pmap->pScreen->devPrivates, CMapScreenKey);
+ CMapColormapPtr pColPriv;
+ CMapLinkPtr pLink;
+ int numColors;
+ LOCO *colors;
+
+ if (CMapColormapUseMax(pmap->pVisual, pScreenPriv))
+ numColors = pmap->pVisual->ColormapEntries;
+ else
+ numColors = 1 << pmap->pVisual->nplanes;
+
+ if(!(colors = xalloc(numColors * sizeof(LOCO))))
+ return FALSE;
+
+ if(!(pColPriv = xalloc(sizeof(CMapColormapRec)))) {
+ xfree(colors);
+ return FALSE;
+ }
+
+ dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv);
+
+ pColPriv->numColors = numColors;
+ pColPriv->colors = colors;
+ pColPriv->recalculate = TRUE;
+ pColPriv->overscan = -1;
+
+ /* add map to list */
+ pLink = xalloc(sizeof(CMapLink));
+ if(pLink) {
+ pLink->cmap = pmap;
+ pLink->next = pScreenPriv->maps;
+ pScreenPriv->maps = pLink;
+ }
+
+ return TRUE;
+}
+
+static Bool
+CMapCreateColormap (ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+ Bool ret = FALSE;
+
+ pScreen->CreateColormap = pScreenPriv->CreateColormap;
+ if((*pScreen->CreateColormap)(pmap)) {
+ if(CMapAllocateColormapPrivate(pmap))
+ ret = TRUE;
+ }
+ pScreen->CreateColormap = CMapCreateColormap;
+
+ return ret;
+}
+
+static void
+CMapDestroyColormap (ColormapPtr cmap)
+{
+ ScreenPtr pScreen = cmap->pScreen;
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+ CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
+ &cmap->devPrivates, CMapColormapKey);
+ CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps;
+
+ if(pColPriv) {
+ if(pColPriv->colors) xfree(pColPriv->colors);
+ xfree(pColPriv);
+ }
+
+ /* remove map from list */
+ while(pLink) {
+ if(pLink->cmap == cmap) {
+ if(prevLink)
+ prevLink->next = pLink->next;
+ else
+ pScreenPriv->maps = pLink->next;
+ xfree(pLink);
+ break;
+ }
+ prevLink = pLink;
+ pLink = pLink->next;
+ }
+
+ if(pScreenPriv->DestroyColormap) {
+ pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
+ (*pScreen->DestroyColormap)(cmap);
+ pScreen->DestroyColormap = CMapDestroyColormap;
+ }
+}
+
+
+
+static void
+CMapStoreColors(
+ ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs
+){
+ ScreenPtr pScreen = pmap->pScreen;
+ VisualPtr pVisual = pmap->pVisual;
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+ int *indices = pScreenPriv->PreAllocIndices;
+ int num = ndef;
+
+ /* At the moment this isn't necessary since there's nobody below us */
+ pScreen->StoreColors = pScreenPriv->StoreColors;
+ (*pScreen->StoreColors)(pmap, ndef, pdefs);
+ pScreen->StoreColors = CMapStoreColors;
+
+ /* should never get here for these */
+ if( (pVisual->class == TrueColor) ||
+ (pVisual->class == StaticColor) ||
+ (pVisual->class == StaticGray))
+ return;
+
+ if(pVisual->class == DirectColor) {
+ CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
+ &pmap->devPrivates, CMapColormapKey);
+ int i;
+
+ if (CMapColormapUseMax(pVisual, pScreenPriv)) {
+ int index;
+
+ num = 0;
+ while(ndef--) {
+ if(pdefs[ndef].flags & DoRed) {
+ index = (pdefs[ndef].pixel & pVisual->redMask) >>
+ pVisual->offsetRed;
+ i = num;
+ while(i--)
+ if(indices[i] == index) break;
+ if(i == -1)
+ indices[num++] = index;
+ }
+ if(pdefs[ndef].flags & DoGreen) {
+ index = (pdefs[ndef].pixel & pVisual->greenMask) >>
+ pVisual->offsetGreen;
+ i = num;
+ while(i--)
+ if(indices[i] == index) break;
+ if(i == -1)
+ indices[num++] = index;
+ }
+ if(pdefs[ndef].flags & DoBlue) {
+ index = (pdefs[ndef].pixel & pVisual->blueMask) >>
+ pVisual->offsetBlue;
+ i = num;
+ while(i--)
+ if(indices[i] == index) break;
+ if(i == -1)
+ indices[num++] = index;
+ }
+ }
+
+ } else {
+ /* not really as overkill as it seems */
+ num = pColPriv->numColors;
+ for(i = 0; i < pColPriv->numColors; i++)
+ indices[i] = i;
+ }
+ } else {
+ while(ndef--)
+ indices[ndef] = pdefs[ndef].pixel;
+ }
+
+ CMapRefreshColors(pmap, num, indices);
+}
+
+
+static void
+CMapInstallColormap(ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ int index = pScreen->myNum;
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+
+ if (pmap == miInstalledMaps[index])
+ return;
+
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ (*pScreen->InstallColormap)(pmap);
+ pScreen->InstallColormap = CMapInstallColormap;
+
+ /* Important. We let the lower layers, namely DGA,
+ overwrite the choice of Colormap to install */
+ if (miInstalledMaps[index])
+ pmap = miInstalledMaps[index];
+
+ if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
+ (pmap->pVisual->class == TrueColor) &&
+ CMapColormapUseMax(pmap->pVisual, pScreenPriv))
+ return;
+
+ if(LOAD_PALETTE(pmap, index))
+ CMapReinstallMap(pmap);
+}
+
+
+/**** ScrnInfoRec functions ****/
+
+static Bool
+CMapEnterVT(int index, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+
+ if((*pScreenPriv->EnterVT)(index, flags)) {
+ if(miInstalledMaps[index])
+ CMapReinstallMap(miInstalledMaps[index]);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static Bool
+CMapSwitchMode(int index, DisplayModePtr mode, int flags)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+
+ if((*pScreenPriv->SwitchMode)(index, mode, flags)) {
+ if(miInstalledMaps[index])
+ CMapReinstallMap(miInstalledMaps[index]);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#ifdef XFreeXDGA
+static int
+CMapSetDGAMode(int index, int num, DGADevicePtr dev)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+ int ret;
+
+ ret = (*pScreenPriv->SetDGAMode)(index, num, dev);
+
+ pScreenPriv->isDGAmode = DGAActive(index);
+
+ if(!pScreenPriv->isDGAmode && miInstalledMaps[index]
+ && xf86Screens[pScreen->myNum]->vtSema)
+ CMapReinstallMap(miInstalledMaps[index]);
+
+ return ret;
+}
+#endif
+
+
+/**** Utilities ****/
+
+static void
+CMapReinstallMap(ColormapPtr pmap)
+{
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pmap->pScreen->devPrivates, CMapScreenKey);
+ CMapColormapPtr cmapPriv = (CMapColormapPtr)dixLookupPrivate(
+ &pmap->devPrivates, CMapColormapKey);
+ ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum];
+ int i = cmapPriv->numColors;
+ int *indices = pScreenPriv->PreAllocIndices;
+
+ while(i--)
+ indices[i] = i;
+
+ if(cmapPriv->recalculate)
+ CMapRefreshColors(pmap, cmapPriv->numColors, indices);
+ else {
+ (*pScrn->LoadPalette)(pScrn, cmapPriv->numColors,
+ indices, cmapPriv->colors, pmap->pVisual);
+ if (pScrn->SetOverscan) {
+#ifdef DEBUGOVERSCAN
+ ErrorF("SetOverscan() called from CMapReinstallMap\n");
+#endif
+ pScrn->SetOverscan(pScrn, cmapPriv->overscan);
+ }
+ }
+
+ cmapPriv->recalculate = FALSE;
+}
+
+
+static void
+CMapRefreshColors(ColormapPtr pmap, int defs, int* indices)
+{
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pmap->pScreen->devPrivates, CMapScreenKey);
+ CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
+ &pmap->devPrivates, CMapColormapKey);
+ VisualPtr pVisual = pmap->pVisual;
+ ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum];
+ int numColors, i;
+ LOCO *gamma, *colors;
+ EntryPtr entry;
+ int reds, greens, blues, maxValue, index, shift;
+
+ numColors = pColPriv->numColors;
+ shift = 16 - pScreenPriv->sigRGBbits;
+ maxValue = (1 << pScreenPriv->sigRGBbits) - 1;
+ gamma = pScreenPriv->gamma;
+ colors = pColPriv->colors;
+
+ reds = pVisual->redMask >> pVisual->offsetRed;
+ greens = pVisual->greenMask >> pVisual->offsetGreen;
+ blues = pVisual->blueMask >> pVisual->offsetBlue;
+
+ switch(pVisual->class) {
+ case StaticGray:
+ for(i = 0; i < numColors; i++) {
+ index = (i+1) * maxValue / numColors;
+ colors[i].red = gamma[index].red;
+ colors[i].green = gamma[index].green;
+ colors[i].blue = gamma[index].blue;
+ }
+ break;
+ case TrueColor:
+ if (CMapColormapUseMax(pVisual, pScreenPriv)) {
+ for(i = 0; i <= reds; i++)
+ colors[i].red = gamma[i * maxValue / reds].red;
+ for(i = 0; i <= greens; i++)
+ colors[i].green = gamma[i * maxValue / greens].green;
+ for(i = 0; i <= blues; i++)
+ colors[i].blue = gamma[i * maxValue / blues].blue;
+ break;
+ }
+ for(i = 0; i < numColors; i++) {
+ colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) *
+ maxValue / reds].red;
+ colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) *
+ maxValue / greens].green;
+ colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) *
+ maxValue / blues].blue;
+ }
+ break;
+ case StaticColor:
+ case PseudoColor:
+ case GrayScale:
+ for(i = 0; i < defs; i++) {
+ index = indices[i];
+ entry = (EntryPtr)&pmap->red[index];
+
+ if(entry->fShared) {
+ colors[index].red =
+ gamma[entry->co.shco.red->color >> shift].red;
+ colors[index].green =
+ gamma[entry->co.shco.green->color >> shift].green;
+ colors[index].blue =
+ gamma[entry->co.shco.blue->color >> shift].blue;
+ } else {
+ colors[index].red =
+ gamma[entry->co.local.red >> shift].red;
+ colors[index].green =
+ gamma[entry->co.local.green >> shift].green;
+ colors[index].blue =
+ gamma[entry->co.local.blue >> shift].blue;
+ }
+ }
+ break;
+ case DirectColor:
+ if (CMapColormapUseMax(pVisual, pScreenPriv)) {
+ for(i = 0; i < defs; i++) {
+ index = indices[i];
+ if(index <= reds)
+ colors[index].red =
+ gamma[pmap->red[index].co.local.red >> shift].red;
+ if(index <= greens)
+ colors[index].green =
+ gamma[pmap->green[index].co.local.green >> shift].green;
+ if(index <= blues)
+ colors[index].blue =
+ gamma[pmap->blue[index].co.local.blue >> shift].blue;
+
+ }
+ break;
+ }
+ for(i = 0; i < defs; i++) {
+ index = indices[i];
+
+ colors[index].red = gamma[pmap->red[
+ (index >> pVisual->offsetRed) & reds
+ ].co.local.red >> shift].red;
+ colors[index].green = gamma[pmap->green[
+ (index >> pVisual->offsetGreen) & greens
+ ].co.local.green >> shift].green;
+ colors[index].blue = gamma[pmap->blue[
+ (index >> pVisual->offsetBlue) & blues
+ ].co.local.blue >> shift].blue;
+ }
+ break;
+ }
+
+
+ if(LOAD_PALETTE(pmap, pmap->pScreen->myNum))
+ (*pScrn->LoadPalette)(pScreenPriv->pScrn, defs, indices,
+ colors, pmap->pVisual);
+
+ if (pScrn->SetOverscan)
+ CMapSetOverscan(pmap, defs, indices);
+
+}
+
+static Bool
+CMapCompareColors(LOCO *color1, LOCO *color2)
+{
+ /* return TRUE if the color1 is "closer" to black than color2 */
+#ifdef DEBUGOVERSCAN
+ ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n",
+ color1->red, color1->green, color1->blue,
+ color2->red, color2->green, color2->blue,
+ color1->red + color1->green + color1->blue,
+ color2->red + color2->green + color2->blue);
+#endif
+ return (color1->red + color1->green + color1->blue <
+ color2->red + color2->green + color2->blue);
+}
+
+static void
+CMapSetOverscan(ColormapPtr pmap, int defs, int *indices)
+{
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pmap->pScreen->devPrivates, CMapScreenKey);
+ CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate(
+ &pmap->devPrivates, CMapColormapKey);
+ ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum];
+ VisualPtr pVisual = pmap->pVisual;
+ int i;
+ LOCO *colors;
+ int index;
+ Bool newOverscan = FALSE;
+ int overscan, tmpOverscan;
+
+ colors = pColPriv->colors;
+ overscan = pColPriv->overscan;
+
+ /*
+ * Search for a new overscan index in the following cases:
+ *
+ * - The index hasn't yet been initialised.  In this case search
+ * for an index that is black or a close match to black.
+ *
+ * - The colour of the old index is changed. In this case search
+ * all indices for a black or close match to black.
+ *
+ * - The colour of the old index wasn't black. In this case only
+ * search the indices that were changed for a better match to black.
+ */
+
+ switch (pVisual->class) {
+ case StaticGray:
+ case TrueColor:
+ /* Should only come here once. Initialise the overscan index to 0 */
+ overscan = 0;
+ newOverscan = TRUE;
+ break;
+ case StaticColor:
+ /*
+ * Only come here once, but search for the overscan in the same way
+ * as for the other cases.
+ */
+ case DirectColor:
+ case PseudoColor:
+ case GrayScale:
+ if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) {
+ /* Uninitialised */
+ newOverscan = TRUE;
+ } else {
+ /* Check if the overscan was changed */
+ for (i = 0; i < defs; i++) {
+ index = indices[i];
+ if (index == overscan) {
+ newOverscan = TRUE;
+ break;
+ }
+ }
+ }
+ if (newOverscan) {
+ /* The overscan is either uninitialised or it has been changed */
+
+ if (overscan < 0 || overscan > pScreenPriv->maxColors - 1)
+ tmpOverscan = pScreenPriv->maxColors - 1;
+ else
+ tmpOverscan = overscan;
+
+ /* search all entries for a close match to black */
+ for (i = pScreenPriv->maxColors - 1; i >= 0; i--) {
+ if (colors[i].red == 0 && colors[i].green == 0 &&
+ colors[i].blue == 0) {
+ overscan = i;
+#ifdef DEBUGOVERSCAN
+ ErrorF("Black found at index 0x%02x\n", i);
+#endif
+ break;
+ } else {
+#ifdef DEBUGOVERSCAN
+ ErrorF("0x%02x: ", i);
+#endif
+ if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) {
+ tmpOverscan = i;
+#ifdef DEBUGOVERSCAN
+ ErrorF("possible \"Black\" at index 0x%02x\n", i);
+#endif
+ }
+ }
+ }
+ if (i < 0)
+ overscan = tmpOverscan;
+ } else {
+ /* Check of the old overscan wasn't black */
+ if (colors[overscan].red != 0 || colors[overscan].green != 0 ||
+ colors[overscan].blue != 0) {
+ int oldOverscan = tmpOverscan = overscan;
+ /* See of there is now a better match */
+ for (i = 0; i < defs; i++) {
+ index = indices[i];
+ if (colors[index].red == 0 && colors[index].green == 0 &&
+ colors[index].blue == 0) {
+ overscan = index;
+#ifdef DEBUGOVERSCAN
+ ErrorF("Black found at index 0x%02x\n", index);
+#endif
+ break;
+ } else {
+#ifdef DEBUGOVERSCAN
+ ErrorF("0x%02x: ", index);
+#endif
+ if (CMapCompareColors(&colors[index],
+ &colors[tmpOverscan])) {
+ tmpOverscan = index;
+#ifdef DEBUGOVERSCAN
+ ErrorF("possible \"Black\" at index 0x%02x\n",
+ index);
+#endif
+ }
+ }
+ }
+ if (i == defs)
+ overscan = tmpOverscan;
+ if (overscan != oldOverscan)
+ newOverscan = TRUE;
+ }
+ }
+ break;
+ }
+ if (newOverscan) {
+ pColPriv->overscan = overscan;
+ if (LOAD_PALETTE(pmap, pmap->pScreen->myNum)) {
+#ifdef DEBUGOVERSCAN
+ ErrorF("SetOverscan() called from CmapSetOverscan\n");
+#endif
+ pScrn->SetOverscan(pScreenPriv->pScrn, overscan);
+ }
+ }
+}
+
+static void
+CMapUnwrapScreen(ScreenPtr pScreen)
+{
+ CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate(
+ &pScreen->devPrivates, CMapScreenKey);
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->CreateColormap = pScreenPriv->CreateColormap;
+ pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ pScreen->StoreColors = pScreenPriv->StoreColors;
+
+ pScrn->EnterVT = pScreenPriv->EnterVT;
+ pScrn->SwitchMode = pScreenPriv->SwitchMode;
+ pScrn->SetDGAMode = pScreenPriv->SetDGAMode;
+ pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
+
+ xfree(pScreenPriv->gamma);
+ xfree(pScreenPriv->PreAllocIndices);
+ xfree(pScreenPriv);
+}
+
+
+static void
+ComputeGamma(CMapScreenPtr priv)
+{
+ int elements = priv->gammaElements - 1;
+ double RedGamma, GreenGamma, BlueGamma;
+ int i;
+
+#ifndef DONT_CHECK_GAMMA
+ /* This check is to catch drivers that are not initialising pScrn->gamma */
+ if (priv->pScrn->gamma.red < GAMMA_MIN ||
+ priv->pScrn->gamma.red > GAMMA_MAX ||
+ priv->pScrn->gamma.green < GAMMA_MIN ||
+ priv->pScrn->gamma.green > GAMMA_MAX ||
+ priv->pScrn->gamma.blue < GAMMA_MIN ||
+ priv->pScrn->gamma.blue > GAMMA_MAX) {
+
+ xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0,
+ "The %s driver didn't call xf86SetGamma() to initialise\n"
+ "\tthe gamma values.\n", priv->pScrn->driverName);
+ xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0,
+ "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName);
+ priv->pScrn->gamma.red = 1.0;
+ priv->pScrn->gamma.green = 1.0;
+ priv->pScrn->gamma.blue = 1.0;
+ }
+#endif
+
+ RedGamma = 1.0 / (double)priv->pScrn->gamma.red;
+ GreenGamma = 1.0 / (double)priv->pScrn->gamma.green;
+ BlueGamma = 1.0 / (double)priv->pScrn->gamma.blue;
+
+ for(i = 0; i <= elements; i++) {
+ if(RedGamma == 1.0)
+ priv->gamma[i].red = i;
+ else
+ priv->gamma[i].red = (CARD16)(pow((double)i/(double)elements,
+ RedGamma) * (double)elements + 0.5);
+
+ if(GreenGamma == 1.0)
+ priv->gamma[i].green = i;
+ else
+ priv->gamma[i].green = (CARD16)(pow((double)i/(double)elements,
+ GreenGamma) * (double)elements + 0.5);
+
+ if(BlueGamma == 1.0)
+ priv->gamma[i].blue = i;
+ else
+ priv->gamma[i].blue = (CARD16)(pow((double)i/(double)elements,
+ BlueGamma) * (double)elements + 0.5);
+ }
+}
+
+
+int
+CMapChangeGamma(
+ int index,
+ Gamma gamma
+){
+ int ret = Success;
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ ScreenPtr pScreen = pScrn->pScreen;
+ CMapColormapPtr pColPriv;
+ CMapScreenPtr pScreenPriv;
+ CMapLinkPtr pLink;
+
+ /* Is this sufficient checking ? */
+ if(CMapScreenKey == NULL)
+ return BadImplementation;
+
+ pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ CMapScreenKey);
+ if(!pScreenPriv)
+ return BadImplementation;
+
+ if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX ||
+ gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX ||
+ gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX)
+ return BadValue;
+
+ pScrn->gamma.red = gamma.red;
+ pScrn->gamma.green = gamma.green;
+ pScrn->gamma.blue = gamma.blue;
+
+ ComputeGamma(pScreenPriv);
+
+ /* mark all colormaps on this screen */
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates,
+ CMapColormapKey);
+ pColPriv->recalculate = TRUE;
+ pLink = pLink->next;
+ }
+
+ if(miInstalledMaps[pScreen->myNum] &&
+ ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
+ pScrn->vtSema || pScreenPriv->isDGAmode)) {
+ ColormapPtr pMap = miInstalledMaps[pScreen->myNum];
+
+ if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
+ (pMap->pVisual->class == TrueColor) &&
+ CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
+
+ /* if the current map doesn't have a palette look
+ for another map to change the gamma on. */
+
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ if(pLink->cmap->pVisual->class == PseudoColor)
+ break;
+ pLink = pLink->next;
+ }
+
+ if(pLink) {
+ /* need to trick CMapRefreshColors() into thinking
+ this is the currently installed map */
+ miInstalledMaps[pScreen->myNum] = pLink->cmap;
+ CMapReinstallMap(pLink->cmap);
+ miInstalledMaps[pScreen->myNum] = pMap;
+ }
+ } else
+ CMapReinstallMap(pMap);
+ }
+
+ pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
+ if (pScrn->ChangeGamma)
+ ret = pScrn->ChangeGamma(index, gamma);
+ pScrn->ChangeGamma = CMapChangeGamma;
+
+ return ret;
+}
+
+
+static void
+ComputeGammaRamp (
+ CMapScreenPtr priv,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+){
+ int elements = priv->gammaElements;
+ LOCO *entry = priv->gamma;
+ int shift = 16 - priv->sigRGBbits;
+
+ while(elements--) {
+ entry->red = *(red++) >> shift;
+ entry->green = *(green++) >> shift;
+ entry->blue = *(blue++) >> shift;
+ entry++;
+ }
+}
+
+int
+xf86ChangeGammaRamp(
+ ScreenPtr pScreen,
+ int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CMapColormapPtr pColPriv;
+ CMapScreenPtr pScreenPriv;
+ CMapLinkPtr pLink;
+
+ if (xf86_crtc_supports_gamma(pScrn)) {
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc;
+
+ if (crtc) {
+ if (crtc->gammaSize != size)
+ return BadValue;
+
+ RRCrtcGammaSet(crtc, red, green, blue);
+
+ return Success;
+ }
+ }
+
+ if(CMapScreenKey == NULL)
+ return BadImplementation;
+
+ pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ CMapScreenKey);
+ if(!pScreenPriv)
+ return BadImplementation;
+
+ if(pScreenPriv->gammaElements != size)
+ return BadValue;
+
+ ComputeGammaRamp(pScreenPriv, red, green, blue);
+
+ /* mark all colormaps on this screen */
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates,
+ CMapColormapKey);
+ pColPriv->recalculate = TRUE;
+ pLink = pLink->next;
+ }
+
+ if(miInstalledMaps[pScreen->myNum] &&
+ ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
+ pScrn->vtSema || pScreenPriv->isDGAmode)) {
+ ColormapPtr pMap = miInstalledMaps[pScreen->myNum];
+
+ if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
+ (pMap->pVisual->class == TrueColor) &&
+ CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
+
+ /* if the current map doesn't have a palette look
+ for another map to change the gamma on. */
+
+ pLink = pScreenPriv->maps;
+ while(pLink) {
+ if(pLink->cmap->pVisual->class == PseudoColor)
+ break;
+ pLink = pLink->next;
+ }
+
+ if(pLink) {
+ /* need to trick CMapRefreshColors() into thinking
+ this is the currently installed map */
+ miInstalledMaps[pScreen->myNum] = pLink->cmap;
+ CMapReinstallMap(pLink->cmap);
+ miInstalledMaps[pScreen->myNum] = pMap;
+ }
+ } else
+ CMapReinstallMap(pMap);
+ }
+
+ return Success;
+}
+
+int
+xf86GetGammaRampSize(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CMapScreenPtr pScreenPriv;
+
+ if (xf86_crtc_supports_gamma(pScrn)) {
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc;
+
+ if (crtc)
+ return crtc->gammaSize;
+ }
+
+ if(CMapScreenKey == NULL) return 0;
+
+ pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ CMapScreenKey);
+ if(!pScreenPriv) return 0;
+
+ return pScreenPriv->gammaElements;
+}
+
+int
+xf86GetGammaRamp(
+ ScreenPtr pScreen,
+ int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CMapScreenPtr pScreenPriv;
+ LOCO *entry;
+ int shift, sigbits;
+
+ if (xf86_crtc_supports_gamma(pScrn)) {
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc;
+
+ if (crtc) {
+ if (crtc->gammaSize < size)
+ return BadValue;
+
+ if (!RRCrtcGammaGet(crtc))
+ return BadImplementation;
+
+ memcpy(red, crtc->gammaRed, size * sizeof(*red));
+ memcpy(green, crtc->gammaGreen, size * sizeof(*green));
+ memcpy(blue, crtc->gammaBlue, size * sizeof(*blue));
+
+ return Success;
+ }
+ }
+
+ if(CMapScreenKey == NULL)
+ return BadImplementation;
+
+ pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ CMapScreenKey);
+ if(!pScreenPriv)
+ return BadImplementation;
+
+ if(size > pScreenPriv->gammaElements)
+ return BadValue;
+
+ entry = pScreenPriv->gamma;
+ sigbits = pScreenPriv->sigRGBbits;
+
+ while(size--) {
+ *red = entry->red << (16 - sigbits);
+ *green = entry->green << (16 - sigbits);
+ *blue = entry->blue << (16 - sigbits);
+ shift = sigbits;
+ while(shift < 16) {
+ *red |= *red >> shift;
+ *green |= *green >> shift;
+ *blue |= *blue >> shift;
+ shift += sigbits;
+ }
+ red++; green++; blue++;
+ entry++;
+ }
+
+ return Success;
+}
+
+int
+xf86ChangeGamma(
+ ScreenPtr pScreen,
+ Gamma gamma
+){
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if(pScrn->ChangeGamma)
+ return (*pScrn->ChangeGamma)(pScreen->myNum, gamma);
+
+ return BadImplementation;
+}
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c
index 3db826e91..787544c20 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.c
+++ b/xorg-server/hw/xfree86/dri2/dri2.c
@@ -1,892 +1,934 @@
-/*
- * Copyright © 2007, 2008 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Soft-
- * ware"), to deal in the Software without restriction, including without
- * limitation the rights to use, copy, modify, merge, publish, distribute,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, provided that the above copyright
- * notice(s) and this permission notice appear in all copies of the Soft-
- * ware and that both the above copyright notice(s) and this permission
- * notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
- * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
- * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
- * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
- * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
- * MANCE OF THIS SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder shall
- * not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization of
- * the copyright holder.
- *
- * Authors:
- * Kristian Høgsberg (krh@redhat.com)
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <errno.h>
-#include <xf86drm.h>
-#include "xf86Module.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "dixstruct.h"
-#include "dri2.h"
-#include "xf86VGAarbiter.h"
-
-#include "xf86.h"
-
-static int dri2ScreenPrivateKeyIndex;
-static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
-static int dri2WindowPrivateKeyIndex;
-static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
-static int dri2PixmapPrivateKeyIndex;
-static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
-
-typedef struct _DRI2Drawable {
- unsigned int refCount;
- int width;
- int height;
- DRI2BufferPtr *buffers;
- int bufferCount;
- unsigned int swapsPending;
- ClientPtr blockedClient;
- int swap_interval;
- CARD64 swap_count;
- CARD64 target_sbc; /* -1 means no SBC wait outstanding */
- CARD64 last_swap_target; /* most recently queued swap target */
- int swap_limit; /* for N-buffering */
-} DRI2DrawableRec, *DRI2DrawablePtr;
-
-typedef struct _DRI2Screen *DRI2ScreenPtr;
-
-typedef struct _DRI2Screen {
- const char *driverName;
- const char *deviceName;
- int fd;
- unsigned int lastSequence;
-
- DRI2CreateBufferProcPtr CreateBuffer;
- DRI2DestroyBufferProcPtr DestroyBuffer;
- DRI2CopyRegionProcPtr CopyRegion;
- DRI2ScheduleSwapProcPtr ScheduleSwap;
- DRI2GetMSCProcPtr GetMSC;
- DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
-
- HandleExposuresProcPtr HandleExposures;
-} DRI2ScreenRec;
-
-static DRI2ScreenPtr
-DRI2GetScreen(ScreenPtr pScreen)
-{
- return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
-}
-
-static DRI2DrawablePtr
-DRI2GetDrawable(DrawablePtr pDraw)
-{
- WindowPtr pWin;
- PixmapPtr pPixmap;
-
- if (!pDraw)
- return NULL;
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pWin = (WindowPtr) pDraw;
- return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
- }
- else
- {
- pPixmap = (PixmapPtr) pDraw;
- return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
- }
-}
-
-int
-DRI2CreateDrawable(DrawablePtr pDraw)
-{
- WindowPtr pWin;
- PixmapPtr pPixmap;
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv != NULL)
- {
- pPriv->refCount++;
- return Success;
- }
-
- pPriv = xalloc(sizeof *pPriv);
- if (pPriv == NULL)
- return BadAlloc;
-
- pPriv->refCount = 1;
- pPriv->width = pDraw->width;
- pPriv->height = pDraw->height;
- pPriv->buffers = NULL;
- pPriv->bufferCount = 0;
- pPriv->swapsPending = 0;
- pPriv->blockedClient = NULL;
- pPriv->swap_count = 0;
- pPriv->target_sbc = -1;
- pPriv->swap_interval = 1;
- pPriv->last_swap_target = -1;
- pPriv->swap_limit = 1; /* default to double buffering */
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pWin = (WindowPtr) pDraw;
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
- }
- else
- {
- pPixmap = (PixmapPtr) pDraw;
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
- }
-
- return Success;
-}
-
-static int
-find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
-{
- int i;
-
- if (pPriv->buffers == NULL) {
- return -1;
- }
-
- for (i = 0; i < pPriv->bufferCount; i++) {
- if ((pPriv->buffers[i] != NULL)
- && (pPriv->buffers[i]->attachment == attachment)) {
- return i;
- }
- }
-
- return -1;
-}
-
-static DRI2BufferPtr
-allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
- DRI2DrawablePtr pPriv,
- unsigned int attachment, unsigned int format,
- int dimensions_match)
-{
- DRI2BufferPtr buffer;
- int old_buf;
-
- old_buf = find_attachment(pPriv, attachment);
-
- if ((old_buf < 0)
- || !dimensions_match
- || (pPriv->buffers[old_buf]->format != format)) {
- buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
- } else {
- buffer = pPriv->buffers[old_buf];
- pPriv->buffers[old_buf] = NULL;
- }
-
- return buffer;
-}
-
-static DRI2BufferPtr *
-do_get_buffers(DrawablePtr pDraw, int *width, int *height,
- unsigned int *attachments, int count, int *out_count,
- int has_format)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
- DRI2BufferPtr *buffers;
- int need_real_front = 0;
- int need_fake_front = 0;
- int have_fake_front = 0;
- int front_format = 0;
- int dimensions_match;
- int i;
-
- if (!pPriv) {
- *width = pDraw->width;
- *height = pDraw->height;
- *out_count = 0;
- return NULL;
- }
-
- dimensions_match = (pDraw->width == pPriv->width)
- && (pDraw->height == pPriv->height);
-
- buffers = xalloc((count + 1) * sizeof(buffers[0]));
-
- for (i = 0; i < count; i++) {
- const unsigned attachment = *(attachments++);
- const unsigned format = (has_format) ? *(attachments++) : 0;
-
- buffers[i] = allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
- format, dimensions_match);
-
- /* If the drawable is a window and the front-buffer is requested,
- * silently add the fake front-buffer to the list of requested
- * attachments. The counting logic in the loop accounts for the case
- * where the client requests both the fake and real front-buffer.
- */
- if (attachment == DRI2BufferBackLeft) {
- need_real_front++;
- front_format = format;
- }
-
- if (attachment == DRI2BufferFrontLeft) {
- need_real_front--;
- front_format = format;
-
- if (pDraw->type == DRAWABLE_WINDOW) {
- need_fake_front++;
- }
- }
-
- if (pDraw->type == DRAWABLE_WINDOW) {
- if (attachment == DRI2BufferFakeFrontLeft) {
- need_fake_front--;
- have_fake_front = 1;
- }
- }
- }
-
- if (need_real_front > 0) {
- buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
- DRI2BufferFrontLeft,
- front_format, dimensions_match);
- }
-
- if (need_fake_front > 0) {
- buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
- DRI2BufferFakeFrontLeft,
- front_format, dimensions_match);
- have_fake_front = 1;
- }
-
- *out_count = i;
-
-
- if (pPriv->buffers != NULL) {
- for (i = 0; i < pPriv->bufferCount; i++) {
- if (pPriv->buffers[i] != NULL) {
- (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
- }
- }
-
- xfree(pPriv->buffers);
- }
-
- pPriv->buffers = buffers;
- pPriv->bufferCount = *out_count;
- pPriv->width = pDraw->width;
- pPriv->height = pDraw->height;
- *width = pPriv->width;
- *height = pPriv->height;
-
-
- /* If the client is getting a fake front-buffer, pre-fill it with the
- * contents of the real front-buffer. This ensures correct operation of
- * applications that call glXWaitX before calling glDrawBuffer.
- */
- if (have_fake_front) {
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pPriv->width;
- box.y2 = pPriv->height;
- REGION_INIT(pDraw->pScreen, &region, &box, 0);
-
- DRI2CopyRegion(pDraw, &region, DRI2BufferFakeFrontLeft,
- DRI2BufferFrontLeft);
- }
-
- return pPriv->buffers;
-}
-
-DRI2BufferPtr *
-DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
- unsigned int *attachments, int count, int *out_count)
-{
- return do_get_buffers(pDraw, width, height, attachments, count,
- out_count, FALSE);
-}
-
-DRI2BufferPtr *
-DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
- unsigned int *attachments, int count, int *out_count)
-{
- return do_get_buffers(pDraw, width, height, attachments, count,
- out_count, TRUE);
-}
-
-/*
- * In the direct rendered case, we throttle the clients that have more
- * than their share of outstanding swaps (and thus busy buffers) when a
- * new GetBuffers request is received. In the AIGLX case, we allow the
- * client to get the new buffers, but throttle when the next GLX request
- * comes in (see __glXDRIcontextWait()).
- */
-Bool
-DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return FALSE;
-
- /* Throttle to swap limit */
- if ((pPriv->swapsPending >= pPriv->swap_limit) &&
- !pPriv->blockedClient) {
- ResetCurrentRequest(client);
- client->sequence--;
- IgnoreClient(client);
- pPriv->blockedClient = client;
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return;
-
- if (pPriv->blockedClient == NULL) {
- IgnoreClient(client);
- pPriv->blockedClient = client;
- }
-}
-
-int
-DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
- unsigned int dest, unsigned int src)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- DRI2BufferPtr pDestBuffer, pSrcBuffer;
- int i;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return BadDrawable;
-
- pDestBuffer = NULL;
- pSrcBuffer = NULL;
- for (i = 0; i < pPriv->bufferCount; i++)
- {
- if (pPriv->buffers[i]->attachment == dest)
- pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- if (pPriv->buffers[i]->attachment == src)
- pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- }
- if (pSrcBuffer == NULL || pDestBuffer == NULL)
- return BadValue;
-
- (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer);
-
- return Success;
-}
-
-/* Can this drawable be page flipped? */
-Bool
-DRI2CanFlip(DrawablePtr pDraw)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- WindowPtr pWin, pRoot;
- PixmapPtr pWinPixmap, pRootPixmap;
-
- if (pDraw->type == DRAWABLE_PIXMAP)
- return TRUE;
-
- pRoot = WindowTable[pScreen->myNum];
- pRootPixmap = pScreen->GetWindowPixmap(pRoot);
-
- pWin = (WindowPtr) pDraw;
- pWinPixmap = pScreen->GetWindowPixmap(pWin);
- if (pRootPixmap != pWinPixmap)
- return FALSE;
- if (!REGION_EQUAL(pScreen, &pWin->clipList, &pRoot->winSize))
- return FALSE;
-
- return TRUE;
-}
-
-/* Can we do a pixmap exchange instead of a blit? */
-Bool
-DRI2CanExchange(DrawablePtr pDraw)
-{
- return FALSE;
-}
-
-void
-DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
- unsigned int tv_sec, unsigned int tv_usec)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return;
-
- ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
- frame, pPriv->swap_count);
-
- if (pPriv->blockedClient)
- AttendClient(pPriv->blockedClient);
-
- pPriv->blockedClient = NULL;
-}
-
-static void
-DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
- unsigned int tv_sec, unsigned int tv_usec)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return;
- }
-
- /*
- * Swap completed. Either wake up an SBC waiter or a client that was
- * blocked due to GLX activity during a swap.
- */
- if (pPriv->target_sbc != -1 &&
- pPriv->target_sbc >= pPriv->swap_count) {
- ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
- frame, pPriv->swap_count);
- pPriv->target_sbc = -1;
-
- AttendClient(pPriv->blockedClient);
- pPriv->blockedClient = NULL;
- } else if (pPriv->target_sbc == -1) {
- if (pPriv->blockedClient)
- AttendClient(pPriv->blockedClient);
- pPriv->blockedClient = NULL;
- }
-}
-
-void
-DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
- unsigned int tv_sec, unsigned int tv_usec, int type,
- DRI2SwapEventPtr swap_complete, void *swap_data)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2DrawablePtr pPriv;
- CARD64 ust = 0;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return;
- }
-
- if (pPriv->refCount == 0) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable refcount\n", __func__);
- xfree(pPriv);
- return;
- }
-
- ust = ((CARD64)tv_sec * 1000000) + tv_usec;
- if (swap_complete)
- swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
-
- pPriv->swapsPending--;
- pPriv->swap_count++;
-
- DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
-}
-
-Bool
-DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
-{
- DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
-
- /* If we're currently waiting for a swap on this drawable, reset
- * the request and suspend the client. We only support one
- * blocked client per drawable. */
- if ((pPriv->swapsPending) &&
- pPriv->blockedClient == NULL) {
- ResetCurrentRequest(client);
- client->sequence--;
- DRI2BlockClient(client, pDrawable);
- return TRUE;
- }
-
- return FALSE;
-}
-
-int
-DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
- CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
- DRI2SwapEventPtr func, void *data)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
- CARD64 ust;
- int ret, i;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return BadDrawable;
- }
-
- for (i = 0; i < pPriv->bufferCount; i++) {
- if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
- pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
- pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- }
- if (pSrcBuffer == NULL || pDestBuffer == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: drawable has no back or front?\n", __func__);
- return BadDrawable;
- }
-
- /* Old DDX, just blit */
- if (!ds->ScheduleSwap) {
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pDraw->width;
- box.y2 = pDraw->height;
- REGION_INIT(pScreen, &region, &box, 0);
-
- pPriv->swapsPending++;
-
- (*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
- DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
- func, data);
- return Success;
- }
-
- /*
- * In the simple glXSwapBuffers case, all params will be 0, and we just
- * need to schedule a swap for the last swap target + the swap interval.
- * If the last swap target hasn't been set yet, call into the driver
- * to get the current count.
- */
- if (target_msc == 0 && divisor == 0 && remainder == 0 &&
- pPriv->last_swap_target < 0) {
- ret = (*ds->GetMSC)(pDraw, &ust, &target_msc);
- if (!ret) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: driver failed to return current MSC\n",
- __func__);
- return BadDrawable;
- }
- }
-
- /* First swap needs to initialize last_swap_target */
- if (pPriv->last_swap_target < 0)
- pPriv->last_swap_target = target_msc;
-
- /*
- * Swap target for this swap is last swap target + swap interval since
- * we have to account for the current swap count, interval, and the
- * number of pending swaps.
- */
- *swap_target = pPriv->last_swap_target + pPriv->swap_interval;
-
- ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
- swap_target, divisor, remainder, func, data);
- if (!ret) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: driver failed to schedule swap\n", __func__);
- return BadDrawable;
- }
-
- pPriv->swapsPending++;
- pPriv->last_swap_target = *swap_target;
-
- return Success;
-}
-
-void
-DRI2SwapInterval(DrawablePtr pDrawable, int interval)
-{
- DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
-
- /* fixme: check against arbitrary max? */
-
- pPriv->swap_interval = interval;
-}
-
-int
-DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- Bool ret;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return BadDrawable;
- }
-
- if (!ds->GetMSC) {
- *ust = 0;
- *msc = 0;
- *sbc = pPriv->swap_count;
- return Success;
- }
-
- /*
- * Spec needs to be updated to include unmapped or redirected
- * drawables
- */
-
- ret = (*ds->GetMSC)(pDraw, ust, msc);
- if (!ret)
- return BadDrawable;
-
- *sbc = pPriv->swap_count;
-
- return Success;
-}
-
-int
-DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
- CARD64 divisor, CARD64 remainder)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- Bool ret;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return BadDrawable;
-
- /* Old DDX just completes immediately */
- if (!ds->ScheduleWaitMSC) {
- DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0);
-
- return Success;
- }
-
- ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder);
- if (!ret)
- return BadDrawable;
-
- return Success;
-}
-
-int
-DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
- CARD64 *ust, CARD64 *msc, CARD64 *sbc)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return BadDrawable;
-
- if (pPriv->swap_count >= target_sbc)
- return Success;
-
- pPriv->target_sbc = target_sbc;
- DRI2BlockClient(client, pDraw);
-
- return Success;
-}
-
-void
-DRI2DestroyDrawable(DrawablePtr pDraw)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- WindowPtr pWin;
- PixmapPtr pPixmap;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return;
-
- pPriv->refCount--;
- if (pPriv->refCount > 0)
- return;
-
- if (pPriv->buffers != NULL) {
- int i;
-
- for (i = 0; i < pPriv->bufferCount; i++)
- (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
-
- xfree(pPriv->buffers);
- }
-
- /* If the window is destroyed while we have a swap pending, don't
- * actually free the priv yet. We'll need it in the DRI2SwapComplete()
- * callback and we'll free it there once we're done. */
- if (!pPriv->swapsPending)
- xfree(pPriv);
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pWin = (WindowPtr) pDraw;
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
- }
- else
- {
- pPixmap = (PixmapPtr) pDraw;
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
- }
-}
-
-Bool
-DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
- const char **driverName, const char **deviceName)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
-
- if (ds == NULL)
- return FALSE;
-
- if (driverType != DRI2DriverDRI)
- return BadValue;
-
- *fd = ds->fd;
- *driverName = ds->driverName;
- *deviceName = ds->deviceName;
-
- return TRUE;
-}
-
-Bool
-DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
-
- if (ds == NULL || drmAuthMagic(ds->fd, magic))
- return FALSE;
-
- return TRUE;
-}
-
-Bool
-DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
-{
- DRI2ScreenPtr ds;
-
- if (info->version < 3)
- return FALSE;
-
- if (!xf86VGAarbiterAllowDRI(pScreen)) {
- xf86DrvMsg(pScreen->myNum, X_WARNING,
- "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n");
- return FALSE;
- }
-
- ds = xcalloc(1, sizeof *ds);
- if (!ds)
- return FALSE;
-
- ds->fd = info->fd;
- ds->driverName = info->driverName;
- ds->deviceName = info->deviceName;
-
- ds->CreateBuffer = info->CreateBuffer;
- ds->DestroyBuffer = info->DestroyBuffer;
- ds->CopyRegion = info->CopyRegion;
-
- if (info->version >= 4) {
- ds->ScheduleSwap = info->ScheduleSwap;
- ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
- ds->GetMSC = info->GetMSC;
- }
-
- dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
-
- xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
-
- return TRUE;
-}
-
-void
-DRI2CloseScreen(ScreenPtr pScreen)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
-
- xfree(ds);
- dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
-}
-
-extern ExtensionModule dri2ExtensionModule;
-
-static pointer
-DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
-{
- static Bool setupDone = FALSE;
-
- if (!setupDone)
- {
- setupDone = TRUE;
- LoadExtension(&dri2ExtensionModule, FALSE);
- }
- else
- {
- if (errmaj)
- *errmaj = LDR_ONCEONLY;
- }
-
- return (pointer) 1;
-}
-
-static XF86ModuleVersionInfo DRI2VersRec =
-{
- "dri2",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 1, 0,
- ABI_CLASS_EXTENSION,
- ABI_EXTENSION_VERSION,
- MOD_CLASS_NONE,
- { 0, 0, 0, 0 }
-};
-
-_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL };
-
-void
-DRI2Version(int *major, int *minor)
-{
- if (major != NULL)
- *major = DRI2VersRec.majorversion;
-
- if (minor != NULL)
- *minor = DRI2VersRec.minorversion;
-}
+/*
+ * Copyright © 2007, 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ * Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <errno.h>
+#include <xf86drm.h>
+#include "xf86Module.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "dri2.h"
+#include "xf86VGAarbiter.h"
+
+#include "xf86.h"
+
+static int dri2ScreenPrivateKeyIndex;
+static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
+static int dri2WindowPrivateKeyIndex;
+static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
+static int dri2PixmapPrivateKeyIndex;
+static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
+
+typedef struct _DRI2Drawable {
+ unsigned int refCount;
+ int width;
+ int height;
+ DRI2BufferPtr *buffers;
+ int bufferCount;
+ unsigned int swapsPending;
+ ClientPtr blockedClient;
+ int swap_interval;
+ CARD64 swap_count;
+ CARD64 target_sbc; /* -1 means no SBC wait outstanding */
+ CARD64 last_swap_target; /* most recently queued swap target */
+ int swap_limit; /* for N-buffering */
+} DRI2DrawableRec, *DRI2DrawablePtr;
+
+typedef struct _DRI2Screen *DRI2ScreenPtr;
+
+typedef struct _DRI2Screen {
+ unsigned int numDrivers;
+ const char **driverNames;
+ const char *deviceName;
+ int fd;
+ unsigned int lastSequence;
+
+ DRI2CreateBufferProcPtr CreateBuffer;
+ DRI2DestroyBufferProcPtr DestroyBuffer;
+ DRI2CopyRegionProcPtr CopyRegion;
+ DRI2ScheduleSwapProcPtr ScheduleSwap;
+ DRI2GetMSCProcPtr GetMSC;
+ DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
+
+ HandleExposuresProcPtr HandleExposures;
+} DRI2ScreenRec;
+
+static DRI2ScreenPtr
+DRI2GetScreen(ScreenPtr pScreen)
+{
+ return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
+}
+
+static DRI2DrawablePtr
+DRI2GetDrawable(DrawablePtr pDraw)
+{
+ WindowPtr pWin;
+ PixmapPtr pPixmap;
+
+ if (!pDraw)
+ return NULL;
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ pWin = (WindowPtr) pDraw;
+ return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDraw;
+ return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
+ }
+}
+
+int
+DRI2CreateDrawable(DrawablePtr pDraw)
+{
+ WindowPtr pWin;
+ PixmapPtr pPixmap;
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv != NULL)
+ {
+ pPriv->refCount++;
+ return Success;
+ }
+
+ pPriv = xalloc(sizeof *pPriv);
+ if (pPriv == NULL)
+ return BadAlloc;
+
+ pPriv->refCount = 1;
+ pPriv->width = pDraw->width;
+ pPriv->height = pDraw->height;
+ pPriv->buffers = NULL;
+ pPriv->bufferCount = 0;
+ pPriv->swapsPending = 0;
+ pPriv->blockedClient = NULL;
+ pPriv->swap_count = 0;
+ pPriv->target_sbc = -1;
+ pPriv->swap_interval = 1;
+ pPriv->last_swap_target = -1;
+ pPriv->swap_limit = 1; /* default to double buffering */
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ pWin = (WindowPtr) pDraw;
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDraw;
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
+ }
+
+ return Success;
+}
+
+static void
+DRI2FreeDrawable(DrawablePtr pDraw)
+{
+ DRI2DrawablePtr pPriv;
+ WindowPtr pWin;
+ PixmapPtr pPixmap;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ xfree(pPriv);
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ pWin = (WindowPtr) pDraw;
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDraw;
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
+ }
+}
+
+static int
+find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
+{
+ int i;
+
+ if (pPriv->buffers == NULL) {
+ return -1;
+ }
+
+ for (i = 0; i < pPriv->bufferCount; i++) {
+ if ((pPriv->buffers[i] != NULL)
+ && (pPriv->buffers[i]->attachment == attachment)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static DRI2BufferPtr
+allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
+ DRI2DrawablePtr pPriv,
+ unsigned int attachment, unsigned int format,
+ int dimensions_match)
+{
+ DRI2BufferPtr buffer;
+ int old_buf;
+
+ old_buf = find_attachment(pPriv, attachment);
+
+ if ((old_buf < 0)
+ || !dimensions_match
+ || (pPriv->buffers[old_buf]->format != format)) {
+ buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
+ } else {
+ buffer = pPriv->buffers[old_buf];
+ pPriv->buffers[old_buf] = NULL;
+ }
+
+ return buffer;
+}
+
+static DRI2BufferPtr *
+do_get_buffers(DrawablePtr pDraw, int *width, int *height,
+ unsigned int *attachments, int count, int *out_count,
+ int has_format)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+ DRI2BufferPtr *buffers;
+ int need_real_front = 0;
+ int need_fake_front = 0;
+ int have_fake_front = 0;
+ int front_format = 0;
+ int dimensions_match;
+ int i;
+
+ if (!pPriv) {
+ *width = pDraw->width;
+ *height = pDraw->height;
+ *out_count = 0;
+ return NULL;
+ }
+
+ dimensions_match = (pDraw->width == pPriv->width)
+ && (pDraw->height == pPriv->height);
+
+ buffers = xalloc((count + 1) * sizeof(buffers[0]));
+
+ for (i = 0; i < count; i++) {
+ const unsigned attachment = *(attachments++);
+ const unsigned format = (has_format) ? *(attachments++) : 0;
+
+ buffers[i] = allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
+ format, dimensions_match);
+
+ /* If the drawable is a window and the front-buffer is requested,
+ * silently add the fake front-buffer to the list of requested
+ * attachments. The counting logic in the loop accounts for the case
+ * where the client requests both the fake and real front-buffer.
+ */
+ if (attachment == DRI2BufferBackLeft) {
+ need_real_front++;
+ front_format = format;
+ }
+
+ if (attachment == DRI2BufferFrontLeft) {
+ need_real_front--;
+ front_format = format;
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ need_fake_front++;
+ }
+ }
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ if (attachment == DRI2BufferFakeFrontLeft) {
+ need_fake_front--;
+ have_fake_front = 1;
+ }
+ }
+ }
+
+ if (need_real_front > 0) {
+ buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
+ DRI2BufferFrontLeft,
+ front_format, dimensions_match);
+ }
+
+ if (need_fake_front > 0) {
+ buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
+ DRI2BufferFakeFrontLeft,
+ front_format, dimensions_match);
+ have_fake_front = 1;
+ }
+
+ *out_count = i;
+
+
+ if (pPriv->buffers != NULL) {
+ for (i = 0; i < pPriv->bufferCount; i++) {
+ if (pPriv->buffers[i] != NULL) {
+ (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+ }
+ }
+
+ xfree(pPriv->buffers);
+ }
+
+ pPriv->buffers = buffers;
+ pPriv->bufferCount = *out_count;
+ pPriv->width = pDraw->width;
+ pPriv->height = pDraw->height;
+ *width = pPriv->width;
+ *height = pPriv->height;
+
+
+ /* If the client is getting a fake front-buffer, pre-fill it with the
+ * contents of the real front-buffer. This ensures correct operation of
+ * applications that call glXWaitX before calling glDrawBuffer.
+ */
+ if (have_fake_front) {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pPriv->width;
+ box.y2 = pPriv->height;
+ REGION_INIT(pDraw->pScreen, &region, &box, 0);
+
+ DRI2CopyRegion(pDraw, &region, DRI2BufferFakeFrontLeft,
+ DRI2BufferFrontLeft);
+ }
+
+ return pPriv->buffers;
+}
+
+DRI2BufferPtr *
+DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
+ unsigned int *attachments, int count, int *out_count)
+{
+ return do_get_buffers(pDraw, width, height, attachments, count,
+ out_count, FALSE);
+}
+
+DRI2BufferPtr *
+DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
+ unsigned int *attachments, int count, int *out_count)
+{
+ return do_get_buffers(pDraw, width, height, attachments, count,
+ out_count, TRUE);
+}
+
+/*
+ * In the direct rendered case, we throttle the clients that have more
+ * than their share of outstanding swaps (and thus busy buffers) when a
+ * new GetBuffers request is received. In the AIGLX case, we allow the
+ * client to get the new buffers, but throttle when the next GLX request
+ * comes in (see __glXDRIcontextWait()).
+ */
+Bool
+DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return FALSE;
+
+ /* Throttle to swap limit */
+ if ((pPriv->swapsPending >= pPriv->swap_limit) &&
+ !pPriv->blockedClient) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ IgnoreClient(client);
+ pPriv->blockedClient = client;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ if (pPriv->blockedClient == NULL) {
+ IgnoreClient(client);
+ pPriv->blockedClient = client;
+ }
+}
+
+int
+DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
+ unsigned int dest, unsigned int src)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ DRI2BufferPtr pDestBuffer, pSrcBuffer;
+ int i;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return BadDrawable;
+
+ pDestBuffer = NULL;
+ pSrcBuffer = NULL;
+ for (i = 0; i < pPriv->bufferCount; i++)
+ {
+ if (pPriv->buffers[i]->attachment == dest)
+ pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ if (pPriv->buffers[i]->attachment == src)
+ pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ }
+ if (pSrcBuffer == NULL || pDestBuffer == NULL)
+ return BadValue;
+
+ (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer);
+
+ return Success;
+}
+
+/* Can this drawable be page flipped? */
+Bool
+DRI2CanFlip(DrawablePtr pDraw)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ WindowPtr pWin, pRoot;
+ PixmapPtr pWinPixmap, pRootPixmap;
+
+ if (pDraw->type == DRAWABLE_PIXMAP)
+ return TRUE;
+
+ pRoot = WindowTable[pScreen->myNum];
+ pRootPixmap = pScreen->GetWindowPixmap(pRoot);
+
+ pWin = (WindowPtr) pDraw;
+ pWinPixmap = pScreen->GetWindowPixmap(pWin);
+ if (pRootPixmap != pWinPixmap)
+ return FALSE;
+ if (!REGION_EQUAL(pScreen, &pWin->clipList, &pRoot->winSize))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Can we do a pixmap exchange instead of a blit? */
+Bool
+DRI2CanExchange(DrawablePtr pDraw)
+{
+ return FALSE;
+}
+
+void
+DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
+ unsigned int tv_sec, unsigned int tv_usec)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
+ frame, pPriv->swap_count);
+
+ if (pPriv->blockedClient)
+ AttendClient(pPriv->blockedClient);
+
+ pPriv->blockedClient = NULL;
+}
+
+static void
+DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
+ unsigned int tv_sec, unsigned int tv_usec)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return;
+ }
+
+ /*
+ * Swap completed. Either wake up an SBC waiter or a client that was
+ * blocked due to GLX activity during a swap.
+ */
+ if (pPriv->target_sbc != -1 &&
+ pPriv->target_sbc >= pPriv->swap_count) {
+ ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
+ frame, pPriv->swap_count);
+ pPriv->target_sbc = -1;
+
+ AttendClient(pPriv->blockedClient);
+ pPriv->blockedClient = NULL;
+ } else if (pPriv->target_sbc == -1) {
+ if (pPriv->blockedClient)
+ AttendClient(pPriv->blockedClient);
+ pPriv->blockedClient = NULL;
+ }
+}
+
+void
+DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
+ unsigned int tv_sec, unsigned int tv_usec, int type,
+ DRI2SwapEventPtr swap_complete, void *swap_data)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2DrawablePtr pPriv;
+ CARD64 ust = 0;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return;
+ }
+
+ if (pPriv->refCount == 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable refcount\n", __func__);
+ DRI2FreeDrawable(pDraw);
+ return;
+ }
+
+ ust = ((CARD64)tv_sec * 1000000) + tv_usec;
+ if (swap_complete)
+ swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
+
+ pPriv->swapsPending--;
+ pPriv->swap_count++;
+
+ DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
+}
+
+Bool
+DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+ /* If we're currently waiting for a swap on this drawable, reset
+ * the request and suspend the client. We only support one
+ * blocked client per drawable. */
+ if ((pPriv->swapsPending) &&
+ pPriv->blockedClient == NULL) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ DRI2BlockClient(client, pDrawable);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int
+DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+ CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+ DRI2SwapEventPtr func, void *data)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
+ CARD64 ust;
+ int ret, i;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return BadDrawable;
+ }
+
+ for (i = 0; i < pPriv->bufferCount; i++) {
+ if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
+ pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
+ pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ }
+ if (pSrcBuffer == NULL || pDestBuffer == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: drawable has no back or front?\n", __func__);
+ return BadDrawable;
+ }
+
+ /* Old DDX, just blit */
+ if (!ds->ScheduleSwap) {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pDraw->width;
+ box.y2 = pDraw->height;
+ REGION_INIT(pScreen, &region, &box, 0);
+
+ pPriv->swapsPending++;
+
+ (*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
+ DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
+ func, data);
+ return Success;
+ }
+
+ /*
+ * In the simple glXSwapBuffers case, all params will be 0, and we just
+ * need to schedule a swap for the last swap target + the swap interval.
+ * If the last swap target hasn't been set yet, call into the driver
+ * to get the current count.
+ */
+ if (target_msc == 0 && divisor == 0 && remainder == 0 &&
+ pPriv->last_swap_target < 0) {
+ ret = (*ds->GetMSC)(pDraw, &ust, &target_msc);
+ if (!ret) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: driver failed to return current MSC\n",
+ __func__);
+ return BadDrawable;
+ }
+ }
+
+ /* First swap needs to initialize last_swap_target */
+ if (pPriv->last_swap_target < 0)
+ pPriv->last_swap_target = target_msc;
+
+ /*
+ * Swap target for this swap is last swap target + swap interval since
+ * we have to account for the current swap count, interval, and the
+ * number of pending swaps.
+ */
+ *swap_target = pPriv->last_swap_target + pPriv->swap_interval;
+
+ ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
+ swap_target, divisor, remainder, func, data);
+ if (!ret) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: driver failed to schedule swap\n", __func__);
+ return BadDrawable;
+ }
+
+ pPriv->swapsPending++;
+ pPriv->last_swap_target = *swap_target;
+
+ return Success;
+}
+
+void
+DRI2SwapInterval(DrawablePtr pDrawable, int interval)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+ /* fixme: check against arbitrary max? */
+
+ pPriv->swap_interval = interval;
+}
+
+int
+DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ Bool ret;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return BadDrawable;
+ }
+
+ if (!ds->GetMSC) {
+ *ust = 0;
+ *msc = 0;
+ *sbc = pPriv->swap_count;
+ return Success;
+ }
+
+ /*
+ * Spec needs to be updated to include unmapped or redirected
+ * drawables
+ */
+
+ ret = (*ds->GetMSC)(pDraw, ust, msc);
+ if (!ret)
+ return BadDrawable;
+
+ *sbc = pPriv->swap_count;
+
+ return Success;
+}
+
+int
+DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+ CARD64 divisor, CARD64 remainder)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ Bool ret;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return BadDrawable;
+
+ /* Old DDX just completes immediately */
+ if (!ds->ScheduleWaitMSC) {
+ DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0);
+
+ return Success;
+ }
+
+ ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder);
+ if (!ret)
+ return BadDrawable;
+
+ return Success;
+}
+
+int
+DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
+ CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return BadDrawable;
+
+ if (pPriv->swap_count >= target_sbc)
+ return Success;
+
+ pPriv->target_sbc = target_sbc;
+ DRI2BlockClient(client, pDraw);
+
+ return Success;
+}
+
+void
+DRI2DestroyDrawable(DrawablePtr pDraw)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ pPriv->refCount--;
+ if (pPriv->refCount > 0)
+ return;
+
+ if (pPriv->buffers != NULL) {
+ int i;
+
+ for (i = 0; i < pPriv->bufferCount; i++)
+ (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+
+ xfree(pPriv->buffers);
+ }
+
+ /* If the window is destroyed while we have a swap pending, don't
+ * actually free the priv yet. We'll need it in the DRI2SwapComplete()
+ * callback and we'll free it there once we're done. */
+ if (!pPriv->swapsPending)
+ DRI2FreeDrawable(pDraw);
+}
+
+Bool
+DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
+ const char **driverName, const char **deviceName)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+ if (ds == NULL || driverType >= ds->numDrivers ||
+ !ds->driverNames[driverType])
+ return FALSE;
+
+ *fd = ds->fd;
+ *driverName = ds->driverNames[driverType];
+ *deviceName = ds->deviceName;
+
+ return TRUE;
+}
+
+Bool
+DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+ if (ds == NULL || drmAuthMagic(ds->fd, magic))
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
+{
+ DRI2ScreenPtr ds;
+ const char* driverTypeNames[] = {
+ "DRI", /* DRI2DriverDRI */
+ "VDPAU", /* DRI2DriverVDPAU */
+ };
+ unsigned int i;
+
+ if (info->version < 3)
+ return FALSE;
+
+ if (!xf86VGAarbiterAllowDRI(pScreen)) {
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n");
+ return FALSE;
+ }
+
+ ds = xcalloc(1, sizeof *ds);
+ if (!ds)
+ return FALSE;
+
+ ds->fd = info->fd;
+ ds->deviceName = info->deviceName;
+
+ ds->CreateBuffer = info->CreateBuffer;
+ ds->DestroyBuffer = info->DestroyBuffer;
+ ds->CopyRegion = info->CopyRegion;
+
+ if (info->version >= 4) {
+ ds->ScheduleSwap = info->ScheduleSwap;
+ ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
+ ds->GetMSC = info->GetMSC;
+ }
+
+ if (info->version == 3 || info->numDrivers == 0) {
+ /* Driver too old: use the old-style driverName field */
+ ds->numDrivers = 1;
+ ds->driverNames = xalloc(sizeof(*ds->driverNames));
+ if (!ds->driverNames) {
+ xfree(ds);
+ return FALSE;
+ }
+ ds->driverNames[0] = info->driverName;
+ } else {
+ ds->numDrivers = info->numDrivers;
+ ds->driverNames = xalloc(info->numDrivers * sizeof(*ds->driverNames));
+ if (!ds->driverNames) {
+ xfree(ds);
+ return FALSE;
+ }
+ memcpy(ds->driverNames, info->driverNames,
+ info->numDrivers * sizeof(*ds->driverNames));
+ }
+
+ dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
+ for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) {
+ if (i < ds->numDrivers && ds->driverNames[i]) {
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] %s driver: %s\n",
+ driverTypeNames[i], ds->driverNames[i]);
+ }
+ }
+
+ return TRUE;
+}
+
+void
+DRI2CloseScreen(ScreenPtr pScreen)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+ xfree(ds->driverNames);
+ xfree(ds);
+ dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
+}
+
+extern ExtensionModule dri2ExtensionModule;
+
+static pointer
+DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone)
+ {
+ setupDone = TRUE;
+ LoadExtension(&dri2ExtensionModule, FALSE);
+ }
+ else
+ {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ }
+
+ return (pointer) 1;
+}
+
+static XF86ModuleVersionInfo DRI2VersRec =
+{
+ "dri2",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 2, 0,
+ ABI_CLASS_EXTENSION,
+ ABI_EXTENSION_VERSION,
+ MOD_CLASS_NONE,
+ { 0, 0, 0, 0 }
+};
+
+_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL };
+
+void
+DRI2Version(int *major, int *minor)
+{
+ if (major != NULL)
+ *major = DRI2VersRec.majorversion;
+
+ if (minor != NULL)
+ *minor = DRI2VersRec.minorversion;
+}
diff --git a/xorg-server/hw/xfree86/dri2/dri2.h b/xorg-server/hw/xfree86/dri2/dri2.h
index dd59297df..cb818f898 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.h
+++ b/xorg-server/hw/xfree86/dri2/dri2.h
@@ -1,259 +1,268 @@
-/*
- * Copyright © 2007 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Soft-
- * ware"), to deal in the Software without restriction, including without
- * limitation the rights to use, copy, modify, merge, publish, distribute,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, provided that the above copyright
- * notice(s) and this permission notice appear in all copies of the Soft-
- * ware and that both the above copyright notice(s) and this permission
- * notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
- * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
- * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
- * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
- * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
- * MANCE OF THIS SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder shall
- * not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization of
- * the copyright holder.
- *
- * Authors:
- * Kristian Høgsberg (krh@redhat.com)
- */
-
-#ifndef _DRI2_H_
-#define _DRI2_H_
-
-#include <X11/extensions/dri2tokens.h>
-
-/* Version 2 structure (with format at the end) */
-typedef struct {
- unsigned int attachment;
- unsigned int name;
- unsigned int pitch;
- unsigned int cpp;
- unsigned int flags;
- unsigned int format;
- void *driverPrivate;
-} DRI2BufferRec, *DRI2BufferPtr;
-
-typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
-typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
- CARD64 ust, CARD64 msc, CARD64 sbc);
-
-
-typedef DRI2BufferPtr (*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
- unsigned int *attachments,
- int count);
-typedef void (*DRI2DestroyBuffersProcPtr)(DrawablePtr pDraw,
- DRI2BufferPtr buffers,
- int count);
-typedef void (*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
- RegionPtr pRegion,
- DRI2BufferPtr pDestBuffer,
- DRI2BufferPtr pSrcBuffer);
-typedef void (*DRI2WaitProcPtr)(WindowPtr pWin,
- unsigned int sequence);
-/**
- * Schedule a buffer swap
- *
- * This callback is used to support glXSwapBuffers and the OML_sync_control
- * extension (see it for a description of the params).
- *
- * Drivers should queue an event for the frame count that satisfies the
- * parameters passed in. If the event is in the future (i.e. the conditions
- * aren't currently satisfied), the server may block the client at the next
- * GLX request using DRI2WaitSwap. When the event arrives, drivers should call
- * \c DRI2SwapComplete, which will handle waking the client and returning
- * the appropriate data.
- *
- * The DDX is responsible for doing a flip, exchange, or blit of the swap
- * when the corresponding event arrives. The \c DRI2CanFlip and
- * \c DRI2CanExchange functions can be used as helpers for this purpose.
- *
- * \param client client pointer (used for block/unblock)
- * \param pDraw drawable whose count we want
- * \param pDestBuffer current front buffer
- * \param pSrcBuffer current back buffer
- * \param target_msc frame count to wait for
- * \param divisor divisor for condition equation
- * \param remainder remainder for division equation
- * \param func function to call when the swap completes
- * \param data data for the callback \p func.
- */
-typedef int (*DRI2ScheduleSwapProcPtr)(ClientPtr client,
- DrawablePtr pDraw,
- DRI2BufferPtr pDestBuffer,
- DRI2BufferPtr pSrcBuffer,
- CARD64 *target_msc,
- CARD64 divisor,
- CARD64 remainder,
- DRI2SwapEventPtr func,
- void *data);
-typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
- unsigned int attachment,
- unsigned int format);
-typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
- DRI2BufferPtr buffer);
-/**
- * Get current media stamp counter values
- *
- * This callback is used to support the SGI_video_sync and OML_sync_control
- * extensions.
- *
- * Drivers should return the current frame counter and the timestamp from
- * when the returned frame count was last incremented.
- *
- * The count should correspond to the screen where the drawable is currently
- * visible. If the drawable isn't visible (e.g. redirected), the server
- * should return BadDrawable to the client, pending GLX spec updates to
- * define this behavior.
- *
- * \param pDraw drawable whose count we want
- * \param ust timestamp from when the count was last incremented.
- * \param mst current frame count
- */
-typedef int (*DRI2GetMSCProcPtr)(DrawablePtr pDraw, CARD64 *ust,
- CARD64 *msc);
-/**
- * Schedule a frame count related wait
- *
- * This callback is used to support the SGI_video_sync and OML_sync_control
- * extensions. See those specifications for details on how to handle
- * the divisor and remainder parameters.
- *
- * Drivers should queue an event for the frame count that satisfies the
- * parameters passed in. If the event is in the future (i.e. the conditions
- * aren't currently satisfied), the driver should block the client using
- * \c DRI2BlockClient. When the event arrives, drivers should call
- * \c DRI2WaitMSCComplete, which will handle waking the client and returning
- * the appropriate data.
- *
- * \param client client pointer (used for block/unblock)
- * \param pDraw drawable whose count we want
- * \param target_msc frame count to wait for
- * \param divisor divisor for condition equation
- * \param remainder remainder for division equation
- */
-typedef int (*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
- DrawablePtr pDraw,
- CARD64 target_msc,
- CARD64 divisor,
- CARD64 remainder);
-/**
- * Version of the DRI2InfoRec structure defined in this header
- */
-#define DRI2INFOREC_VERSION 4
-
-typedef struct {
- unsigned int version; /**< Version of this struct */
- int fd;
- const char *driverName;
- const char *deviceName;
-
- DRI2CreateBufferProcPtr CreateBuffer;
- DRI2DestroyBufferProcPtr DestroyBuffer;
- DRI2CopyRegionProcPtr CopyRegion;
- DRI2WaitProcPtr Wait;
- DRI2ScheduleSwapProcPtr ScheduleSwap;
- DRI2GetMSCProcPtr GetMSC;
- DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
-} DRI2InfoRec, *DRI2InfoPtr;
-
-extern _X_EXPORT int DRI2EventBase;
-
-extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
- DRI2InfoPtr info);
-
-extern _X_EXPORT void DRI2CloseScreen(ScreenPtr pScreen);
-
-extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
- unsigned int driverType,
- int *fd,
- const char **driverName,
- const char **deviceName);
-
-extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
-
-extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
-
-extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
-
-extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffers(DrawablePtr pDraw,
- int *width,
- int *height,
- unsigned int *attachments,
- int count,
- int *out_count);
-
-extern _X_EXPORT int DRI2CopyRegion(DrawablePtr pDraw,
- RegionPtr pRegion,
- unsigned int dest,
- unsigned int src);
-
-/**
- * Determine the major and minor version of the DRI2 extension.
- *
- * Provides a mechanism to other modules (e.g., 2D drivers) to determine the
- * version of the DRI2 extension. While it is possible to peek directly at
- * the \c XF86ModuleData from a layered module, such a module will fail to
- * load (due to an unresolved symbol) if the DRI2 extension is not loaded.
- *
- * \param major Location to store the major verion of the DRI2 extension
- * \param minor Location to store the minor verion of the DRI2 extension
- *
- * \note
- * This interface was added some time after the initial release of the DRI2
- * module. Layered modules that wish to use this interface must first test
- * its existance by calling \c xf86LoaderCheckSymbol.
- */
-extern _X_EXPORT void DRI2Version(int *major, int *minor);
-
-extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
- int *width, int *height, unsigned int *attachments, int count,
- int *out_count);
-
-extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
-extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
- CARD64 target_msc, CARD64 divisor,
- CARD64 remainder, CARD64 *swap_target,
- DRI2SwapEventPtr func, void *data);
-extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
-
-extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
- CARD64 *msc, CARD64 *sbc);
-extern _X_EXPORT int DRI2WaitMSC(ClientPtr client, DrawablePtr pDrawable,
- CARD64 target_msc, CARD64 divisor,
- CARD64 remainder);
-extern _X_EXPORT int ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust,
- CARD64 msc, CARD64 sbc);
-extern _X_EXPORT int DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw,
- CARD64 target_sbc, CARD64 *ust, CARD64 *msc,
- CARD64 *sbc);
-extern _X_EXPORT Bool DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw);
-
-extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
-
-extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
-
-extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
-
-extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
- int frame, unsigned int tv_sec,
- unsigned int tv_usec, int type,
- DRI2SwapEventPtr swap_complete,
- void *swap_data);
-extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
- int frame, unsigned int tv_sec,
- unsigned int tv_usec);
-
-#endif
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ * Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifndef _DRI2_H_
+#define _DRI2_H_
+
+#include <X11/extensions/dri2tokens.h>
+
+/* Version 2 structure (with format at the end) */
+typedef struct {
+ unsigned int attachment;
+ unsigned int name;
+ unsigned int pitch;
+ unsigned int cpp;
+ unsigned int flags;
+ unsigned int format;
+ void *driverPrivate;
+} DRI2BufferRec, *DRI2BufferPtr;
+
+typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
+typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
+ CARD64 ust, CARD64 msc, CARD64 sbc);
+
+
+typedef DRI2BufferPtr (*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
+ unsigned int *attachments,
+ int count);
+typedef void (*DRI2DestroyBuffersProcPtr)(DrawablePtr pDraw,
+ DRI2BufferPtr buffers,
+ int count);
+typedef void (*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
+ RegionPtr pRegion,
+ DRI2BufferPtr pDestBuffer,
+ DRI2BufferPtr pSrcBuffer);
+typedef void (*DRI2WaitProcPtr)(WindowPtr pWin,
+ unsigned int sequence);
+/**
+ * Schedule a buffer swap
+ *
+ * This callback is used to support glXSwapBuffers and the OML_sync_control
+ * extension (see it for a description of the params).
+ *
+ * Drivers should queue an event for the frame count that satisfies the
+ * parameters passed in. If the event is in the future (i.e. the conditions
+ * aren't currently satisfied), the server may block the client at the next
+ * GLX request using DRI2WaitSwap. When the event arrives, drivers should call
+ * \c DRI2SwapComplete, which will handle waking the client and returning
+ * the appropriate data.
+ *
+ * The DDX is responsible for doing a flip, exchange, or blit of the swap
+ * when the corresponding event arrives. The \c DRI2CanFlip and
+ * \c DRI2CanExchange functions can be used as helpers for this purpose.
+ *
+ * \param client client pointer (used for block/unblock)
+ * \param pDraw drawable whose count we want
+ * \param pDestBuffer current front buffer
+ * \param pSrcBuffer current back buffer
+ * \param target_msc frame count to wait for
+ * \param divisor divisor for condition equation
+ * \param remainder remainder for division equation
+ * \param func function to call when the swap completes
+ * \param data data for the callback \p func.
+ */
+typedef int (*DRI2ScheduleSwapProcPtr)(ClientPtr client,
+ DrawablePtr pDraw,
+ DRI2BufferPtr pDestBuffer,
+ DRI2BufferPtr pSrcBuffer,
+ CARD64 *target_msc,
+ CARD64 divisor,
+ CARD64 remainder,
+ DRI2SwapEventPtr func,
+ void *data);
+typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
+ unsigned int attachment,
+ unsigned int format);
+typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
+ DRI2BufferPtr buffer);
+/**
+ * Get current media stamp counter values
+ *
+ * This callback is used to support the SGI_video_sync and OML_sync_control
+ * extensions.
+ *
+ * Drivers should return the current frame counter and the timestamp from
+ * when the returned frame count was last incremented.
+ *
+ * The count should correspond to the screen where the drawable is currently
+ * visible. If the drawable isn't visible (e.g. redirected), the server
+ * should return BadDrawable to the client, pending GLX spec updates to
+ * define this behavior.
+ *
+ * \param pDraw drawable whose count we want
+ * \param ust timestamp from when the count was last incremented.
+ * \param mst current frame count
+ */
+typedef int (*DRI2GetMSCProcPtr)(DrawablePtr pDraw, CARD64 *ust,
+ CARD64 *msc);
+/**
+ * Schedule a frame count related wait
+ *
+ * This callback is used to support the SGI_video_sync and OML_sync_control
+ * extensions. See those specifications for details on how to handle
+ * the divisor and remainder parameters.
+ *
+ * Drivers should queue an event for the frame count that satisfies the
+ * parameters passed in. If the event is in the future (i.e. the conditions
+ * aren't currently satisfied), the driver should block the client using
+ * \c DRI2BlockClient. When the event arrives, drivers should call
+ * \c DRI2WaitMSCComplete, which will handle waking the client and returning
+ * the appropriate data.
+ *
+ * \param client client pointer (used for block/unblock)
+ * \param pDraw drawable whose count we want
+ * \param target_msc frame count to wait for
+ * \param divisor divisor for condition equation
+ * \param remainder remainder for division equation
+ */
+typedef int (*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
+ DrawablePtr pDraw,
+ CARD64 target_msc,
+ CARD64 divisor,
+ CARD64 remainder);
+/**
+ * Version of the DRI2InfoRec structure defined in this header
+ */
+#define DRI2INFOREC_VERSION 4
+
+typedef struct {
+ unsigned int version; /**< Version of this struct */
+ int fd;
+ const char *driverName;
+ const char *deviceName;
+
+ DRI2CreateBufferProcPtr CreateBuffer;
+ DRI2DestroyBufferProcPtr DestroyBuffer;
+ DRI2CopyRegionProcPtr CopyRegion;
+ DRI2WaitProcPtr Wait;
+
+ /* added in version 4 */
+
+ DRI2ScheduleSwapProcPtr ScheduleSwap;
+ DRI2GetMSCProcPtr GetMSC;
+ DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
+
+ /* number of drivers in the driverNames array */
+ unsigned int numDrivers;
+ /* array of driver names, indexed by DRI2Driver* driver types */
+ /* a name of NULL means that driver is not supported */
+ const char * const *driverNames;
+} DRI2InfoRec, *DRI2InfoPtr;
+
+extern _X_EXPORT int DRI2EventBase;
+
+extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
+ DRI2InfoPtr info);
+
+extern _X_EXPORT void DRI2CloseScreen(ScreenPtr pScreen);
+
+extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
+ unsigned int driverType,
+ int *fd,
+ const char **driverName,
+ const char **deviceName);
+
+extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
+
+extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
+
+extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffers(DrawablePtr pDraw,
+ int *width,
+ int *height,
+ unsigned int *attachments,
+ int count,
+ int *out_count);
+
+extern _X_EXPORT int DRI2CopyRegion(DrawablePtr pDraw,
+ RegionPtr pRegion,
+ unsigned int dest,
+ unsigned int src);
+
+/**
+ * Determine the major and minor version of the DRI2 extension.
+ *
+ * Provides a mechanism to other modules (e.g., 2D drivers) to determine the
+ * version of the DRI2 extension. While it is possible to peek directly at
+ * the \c XF86ModuleData from a layered module, such a module will fail to
+ * load (due to an unresolved symbol) if the DRI2 extension is not loaded.
+ *
+ * \param major Location to store the major verion of the DRI2 extension
+ * \param minor Location to store the minor verion of the DRI2 extension
+ *
+ * \note
+ * This interface was added some time after the initial release of the DRI2
+ * module. Layered modules that wish to use this interface must first test
+ * its existance by calling \c xf86LoaderCheckSymbol.
+ */
+extern _X_EXPORT void DRI2Version(int *major, int *minor);
+
+extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
+ int *width, int *height, unsigned int *attachments, int count,
+ int *out_count);
+
+extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
+extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
+ CARD64 target_msc, CARD64 divisor,
+ CARD64 remainder, CARD64 *swap_target,
+ DRI2SwapEventPtr func, void *data);
+extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
+
+extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
+ CARD64 *msc, CARD64 *sbc);
+extern _X_EXPORT int DRI2WaitMSC(ClientPtr client, DrawablePtr pDrawable,
+ CARD64 target_msc, CARD64 divisor,
+ CARD64 remainder);
+extern _X_EXPORT int ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust,
+ CARD64 msc, CARD64 sbc);
+extern _X_EXPORT int DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw,
+ CARD64 target_sbc, CARD64 *ust, CARD64 *msc,
+ CARD64 *sbc);
+extern _X_EXPORT Bool DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw);
+
+extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
+
+extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
+ int frame, unsigned int tv_sec,
+ unsigned int tv_usec, int type,
+ DRI2SwapEventPtr swap_complete,
+ void *swap_data);
+extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
+ int frame, unsigned int tv_sec,
+ unsigned int tv_usec);
+
+#endif
diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c
index d015c6a77..cfe808e3e 100644
--- a/xorg-server/hw/xfree86/modes/xf86Crtc.c
+++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c
@@ -1,3198 +1,3198 @@
-/*
- * Copyright © 2006 Keith Packard
- * Copyright © 2008 Red Hat, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#else
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#endif
-
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "xf86.h"
-#include "xf86DDC.h"
-#include "xf86Crtc.h"
-#include "xf86Modes.h"
-#include "xf86Priv.h"
-#include "xf86RandR12.h"
-#include "X11/extensions/render.h"
-#include "X11/extensions/dpmsconst.h"
-#include "X11/Xatom.h"
-#ifdef RENDER
-#include "picturestr.h"
-#endif
-
-#include "xf86xv.h"
-
-/*
- * Initialize xf86CrtcConfig structure
- */
-
-int xf86CrtcConfigPrivateIndex = -1;
-
-void
-xf86CrtcConfigInit (ScrnInfoPtr scrn,
- const xf86CrtcConfigFuncsRec *funcs)
-{
- xf86CrtcConfigPtr config;
-
- if (xf86CrtcConfigPrivateIndex == -1)
- xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
- config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
-
- config->funcs = funcs;
-
- scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
-}
-
-void
-xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
- int minWidth, int minHeight,
- int maxWidth, int maxHeight)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
-
- config->minWidth = minWidth;
- config->minHeight = minHeight;
- config->maxWidth = maxWidth;
- config->maxHeight = maxHeight;
-}
-
-/*
- * Crtc functions
- */
-xf86CrtcPtr
-xf86CrtcCreate (ScrnInfoPtr scrn,
- const xf86CrtcFuncsRec *funcs)
-{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- xf86CrtcPtr crtc, *crtcs;
-
- crtc = xcalloc (sizeof (xf86CrtcRec), 1);
- if (!crtc)
- return NULL;
- crtc->version = XF86_CRTC_VERSION;
- crtc->scrn = scrn;
- crtc->funcs = funcs;
-#ifdef RANDR_12_INTERFACE
- crtc->randr_crtc = NULL;
-#endif
- crtc->rotation = RR_Rotate_0;
- crtc->desiredRotation = RR_Rotate_0;
- pixman_transform_init_identity (&crtc->crtc_to_framebuffer);
- pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
- pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
- crtc->filter = NULL;
- crtc->params = NULL;
- crtc->nparams = 0;
- crtc->filter_width = 0;
- crtc->filter_height = 0;
- crtc->transform_in_use = FALSE;
- crtc->transformPresent = FALSE;
- crtc->desiredTransformPresent = FALSE;
- memset (&crtc->bounds, '\0', sizeof (crtc->bounds));
-
- /* Preallocate gamma at a sensible size. */
- crtc->gamma_size = 256;
- crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16));
- if (!crtc->gamma_red) {
- xfree (crtc);
- return NULL;
- }
- crtc->gamma_green = crtc->gamma_red + crtc->gamma_size;
- crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size;
-
- if (xf86_config->crtc)
- crtcs = xrealloc (xf86_config->crtc,
- (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
- else
- crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
- if (!crtcs)
- {
- xfree (crtc);
- return NULL;
- }
- xf86_config->crtc = crtcs;
- xf86_config->crtc[xf86_config->num_crtc++] = crtc;
- return crtc;
-}
-
-void
-xf86CrtcDestroy (xf86CrtcPtr crtc)
-{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
- int c;
-
- (*crtc->funcs->destroy) (crtc);
- for (c = 0; c < xf86_config->num_crtc; c++)
- if (xf86_config->crtc[c] == crtc)
- {
- memmove (&xf86_config->crtc[c],
- &xf86_config->crtc[c+1],
- ((xf86_config->num_crtc - (c + 1)) * sizeof(void*)));
- xf86_config->num_crtc--;
- break;
- }
- if (crtc->params)
- xfree (crtc->params);
- free(crtc->gamma_red);
- xfree (crtc);
-}
-
-
-/**
- * Return whether any outputs are connected to the specified pipe
- */
-
-Bool
-xf86CrtcInUse (xf86CrtcPtr crtc)
-{
- ScrnInfoPtr pScrn = crtc->scrn;
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- int o;
-
- for (o = 0; o < xf86_config->num_output; o++)
- if (xf86_config->output[o]->crtc == crtc)
- return TRUE;
- return FALSE;
-}
-
-void
-xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
-{
-#ifdef RENDER
- int subpixel_order = SubPixelUnknown;
- Bool has_none = FALSE;
- ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- int c, o;
-
- for (c = 0; c < xf86_config->num_crtc; c++)
- {
- xf86CrtcPtr crtc = xf86_config->crtc[c];
-
- for (o = 0; o < xf86_config->num_output; o++)
- {
- xf86OutputPtr output = xf86_config->output[o];
-
- if (output->crtc == crtc)
- {
- switch (output->subpixel_order) {
- case SubPixelNone:
- has_none = TRUE;
- break;
- case SubPixelUnknown:
- break;
- default:
- subpixel_order = output->subpixel_order;
- break;
- }
- }
- if (subpixel_order != SubPixelUnknown)
- break;
- }
- if (subpixel_order != SubPixelUnknown)
- {
- static const int circle[4] = {
- SubPixelHorizontalRGB,
- SubPixelVerticalRGB,
- SubPixelHorizontalBGR,
- SubPixelVerticalBGR,
- };
- int rotate;
- int c;
- for (rotate = 0; rotate < 4; rotate++)
- if (crtc->rotation & (1 << rotate))
- break;
- for (c = 0; c < 4; c++)
- if (circle[c] == subpixel_order)
- break;
- c = (c + rotate) & 0x3;
- if ((crtc->rotation & RR_Reflect_X) && !(c & 1))
- c ^= 2;
- if ((crtc->rotation & RR_Reflect_Y) && (c & 1))
- c ^= 2;
- subpixel_order = circle[c];
- break;
- }
- }
- if (subpixel_order == SubPixelUnknown && has_none)
- subpixel_order = SubPixelNone;
- PictureSetSubpixelOrder (pScreen, subpixel_order);
-#endif
-}
-
-/**
- * Sets the given video mode on the given crtc
- */
-Bool
-xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
- RRTransformPtr transform, int x, int y)
-{
- ScrnInfoPtr scrn = crtc->scrn;
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- int i;
- Bool ret = FALSE;
- Bool didLock = FALSE;
- DisplayModePtr adjusted_mode;
- DisplayModeRec saved_mode;
- int saved_x, saved_y;
- Rotation saved_rotation;
- RRTransformRec saved_transform;
- Bool saved_transform_present;
-
- crtc->enabled = xf86CrtcInUse (crtc);
-
- /* We only hit this if someone explicitly sends a "disabled" modeset. */
- if (!crtc->enabled)
- {
- /* Check everything for stuff that should be off. */
- xf86DisableUnusedFunctions(scrn);
- return TRUE;
- }
-
- adjusted_mode = xf86DuplicateMode(mode);
-
-
- saved_mode = crtc->mode;
- saved_x = crtc->x;
- saved_y = crtc->y;
- saved_rotation = crtc->rotation;
- if (crtc->transformPresent) {
- RRTransformInit (&saved_transform);
- RRTransformCopy (&saved_transform, &crtc->transform);
- }
- saved_transform_present = crtc->transformPresent;
-
- /* Update crtc values up front so the driver can rely on them for mode
- * setting.
- */
- crtc->mode = *mode;
- crtc->x = x;
- crtc->y = y;
- crtc->rotation = rotation;
- if (transform) {
- RRTransformCopy (&crtc->transform, transform);
- crtc->transformPresent = TRUE;
- } else
- crtc->transformPresent = FALSE;
-
- if (crtc->funcs->set_mode_major) {
- ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y);
- goto done;
- }
-
- didLock = crtc->funcs->lock (crtc);
- /* Pass our mode to the outputs and the CRTC to give them a chance to
- * adjust it according to limitations or output properties, and also
- * a chance to reject the mode entirely.
- */
- for (i = 0; i < xf86_config->num_output; i++) {
- xf86OutputPtr output = xf86_config->output[i];
-
- if (output->crtc != crtc)
- continue;
-
- if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
- goto done;
- }
- }
-
- if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
- goto done;
- }
-
- if (!xf86CrtcRotate (crtc))
- goto done;
-
- /* Prepare the outputs and CRTCs before setting the mode. */
- for (i = 0; i < xf86_config->num_output; i++) {
- xf86OutputPtr output = xf86_config->output[i];
-
- if (output->crtc != crtc)
- continue;
-
- /* Disable the output as the first thing we do. */
- output->funcs->prepare(output);
- }
-
- crtc->funcs->prepare(crtc);
-
- /* Set up the DPLL and any output state that needs to adjust or depend
- * on the DPLL.
- */
- crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y);
- for (i = 0; i < xf86_config->num_output; i++)
- {
- xf86OutputPtr output = xf86_config->output[i];
- if (output->crtc == crtc)
- output->funcs->mode_set(output, mode, adjusted_mode);
- }
-
- /* Only upload when needed, to avoid unneeded delays. */
- if (!crtc->active)
- crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
- crtc->gamma_blue, crtc->gamma_size);
-
- /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
- crtc->funcs->commit(crtc);
- for (i = 0; i < xf86_config->num_output; i++)
- {
- xf86OutputPtr output = xf86_config->output[i];
- if (output->crtc == crtc)
- output->funcs->commit(output);
- }
-
- ret = TRUE;
-
-done:
- if (ret) {
- crtc->active = TRUE;
- if (scrn->pScreen)
- xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
- } else {
- crtc->x = saved_x;
- crtc->y = saved_y;
- crtc->rotation = saved_rotation;
- crtc->mode = saved_mode;
- if (saved_transform_present)
- RRTransformCopy (&crtc->transform, &saved_transform);
- crtc->transformPresent = saved_transform_present;
- }
-
- if (adjusted_mode->name)
- xfree(adjusted_mode->name);
- xfree(adjusted_mode);
-
- if (didLock)
- crtc->funcs->unlock (crtc);
-
- return ret;
-}
-
-/**
- * Sets the given video mode on the given crtc, but without providing
- * a transform
- */
-Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
- int x, int y)
-{
- return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y);
-}
-
-/**
- * Pans the screen, does not change the mode
- */
-void
-xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y)
-{
- crtc->x = x;
- crtc->y = y;
- if (crtc->funcs->set_origin) {
- if (!xf86CrtcRotate (crtc))
- return;
- crtc->funcs->set_origin (crtc, x, y);
- }
- else
- xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y);
-}
-
-/*
- * Output functions
- */
-
-extern XF86ConfigPtr xf86configptr;
-
-typedef enum {
- OPTION_PREFERRED_MODE,
- OPTION_POSITION,
- OPTION_BELOW,
- OPTION_RIGHT_OF,
- OPTION_ABOVE,
- OPTION_LEFT_OF,
- OPTION_ENABLE,
- OPTION_DISABLE,
- OPTION_MIN_CLOCK,
- OPTION_MAX_CLOCK,
- OPTION_IGNORE,
- OPTION_ROTATE,
- OPTION_PANNING,
- OPTION_PRIMARY,
-} OutputOpts;
-
-static OptionInfoRec xf86OutputOptions[] = {
- {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE },
- {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE },
- {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE },
- {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE },
- {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE },
- {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE },
- {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE },
- {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE },
- {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE },
- {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE },
- {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE },
- {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE },
- {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE },
- {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE },
- {-1, NULL, OPTV_NONE, {0}, FALSE },
-};
-
-enum {
- OPTION_MODEDEBUG,
-};
-
-static OptionInfoRec xf86DeviceOptions[] = {
- {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE },
- {-1, NULL, OPTV_NONE, {0}, FALSE },
-};
-
-static void
-xf86OutputSetMonitor (xf86OutputPtr output)
-{
- char *option_name;
- static const char monitor_prefix[] = "monitor-";
- char *monitor;
-
- if (!output->name)
- return;
-
- if (output->options)
- xfree (output->options);
-
- output->options = xnfalloc (sizeof (xf86OutputOptions));
- memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions));
-
- option_name = xnfalloc (strlen (monitor_prefix) +
- strlen (output->name) + 1);
- strcpy (option_name, monitor_prefix);
- strcat (option_name, output->name);
- monitor = xf86findOptionValue (output->scrn->options, option_name);
- if (!monitor)
- monitor = output->name;
- else
- xf86MarkOptionUsedByName (output->scrn->options, option_name);
- xfree (option_name);
- output->conf_monitor = xf86findMonitor (monitor,
- xf86configptr->conf_monitor_lst);
- /*
- * Find the monitor section of the screen and use that
- */
- if (!output->conf_monitor && output->use_screen_monitor)
- output->conf_monitor = xf86findMonitor (output->scrn->monitor->id,
- xf86configptr->conf_monitor_lst);
- if (output->conf_monitor)
- {
- xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
- "Output %s using monitor section %s\n",
- output->name, output->conf_monitor->mon_identifier);
- xf86ProcessOptions (output->scrn->scrnIndex,
- output->conf_monitor->mon_option_lst,
- output->options);
- }
- else
- xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
- "Output %s has no monitor section\n",
- output->name);
-}
-
-static Bool
-xf86OutputEnabled (xf86OutputPtr output, Bool strict)
-{
- Bool enable, disable;
-
- /* check to see if this output was enabled in the config file */
- if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable)
- {
- xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
- "Output %s enabled by config file\n", output->name);
- return TRUE;
- }
- /* or if this output was disabled in the config file */
- if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable)
- {
- xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
- "Output %s disabled by config file\n", output->name);
- return FALSE;
- }
-
- /* If not, try to only light up the ones we know are connected */
- if (strict) {
- enable = output->status == XF86OutputStatusConnected;
- }
- /* But if that fails, try to light up even outputs we're unsure of */
- else {
- enable = output->status != XF86OutputStatusDisconnected;
- }
-
- xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
- "Output %s %sconnected\n", output->name, enable ? "" : "dis");
- return enable;
-}
-
-static Bool
-xf86OutputIgnored (xf86OutputPtr output)
-{
- return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);
-}
-
-static char *direction[4] = {
- "normal",
- "left",
- "inverted",
- "right"
-};
-
-static Rotation
-xf86OutputInitialRotation (xf86OutputPtr output)
-{
- char *rotate_name = xf86GetOptValString (output->options,
- OPTION_ROTATE);
- int i;
-
- if (!rotate_name)
- return RR_Rotate_0;
-
- for (i = 0; i < 4; i++)
- if (xf86nameCompare (direction[i], rotate_name) == 0)
- return (1 << i);
- return RR_Rotate_0;
-}
-
-xf86OutputPtr
-xf86OutputCreate (ScrnInfoPtr scrn,
- const xf86OutputFuncsRec *funcs,
- const char *name)
-{
- xf86OutputPtr output, *outputs;
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- int len;
- Bool primary;
-
- if (name)
- len = strlen (name) + 1;
- else
- len = 0;
-
- output = xcalloc (sizeof (xf86OutputRec) + len, 1);
- if (!output)
- return NULL;
- output->scrn = scrn;
- output->funcs = funcs;
- if (name)
- {
- output->name = (char *) (output + 1);
- strcpy (output->name, name);
- }
- output->subpixel_order = SubPixelUnknown;
- /*
- * Use the old per-screen monitor section for the first output
- */
- output->use_screen_monitor = (xf86_config->num_output == 0);
-#ifdef RANDR_12_INTERFACE
- output->randr_output = NULL;
-#endif
- if (name)
- {
- xf86OutputSetMonitor (output);
- if (xf86OutputIgnored (output))
- {
- xfree (output);
- return FALSE;
- }
- }
-
-
- if (xf86_config->output)
- outputs = xrealloc (xf86_config->output,
- (xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
- else
- outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
- if (!outputs)
- {
- xfree (output);
- return NULL;
- }
-
- xf86_config->output = outputs;
-
- if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary)
- {
- memmove(xf86_config->output + 1, xf86_config->output,
- xf86_config->num_output * sizeof (xf86OutputPtr));
- xf86_config->output[0] = output;
- }
- else
- {
- xf86_config->output[xf86_config->num_output] = output;
- }
-
- xf86_config->num_output++;
-
- return output;
-}
-
-Bool
-xf86OutputRename (xf86OutputPtr output, const char *name)
-{
- int len = strlen(name) + 1;
- char *newname = xalloc (len);
-
- if (!newname)
- return FALSE; /* so sorry... */
-
- strcpy (newname, name);
- if (output->name && output->name != (char *) (output + 1))
- xfree (output->name);
- output->name = newname;
- xf86OutputSetMonitor (output);
- if (xf86OutputIgnored (output))
- return FALSE;
- return TRUE;
-}
-
-void
-xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor)
-{
- if (use_screen_monitor != output->use_screen_monitor)
- {
- output->use_screen_monitor = use_screen_monitor;
- xf86OutputSetMonitor (output);
- }
-}
-
-void
-xf86OutputDestroy (xf86OutputPtr output)
-{
- ScrnInfoPtr scrn = output->scrn;
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- int o;
-
- (*output->funcs->destroy) (output);
- while (output->probed_modes)
- xf86DeleteMode (&output->probed_modes, output->probed_modes);
- for (o = 0; o < xf86_config->num_output; o++)
- if (xf86_config->output[o] == output)
- {
- memmove (&xf86_config->output[o],
- &xf86_config->output[o+1],
- ((xf86_config->num_output - (o + 1)) * sizeof(void*)));
- xf86_config->num_output--;
- break;
- }
- if (output->name && output->name != (char *) (output + 1))
- xfree (output->name);
- xfree (output);
-}
-
-/*
- * Called during CreateScreenResources to hook up RandR
- */
-static Bool
-xf86CrtcCreateScreenResources (ScreenPtr screen)
-{
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
-
- screen->CreateScreenResources = config->CreateScreenResources;
-
- if (!(*screen->CreateScreenResources)(screen))
- return FALSE;
-
- if (!xf86RandR12CreateScreenResources (screen))
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * Clean up config on server reset
- */
-static Bool
-xf86CrtcCloseScreen (int index, ScreenPtr screen)
-{
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int o, c;
-
- screen->CloseScreen = config->CloseScreen;
-
- xf86RotateCloseScreen (screen);
-
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
-
- output->randr_output = NULL;
- }
- for (c = 0; c < config->num_crtc; c++)
- {
- xf86CrtcPtr crtc = config->crtc[c];
-
- crtc->randr_crtc = NULL;
- }
- return screen->CloseScreen (index, screen);
-}
-
-/*
- * Called at ScreenInit time to set up
- */
-#ifdef RANDR_13_INTERFACE
-int
-#else
-Bool
-#endif
-xf86CrtcScreenInit (ScreenPtr screen)
-{
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int c;
-
- /* Rotation */
- xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n");
- xf86DisableRandR(); /* Disable old RandR extension support */
- xf86RandR12Init (screen);
-
- /* support all rotations if every crtc has the shadow alloc funcs */
- for (c = 0; c < config->num_crtc; c++)
- {
- xf86CrtcPtr crtc = config->crtc[c];
- if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create)
- break;
- }
- if (c == config->num_crtc)
- {
- xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 |
- RR_Rotate_180 | RR_Rotate_270 |
- RR_Reflect_X | RR_Reflect_Y);
- xf86RandR12SetTransformSupport (screen, TRUE);
- }
- else
- {
- xf86RandR12SetRotations (screen, RR_Rotate_0);
- xf86RandR12SetTransformSupport (screen, FALSE);
- }
-
- /* Wrap CreateScreenResources so we can initialize the RandR code */
- config->CreateScreenResources = screen->CreateScreenResources;
- screen->CreateScreenResources = xf86CrtcCreateScreenResources;
-
- config->CloseScreen = screen->CloseScreen;
- screen->CloseScreen = xf86CrtcCloseScreen;
-
-#ifdef XFreeXDGA
- _xf86_di_dga_init_internal(screen);
-#endif
-#ifdef RANDR_13_INTERFACE
- return RANDR_INTERFACE_VERSION;
-#else
- return TRUE;
-#endif
-}
-
-static DisplayModePtr
-xf86DefaultMode (xf86OutputPtr output, int width, int height)
-{
- DisplayModePtr target_mode = NULL;
- DisplayModePtr mode;
- int target_diff = 0;
- int target_preferred = 0;
- int mm_height;
-
- mm_height = output->mm_height;
- if (!mm_height)
- mm_height = (768 * 25.4) / DEFAULT_DPI;
- /*
- * Pick a mode closest to DEFAULT_DPI
- */
- for (mode = output->probed_modes; mode; mode = mode->next)
- {
- int dpi;
- int preferred = (((mode->type & M_T_PREFERRED) != 0) +
- ((mode->type & M_T_USERPREF) != 0));
- int diff;
-
- if (xf86ModeWidth (mode, output->initial_rotation) > width ||
- xf86ModeHeight (mode, output->initial_rotation) > height)
- continue;
-
- /* yes, use VDisplay here, not xf86ModeHeight */
- dpi = (mode->VDisplay * 254) / (mm_height * 10);
- diff = dpi - DEFAULT_DPI;
- diff = diff < 0 ? -diff : diff;
- if (target_mode == NULL || (preferred > target_preferred) ||
- (preferred == target_preferred && diff < target_diff))
- {
- target_mode = mode;
- target_diff = diff;
- target_preferred = preferred;
- }
- }
- return target_mode;
-}
-
-static DisplayModePtr
-xf86ClosestMode (xf86OutputPtr output,
- DisplayModePtr match, Rotation match_rotation,
- int width, int height)
-{
- DisplayModePtr target_mode = NULL;
- DisplayModePtr mode;
- int target_diff = 0;
-
- /*
- * Pick a mode closest to the specified mode
- */
- for (mode = output->probed_modes; mode; mode = mode->next)
- {
- int dx, dy;
- int diff;
-
- if (xf86ModeWidth (mode, output->initial_rotation) > width ||
- xf86ModeHeight (mode, output->initial_rotation) > height)
- continue;
-
- /* exact matches are preferred */
- if (output->initial_rotation == match_rotation &&
- xf86ModesEqual (mode, match))
- return mode;
-
- dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation);
- dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation);
- diff = dx * dx + dy * dy;
- if (target_mode == NULL || diff < target_diff)
- {
- target_mode = mode;
- target_diff = diff;
- }
- }
- return target_mode;
-}
-
-static DisplayModePtr
-xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
-{
- DisplayModePtr mode;
-
- for (mode = output->probed_modes; mode; mode = mode->next)
- {
- if (xf86ModeWidth (mode, output->initial_rotation) > width ||
- xf86ModeHeight (mode, output->initial_rotation) > height)
- continue;
-
- if (mode->type & M_T_PREFERRED)
- return mode;
- }
- return NULL;
-}
-
-static DisplayModePtr
-xf86OutputHasUserPreferredMode (xf86OutputPtr output)
-{
- DisplayModePtr mode, first = output->probed_modes;
-
- for (mode = first; mode && mode->next != first; mode = mode->next)
- if (mode->type & M_T_USERPREF)
- return mode;
-
- return NULL;
-}
-
-static int
-xf86PickCrtcs (ScrnInfoPtr scrn,
- xf86CrtcPtr *best_crtcs,
- DisplayModePtr *modes,
- int n,
- int width,
- int height)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int c, o;
- xf86OutputPtr output;
- xf86CrtcPtr crtc;
- xf86CrtcPtr *crtcs;
- xf86CrtcPtr best_crtc;
- int best_score;
- int score;
- int my_score;
-
- if (n == config->num_output)
- return 0;
- output = config->output[n];
-
- /*
- * Compute score with this output disabled
- */
- best_crtcs[n] = NULL;
- best_crtc = NULL;
- best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height);
- if (modes[n] == NULL)
- return best_score;
-
- crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr));
- if (!crtcs)
- return best_score;
-
- my_score = 1;
- /* Score outputs that are known to be connected higher */
- if (output->status == XF86OutputStatusConnected)
- my_score++;
- /* Score outputs with preferred modes higher */
- if (xf86OutputHasPreferredMode (output, width, height))
- my_score++;
- /*
- * Select a crtc for this output and
- * then attempt to configure the remaining
- * outputs
- */
- for (c = 0; c < config->num_crtc; c++)
- {
- if ((output->possible_crtcs & (1 << c)) == 0)
- continue;
-
- crtc = config->crtc[c];
- /*
- * Check to see if some other output is
- * using this crtc
- */
- for (o = 0; o < n; o++)
- if (best_crtcs[o] == crtc)
- break;
- if (o < n)
- {
- /*
- * If the two outputs desire the same mode,
- * see if they can be cloned
- */
- if (xf86ModesEqual (modes[o], modes[n]) &&
- config->output[o]->initial_rotation == config->output[n]->initial_rotation &&
- config->output[o]->initial_x == config->output[n]->initial_x &&
- config->output[o]->initial_y == config->output[n]->initial_y)
- {
- if ((output->possible_clones & (1 << o)) == 0)
- continue; /* nope, try next CRTC */
- }
- else
- continue; /* different modes, can't clone */
- }
- crtcs[n] = crtc;
- memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
- score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height);
- if (score > best_score)
- {
- best_crtc = crtc;
- best_score = score;
- memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr));
- }
- }
- xfree (crtcs);
- return best_score;
-}
-
-
-/*
- * Compute the virtual size necessary to place all of the available
- * crtcs in the specified configuration.
- *
- * canGrow indicates that the driver can make the screen larger than its initial
- * configuration. If FALSE, this function will enlarge the screen to include
- * the largest available mode.
- */
-
-static void
-xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp,
- Bool canGrow)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int width = 0, height = 0;
- int o;
- int c;
- int s;
-
- for (c = 0; c < config->num_crtc; c++)
- {
- int crtc_width = 0, crtc_height = 0;
- xf86CrtcPtr crtc = config->crtc[c];
-
- if (crtc->enabled)
- {
- crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation);
- crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation);
- }
- if (!canGrow) {
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
-
- for (s = 0; s < config->num_crtc; s++)
- if (output->possible_crtcs & (1 << s))
- {
- DisplayModePtr mode;
- for (mode = output->probed_modes; mode; mode = mode->next)
- {
- if (mode->HDisplay > crtc_width)
- crtc_width = mode->HDisplay;
- if (mode->VDisplay > crtc_width)
- crtc_width = mode->VDisplay;
- if (mode->VDisplay > crtc_height)
- crtc_height = mode->VDisplay;
- if (mode->HDisplay > crtc_height)
- crtc_height = mode->HDisplay;
- }
- }
- }
- }
- if (crtc_width > width)
- width = crtc_width;
- if (crtc_height > height)
- height = crtc_height;
- }
- if (config->maxWidth && width > config->maxWidth) width = config->maxWidth;
- if (config->maxHeight && height > config->maxHeight) height = config->maxHeight;
- if (config->minWidth && width < config->minWidth) width = config->minWidth;
- if (config->minHeight && height < config->minHeight) height = config->minHeight;
- *widthp = width;
- *heightp = height;
-}
-
-#define POSITION_UNSET -100000
-
-/*
- * check if the user configured any outputs at all
- * with either a position or a relative setting or a mode.
- */
-static Bool
-xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int o;
- Bool user_conf = FALSE;
-
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
- char *position;
- char *relative_name;
- OutputOpts relation;
- int r;
- static const OutputOpts relations[] = {
- OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
- };
-
- position = xf86GetOptValString (output->options,
- OPTION_POSITION);
- if (position)
- user_conf = TRUE;
-
- relation = 0;
- relative_name = NULL;
- for (r = 0; r < 4; r++)
- {
- relation = relations[r];
- relative_name = xf86GetOptValString (output->options,
- relation);
- if (relative_name)
- break;
- }
- if (relative_name)
- user_conf = TRUE;
-
- modes[o] = xf86OutputHasUserPreferredMode(output);
- if (modes[o])
- user_conf = TRUE;
- }
-
- return user_conf;
-}
-
-static Bool
-xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int o;
- int min_x, min_y;
-
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
-
- output->initial_x = output->initial_y = POSITION_UNSET;
- }
-
- /*
- * Loop until all outputs are set
- */
- for (;;)
- {
- Bool any_set = FALSE;
- Bool keep_going = FALSE;
-
- for (o = 0; o < config->num_output; o++)
- {
- static const OutputOpts relations[] = {
- OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
- };
- xf86OutputPtr output = config->output[o];
- xf86OutputPtr relative;
- char *relative_name;
- char *position;
- OutputOpts relation;
- int r;
-
- if (output->initial_x != POSITION_UNSET)
- continue;
- position = xf86GetOptValString (output->options,
- OPTION_POSITION);
- /*
- * Absolute position wins
- */
- if (position)
- {
- int x, y;
- if (sscanf (position, "%d %d", &x, &y) == 2)
- {
- output->initial_x = x;
- output->initial_y = y;
- }
- else
- {
- xf86DrvMsg (scrn->scrnIndex, X_ERROR,
- "Output %s position not of form \"x y\"\n",
- output->name);
- output->initial_x = output->initial_y = 0;
- }
- any_set = TRUE;
- continue;
- }
- /*
- * Next comes relative positions
- */
- relation = 0;
- relative_name = NULL;
- for (r = 0; r < 4; r++)
- {
- relation = relations[r];
- relative_name = xf86GetOptValString (output->options,
- relation);
- if (relative_name)
- break;
- }
- if (relative_name)
- {
- int or;
- relative = NULL;
- for (or = 0; or < config->num_output; or++)
- {
- xf86OutputPtr out_rel = config->output[or];
- XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor;
-
- if (rel_mon)
- {
- if (xf86nameCompare (rel_mon->mon_identifier,
- relative_name) == 0)
- {
- relative = config->output[or];
- break;
- }
- }
- if (strcmp (out_rel->name, relative_name) == 0)
- {
- relative = config->output[or];
- break;
- }
- }
- if (!relative)
- {
- xf86DrvMsg (scrn->scrnIndex, X_ERROR,
- "Cannot position output %s relative to unknown output %s\n",
- output->name, relative_name);
- output->initial_x = 0;
- output->initial_y = 0;
- any_set = TRUE;
- continue;
- }
- if (!modes[or])
- {
- xf86DrvMsg (scrn->scrnIndex, X_ERROR,
- "Cannot position output %s relative to output %s without modes\n",
- output->name, relative_name);
- output->initial_x = 0;
- output->initial_y = 0;
- any_set = TRUE;
- continue;
- }
- if (relative->initial_x == POSITION_UNSET)
- {
- keep_going = TRUE;
- continue;
- }
- output->initial_x = relative->initial_x;
- output->initial_y = relative->initial_y;
- switch (relation) {
- case OPTION_BELOW:
- output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation);
- break;
- case OPTION_RIGHT_OF:
- output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation);
- break;
- case OPTION_ABOVE:
- if (modes[o])
- output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation);
- break;
- case OPTION_LEFT_OF:
- if (modes[o])
- output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation);
- break;
- default:
- break;
- }
- any_set = TRUE;
- continue;
- }
-
- /* Nothing set, just stick them at 0,0 */
- output->initial_x = 0;
- output->initial_y = 0;
- any_set = TRUE;
- }
- if (!keep_going)
- break;
- if (!any_set)
- {
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
- if (output->initial_x == POSITION_UNSET)
- {
- xf86DrvMsg (scrn->scrnIndex, X_ERROR,
- "Output position loop. Moving %s to 0,0\n",
- output->name);
- output->initial_x = output->initial_y = 0;
- break;
- }
- }
- }
- }
-
- /*
- * normalize positions
- */
- min_x = 1000000;
- min_y = 1000000;
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
-
- if (output->initial_x < min_x)
- min_x = output->initial_x;
- if (output->initial_y < min_y)
- min_y = output->initial_y;
- }
-
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
-
- output->initial_x -= min_x;
- output->initial_y -= min_y;
- }
- return TRUE;
-}
-
-static void
-xf86InitialPanning (ScrnInfoPtr scrn)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int o;
-
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
- char *panning = xf86GetOptValString (output->options, OPTION_PANNING);
- int width, height, left, top;
- int track_width, track_height, track_left, track_top;
- int brdr[4];
-
- memset (&output->initialTotalArea, 0, sizeof(BoxRec));
- memset (&output->initialTrackingArea, 0, sizeof(BoxRec));
- memset (output->initialBorder, 0, 4*sizeof(INT16));
-
- if (! panning)
- continue;
-
- switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d",
- &width, &height, &left, &top,
- &track_width, &track_height, &track_left, &track_top,
- &brdr[0], &brdr[1], &brdr[2], &brdr[3])) {
- case 12:
- output->initialBorder[0] = brdr[0];
- output->initialBorder[1] = brdr[1];
- output->initialBorder[2] = brdr[2];
- output->initialBorder[3] = brdr[3];
- /* fall through */
- case 8:
- output->initialTrackingArea.x1 = track_left;
- output->initialTrackingArea.y1 = track_top;
- output->initialTrackingArea.x2 = track_left + track_width;
- output->initialTrackingArea.y2 = track_top + track_height;
- /* fall through */
- case 4:
- output->initialTotalArea.x1 = left;
- output->initialTotalArea.y1 = top;
- /* fall through */
- case 2:
- output->initialTotalArea.x2 = output->initialTotalArea.x1 + width;
- output->initialTotalArea.y2 = output->initialTotalArea.y1 + height;
- break;
- default:
- xf86DrvMsg (scrn->scrnIndex, X_ERROR,
- "Broken panning specification '%s' for output %s in config file\n",
- panning, output->name);
- }
- }
-}
-
-/** Return - 0 + if a should be earlier, same or later than b in list
- */
-static int
-xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
-{
- int diff;
-
- diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0);
- if (diff)
- return diff;
- diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
- if (diff)
- return diff;
- diff = b->Clock - a->Clock;
- return diff;
-}
-
-/**
- * Insertion sort input in-place and return the resulting head
- */
-static DisplayModePtr
-xf86SortModes (DisplayModePtr input)
-{
- DisplayModePtr output = NULL, i, o, n, *op, prev;
-
- /* sort by preferred status and pixel area */
- while (input)
- {
- i = input;
- input = input->next;
- for (op = &output; (o = *op); op = &o->next)
- if (xf86ModeCompare (o, i) > 0)
- break;
- i->next = *op;
- *op = i;
- }
- /* prune identical modes */
- for (o = output; o && (n = o->next); o = n)
- {
- if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n))
- {
- o->next = n->next;
- xfree (n->name);
- xfree (n);
- n = o;
- }
- }
- /* hook up backward links */
- prev = NULL;
- for (o = output; o; o = o->next)
- {
- o->prev = prev;
- prev = o;
- }
- return output;
-}
-
-static char *
-preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output)
-{
- char *preferred_mode = NULL;
-
- /* Check for a configured preference for a particular mode */
- preferred_mode = xf86GetOptValString (output->options,
- OPTION_PREFERRED_MODE);
- if (preferred_mode)
- return preferred_mode;
-
- if (pScrn->display->modes && *pScrn->display->modes)
- preferred_mode = *pScrn->display->modes;
-
- return preferred_mode;
-}
-
-static void
-GuessRangeFromModes(MonPtr mon, DisplayModePtr mode)
-{
- if (!mon || !mode)
- return;
-
- mon->nHsync = 1;
- mon->hsync[0].lo = 1024.0;
- mon->hsync[0].hi = 0.0;
-
- mon->nVrefresh = 1;
- mon->vrefresh[0].lo = 1024.0;
- mon->vrefresh[0].hi = 0.0;
-
- while (mode) {
- if (!mode->HSync)
- mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal);
-
- if (!mode->VRefresh)
- mode->VRefresh = (1000.0 * ((float) mode->Clock)) /
- ((float) (mode->HTotal * mode->VTotal));
-
- if (mode->HSync < mon->hsync[0].lo)
- mon->hsync[0].lo = mode->HSync;
-
- if (mode->HSync > mon->hsync[0].hi)
- mon->hsync[0].hi = mode->HSync;
-
- if (mode->VRefresh < mon->vrefresh[0].lo)
- mon->vrefresh[0].lo = mode->VRefresh;
-
- if (mode->VRefresh > mon->vrefresh[0].hi)
- mon->vrefresh[0].hi = mode->VRefresh;
-
- mode = mode->next;
- }
-
- /* stretch out the bottom to fit 640x480@60 */
- if (mon->hsync[0].lo > 31.0)
- mon->hsync[0].lo = 31.0;
- if (mon->vrefresh[0].lo > 58.0)
- mon->vrefresh[0].lo = 58.0;
-}
-
-struct det_monrec_parameter {
- MonRec *mon_rec;
- int *max_clock;
- Bool set_hsync;
- Bool set_vrefresh;
- enum { sync_config, sync_edid, sync_default } *sync_source;
-};
-
-static void handle_detailed_monrec(struct detailed_monitor_section *det_mon,
- void *data)
-{
- enum { sync_config, sync_edid, sync_default };
- struct det_monrec_parameter *p;
- p = (struct det_monrec_parameter *)data;
-
- if (det_mon->type == DS_RANGES) {
- struct monitor_ranges *ranges = &det_mon->section.ranges;
- if (p->set_hsync && ranges->max_h) {
- p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h;
- p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h;
- p->mon_rec->nHsync++;
- if (*p->sync_source == sync_default)
- *p->sync_source = sync_edid;
- }
- if (p->set_vrefresh && ranges->max_v) {
- p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v;
- p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v;
- p->mon_rec->nVrefresh++;
- if (*p->sync_source == sync_default)
- *p->sync_source = sync_edid;
- }
- if (ranges->max_clock * 1000 > *p->max_clock)
- *p->max_clock = ranges->max_clock * 1000;
- }
-}
-
-void
-xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int o;
-
- /* When canGrow was TRUE in the initial configuration we have to
- * compare against the maximum values so that we don't drop modes.
- * When canGrow was FALSE, the maximum values would have been clamped
- * anyway.
- */
- if (maxX == 0 || maxY == 0) {
- maxX = config->maxWidth;
- maxY = config->maxHeight;
- }
-
- /* Probe the list of modes for each output. */
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
- DisplayModePtr mode;
- DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL;
- char *preferred_mode;
- xf86MonPtr edid_monitor;
- XF86ConfMonitorPtr conf_monitor;
- MonRec mon_rec;
- int min_clock = 0;
- int max_clock = 0;
- double clock;
- Bool add_default_modes = TRUE;
- Bool debug_modes = config->debug_modes ||
- xf86Initialising;
- enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
-
- while (output->probed_modes != NULL)
- xf86DeleteMode(&output->probed_modes, output->probed_modes);
-
- /*
- * Check connection status
- */
- output->status = (*output->funcs->detect)(output);
-
- if (output->status == XF86OutputStatusDisconnected)
- {
- xf86OutputSetEDID (output, NULL);
- continue;
- }
-
- memset (&mon_rec, '\0', sizeof (mon_rec));
-
- conf_monitor = output->conf_monitor;
-
- if (conf_monitor)
- {
- int i;
-
- for (i = 0; i < conf_monitor->mon_n_hsync; i++)
- {
- mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
- mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
- mon_rec.nHsync++;
- sync_source = sync_config;
- }
- for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
- {
- mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
- mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
- mon_rec.nVrefresh++;
- sync_source = sync_config;
- }
- config_modes = xf86GetMonitorModes (scrn, conf_monitor);
- }
-
- output_modes = (*output->funcs->get_modes) (output);
-
- edid_monitor = output->MonInfo;
-
- if (edid_monitor)
- {
- struct det_monrec_parameter p;
- struct disp_features *features = &edid_monitor->features;
-
- /* if display is not continuous-frequency, don't add default modes */
- if (!GTF_SUPPORTED(features->msc))
- add_default_modes = FALSE;
-
- p.mon_rec = &mon_rec;
- p.max_clock = &max_clock;
- p.set_hsync = mon_rec.nHsync == 0;
- p.set_vrefresh = mon_rec.nVrefresh == 0;
- p.sync_source = &sync_source;
-
- xf86ForEachDetailedBlock(edid_monitor,
- handle_detailed_monrec,
- &p);
- }
-
- if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
- OPTUNITS_KHZ, &clock))
- min_clock = (int) clock;
- if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
- OPTUNITS_KHZ, &clock))
- max_clock = (int) clock;
-
- /* If we still don't have a sync range, guess wildly */
- if (!mon_rec.nHsync || !mon_rec.nVrefresh)
- GuessRangeFromModes(&mon_rec, output_modes);
-
- /*
- * These limits will end up setting a 1024x768@60Hz mode by default,
- * which seems like a fairly good mode to use when nothing else is
- * specified
- */
- if (mon_rec.nHsync == 0)
- {
- mon_rec.hsync[0].lo = 31.0;
- mon_rec.hsync[0].hi = 55.0;
- mon_rec.nHsync = 1;
- }
- if (mon_rec.nVrefresh == 0)
- {
- mon_rec.vrefresh[0].lo = 58.0;
- mon_rec.vrefresh[0].hi = 62.0;
- mon_rec.nVrefresh = 1;
- }
-
- if (add_default_modes)
- default_modes = xf86GetDefaultModes ();
-
- /*
- * If this is not an RB monitor, remove RB modes from the default
- * pool. RB modes from the config or the monitor itself are fine.
- */
- if (!mon_rec.reducedblanking)
- xf86ValidateModesReducedBlanking (scrn, default_modes);
-
- if (sync_source == sync_config)
- {
- /*
- * Check output and config modes against sync range from config file
- */
- xf86ValidateModesSync (scrn, output_modes, &mon_rec);
- xf86ValidateModesSync (scrn, config_modes, &mon_rec);
- }
- /*
- * Check default modes against sync range
- */
- xf86ValidateModesSync (scrn, default_modes, &mon_rec);
- /*
- * Check default modes against monitor max clock
- */
- if (max_clock) {
- xf86ValidateModesClocks(scrn, default_modes,
- &min_clock, &max_clock, 1);
- xf86ValidateModesClocks(scrn, output_modes,
- &min_clock, &max_clock, 1);
- }
-
- output->probed_modes = NULL;
- output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
- output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes);
- output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
-
- /*
- * Check all modes against max size, interlace, and doublescan
- */
- if (maxX && maxY)
- xf86ValidateModesSize (scrn, output->probed_modes,
- maxX, maxY, 0);
-
- {
- int flags = (output->interlaceAllowed ? V_INTERLACE : 0) |
- (output->doubleScanAllowed ? V_DBLSCAN : 0);
- xf86ValidateModesFlags (scrn, output->probed_modes, flags);
- }
-
- /*
- * Check all modes against output
- */
- for (mode = output->probed_modes; mode != NULL; mode = mode->next)
- if (mode->status == MODE_OK)
- mode->status = (*output->funcs->mode_valid)(output, mode);
-
- xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes);
-
- output->probed_modes = xf86SortModes (output->probed_modes);
-
- /* Check for a configured preference for a particular mode */
- preferred_mode = preferredMode(scrn, output);
-
- if (preferred_mode)
- {
- for (mode = output->probed_modes; mode; mode = mode->next)
- {
- if (!strcmp (preferred_mode, mode->name))
- {
- if (mode != output->probed_modes)
- {
- if (mode->prev)
- mode->prev->next = mode->next;
- if (mode->next)
- mode->next->prev = mode->prev;
- mode->next = output->probed_modes;
- output->probed_modes->prev = mode;
- mode->prev = NULL;
- output->probed_modes = mode;
- }
- mode->type |= (M_T_PREFERRED|M_T_USERPREF);
- break;
- }
- }
- }
-
- output->initial_rotation = xf86OutputInitialRotation (output);
-
- if (debug_modes) {
- if (output->probed_modes != NULL) {
- xf86DrvMsg(scrn->scrnIndex, X_INFO,
- "Printing probed modes for output %s\n",
- output->name);
- } else {
- xf86DrvMsg(scrn->scrnIndex, X_INFO,
- "No remaining probed modes for output %s\n",
- output->name);
- }
- }
- for (mode = output->probed_modes; mode != NULL; mode = mode->next)
- {
- /* The code to choose the best mode per pipe later on will require
- * VRefresh to be set.
- */
- mode->VRefresh = xf86ModeVRefresh(mode);
- xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
-
- if (debug_modes)
- xf86PrintModeline(scrn->scrnIndex, mode);
- }
- }
-}
-
-
-/**
- * Copy one of the output mode lists to the ScrnInfo record
- */
-
-/* XXX where does this function belong? Here? */
-void
-xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
-
-static DisplayModePtr
-biggestMode(DisplayModePtr a, DisplayModePtr b)
-{
- int A, B;
-
- if (!a)
- return b;
- if (!b)
- return a;
-
- A = a->HDisplay * a->VDisplay;
- B = b->HDisplay * b->VDisplay;
-
- if (A > B)
- return a;
-
- return b;
-}
-
-static xf86OutputPtr
-SetCompatOutput(xf86CrtcConfigPtr config)
-{
- xf86OutputPtr output = NULL, test = NULL;
- DisplayModePtr maxmode = NULL, testmode, mode;
- int o, compat = -1, count, mincount = 0;
-
- /* Look for one that's definitely connected */
- for (o = 0; o < config->num_output; o++)
- {
- test = config->output[o];
- if (!test->crtc)
- continue;
- if (test->status != XF86OutputStatusConnected)
- continue;
- if (!test->probed_modes)
- continue;
-
- testmode = mode = test->probed_modes;
- for (count = 0; mode; mode = mode->next, count++)
- testmode = biggestMode(testmode, mode);
-
- if (!output) {
- output = test;
- compat = o;
- maxmode = testmode;
- mincount = count;
- } else if (maxmode == biggestMode(maxmode, testmode)) {
- output = test;
- compat = o;
- maxmode = testmode;
- mincount = count;
- } else if ((maxmode->HDisplay == testmode->HDisplay) &&
- (maxmode->VDisplay == testmode->VDisplay) &&
- count <= mincount) {
- output = test;
- compat = o;
- maxmode = testmode;
- mincount = count;
- }
- }
-
- /* If we didn't find one, take anything we can get */
- if (!output)
- {
- for (o = 0; o < config->num_output; o++)
- {
- test = config->output[o];
- if (!test->crtc)
- continue;
- if (!test->probed_modes)
- continue;
-
- if (!output) {
- output = test;
- compat = o;
- } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) {
- output = test;
- compat = o;
- }
- }
- }
-
- if (compat >= 0) {
- config->compat_output = compat;
- } else {
- /* Don't change the compat output when no valid outputs found */
- output = config->output[config->compat_output];
- }
-
- return output;
-}
-
-void
-xf86SetScrnInfoModes (ScrnInfoPtr scrn)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- xf86OutputPtr output;
- xf86CrtcPtr crtc;
- DisplayModePtr last, mode = NULL;
-
- output = SetCompatOutput(config);
-
- if (!output)
- return; /* punt */
-
- crtc = output->crtc;
-
- /* Clear any existing modes from scrn->modes */
- while (scrn->modes != NULL)
- xf86DeleteMode(&scrn->modes, scrn->modes);
-
- /* Set scrn->modes to the mode list for the 'compat' output */
- scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
-
- if (crtc) {
- for (mode = scrn->modes; mode; mode = mode->next)
- if (xf86ModesEqual (mode, &crtc->desiredMode))
- break;
- }
-
- if (scrn->modes != NULL) {
- /* For some reason, scrn->modes is circular, unlike the other mode
- * lists. How great is that?
- */
- for (last = scrn->modes; last && last->next; last = last->next)
- ;
- last->next = scrn->modes;
- scrn->modes->prev = last;
- if (mode) {
- while (scrn->modes != mode)
- scrn->modes = scrn->modes->next;
- }
- }
- scrn->currentMode = scrn->modes;
-#ifdef XFreeXDGA
- if (scrn->pScreen)
- _xf86_di_dga_reinit_internal(scrn->pScreen);
-#endif
-}
-
-static void
-xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
- Bool *enabled)
-{
- Bool any_enabled = FALSE;
- int o;
-
- for (o = 0; o < config->num_output; o++)
- any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE);
-
- if (!any_enabled) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "No outputs definitely connected, trying again...\n");
-
- for (o = 0; o < config->num_output; o++)
- enabled[o] = xf86OutputEnabled(config->output[o], FALSE);
- }
-}
-
-static Bool
-nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
-{
- int o = *index;
-
- for (o++; o < config->num_output; o++) {
- if (enabled[o]) {
- *index = o;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static Bool
-aspectMatch(float a, float b)
-{
- return fabs(1 - (a / b)) < 0.05;
-}
-
-static DisplayModePtr
-nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
-{
- DisplayModePtr m = NULL;
-
- if (!o)
- return NULL;
-
- if (!last)
- m = o->probed_modes;
- else
- m = last->next;
-
- for (; m; m = m->next)
- if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
- return m;
-
- return NULL;
-}
-
-static DisplayModePtr
-bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
-{
- int o = -1, p;
- DisplayModePtr mode = NULL, test = NULL, match = NULL;
-
- if (!nextEnabledOutput(config, enabled, &o))
- return NULL;
- while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
- test = mode;
- for (p = o; nextEnabledOutput(config, enabled, &p); ) {
- test = xf86OutputFindClosestMode(config->output[p], mode);
- if (!test)
- break;
- if (test->HDisplay != mode->HDisplay ||
- test->VDisplay != mode->VDisplay) {
- test = NULL;
- break;
- }
- }
-
- /* if we didn't match it on all outputs, try the next one */
- if (!test)
- continue;
-
- /* if it's bigger than the last one, save it */
- if (!match || (test->HDisplay > match->HDisplay))
- match = test;
- }
-
- /* return the biggest one found */
- return match;
-}
-
-static Bool
-xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
- DisplayModePtr *modes, Bool *enabled,
- int width, int height)
-{
- int o, p;
- int max_pref_width = 0, max_pref_height = 0;
- DisplayModePtr *preferred, *preferred_match;
- Bool ret = FALSE;
-
- preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
- preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
-
- /* Check if the preferred mode is available on all outputs */
- for (p = -1; nextEnabledOutput(config, enabled, &p); ) {
- Rotation r = config->output[p]->initial_rotation;
- DisplayModePtr mode;
- if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p],
- width, height))) {
- int pref_width = xf86ModeWidth(preferred[p], r);
- int pref_height = xf86ModeHeight(preferred[p], r);
- Bool all_match = TRUE;
-
- for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
- Bool match = FALSE;
- xf86OutputPtr output = config->output[o];
- if (o == p)
- continue;
-
- for (mode = output->probed_modes; mode; mode = mode->next) {
- Rotation r = output->initial_rotation;
- if (xf86ModeWidth(mode, r) == pref_width &&
- xf86ModeHeight(mode, r) == pref_height) {
- preferred[o] = mode;
- match = TRUE;
- }
- }
-
- all_match &= match;
- }
-
- if (all_match &&
- (pref_width*pref_height > max_pref_width*max_pref_height)) {
- for (o = -1; nextEnabledOutput(config, enabled, &o); )
- preferred_match[o] = preferred[o];
- max_pref_width = pref_width;
- max_pref_height = pref_height;
- ret = TRUE;
- }
- }
- }
-
- /*
- * If there's no preferred mode, but only one monitor, pick the
- * biggest mode for its aspect ratio, assuming one exists.
- */
- if (!ret) do {
- int i = 0;
- float aspect = 0.0;
-
- /* count the number of enabled outputs */
- for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ;
-
- if (i != 1)
- break;
-
- p = -1;
- nextEnabledOutput(config, enabled, &p);
- if (config->output[p]->mm_height)
- aspect = (float)config->output[p]->mm_width /
- (float)config->output[p]->mm_height;
-
- if (aspect)
- preferred_match[p] = bestModeForAspect(config, enabled, aspect);
-
- if (preferred_match[p])
- ret = TRUE;
-
- } while (0);
-
- if (ret) {
- /* oh good, there is a match. stash the selected modes and return. */
- memcpy(modes, preferred_match,
- config->num_output * sizeof(DisplayModePtr));
- }
-
- xfree(preferred);
- xfree(preferred_match);
- return ret;
-}
-
-static Bool
-xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
- DisplayModePtr *modes, Bool *enabled,
- int width, int height)
-{
- int o;
- float aspect = 0.0, *aspects;
- xf86OutputPtr output;
- Bool ret = FALSE;
- DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL;
-
- aspects = xnfcalloc(config->num_output, sizeof(float));
-
- /* collect the aspect ratios */
- for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
- output = config->output[o];
- if (output->mm_height)
- aspects[o] = (float)output->mm_width / (float)output->mm_height;
- else
- aspects[o] = 4.0 / 3.0;
- }
-
- /* check that they're all the same */
- for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
- output = config->output[o];
- if (!aspect) {
- aspect = aspects[o];
- } else if (!aspectMatch(aspect, aspects[o])) {
- goto no_aspect_match;
- }
- }
-
- /* if they're all 4:3, just skip ahead and save effort */
- if (!aspectMatch(aspect, 4.0/3.0))
- aspect_guess = bestModeForAspect(config, enabled, aspect);
-
-no_aspect_match:
- base_guess = bestModeForAspect(config, enabled, 4.0/3.0);
-
- guess = biggestMode(base_guess, aspect_guess);
-
- if (!guess)
- goto out;
-
- /* found a mode that works everywhere, now apply it */
- for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
- modes[o] = xf86OutputFindClosestMode(config->output[o], guess);
- }
- ret = TRUE;
-
-out:
- xfree(aspects);
- return ret;
-}
-
-static Bool
-xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
- DisplayModePtr *modes, Bool *enabled,
- int width, int height)
-{
- DisplayModePtr target_mode = NULL;
- Rotation target_rotation = RR_Rotate_0;
- DisplayModePtr default_mode;
- int default_preferred, target_preferred = 0, o;
-
- /* User preferred > preferred > other modes */
- for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
- default_mode = xf86DefaultMode (config->output[o], width, height);
- if (!default_mode)
- continue;
-
- default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
- ((default_mode->type & M_T_USERPREF) != 0));
-
- if (default_preferred > target_preferred || !target_mode) {
- target_mode = default_mode;
- target_preferred = default_preferred;
- target_rotation = config->output[o]->initial_rotation;
- config->compat_output = o;
- }
- }
-
- if (target_mode)
- modes[config->compat_output] = target_mode;
-
- /* Fill in other output modes */
- for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
- if (!modes[o])
- modes[o] = xf86ClosestMode(config->output[o], target_mode,
- target_rotation, width, height);
- }
-
- return (target_mode != NULL);
-}
-
-static Bool
-xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
- DisplayModePtr *modes, Bool *enabled,
- int width, int height)
-{
- int o;
-
- if (xf86UserConfiguredOutputs(scrn, modes))
- return xf86TargetFallback(scrn, config, modes, enabled, width, height);
-
- for (o = -1; nextEnabledOutput(config, enabled, &o); )
- if (xf86OutputHasUserPreferredMode(config->output[o]))
- return
- xf86TargetFallback(scrn, config, modes, enabled, width, height);
-
- return FALSE;
-}
-
-static Bool
-xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green,
- float gamma_blue)
-{
- int i, size = 256;
- CARD16 *red, *green, *blue;
-
- red = malloc(3 * size * sizeof(CARD16));
- green = red + size;
- blue = green + size;
-
- /* Only cause warning if user wanted gamma to be set. */
- if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) {
- free(red);
- return FALSE;
- } else if (!crtc->funcs->gamma_set) {
- free(red);
- return TRUE;
- }
-
- /* At this early stage none of the randr-interface stuff is up.
- * So take the default gamma size for lack of something better.
- */
- for (i = 0; i < size; i++) {
- if (gamma_red == 1.0)
- red[i] = i << 8;
- else
- red[i] = (CARD16)(pow((double)i/(double)(size - 1),
- 1. / (double)gamma_red) * (double)(size - 1) * 256);
-
- if (gamma_green == 1.0)
- green[i] = i << 8;
- else
- green[i] = (CARD16)(pow((double)i/(double)(size - 1),
- 1. / (double)gamma_green) * (double)(size - 1) * 256);
-
- if (gamma_blue == 1.0)
- blue[i] = i << 8;
- else
- blue[i] = (CARD16)(pow((double)i/(double)(size - 1),
- 1. / (double)gamma_blue) * (double)(size - 1) * 256);
- }
-
- /* Default size is 256, so anything else is failure. */
- if (size != crtc->gamma_size) {
- free(red);
- return FALSE;
- }
-
- crtc->gamma_size = size;
- memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16));
- memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16));
- memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16));
-
- /* Do not set gamma now, delay until the crtc is activated. */
-
- free(red);
-
- return TRUE;
-}
-
-static Bool
-xf86OutputSetInitialGamma(xf86OutputPtr output)
-{
- XF86ConfMonitorPtr mon = output->conf_monitor;
- float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0;
-
- if (!mon)
- return TRUE;
-
- if (!output->crtc)
- return FALSE;
-
- /* Get configured values, where they exist. */
- if (mon->mon_gamma_red >= GAMMA_MIN &&
- mon->mon_gamma_red <= GAMMA_MAX)
- gamma_red = mon->mon_gamma_red;
-
- if (mon->mon_gamma_green >= GAMMA_MIN &&
- mon->mon_gamma_green <= GAMMA_MAX)
- gamma_green = mon->mon_gamma_green;
-
- if (mon->mon_gamma_blue >= GAMMA_MIN &&
- mon->mon_gamma_blue <= GAMMA_MAX)
- gamma_blue = mon->mon_gamma_blue;
-
- /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */
- if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) {
- xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue);
- return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue);
- }else
- return TRUE;
-}
-
-/**
- * Construct default screen configuration
- *
- * Given auto-detected (and, eventually, configured) values,
- * construct a usable configuration for the system
- *
- * canGrow indicates that the driver can resize the screen to larger than its
- * initially configured size via the config->funcs->resize hook. If TRUE, this
- * function will set virtualX and virtualY to match the initial configuration
- * and leave config->max{Width,Height} alone. If FALSE, it will bloat
- * virtual[XY] to include the largest modes and set config->max{Width,Height}
- * accordingly.
- */
-
-Bool
-xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int o, c;
- xf86CrtcPtr *crtcs;
- DisplayModePtr *modes;
- Bool *enabled;
- int width, height;
- int i = scrn->scrnIndex;
-
- /* Set up the device options */
- config->options = xnfalloc (sizeof (xf86DeviceOptions));
- memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions));
- xf86ProcessOptions (scrn->scrnIndex,
- scrn->options,
- config->options);
- config->debug_modes = xf86ReturnOptValBool (config->options,
- OPTION_MODEDEBUG, FALSE);
-
- if (scrn->display->virtualX)
- width = scrn->display->virtualX;
- else
- width = config->maxWidth;
- if (scrn->display->virtualY)
- height = scrn->display->virtualY;
- else
- height = config->maxHeight;
-
- xf86ProbeOutputModes (scrn, width, height);
-
- crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
- modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
- enabled = xnfcalloc (config->num_output, sizeof (Bool));
-
- xf86CollectEnabledOutputs(scrn, config, enabled);
-
- if (xf86TargetUserpref(scrn, config, modes, enabled, width, height))
- xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n");
- else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height))
- xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n");
- else if (xf86TargetAspect(scrn, config, modes, enabled, width, height))
- xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n");
- else if (xf86TargetFallback(scrn, config, modes, enabled, width, height))
- xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n");
- else
- xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n");
-
- for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
- if (!modes[o])
- xf86DrvMsg (scrn->scrnIndex, X_ERROR,
- "Output %s enabled but has no modes\n",
- config->output[o]->name);
- else
- xf86DrvMsg (scrn->scrnIndex, X_INFO,
- "Output %s using initial mode %s\n",
- config->output[o]->name, modes[o]->name);
- }
-
- /*
- * Set the position of each output
- */
- if (!xf86InitialOutputPositions (scrn, modes))
- {
- xfree (crtcs);
- xfree (modes);
- return FALSE;
- }
-
- /*
- * Set initial panning of each output
- */
- xf86InitialPanning (scrn);
-
- /*
- * Assign CRTCs to fit output configuration
- */
- if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height))
- {
- xfree (crtcs);
- xfree (modes);
- return FALSE;
- }
-
- /* XXX override xf86 common frame computation code */
-
- scrn->display->frameX0 = 0;
- scrn->display->frameY0 = 0;
-
- for (c = 0; c < config->num_crtc; c++)
- {
- xf86CrtcPtr crtc = config->crtc[c];
-
- crtc->enabled = FALSE;
- memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
- /* Set default gamma for all crtc's. */
- /* This is done to avoid problems later on with cloned outputs. */
- xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0);
- }
-
- if (xf86_crtc_supports_gamma(scrn))
- xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n");
-
- /*
- * Set initial configuration
- */
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
- DisplayModePtr mode = modes[o];
- xf86CrtcPtr crtc = crtcs[o];
-
- if (mode && crtc)
- {
- crtc->desiredMode = *mode;
- crtc->desiredRotation = output->initial_rotation;
- crtc->desiredX = output->initial_x;
- crtc->desiredY = output->initial_y;
- crtc->desiredTransformPresent = FALSE;
- crtc->enabled = TRUE;
- memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec));
- memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec));
- memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16));
- output->crtc = crtc;
- if (!xf86OutputSetInitialGamma(output))
- xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name);
- } else {
- output->crtc = NULL;
- }
- }
-
- if (scrn->display->virtualX == 0)
- {
- /*
- * Expand virtual size to cover the current config and potential mode
- * switches, if the driver can't enlarge the screen later.
- */
- xf86DefaultScreenLimits (scrn, &width, &height, canGrow);
-
- scrn->display->virtualX = width;
- scrn->display->virtualY = height;
- }
-
- if (width > scrn->virtualX)
- scrn->virtualX = width;
- if (height > scrn->virtualY)
- scrn->virtualY = height;
-
- /*
- * Make sure the configuration isn't too small.
- */
- if (width < config->minWidth || height < config->minHeight)
- return FALSE;
-
- /*
- * Limit the crtc config to virtual[XY] if the driver can't grow the
- * desktop.
- */
- if (!canGrow)
- {
- xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight,
- width, height);
- }
-
- /* Mirror output modes to scrn mode list */
- xf86SetScrnInfoModes (scrn);
-
- xfree (crtcs);
- xfree (modes);
- return TRUE;
-}
-
-/*
- * Check the CRTC we're going to map each output to vs. it's current
- * CRTC. If they don't match, we have to disable the output and the CRTC
- * since the driver will have to re-route things.
- */
-static void
-xf86PrepareOutputs (ScrnInfoPtr scrn)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int o;
-
- for (o = 0; o < config->num_output; o++) {
- xf86OutputPtr output = config->output[o];
-#if RANDR_GET_CRTC_INTERFACE
- /* Disable outputs that are unused or will be re-routed */
- if (!output->funcs->get_crtc ||
- output->crtc != (*output->funcs->get_crtc)(output) ||
- output->crtc == NULL)
-#endif
- (*output->funcs->dpms)(output, DPMSModeOff);
- }
-}
-
-static void
-xf86PrepareCrtcs (ScrnInfoPtr scrn)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int c;
-
- for (c = 0; c < config->num_crtc; c++) {
-#if RANDR_GET_CRTC_INTERFACE
- xf86CrtcPtr crtc = config->crtc[c];
- xf86OutputPtr output = NULL;
- uint32_t desired_outputs = 0, current_outputs = 0;
- int o;
-
- for (o = 0; o < config->num_output; o++) {
- output = config->output[o];
- if (output->crtc == crtc)
- desired_outputs |= (1<<o);
- /* If we can't tell where it's mapped, force it off */
- if (!output->funcs->get_crtc) {
- desired_outputs = 0;
- break;
- }
- if ((*output->funcs->get_crtc)(output) == crtc)
- current_outputs |= (1<<o);
- }
-
- /*
- * If mappings are different or the CRTC is unused,
- * we need to disable it
- */
- if (desired_outputs != current_outputs ||
- !desired_outputs)
- (*crtc->funcs->dpms)(crtc, DPMSModeOff);
-#else
- (*crtc->funcs->dpms)(crtc, DPMSModeOff);
-#endif
- }
-}
-
-/*
- * Using the desired mode information in each crtc, set
- * modes (used in EnterVT functions, or at server startup)
- */
-
-Bool
-xf86SetDesiredModes (ScrnInfoPtr scrn)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- xf86CrtcPtr crtc = config->crtc[0];
- int c;
-
- /* A driver with this hook will take care of this */
- if (!crtc->funcs->set_mode_major) {
- xf86PrepareOutputs(scrn);
- xf86PrepareCrtcs(scrn);
- }
-
- for (c = 0; c < config->num_crtc; c++)
- {
- xf86OutputPtr output = NULL;
- int o;
- RRTransformPtr transform;
-
- crtc = config->crtc[c];
-
- /* Skip disabled CRTCs */
- if (!crtc->enabled)
- continue;
-
- if (config->output[config->compat_output]->crtc == crtc)
- output = config->output[config->compat_output];
- else
- {
- for (o = 0; o < config->num_output; o++)
- if (config->output[o]->crtc == crtc)
- {
- output = config->output[o];
- break;
- }
- }
- /* paranoia */
- if (!output)
- continue;
-
- /* Mark that we'll need to re-set the mode for sure */
- memset(&crtc->mode, 0, sizeof(crtc->mode));
- if (!crtc->desiredMode.CrtcHDisplay)
- {
- DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode);
-
- if (!mode)
- return FALSE;
- crtc->desiredMode = *mode;
- crtc->desiredRotation = RR_Rotate_0;
- crtc->desiredTransformPresent = FALSE;
- crtc->desiredX = 0;
- crtc->desiredY = 0;
- }
-
- if (crtc->desiredTransformPresent)
- transform = &crtc->desiredTransform;
- else
- transform = NULL;
- if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation,
- transform, crtc->desiredX, crtc->desiredY))
- return FALSE;
- }
-
- xf86DisableUnusedFunctions(scrn);
- return TRUE;
-}
-
-/**
- * In the current world order, there are lists of modes per output, which may
- * or may not include the mode that was asked to be set by XFree86's mode
- * selection. Find the closest one, in the following preference order:
- *
- * - Equality
- * - Closer in size to the requested mode, but no larger
- * - Closer in refresh rate to the requested mode.
- */
-
-DisplayModePtr
-xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired)
-{
- DisplayModePtr best = NULL, scan = NULL;
-
- for (scan = output->probed_modes; scan != NULL; scan = scan->next)
- {
- /* If there's an exact match, we're done. */
- if (xf86ModesEqual(scan, desired)) {
- best = desired;
- break;
- }
-
- /* Reject if it's larger than the desired mode. */
- if (scan->HDisplay > desired->HDisplay ||
- scan->VDisplay > desired->VDisplay)
- {
- continue;
- }
-
- /*
- * If we haven't picked a best mode yet, use the first
- * one in the size range
- */
- if (best == NULL)
- {
- best = scan;
- continue;
- }
-
- /* Find if it's closer to the right size than the current best
- * option.
- */
- if ((scan->HDisplay > best->HDisplay &&
- scan->VDisplay >= best->VDisplay) ||
- (scan->HDisplay >= best->HDisplay &&
- scan->VDisplay > best->VDisplay))
- {
- best = scan;
- continue;
- }
-
- /* Find if it's still closer to the right refresh than the current
- * best resolution.
- */
- if (scan->HDisplay == best->HDisplay &&
- scan->VDisplay == best->VDisplay &&
- (fabs(scan->VRefresh - desired->VRefresh) <
- fabs(best->VRefresh - desired->VRefresh))) {
- best = scan;
- }
- }
- return best;
-}
-
-/**
- * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
- * take the specified mode and apply it to the crtc connected to the compat
- * output. Then, find similar modes for the other outputs, as with the
- * InitialConfiguration code above. The goal is to clone the desired
- * mode across all outputs that are currently active.
- */
-
-Bool
-xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
- Bool ok = TRUE;
- xf86OutputPtr compat_output = config->output[config->compat_output];
- DisplayModePtr compat_mode;
- int c;
-
- /*
- * Let the compat output drive the final mode selection
- */
- compat_mode = xf86OutputFindClosestMode (compat_output, desired);
- if (compat_mode)
- desired = compat_mode;
-
- for (c = 0; c < config->num_crtc; c++)
- {
- xf86CrtcPtr crtc = config->crtc[c];
- DisplayModePtr crtc_mode = NULL;
- int o;
-
- if (!crtc->enabled)
- continue;
-
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
- DisplayModePtr output_mode;
-
- /* skip outputs not on this crtc */
- if (output->crtc != crtc)
- continue;
-
- if (crtc_mode)
- {
- output_mode = xf86OutputFindClosestMode (output, crtc_mode);
- if (output_mode != crtc_mode)
- output->crtc = NULL;
- }
- else
- crtc_mode = xf86OutputFindClosestMode (output, desired);
- }
- if (!crtc_mode)
- {
- crtc->enabled = FALSE;
- continue;
- }
- if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0))
- ok = FALSE;
- else
- {
- crtc->desiredMode = *crtc_mode;
- crtc->desiredRotation = rotation;
- crtc->desiredTransformPresent = FALSE;
- crtc->desiredX = 0;
- crtc->desiredY = 0;
- }
- }
- xf86DisableUnusedFunctions(pScrn);
-#ifdef RANDR_12_INTERFACE
- xf86RandR12TellChanged (pScrn->pScreen);
-#endif
- return ok;
-}
-
-
-/**
- * Set the DPMS power mode of all outputs and CRTCs.
- *
- * If the new mode is off, it will turn off outputs and then CRTCs.
- * Otherwise, it will affect CRTCs before outputs.
- */
-void
-xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
-{
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int i;
-
- if (!scrn->vtSema)
- return;
-
- if (mode == DPMSModeOff) {
- for (i = 0; i < config->num_output; i++) {
- xf86OutputPtr output = config->output[i];
- if (output->crtc != NULL)
- (*output->funcs->dpms) (output, mode);
- }
- }
-
- for (i = 0; i < config->num_crtc; i++) {
- xf86CrtcPtr crtc = config->crtc[i];
- if (crtc->enabled)
- (*crtc->funcs->dpms) (crtc, mode);
- }
-
- if (mode != DPMSModeOff) {
- for (i = 0; i < config->num_output; i++) {
- xf86OutputPtr output = config->output[i];
- if (output->crtc != NULL)
- (*output->funcs->dpms) (output, mode);
- }
- }
-}
-
-/**
- * Implement the screensaver by just calling down into the driver DPMS hooks.
- *
- * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
- * the outputs will still get disabled (blanked).
- */
-Bool
-xf86SaveScreen(ScreenPtr pScreen, int mode)
-{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-
- if (xf86IsUnblank(mode))
- xf86DPMSSet(pScrn, DPMSModeOn, 0);
- else
- xf86DPMSSet(pScrn, DPMSModeOff, 0);
-
- return TRUE;
-}
-
-/**
- * Disable all inactive crtcs and outputs
- */
-void
-xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
-{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- int o, c;
-
- for (o = 0; o < xf86_config->num_output; o++)
- {
- xf86OutputPtr output = xf86_config->output[o];
- if (!output->crtc)
- (*output->funcs->dpms)(output, DPMSModeOff);
- }
-
- for (c = 0; c < xf86_config->num_crtc; c++)
- {
- xf86CrtcPtr crtc = xf86_config->crtc[c];
-
- if (!crtc->enabled)
- {
- crtc->funcs->dpms(crtc, DPMSModeOff);
- memset(&crtc->mode, 0, sizeof(crtc->mode));
- xf86RotateDestroy(crtc);
- crtc->active = FALSE;
- }
- }
- if (pScrn->pScreen)
- xf86_crtc_notify(pScrn->pScreen);
-}
-
-#ifdef RANDR_12_INTERFACE
-
-#define EDID_ATOM_NAME "EDID"
-
-/**
- * Set the RandR EDID property
- */
-static void
-xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
-{
- Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE);
-
- /* This may get called before the RandR resources have been created */
- if (output->randr_output == NULL)
- return;
-
- if (data_len != 0) {
- RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
- PropModeReplace, data_len, data, FALSE, TRUE);
- } else {
- RRDeleteOutputProperty(output->randr_output, edid_atom);
- }
-}
-
-#endif
-
-/* Pull out a phyiscal size from a detailed timing if available. */
-struct det_phySize_parameter {
- xf86OutputPtr output;
- ddc_quirk_t quirks;
- Bool ret;
-};
-
-static void handle_detailed_physical_size(struct detailed_monitor_section
- *det_mon, void *data)
-{
- struct det_phySize_parameter *p;
- p = (struct det_phySize_parameter *)data;
-
- if (p->ret == TRUE )
- return ;
-
- xf86DetTimingApplyQuirks(det_mon, p->quirks,
- p->output->MonInfo->features.hsize,
- p->output->MonInfo->features.vsize);
- if (det_mon->type == DT &&
- det_mon->section.d_timings.h_size != 0 &&
- det_mon->section.d_timings.v_size != 0) {
-
- p->output->mm_width = det_mon->section.d_timings.h_size;
- p->output->mm_height = det_mon->section.d_timings.v_size;
- p->ret = TRUE;
- }
-}
-
-/**
- * Set the EDID information for the specified output
- */
-void
-xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
-{
- ScrnInfoPtr scrn = output->scrn;
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- Bool debug_modes = config->debug_modes || xf86Initialising;
-#ifdef RANDR_12_INTERFACE
- int size;
-#endif
-
- if (output->MonInfo != NULL)
- xfree(output->MonInfo);
-
- output->MonInfo = edid_mon;
-
- if (debug_modes) {
- xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n",
- output->name);
- xf86PrintEDID(edid_mon);
- }
-
- /* Set the DDC properties for the 'compat' output */
- if (output == config->output[config->compat_output])
- xf86SetDDCproperties(scrn, edid_mon);
-
-#ifdef RANDR_12_INTERFACE
- /* Set the RandR output properties */
- size = 0;
- if (edid_mon)
- {
- if (edid_mon->ver.version == 1) {
- size = 128;
- if (edid_mon->flags & EDID_COMPLETE_RAWDATA)
- size += edid_mon->no_sections * 128;
- } else if (edid_mon->ver.version == 2)
- size = 256;
- }
- xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
-#endif
-
- if (edid_mon) {
-
- struct det_phySize_parameter p;
- p.output = output;
- p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE);
- p.ret = FALSE;
- xf86ForEachDetailedBlock(edid_mon,
- handle_detailed_physical_size, &p);
-
- /* if no mm size is available from a detailed timing, check the max size field */
- if ((!output->mm_width || !output->mm_height) &&
- (edid_mon->features.hsize && edid_mon->features.vsize))
- {
- output->mm_width = edid_mon->features.hsize * 10;
- output->mm_height = edid_mon->features.vsize * 10;
- }
- }
-}
-
-/**
- * Return the list of modes supported by the EDID information
- * stored in 'output'
- */
-DisplayModePtr
-xf86OutputGetEDIDModes (xf86OutputPtr output)
-{
- ScrnInfoPtr scrn = output->scrn;
- xf86MonPtr edid_mon = output->MonInfo;
-
- if (!edid_mon)
- return NULL;
- return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
-}
-
-/* maybe we should care about DDC1? meh. */
-xf86MonPtr
-xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
-{
- ScrnInfoPtr scrn = output->scrn;
- xf86MonPtr mon;
-
- mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE);
- if (mon)
- xf86DDCApplyQuirks(scrn->scrnIndex, mon);
-
- return mon;
-}
-
-static char *_xf86ConnectorNames[] = {
- "None", "VGA", "DVI-I", "DVI-D",
- "DVI-A", "Composite", "S-Video",
- "Component", "LFP", "Proprietary",
- "HDMI", "DisplayPort",
- };
-char *
-xf86ConnectorGetName(xf86ConnectorType connector)
-{
- return _xf86ConnectorNames[connector];
-}
-
-static void
-x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
-{
- dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
- dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
- dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
- dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
-
- if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
- dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
-}
-
-static void
-x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
-{
- if (crtc->enabled) {
- crtc_box->x1 = crtc->x;
- crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
- crtc_box->y1 = crtc->y;
- crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
- } else
- crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
-}
-
-static int
-xf86_crtc_box_area(BoxPtr box)
-{
- return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
-}
-
-/*
- * Return the crtc covering 'box'. If two crtcs cover a portion of
- * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
- * with greater coverage
- */
-
-static xf86CrtcPtr
-xf86_covering_crtc(ScrnInfoPtr pScrn,
- BoxPtr box,
- xf86CrtcPtr desired,
- BoxPtr crtc_box_ret)
-{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- xf86CrtcPtr crtc, best_crtc;
- int coverage, best_coverage;
- int c;
- BoxRec crtc_box, cover_box;
-
- best_crtc = NULL;
- best_coverage = 0;
- crtc_box_ret->x1 = 0;
- crtc_box_ret->x2 = 0;
- crtc_box_ret->y1 = 0;
- crtc_box_ret->y2 = 0;
- for (c = 0; c < xf86_config->num_crtc; c++) {
- crtc = xf86_config->crtc[c];
- x86_crtc_box(crtc, &crtc_box);
- x86_crtc_box_intersect(&cover_box, &crtc_box, box);
- coverage = xf86_crtc_box_area(&cover_box);
- if (coverage && crtc == desired) {
- *crtc_box_ret = crtc_box;
- return crtc;
- } else if (coverage > best_coverage) {
- *crtc_box_ret = crtc_box;
- best_crtc = crtc;
- best_coverage = coverage;
- }
- }
- return best_crtc;
-}
-
-/*
- * For overlay video, compute the relevant CRTC and
- * clip video to that.
- *
- * returning FALSE means there was a memory failure of some kind,
- * not that the video shouldn't be displayed
- */
-
-Bool
-xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
- xf86CrtcPtr *crtc_ret,
- xf86CrtcPtr desired_crtc,
- BoxPtr dst,
- INT32 *xa,
- INT32 *xb,
- INT32 *ya,
- INT32 *yb,
- RegionPtr reg,
- INT32 width,
- INT32 height)
-{
- Bool ret;
- RegionRec crtc_region_local;
- RegionPtr crtc_region = reg;
-
- if (crtc_ret) {
- BoxRec crtc_box;
- xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst,
- desired_crtc,
- &crtc_box);
-
- if (crtc) {
- REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
- crtc_region = &crtc_region_local;
- REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
- }
- *crtc_ret = crtc;
- }
-
- ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb,
- crtc_region, width, height);
-
- if (crtc_region != reg)
- REGION_UNINIT (pScreen, &crtc_region_local);
-
- return ret;
-}
-
-xf86_crtc_notify_proc_ptr
-xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new)
-{
- if (xf86CrtcConfigPrivateIndex != -1)
- {
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- xf86_crtc_notify_proc_ptr old;
-
- old = config->xf86_crtc_notify;
- config->xf86_crtc_notify = new;
- return old;
- }
- return NULL;
-}
-
-void
-xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old)
-{
- if (xf86CrtcConfigPrivateIndex != -1)
- {
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
-
- config->xf86_crtc_notify = old;
- }
-}
-
-void
-xf86_crtc_notify(ScreenPtr screen)
-{
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
-
- if (config->xf86_crtc_notify)
- config->xf86_crtc_notify(screen);
-}
-
-Bool
-xf86_crtc_supports_gamma(ScrnInfoPtr pScrn)
-{
- if (xf86CrtcConfigPrivateIndex != -1) {
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- xf86CrtcPtr crtc;
-
- /* for multiple drivers loaded we need this */
- if (!xf86_config)
- return FALSE;
- if (xf86_config->num_crtc == 0)
- return FALSE;
- crtc = xf86_config->crtc[0];
-
- return (crtc->funcs->gamma_set != NULL);
- }
-
- return FALSE;
-}
+/*
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+#include "xf86Priv.h"
+#include "xf86RandR12.h"
+#include "X11/extensions/render.h"
+#include "X11/extensions/dpmsconst.h"
+#include "X11/Xatom.h"
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+#include "xf86xv.h"
+
+/*
+ * Initialize xf86CrtcConfig structure
+ */
+
+int xf86CrtcConfigPrivateIndex = -1;
+
+void
+xf86CrtcConfigInit (ScrnInfoPtr scrn,
+ const xf86CrtcConfigFuncsRec *funcs)
+{
+ xf86CrtcConfigPtr config;
+
+ if (xf86CrtcConfigPrivateIndex == -1)
+ xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
+ config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
+
+ config->funcs = funcs;
+
+ scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
+}
+
+void
+xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
+ int minWidth, int minHeight,
+ int maxWidth, int maxHeight)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ config->minWidth = minWidth;
+ config->minHeight = minHeight;
+ config->maxWidth = maxWidth;
+ config->maxHeight = maxHeight;
+}
+
+/*
+ * Crtc functions
+ */
+xf86CrtcPtr
+xf86CrtcCreate (ScrnInfoPtr scrn,
+ const xf86CrtcFuncsRec *funcs)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CrtcPtr crtc, *crtcs;
+
+ crtc = xcalloc (sizeof (xf86CrtcRec), 1);
+ if (!crtc)
+ return NULL;
+ crtc->version = XF86_CRTC_VERSION;
+ crtc->scrn = scrn;
+ crtc->funcs = funcs;
+#ifdef RANDR_12_INTERFACE
+ crtc->randr_crtc = NULL;
+#endif
+ crtc->rotation = RR_Rotate_0;
+ crtc->desiredRotation = RR_Rotate_0;
+ pixman_transform_init_identity (&crtc->crtc_to_framebuffer);
+ pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
+ pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
+ crtc->filter = NULL;
+ crtc->params = NULL;
+ crtc->nparams = 0;
+ crtc->filter_width = 0;
+ crtc->filter_height = 0;
+ crtc->transform_in_use = FALSE;
+ crtc->transformPresent = FALSE;
+ crtc->desiredTransformPresent = FALSE;
+ memset (&crtc->bounds, '\0', sizeof (crtc->bounds));
+
+ /* Preallocate gamma at a sensible size. */
+ crtc->gamma_size = 256;
+ crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16));
+ if (!crtc->gamma_red) {
+ xfree (crtc);
+ return NULL;
+ }
+ crtc->gamma_green = crtc->gamma_red + crtc->gamma_size;
+ crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size;
+
+ if (xf86_config->crtc)
+ crtcs = xrealloc (xf86_config->crtc,
+ (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+ else
+ crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+ if (!crtcs)
+ {
+ xfree (crtc);
+ return NULL;
+ }
+ xf86_config->crtc = crtcs;
+ xf86_config->crtc[xf86_config->num_crtc++] = crtc;
+ return crtc;
+}
+
+void
+xf86CrtcDestroy (xf86CrtcPtr crtc)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ int c;
+
+ (*crtc->funcs->destroy) (crtc);
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ if (xf86_config->crtc[c] == crtc)
+ {
+ memmove (&xf86_config->crtc[c],
+ &xf86_config->crtc[c+1],
+ ((xf86_config->num_crtc - (c + 1)) * sizeof(void*)));
+ xf86_config->num_crtc--;
+ break;
+ }
+ if (crtc->params)
+ xfree (crtc->params);
+ free(crtc->gamma_red);
+ xfree (crtc);
+}
+
+
+/**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+Bool
+xf86CrtcInUse (xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o;
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ if (xf86_config->output[o]->crtc == crtc)
+ return TRUE;
+ return FALSE;
+}
+
+void
+xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
+{
+#ifdef RENDER
+ int subpixel_order = SubPixelUnknown;
+ Bool has_none = FALSE;
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ {
+ xf86OutputPtr output = xf86_config->output[o];
+
+ if (output->crtc == crtc)
+ {
+ switch (output->subpixel_order) {
+ case SubPixelNone:
+ has_none = TRUE;
+ break;
+ case SubPixelUnknown:
+ break;
+ default:
+ subpixel_order = output->subpixel_order;
+ break;
+ }
+ }
+ if (subpixel_order != SubPixelUnknown)
+ break;
+ }
+ if (subpixel_order != SubPixelUnknown)
+ {
+ static const int circle[4] = {
+ SubPixelHorizontalRGB,
+ SubPixelVerticalRGB,
+ SubPixelHorizontalBGR,
+ SubPixelVerticalBGR,
+ };
+ int rotate;
+ int c;
+ for (rotate = 0; rotate < 4; rotate++)
+ if (crtc->rotation & (1 << rotate))
+ break;
+ for (c = 0; c < 4; c++)
+ if (circle[c] == subpixel_order)
+ break;
+ c = (c + rotate) & 0x3;
+ if ((crtc->rotation & RR_Reflect_X) && !(c & 1))
+ c ^= 2;
+ if ((crtc->rotation & RR_Reflect_Y) && (c & 1))
+ c ^= 2;
+ subpixel_order = circle[c];
+ break;
+ }
+ }
+ if (subpixel_order == SubPixelUnknown && has_none)
+ subpixel_order = SubPixelNone;
+ PictureSetSubpixelOrder (pScreen, subpixel_order);
+#endif
+}
+
+/**
+ * Sets the given video mode on the given crtc
+ */
+Bool
+xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+ RRTransformPtr transform, int x, int y)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int i;
+ Bool ret = FALSE;
+ Bool didLock = FALSE;
+ DisplayModePtr adjusted_mode;
+ DisplayModeRec saved_mode;
+ int saved_x, saved_y;
+ Rotation saved_rotation;
+ RRTransformRec saved_transform;
+ Bool saved_transform_present;
+
+ crtc->enabled = xf86CrtcInUse (crtc);
+
+ /* We only hit this if someone explicitly sends a "disabled" modeset. */
+ if (!crtc->enabled)
+ {
+ /* Check everything for stuff that should be off. */
+ xf86DisableUnusedFunctions(scrn);
+ return TRUE;
+ }
+
+ adjusted_mode = xf86DuplicateMode(mode);
+
+
+ saved_mode = crtc->mode;
+ saved_x = crtc->x;
+ saved_y = crtc->y;
+ saved_rotation = crtc->rotation;
+ if (crtc->transformPresent) {
+ RRTransformInit (&saved_transform);
+ RRTransformCopy (&saved_transform, &crtc->transform);
+ }
+ saved_transform_present = crtc->transformPresent;
+
+ /* Update crtc values up front so the driver can rely on them for mode
+ * setting.
+ */
+ crtc->mode = *mode;
+ crtc->x = x;
+ crtc->y = y;
+ crtc->rotation = rotation;
+ if (transform) {
+ RRTransformCopy (&crtc->transform, transform);
+ crtc->transformPresent = TRUE;
+ } else
+ crtc->transformPresent = FALSE;
+
+ if (crtc->funcs->set_mode_major) {
+ ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y);
+ goto done;
+ }
+
+ didLock = crtc->funcs->lock (crtc);
+ /* Pass our mode to the outputs and the CRTC to give them a chance to
+ * adjust it according to limitations or output properties, and also
+ * a chance to reject the mode entirely.
+ */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+
+ if (output->crtc != crtc)
+ continue;
+
+ if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
+ goto done;
+ }
+ }
+
+ if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
+ goto done;
+ }
+
+ if (!xf86CrtcRotate (crtc))
+ goto done;
+
+ /* Prepare the outputs and CRTCs before setting the mode. */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+
+ if (output->crtc != crtc)
+ continue;
+
+ /* Disable the output as the first thing we do. */
+ output->funcs->prepare(output);
+ }
+
+ crtc->funcs->prepare(crtc);
+
+ /* Set up the DPLL and any output state that needs to adjust or depend
+ * on the DPLL.
+ */
+ crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y);
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ if (output->crtc == crtc)
+ output->funcs->mode_set(output, mode, adjusted_mode);
+ }
+
+ /* Only upload when needed, to avoid unneeded delays. */
+ if (!crtc->active && crtc->funcs->gamma_set)
+ crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
+ crtc->gamma_blue, crtc->gamma_size);
+
+ /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
+ crtc->funcs->commit(crtc);
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ if (output->crtc == crtc)
+ output->funcs->commit(output);
+ }
+
+ ret = TRUE;
+
+done:
+ if (ret) {
+ crtc->active = TRUE;
+ if (scrn->pScreen)
+ xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
+ } else {
+ crtc->x = saved_x;
+ crtc->y = saved_y;
+ crtc->rotation = saved_rotation;
+ crtc->mode = saved_mode;
+ if (saved_transform_present)
+ RRTransformCopy (&crtc->transform, &saved_transform);
+ crtc->transformPresent = saved_transform_present;
+ }
+
+ if (adjusted_mode->name)
+ xfree(adjusted_mode->name);
+ xfree(adjusted_mode);
+
+ if (didLock)
+ crtc->funcs->unlock (crtc);
+
+ return ret;
+}
+
+/**
+ * Sets the given video mode on the given crtc, but without providing
+ * a transform
+ */
+Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+ int x, int y)
+{
+ return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y);
+}
+
+/**
+ * Pans the screen, does not change the mode
+ */
+void
+xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y)
+{
+ crtc->x = x;
+ crtc->y = y;
+ if (crtc->funcs->set_origin) {
+ if (!xf86CrtcRotate (crtc))
+ return;
+ crtc->funcs->set_origin (crtc, x, y);
+ }
+ else
+ xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y);
+}
+
+/*
+ * Output functions
+ */
+
+extern XF86ConfigPtr xf86configptr;
+
+typedef enum {
+ OPTION_PREFERRED_MODE,
+ OPTION_POSITION,
+ OPTION_BELOW,
+ OPTION_RIGHT_OF,
+ OPTION_ABOVE,
+ OPTION_LEFT_OF,
+ OPTION_ENABLE,
+ OPTION_DISABLE,
+ OPTION_MIN_CLOCK,
+ OPTION_MAX_CLOCK,
+ OPTION_IGNORE,
+ OPTION_ROTATE,
+ OPTION_PANNING,
+ OPTION_PRIMARY,
+} OutputOpts;
+
+static OptionInfoRec xf86OutputOptions[] = {
+ {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE },
+ {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE },
+ {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE },
+ {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE },
+ {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE },
+ {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE },
+ {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE },
+ {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE },
+ {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE },
+};
+
+enum {
+ OPTION_MODEDEBUG,
+};
+
+static OptionInfoRec xf86DeviceOptions[] = {
+ {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE },
+};
+
+static void
+xf86OutputSetMonitor (xf86OutputPtr output)
+{
+ char *option_name;
+ static const char monitor_prefix[] = "monitor-";
+ char *monitor;
+
+ if (!output->name)
+ return;
+
+ if (output->options)
+ xfree (output->options);
+
+ output->options = xnfalloc (sizeof (xf86OutputOptions));
+ memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions));
+
+ option_name = xnfalloc (strlen (monitor_prefix) +
+ strlen (output->name) + 1);
+ strcpy (option_name, monitor_prefix);
+ strcat (option_name, output->name);
+ monitor = xf86findOptionValue (output->scrn->options, option_name);
+ if (!monitor)
+ monitor = output->name;
+ else
+ xf86MarkOptionUsedByName (output->scrn->options, option_name);
+ xfree (option_name);
+ output->conf_monitor = xf86findMonitor (monitor,
+ xf86configptr->conf_monitor_lst);
+ /*
+ * Find the monitor section of the screen and use that
+ */
+ if (!output->conf_monitor && output->use_screen_monitor)
+ output->conf_monitor = xf86findMonitor (output->scrn->monitor->id,
+ xf86configptr->conf_monitor_lst);
+ if (output->conf_monitor)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s using monitor section %s\n",
+ output->name, output->conf_monitor->mon_identifier);
+ xf86ProcessOptions (output->scrn->scrnIndex,
+ output->conf_monitor->mon_option_lst,
+ output->options);
+ }
+ else
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s has no monitor section\n",
+ output->name);
+}
+
+static Bool
+xf86OutputEnabled (xf86OutputPtr output, Bool strict)
+{
+ Bool enable, disable;
+
+ /* check to see if this output was enabled in the config file */
+ if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s enabled by config file\n", output->name);
+ return TRUE;
+ }
+ /* or if this output was disabled in the config file */
+ if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s disabled by config file\n", output->name);
+ return FALSE;
+ }
+
+ /* If not, try to only light up the ones we know are connected */
+ if (strict) {
+ enable = output->status == XF86OutputStatusConnected;
+ }
+ /* But if that fails, try to light up even outputs we're unsure of */
+ else {
+ enable = output->status != XF86OutputStatusDisconnected;
+ }
+
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s %sconnected\n", output->name, enable ? "" : "dis");
+ return enable;
+}
+
+static Bool
+xf86OutputIgnored (xf86OutputPtr output)
+{
+ return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);
+}
+
+static char *direction[4] = {
+ "normal",
+ "left",
+ "inverted",
+ "right"
+};
+
+static Rotation
+xf86OutputInitialRotation (xf86OutputPtr output)
+{
+ char *rotate_name = xf86GetOptValString (output->options,
+ OPTION_ROTATE);
+ int i;
+
+ if (!rotate_name)
+ return RR_Rotate_0;
+
+ for (i = 0; i < 4; i++)
+ if (xf86nameCompare (direction[i], rotate_name) == 0)
+ return (1 << i);
+ return RR_Rotate_0;
+}
+
+xf86OutputPtr
+xf86OutputCreate (ScrnInfoPtr scrn,
+ const xf86OutputFuncsRec *funcs,
+ const char *name)
+{
+ xf86OutputPtr output, *outputs;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int len;
+ Bool primary;
+
+ if (name)
+ len = strlen (name) + 1;
+ else
+ len = 0;
+
+ output = xcalloc (sizeof (xf86OutputRec) + len, 1);
+ if (!output)
+ return NULL;
+ output->scrn = scrn;
+ output->funcs = funcs;
+ if (name)
+ {
+ output->name = (char *) (output + 1);
+ strcpy (output->name, name);
+ }
+ output->subpixel_order = SubPixelUnknown;
+ /*
+ * Use the old per-screen monitor section for the first output
+ */
+ output->use_screen_monitor = (xf86_config->num_output == 0);
+#ifdef RANDR_12_INTERFACE
+ output->randr_output = NULL;
+#endif
+ if (name)
+ {
+ xf86OutputSetMonitor (output);
+ if (xf86OutputIgnored (output))
+ {
+ xfree (output);
+ return FALSE;
+ }
+ }
+
+
+ if (xf86_config->output)
+ outputs = xrealloc (xf86_config->output,
+ (xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+ else
+ outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+ if (!outputs)
+ {
+ xfree (output);
+ return NULL;
+ }
+
+ xf86_config->output = outputs;
+
+ if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary)
+ {
+ memmove(xf86_config->output + 1, xf86_config->output,
+ xf86_config->num_output * sizeof (xf86OutputPtr));
+ xf86_config->output[0] = output;
+ }
+ else
+ {
+ xf86_config->output[xf86_config->num_output] = output;
+ }
+
+ xf86_config->num_output++;
+
+ return output;
+}
+
+Bool
+xf86OutputRename (xf86OutputPtr output, const char *name)
+{
+ int len = strlen(name) + 1;
+ char *newname = xalloc (len);
+
+ if (!newname)
+ return FALSE; /* so sorry... */
+
+ strcpy (newname, name);
+ if (output->name && output->name != (char *) (output + 1))
+ xfree (output->name);
+ output->name = newname;
+ xf86OutputSetMonitor (output);
+ if (xf86OutputIgnored (output))
+ return FALSE;
+ return TRUE;
+}
+
+void
+xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor)
+{
+ if (use_screen_monitor != output->use_screen_monitor)
+ {
+ output->use_screen_monitor = use_screen_monitor;
+ xf86OutputSetMonitor (output);
+ }
+}
+
+void
+xf86OutputDestroy (xf86OutputPtr output)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ (*output->funcs->destroy) (output);
+ while (output->probed_modes)
+ xf86DeleteMode (&output->probed_modes, output->probed_modes);
+ for (o = 0; o < xf86_config->num_output; o++)
+ if (xf86_config->output[o] == output)
+ {
+ memmove (&xf86_config->output[o],
+ &xf86_config->output[o+1],
+ ((xf86_config->num_output - (o + 1)) * sizeof(void*)));
+ xf86_config->num_output--;
+ break;
+ }
+ if (output->name && output->name != (char *) (output + 1))
+ xfree (output->name);
+ xfree (output);
+}
+
+/*
+ * Called during CreateScreenResources to hook up RandR
+ */
+static Bool
+xf86CrtcCreateScreenResources (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ screen->CreateScreenResources = config->CreateScreenResources;
+
+ if (!(*screen->CreateScreenResources)(screen))
+ return FALSE;
+
+ if (!xf86RandR12CreateScreenResources (screen))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * Clean up config on server reset
+ */
+static Bool
+xf86CrtcCloseScreen (int index, ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o, c;
+
+ screen->CloseScreen = config->CloseScreen;
+
+ xf86RotateCloseScreen (screen);
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->randr_output = NULL;
+ }
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->randr_crtc = NULL;
+ }
+ return screen->CloseScreen (index, screen);
+}
+
+/*
+ * Called at ScreenInit time to set up
+ */
+#ifdef RANDR_13_INTERFACE
+int
+#else
+Bool
+#endif
+xf86CrtcScreenInit (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ /* Rotation */
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n");
+ xf86DisableRandR(); /* Disable old RandR extension support */
+ xf86RandR12Init (screen);
+
+ /* support all rotations if every crtc has the shadow alloc funcs */
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create)
+ break;
+ }
+ if (c == config->num_crtc)
+ {
+ xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 |
+ RR_Rotate_180 | RR_Rotate_270 |
+ RR_Reflect_X | RR_Reflect_Y);
+ xf86RandR12SetTransformSupport (screen, TRUE);
+ }
+ else
+ {
+ xf86RandR12SetRotations (screen, RR_Rotate_0);
+ xf86RandR12SetTransformSupport (screen, FALSE);
+ }
+
+ /* Wrap CreateScreenResources so we can initialize the RandR code */
+ config->CreateScreenResources = screen->CreateScreenResources;
+ screen->CreateScreenResources = xf86CrtcCreateScreenResources;
+
+ config->CloseScreen = screen->CloseScreen;
+ screen->CloseScreen = xf86CrtcCloseScreen;
+
+#ifdef XFreeXDGA
+ _xf86_di_dga_init_internal(screen);
+#endif
+#ifdef RANDR_13_INTERFACE
+ return RANDR_INTERFACE_VERSION;
+#else
+ return TRUE;
+#endif
+}
+
+static DisplayModePtr
+xf86DefaultMode (xf86OutputPtr output, int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ DisplayModePtr mode;
+ int target_diff = 0;
+ int target_preferred = 0;
+ int mm_height;
+
+ mm_height = output->mm_height;
+ if (!mm_height)
+ mm_height = (768 * 25.4) / DEFAULT_DPI;
+ /*
+ * Pick a mode closest to DEFAULT_DPI
+ */
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ int dpi;
+ int preferred = (((mode->type & M_T_PREFERRED) != 0) +
+ ((mode->type & M_T_USERPREF) != 0));
+ int diff;
+
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ /* yes, use VDisplay here, not xf86ModeHeight */
+ dpi = (mode->VDisplay * 254) / (mm_height * 10);
+ diff = dpi - DEFAULT_DPI;
+ diff = diff < 0 ? -diff : diff;
+ if (target_mode == NULL || (preferred > target_preferred) ||
+ (preferred == target_preferred && diff < target_diff))
+ {
+ target_mode = mode;
+ target_diff = diff;
+ target_preferred = preferred;
+ }
+ }
+ return target_mode;
+}
+
+static DisplayModePtr
+xf86ClosestMode (xf86OutputPtr output,
+ DisplayModePtr match, Rotation match_rotation,
+ int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ DisplayModePtr mode;
+ int target_diff = 0;
+
+ /*
+ * Pick a mode closest to the specified mode
+ */
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ int dx, dy;
+ int diff;
+
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ /* exact matches are preferred */
+ if (output->initial_rotation == match_rotation &&
+ xf86ModesEqual (mode, match))
+ return mode;
+
+ dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation);
+ dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation);
+ diff = dx * dx + dy * dy;
+ if (target_mode == NULL || diff < target_diff)
+ {
+ target_mode = mode;
+ target_diff = diff;
+ }
+ }
+ return target_mode;
+}
+
+static DisplayModePtr
+xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
+{
+ DisplayModePtr mode;
+
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ if (mode->type & M_T_PREFERRED)
+ return mode;
+ }
+ return NULL;
+}
+
+static DisplayModePtr
+xf86OutputHasUserPreferredMode (xf86OutputPtr output)
+{
+ DisplayModePtr mode, first = output->probed_modes;
+
+ for (mode = first; mode && mode->next != first; mode = mode->next)
+ if (mode->type & M_T_USERPREF)
+ return mode;
+
+ return NULL;
+}
+
+static int
+xf86PickCrtcs (ScrnInfoPtr scrn,
+ xf86CrtcPtr *best_crtcs,
+ DisplayModePtr *modes,
+ int n,
+ int width,
+ int height)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+ xf86OutputPtr output;
+ xf86CrtcPtr crtc;
+ xf86CrtcPtr *crtcs;
+ xf86CrtcPtr best_crtc;
+ int best_score;
+ int score;
+ int my_score;
+
+ if (n == config->num_output)
+ return 0;
+ output = config->output[n];
+
+ /*
+ * Compute score with this output disabled
+ */
+ best_crtcs[n] = NULL;
+ best_crtc = NULL;
+ best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height);
+ if (modes[n] == NULL)
+ return best_score;
+
+ crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr));
+ if (!crtcs)
+ return best_score;
+
+ my_score = 1;
+ /* Score outputs that are known to be connected higher */
+ if (output->status == XF86OutputStatusConnected)
+ my_score++;
+ /* Score outputs with preferred modes higher */
+ if (xf86OutputHasPreferredMode (output, width, height))
+ my_score++;
+ /*
+ * Select a crtc for this output and
+ * then attempt to configure the remaining
+ * outputs
+ */
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ if ((output->possible_crtcs & (1 << c)) == 0)
+ continue;
+
+ crtc = config->crtc[c];
+ /*
+ * Check to see if some other output is
+ * using this crtc
+ */
+ for (o = 0; o < n; o++)
+ if (best_crtcs[o] == crtc)
+ break;
+ if (o < n)
+ {
+ /*
+ * If the two outputs desire the same mode,
+ * see if they can be cloned
+ */
+ if (xf86ModesEqual (modes[o], modes[n]) &&
+ config->output[o]->initial_rotation == config->output[n]->initial_rotation &&
+ config->output[o]->initial_x == config->output[n]->initial_x &&
+ config->output[o]->initial_y == config->output[n]->initial_y)
+ {
+ if ((output->possible_clones & (1 << o)) == 0)
+ continue; /* nope, try next CRTC */
+ }
+ else
+ continue; /* different modes, can't clone */
+ }
+ crtcs[n] = crtc;
+ memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
+ score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height);
+ if (score > best_score)
+ {
+ best_crtc = crtc;
+ best_score = score;
+ memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr));
+ }
+ }
+ xfree (crtcs);
+ return best_score;
+}
+
+
+/*
+ * Compute the virtual size necessary to place all of the available
+ * crtcs in the specified configuration.
+ *
+ * canGrow indicates that the driver can make the screen larger than its initial
+ * configuration. If FALSE, this function will enlarge the screen to include
+ * the largest available mode.
+ */
+
+static void
+xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp,
+ Bool canGrow)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int width = 0, height = 0;
+ int o;
+ int c;
+ int s;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ int crtc_width = 0, crtc_height = 0;
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ if (crtc->enabled)
+ {
+ crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation);
+ crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation);
+ }
+ if (!canGrow) {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ for (s = 0; s < config->num_crtc; s++)
+ if (output->possible_crtcs & (1 << s))
+ {
+ DisplayModePtr mode;
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (mode->HDisplay > crtc_width)
+ crtc_width = mode->HDisplay;
+ if (mode->VDisplay > crtc_width)
+ crtc_width = mode->VDisplay;
+ if (mode->VDisplay > crtc_height)
+ crtc_height = mode->VDisplay;
+ if (mode->HDisplay > crtc_height)
+ crtc_height = mode->HDisplay;
+ }
+ }
+ }
+ }
+ if (crtc_width > width)
+ width = crtc_width;
+ if (crtc_height > height)
+ height = crtc_height;
+ }
+ if (config->maxWidth && width > config->maxWidth) width = config->maxWidth;
+ if (config->maxHeight && height > config->maxHeight) height = config->maxHeight;
+ if (config->minWidth && width < config->minWidth) width = config->minWidth;
+ if (config->minHeight && height < config->minHeight) height = config->minHeight;
+ *widthp = width;
+ *heightp = height;
+}
+
+#define POSITION_UNSET -100000
+
+/*
+ * check if the user configured any outputs at all
+ * with either a position or a relative setting or a mode.
+ */
+static Bool
+xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+ Bool user_conf = FALSE;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ char *position;
+ char *relative_name;
+ OutputOpts relation;
+ int r;
+ static const OutputOpts relations[] = {
+ OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
+ };
+
+ position = xf86GetOptValString (output->options,
+ OPTION_POSITION);
+ if (position)
+ user_conf = TRUE;
+
+ relation = 0;
+ relative_name = NULL;
+ for (r = 0; r < 4; r++)
+ {
+ relation = relations[r];
+ relative_name = xf86GetOptValString (output->options,
+ relation);
+ if (relative_name)
+ break;
+ }
+ if (relative_name)
+ user_conf = TRUE;
+
+ modes[o] = xf86OutputHasUserPreferredMode(output);
+ if (modes[o])
+ user_conf = TRUE;
+ }
+
+ return user_conf;
+}
+
+static Bool
+xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+ int min_x, min_y;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x = output->initial_y = POSITION_UNSET;
+ }
+
+ /*
+ * Loop until all outputs are set
+ */
+ for (;;)
+ {
+ Bool any_set = FALSE;
+ Bool keep_going = FALSE;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ static const OutputOpts relations[] = {
+ OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
+ };
+ xf86OutputPtr output = config->output[o];
+ xf86OutputPtr relative;
+ char *relative_name;
+ char *position;
+ OutputOpts relation;
+ int r;
+
+ if (output->initial_x != POSITION_UNSET)
+ continue;
+ position = xf86GetOptValString (output->options,
+ OPTION_POSITION);
+ /*
+ * Absolute position wins
+ */
+ if (position)
+ {
+ int x, y;
+ if (sscanf (position, "%d %d", &x, &y) == 2)
+ {
+ output->initial_x = x;
+ output->initial_y = y;
+ }
+ else
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output %s position not of form \"x y\"\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ }
+ any_set = TRUE;
+ continue;
+ }
+ /*
+ * Next comes relative positions
+ */
+ relation = 0;
+ relative_name = NULL;
+ for (r = 0; r < 4; r++)
+ {
+ relation = relations[r];
+ relative_name = xf86GetOptValString (output->options,
+ relation);
+ if (relative_name)
+ break;
+ }
+ if (relative_name)
+ {
+ int or;
+ relative = NULL;
+ for (or = 0; or < config->num_output; or++)
+ {
+ xf86OutputPtr out_rel = config->output[or];
+ XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor;
+
+ if (rel_mon)
+ {
+ if (xf86nameCompare (rel_mon->mon_identifier,
+ relative_name) == 0)
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (strcmp (out_rel->name, relative_name) == 0)
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (!relative)
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Cannot position output %s relative to unknown output %s\n",
+ output->name, relative_name);
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ continue;
+ }
+ if (!modes[or])
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Cannot position output %s relative to output %s without modes\n",
+ output->name, relative_name);
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ continue;
+ }
+ if (relative->initial_x == POSITION_UNSET)
+ {
+ keep_going = TRUE;
+ continue;
+ }
+ output->initial_x = relative->initial_x;
+ output->initial_y = relative->initial_y;
+ switch (relation) {
+ case OPTION_BELOW:
+ output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation);
+ break;
+ case OPTION_RIGHT_OF:
+ output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation);
+ break;
+ case OPTION_ABOVE:
+ if (modes[o])
+ output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation);
+ break;
+ case OPTION_LEFT_OF:
+ if (modes[o])
+ output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation);
+ break;
+ default:
+ break;
+ }
+ any_set = TRUE;
+ continue;
+ }
+
+ /* Nothing set, just stick them at 0,0 */
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ }
+ if (!keep_going)
+ break;
+ if (!any_set)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ if (output->initial_x == POSITION_UNSET)
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output position loop. Moving %s to 0,0\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * normalize positions
+ */
+ min_x = 1000000;
+ min_y = 1000000;
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ if (output->initial_x < min_x)
+ min_x = output->initial_x;
+ if (output->initial_y < min_y)
+ min_y = output->initial_y;
+ }
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x -= min_x;
+ output->initial_y -= min_y;
+ }
+ return TRUE;
+}
+
+static void
+xf86InitialPanning (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ char *panning = xf86GetOptValString (output->options, OPTION_PANNING);
+ int width, height, left, top;
+ int track_width, track_height, track_left, track_top;
+ int brdr[4];
+
+ memset (&output->initialTotalArea, 0, sizeof(BoxRec));
+ memset (&output->initialTrackingArea, 0, sizeof(BoxRec));
+ memset (output->initialBorder, 0, 4*sizeof(INT16));
+
+ if (! panning)
+ continue;
+
+ switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d",
+ &width, &height, &left, &top,
+ &track_width, &track_height, &track_left, &track_top,
+ &brdr[0], &brdr[1], &brdr[2], &brdr[3])) {
+ case 12:
+ output->initialBorder[0] = brdr[0];
+ output->initialBorder[1] = brdr[1];
+ output->initialBorder[2] = brdr[2];
+ output->initialBorder[3] = brdr[3];
+ /* fall through */
+ case 8:
+ output->initialTrackingArea.x1 = track_left;
+ output->initialTrackingArea.y1 = track_top;
+ output->initialTrackingArea.x2 = track_left + track_width;
+ output->initialTrackingArea.y2 = track_top + track_height;
+ /* fall through */
+ case 4:
+ output->initialTotalArea.x1 = left;
+ output->initialTotalArea.y1 = top;
+ /* fall through */
+ case 2:
+ output->initialTotalArea.x2 = output->initialTotalArea.x1 + width;
+ output->initialTotalArea.y2 = output->initialTotalArea.y1 + height;
+ break;
+ default:
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Broken panning specification '%s' for output %s in config file\n",
+ panning, output->name);
+ }
+ }
+}
+
+/** Return - 0 + if a should be earlier, same or later than b in list
+ */
+static int
+xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
+{
+ int diff;
+
+ diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0);
+ if (diff)
+ return diff;
+ diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
+ if (diff)
+ return diff;
+ diff = b->Clock - a->Clock;
+ return diff;
+}
+
+/**
+ * Insertion sort input in-place and return the resulting head
+ */
+static DisplayModePtr
+xf86SortModes (DisplayModePtr input)
+{
+ DisplayModePtr output = NULL, i, o, n, *op, prev;
+
+ /* sort by preferred status and pixel area */
+ while (input)
+ {
+ i = input;
+ input = input->next;
+ for (op = &output; (o = *op); op = &o->next)
+ if (xf86ModeCompare (o, i) > 0)
+ break;
+ i->next = *op;
+ *op = i;
+ }
+ /* prune identical modes */
+ for (o = output; o && (n = o->next); o = n)
+ {
+ if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n))
+ {
+ o->next = n->next;
+ xfree (n->name);
+ xfree (n);
+ n = o;
+ }
+ }
+ /* hook up backward links */
+ prev = NULL;
+ for (o = output; o; o = o->next)
+ {
+ o->prev = prev;
+ prev = o;
+ }
+ return output;
+}
+
+static char *
+preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+ char *preferred_mode = NULL;
+
+ /* Check for a configured preference for a particular mode */
+ preferred_mode = xf86GetOptValString (output->options,
+ OPTION_PREFERRED_MODE);
+ if (preferred_mode)
+ return preferred_mode;
+
+ if (pScrn->display->modes && *pScrn->display->modes)
+ preferred_mode = *pScrn->display->modes;
+
+ return preferred_mode;
+}
+
+static void
+GuessRangeFromModes(MonPtr mon, DisplayModePtr mode)
+{
+ if (!mon || !mode)
+ return;
+
+ mon->nHsync = 1;
+ mon->hsync[0].lo = 1024.0;
+ mon->hsync[0].hi = 0.0;
+
+ mon->nVrefresh = 1;
+ mon->vrefresh[0].lo = 1024.0;
+ mon->vrefresh[0].hi = 0.0;
+
+ while (mode) {
+ if (!mode->HSync)
+ mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal);
+
+ if (!mode->VRefresh)
+ mode->VRefresh = (1000.0 * ((float) mode->Clock)) /
+ ((float) (mode->HTotal * mode->VTotal));
+
+ if (mode->HSync < mon->hsync[0].lo)
+ mon->hsync[0].lo = mode->HSync;
+
+ if (mode->HSync > mon->hsync[0].hi)
+ mon->hsync[0].hi = mode->HSync;
+
+ if (mode->VRefresh < mon->vrefresh[0].lo)
+ mon->vrefresh[0].lo = mode->VRefresh;
+
+ if (mode->VRefresh > mon->vrefresh[0].hi)
+ mon->vrefresh[0].hi = mode->VRefresh;
+
+ mode = mode->next;
+ }
+
+ /* stretch out the bottom to fit 640x480@60 */
+ if (mon->hsync[0].lo > 31.0)
+ mon->hsync[0].lo = 31.0;
+ if (mon->vrefresh[0].lo > 58.0)
+ mon->vrefresh[0].lo = 58.0;
+}
+
+struct det_monrec_parameter {
+ MonRec *mon_rec;
+ int *max_clock;
+ Bool set_hsync;
+ Bool set_vrefresh;
+ enum { sync_config, sync_edid, sync_default } *sync_source;
+};
+
+static void handle_detailed_monrec(struct detailed_monitor_section *det_mon,
+ void *data)
+{
+ enum { sync_config, sync_edid, sync_default };
+ struct det_monrec_parameter *p;
+ p = (struct det_monrec_parameter *)data;
+
+ if (det_mon->type == DS_RANGES) {
+ struct monitor_ranges *ranges = &det_mon->section.ranges;
+ if (p->set_hsync && ranges->max_h) {
+ p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h;
+ p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h;
+ p->mon_rec->nHsync++;
+ if (*p->sync_source == sync_default)
+ *p->sync_source = sync_edid;
+ }
+ if (p->set_vrefresh && ranges->max_v) {
+ p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v;
+ p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v;
+ p->mon_rec->nVrefresh++;
+ if (*p->sync_source == sync_default)
+ *p->sync_source = sync_edid;
+ }
+ if (ranges->max_clock * 1000 > *p->max_clock)
+ *p->max_clock = ranges->max_clock * 1000;
+ }
+}
+
+void
+xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ /* When canGrow was TRUE in the initial configuration we have to
+ * compare against the maximum values so that we don't drop modes.
+ * When canGrow was FALSE, the maximum values would have been clamped
+ * anyway.
+ */
+ if (maxX == 0 || maxY == 0) {
+ maxX = config->maxWidth;
+ maxY = config->maxHeight;
+ }
+
+ /* Probe the list of modes for each output. */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr mode;
+ DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL;
+ char *preferred_mode;
+ xf86MonPtr edid_monitor;
+ XF86ConfMonitorPtr conf_monitor;
+ MonRec mon_rec;
+ int min_clock = 0;
+ int max_clock = 0;
+ double clock;
+ Bool add_default_modes = TRUE;
+ Bool debug_modes = config->debug_modes ||
+ xf86Initialising;
+ enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
+
+ while (output->probed_modes != NULL)
+ xf86DeleteMode(&output->probed_modes, output->probed_modes);
+
+ /*
+ * Check connection status
+ */
+ output->status = (*output->funcs->detect)(output);
+
+ if (output->status == XF86OutputStatusDisconnected)
+ {
+ xf86OutputSetEDID (output, NULL);
+ continue;
+ }
+
+ memset (&mon_rec, '\0', sizeof (mon_rec));
+
+ conf_monitor = output->conf_monitor;
+
+ if (conf_monitor)
+ {
+ int i;
+
+ for (i = 0; i < conf_monitor->mon_n_hsync; i++)
+ {
+ mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
+ mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
+ mon_rec.nHsync++;
+ sync_source = sync_config;
+ }
+ for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
+ {
+ mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
+ mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
+ mon_rec.nVrefresh++;
+ sync_source = sync_config;
+ }
+ config_modes = xf86GetMonitorModes (scrn, conf_monitor);
+ }
+
+ output_modes = (*output->funcs->get_modes) (output);
+
+ edid_monitor = output->MonInfo;
+
+ if (edid_monitor)
+ {
+ struct det_monrec_parameter p;
+ struct disp_features *features = &edid_monitor->features;
+
+ /* if display is not continuous-frequency, don't add default modes */
+ if (!GTF_SUPPORTED(features->msc))
+ add_default_modes = FALSE;
+
+ p.mon_rec = &mon_rec;
+ p.max_clock = &max_clock;
+ p.set_hsync = mon_rec.nHsync == 0;
+ p.set_vrefresh = mon_rec.nVrefresh == 0;
+ p.sync_source = &sync_source;
+
+ xf86ForEachDetailedBlock(edid_monitor,
+ handle_detailed_monrec,
+ &p);
+ }
+
+ if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ min_clock = (int) clock;
+ if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ max_clock = (int) clock;
+
+ /* If we still don't have a sync range, guess wildly */
+ if (!mon_rec.nHsync || !mon_rec.nVrefresh)
+ GuessRangeFromModes(&mon_rec, output_modes);
+
+ /*
+ * These limits will end up setting a 1024x768@60Hz mode by default,
+ * which seems like a fairly good mode to use when nothing else is
+ * specified
+ */
+ if (mon_rec.nHsync == 0)
+ {
+ mon_rec.hsync[0].lo = 31.0;
+ mon_rec.hsync[0].hi = 55.0;
+ mon_rec.nHsync = 1;
+ }
+ if (mon_rec.nVrefresh == 0)
+ {
+ mon_rec.vrefresh[0].lo = 58.0;
+ mon_rec.vrefresh[0].hi = 62.0;
+ mon_rec.nVrefresh = 1;
+ }
+
+ if (add_default_modes)
+ default_modes = xf86GetDefaultModes ();
+
+ /*
+ * If this is not an RB monitor, remove RB modes from the default
+ * pool. RB modes from the config or the monitor itself are fine.
+ */
+ if (!mon_rec.reducedblanking)
+ xf86ValidateModesReducedBlanking (scrn, default_modes);
+
+ if (sync_source == sync_config)
+ {
+ /*
+ * Check output and config modes against sync range from config file
+ */
+ xf86ValidateModesSync (scrn, output_modes, &mon_rec);
+ xf86ValidateModesSync (scrn, config_modes, &mon_rec);
+ }
+ /*
+ * Check default modes against sync range
+ */
+ xf86ValidateModesSync (scrn, default_modes, &mon_rec);
+ /*
+ * Check default modes against monitor max clock
+ */
+ if (max_clock) {
+ xf86ValidateModesClocks(scrn, default_modes,
+ &min_clock, &max_clock, 1);
+ xf86ValidateModesClocks(scrn, output_modes,
+ &min_clock, &max_clock, 1);
+ }
+
+ output->probed_modes = NULL;
+ output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
+ output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes);
+ output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
+
+ /*
+ * Check all modes against max size, interlace, and doublescan
+ */
+ if (maxX && maxY)
+ xf86ValidateModesSize (scrn, output->probed_modes,
+ maxX, maxY, 0);
+
+ {
+ int flags = (output->interlaceAllowed ? V_INTERLACE : 0) |
+ (output->doubleScanAllowed ? V_DBLSCAN : 0);
+ xf86ValidateModesFlags (scrn, output->probed_modes, flags);
+ }
+
+ /*
+ * Check all modes against output
+ */
+ for (mode = output->probed_modes; mode != NULL; mode = mode->next)
+ if (mode->status == MODE_OK)
+ mode->status = (*output->funcs->mode_valid)(output, mode);
+
+ xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes);
+
+ output->probed_modes = xf86SortModes (output->probed_modes);
+
+ /* Check for a configured preference for a particular mode */
+ preferred_mode = preferredMode(scrn, output);
+
+ if (preferred_mode)
+ {
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (!strcmp (preferred_mode, mode->name))
+ {
+ if (mode != output->probed_modes)
+ {
+ if (mode->prev)
+ mode->prev->next = mode->next;
+ if (mode->next)
+ mode->next->prev = mode->prev;
+ mode->next = output->probed_modes;
+ output->probed_modes->prev = mode;
+ mode->prev = NULL;
+ output->probed_modes = mode;
+ }
+ mode->type |= (M_T_PREFERRED|M_T_USERPREF);
+ break;
+ }
+ }
+ }
+
+ output->initial_rotation = xf86OutputInitialRotation (output);
+
+ if (debug_modes) {
+ if (output->probed_modes != NULL) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "Printing probed modes for output %s\n",
+ output->name);
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "No remaining probed modes for output %s\n",
+ output->name);
+ }
+ }
+ for (mode = output->probed_modes; mode != NULL; mode = mode->next)
+ {
+ /* The code to choose the best mode per pipe later on will require
+ * VRefresh to be set.
+ */
+ mode->VRefresh = xf86ModeVRefresh(mode);
+ xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
+
+ if (debug_modes)
+ xf86PrintModeline(scrn->scrnIndex, mode);
+ }
+ }
+}
+
+
+/**
+ * Copy one of the output mode lists to the ScrnInfo record
+ */
+
+/* XXX where does this function belong? Here? */
+void
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
+
+static DisplayModePtr
+biggestMode(DisplayModePtr a, DisplayModePtr b)
+{
+ int A, B;
+
+ if (!a)
+ return b;
+ if (!b)
+ return a;
+
+ A = a->HDisplay * a->VDisplay;
+ B = b->HDisplay * b->VDisplay;
+
+ if (A > B)
+ return a;
+
+ return b;
+}
+
+static xf86OutputPtr
+SetCompatOutput(xf86CrtcConfigPtr config)
+{
+ xf86OutputPtr output = NULL, test = NULL;
+ DisplayModePtr maxmode = NULL, testmode, mode;
+ int o, compat = -1, count, mincount = 0;
+
+ /* Look for one that's definitely connected */
+ for (o = 0; o < config->num_output; o++)
+ {
+ test = config->output[o];
+ if (!test->crtc)
+ continue;
+ if (test->status != XF86OutputStatusConnected)
+ continue;
+ if (!test->probed_modes)
+ continue;
+
+ testmode = mode = test->probed_modes;
+ for (count = 0; mode; mode = mode->next, count++)
+ testmode = biggestMode(testmode, mode);
+
+ if (!output) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ } else if (maxmode == biggestMode(maxmode, testmode)) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ } else if ((maxmode->HDisplay == testmode->HDisplay) &&
+ (maxmode->VDisplay == testmode->VDisplay) &&
+ count <= mincount) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ }
+ }
+
+ /* If we didn't find one, take anything we can get */
+ if (!output)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ test = config->output[o];
+ if (!test->crtc)
+ continue;
+ if (!test->probed_modes)
+ continue;
+
+ if (!output) {
+ output = test;
+ compat = o;
+ } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) {
+ output = test;
+ compat = o;
+ }
+ }
+ }
+
+ if (compat >= 0) {
+ config->compat_output = compat;
+ } else {
+ /* Don't change the compat output when no valid outputs found */
+ output = config->output[config->compat_output];
+ }
+
+ return output;
+}
+
+void
+xf86SetScrnInfoModes (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86OutputPtr output;
+ xf86CrtcPtr crtc;
+ DisplayModePtr last, mode = NULL;
+
+ output = SetCompatOutput(config);
+
+ if (!output)
+ return; /* punt */
+
+ crtc = output->crtc;
+
+ /* Clear any existing modes from scrn->modes */
+ while (scrn->modes != NULL)
+ xf86DeleteMode(&scrn->modes, scrn->modes);
+
+ /* Set scrn->modes to the mode list for the 'compat' output */
+ scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
+
+ if (crtc) {
+ for (mode = scrn->modes; mode; mode = mode->next)
+ if (xf86ModesEqual (mode, &crtc->desiredMode))
+ break;
+ }
+
+ if (scrn->modes != NULL) {
+ /* For some reason, scrn->modes is circular, unlike the other mode
+ * lists. How great is that?
+ */
+ for (last = scrn->modes; last && last->next; last = last->next)
+ ;
+ last->next = scrn->modes;
+ scrn->modes->prev = last;
+ if (mode) {
+ while (scrn->modes != mode)
+ scrn->modes = scrn->modes->next;
+ }
+ }
+ scrn->currentMode = scrn->modes;
+#ifdef XFreeXDGA
+ if (scrn->pScreen)
+ _xf86_di_dga_reinit_internal(scrn->pScreen);
+#endif
+}
+
+static void
+xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ Bool *enabled)
+{
+ Bool any_enabled = FALSE;
+ int o;
+
+ for (o = 0; o < config->num_output; o++)
+ any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE);
+
+ if (!any_enabled) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "No outputs definitely connected, trying again...\n");
+
+ for (o = 0; o < config->num_output; o++)
+ enabled[o] = xf86OutputEnabled(config->output[o], FALSE);
+ }
+}
+
+static Bool
+nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
+{
+ int o = *index;
+
+ for (o++; o < config->num_output; o++) {
+ if (enabled[o]) {
+ *index = o;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static Bool
+aspectMatch(float a, float b)
+{
+ return fabs(1 - (a / b)) < 0.05;
+}
+
+static DisplayModePtr
+nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
+{
+ DisplayModePtr m = NULL;
+
+ if (!o)
+ return NULL;
+
+ if (!last)
+ m = o->probed_modes;
+ else
+ m = last->next;
+
+ for (; m; m = m->next)
+ if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
+ return m;
+
+ return NULL;
+}
+
+static DisplayModePtr
+bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
+{
+ int o = -1, p;
+ DisplayModePtr mode = NULL, test = NULL, match = NULL;
+
+ if (!nextEnabledOutput(config, enabled, &o))
+ return NULL;
+ while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
+ test = mode;
+ for (p = o; nextEnabledOutput(config, enabled, &p); ) {
+ test = xf86OutputFindClosestMode(config->output[p], mode);
+ if (!test)
+ break;
+ if (test->HDisplay != mode->HDisplay ||
+ test->VDisplay != mode->VDisplay) {
+ test = NULL;
+ break;
+ }
+ }
+
+ /* if we didn't match it on all outputs, try the next one */
+ if (!test)
+ continue;
+
+ /* if it's bigger than the last one, save it */
+ if (!match || (test->HDisplay > match->HDisplay))
+ match = test;
+ }
+
+ /* return the biggest one found */
+ return match;
+}
+
+static Bool
+xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o, p;
+ int max_pref_width = 0, max_pref_height = 0;
+ DisplayModePtr *preferred, *preferred_match;
+ Bool ret = FALSE;
+
+ preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
+ preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
+
+ /* Check if the preferred mode is available on all outputs */
+ for (p = -1; nextEnabledOutput(config, enabled, &p); ) {
+ Rotation r = config->output[p]->initial_rotation;
+ DisplayModePtr mode;
+ if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p],
+ width, height))) {
+ int pref_width = xf86ModeWidth(preferred[p], r);
+ int pref_height = xf86ModeHeight(preferred[p], r);
+ Bool all_match = TRUE;
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ Bool match = FALSE;
+ xf86OutputPtr output = config->output[o];
+ if (o == p)
+ continue;
+
+ for (mode = output->probed_modes; mode; mode = mode->next) {
+ Rotation r = output->initial_rotation;
+ if (xf86ModeWidth(mode, r) == pref_width &&
+ xf86ModeHeight(mode, r) == pref_height) {
+ preferred[o] = mode;
+ match = TRUE;
+ }
+ }
+
+ all_match &= match;
+ }
+
+ if (all_match &&
+ (pref_width*pref_height > max_pref_width*max_pref_height)) {
+ for (o = -1; nextEnabledOutput(config, enabled, &o); )
+ preferred_match[o] = preferred[o];
+ max_pref_width = pref_width;
+ max_pref_height = pref_height;
+ ret = TRUE;
+ }
+ }
+ }
+
+ /*
+ * If there's no preferred mode, but only one monitor, pick the
+ * biggest mode for its aspect ratio, assuming one exists.
+ */
+ if (!ret) do {
+ int i = 0;
+ float aspect = 0.0;
+
+ /* count the number of enabled outputs */
+ for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ;
+
+ if (i != 1)
+ break;
+
+ p = -1;
+ nextEnabledOutput(config, enabled, &p);
+ if (config->output[p]->mm_height)
+ aspect = (float)config->output[p]->mm_width /
+ (float)config->output[p]->mm_height;
+
+ if (aspect)
+ preferred_match[p] = bestModeForAspect(config, enabled, aspect);
+
+ if (preferred_match[p])
+ ret = TRUE;
+
+ } while (0);
+
+ if (ret) {
+ /* oh good, there is a match. stash the selected modes and return. */
+ memcpy(modes, preferred_match,
+ config->num_output * sizeof(DisplayModePtr));
+ }
+
+ xfree(preferred);
+ xfree(preferred_match);
+ return ret;
+}
+
+static Bool
+xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o;
+ float aspect = 0.0, *aspects;
+ xf86OutputPtr output;
+ Bool ret = FALSE;
+ DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL;
+
+ aspects = xnfcalloc(config->num_output, sizeof(float));
+
+ /* collect the aspect ratios */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ output = config->output[o];
+ if (output->mm_height)
+ aspects[o] = (float)output->mm_width / (float)output->mm_height;
+ else
+ aspects[o] = 4.0 / 3.0;
+ }
+
+ /* check that they're all the same */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ output = config->output[o];
+ if (!aspect) {
+ aspect = aspects[o];
+ } else if (!aspectMatch(aspect, aspects[o])) {
+ goto no_aspect_match;
+ }
+ }
+
+ /* if they're all 4:3, just skip ahead and save effort */
+ if (!aspectMatch(aspect, 4.0/3.0))
+ aspect_guess = bestModeForAspect(config, enabled, aspect);
+
+no_aspect_match:
+ base_guess = bestModeForAspect(config, enabled, 4.0/3.0);
+
+ guess = biggestMode(base_guess, aspect_guess);
+
+ if (!guess)
+ goto out;
+
+ /* found a mode that works everywhere, now apply it */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ modes[o] = xf86OutputFindClosestMode(config->output[o], guess);
+ }
+ ret = TRUE;
+
+out:
+ xfree(aspects);
+ return ret;
+}
+
+static Bool
+xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ Rotation target_rotation = RR_Rotate_0;
+ DisplayModePtr default_mode;
+ int default_preferred, target_preferred = 0, o;
+
+ /* User preferred > preferred > other modes */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ default_mode = xf86DefaultMode (config->output[o], width, height);
+ if (!default_mode)
+ continue;
+
+ default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
+ ((default_mode->type & M_T_USERPREF) != 0));
+
+ if (default_preferred > target_preferred || !target_mode) {
+ target_mode = default_mode;
+ target_preferred = default_preferred;
+ target_rotation = config->output[o]->initial_rotation;
+ config->compat_output = o;
+ }
+ }
+
+ if (target_mode)
+ modes[config->compat_output] = target_mode;
+
+ /* Fill in other output modes */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ if (!modes[o])
+ modes[o] = xf86ClosestMode(config->output[o], target_mode,
+ target_rotation, width, height);
+ }
+
+ return (target_mode != NULL);
+}
+
+static Bool
+xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o;
+
+ if (xf86UserConfiguredOutputs(scrn, modes))
+ return xf86TargetFallback(scrn, config, modes, enabled, width, height);
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); )
+ if (xf86OutputHasUserPreferredMode(config->output[o]))
+ return
+ xf86TargetFallback(scrn, config, modes, enabled, width, height);
+
+ return FALSE;
+}
+
+static Bool
+xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green,
+ float gamma_blue)
+{
+ int i, size = 256;
+ CARD16 *red, *green, *blue;
+
+ red = malloc(3 * size * sizeof(CARD16));
+ green = red + size;
+ blue = green + size;
+
+ /* Only cause warning if user wanted gamma to be set. */
+ if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) {
+ free(red);
+ return FALSE;
+ } else if (!crtc->funcs->gamma_set) {
+ free(red);
+ return TRUE;
+ }
+
+ /* At this early stage none of the randr-interface stuff is up.
+ * So take the default gamma size for lack of something better.
+ */
+ for (i = 0; i < size; i++) {
+ if (gamma_red == 1.0)
+ red[i] = i << 8;
+ else
+ red[i] = (CARD16)(pow((double)i/(double)(size - 1),
+ 1. / (double)gamma_red) * (double)(size - 1) * 256);
+
+ if (gamma_green == 1.0)
+ green[i] = i << 8;
+ else
+ green[i] = (CARD16)(pow((double)i/(double)(size - 1),
+ 1. / (double)gamma_green) * (double)(size - 1) * 256);
+
+ if (gamma_blue == 1.0)
+ blue[i] = i << 8;
+ else
+ blue[i] = (CARD16)(pow((double)i/(double)(size - 1),
+ 1. / (double)gamma_blue) * (double)(size - 1) * 256);
+ }
+
+ /* Default size is 256, so anything else is failure. */
+ if (size != crtc->gamma_size) {
+ free(red);
+ return FALSE;
+ }
+
+ crtc->gamma_size = size;
+ memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16));
+ memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16));
+ memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16));
+
+ /* Do not set gamma now, delay until the crtc is activated. */
+
+ free(red);
+
+ return TRUE;
+}
+
+static Bool
+xf86OutputSetInitialGamma(xf86OutputPtr output)
+{
+ XF86ConfMonitorPtr mon = output->conf_monitor;
+ float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0;
+
+ if (!mon)
+ return TRUE;
+
+ if (!output->crtc)
+ return FALSE;
+
+ /* Get configured values, where they exist. */
+ if (mon->mon_gamma_red >= GAMMA_MIN &&
+ mon->mon_gamma_red <= GAMMA_MAX)
+ gamma_red = mon->mon_gamma_red;
+
+ if (mon->mon_gamma_green >= GAMMA_MIN &&
+ mon->mon_gamma_green <= GAMMA_MAX)
+ gamma_green = mon->mon_gamma_green;
+
+ if (mon->mon_gamma_blue >= GAMMA_MIN &&
+ mon->mon_gamma_blue <= GAMMA_MAX)
+ gamma_blue = mon->mon_gamma_blue;
+
+ /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */
+ if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue);
+ return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue);
+ }else
+ return TRUE;
+}
+
+/**
+ * Construct default screen configuration
+ *
+ * Given auto-detected (and, eventually, configured) values,
+ * construct a usable configuration for the system
+ *
+ * canGrow indicates that the driver can resize the screen to larger than its
+ * initially configured size via the config->funcs->resize hook. If TRUE, this
+ * function will set virtualX and virtualY to match the initial configuration
+ * and leave config->max{Width,Height} alone. If FALSE, it will bloat
+ * virtual[XY] to include the largest modes and set config->max{Width,Height}
+ * accordingly.
+ */
+
+Bool
+xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o, c;
+ xf86CrtcPtr *crtcs;
+ DisplayModePtr *modes;
+ Bool *enabled;
+ int width, height;
+ int i = scrn->scrnIndex;
+
+ /* Set up the device options */
+ config->options = xnfalloc (sizeof (xf86DeviceOptions));
+ memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions));
+ xf86ProcessOptions (scrn->scrnIndex,
+ scrn->options,
+ config->options);
+ config->debug_modes = xf86ReturnOptValBool (config->options,
+ OPTION_MODEDEBUG, FALSE);
+
+ if (scrn->display->virtualX)
+ width = scrn->display->virtualX;
+ else
+ width = config->maxWidth;
+ if (scrn->display->virtualY)
+ height = scrn->display->virtualY;
+ else
+ height = config->maxHeight;
+
+ xf86ProbeOutputModes (scrn, width, height);
+
+ crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
+ modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
+ enabled = xnfcalloc (config->num_output, sizeof (Bool));
+
+ xf86CollectEnabledOutputs(scrn, config, enabled);
+
+ if (xf86TargetUserpref(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n");
+ else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n");
+ else if (xf86TargetAspect(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n");
+ else if (xf86TargetFallback(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n");
+ else
+ xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n");
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ if (!modes[o])
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output %s enabled but has no modes\n",
+ config->output[o]->name);
+ else
+ xf86DrvMsg (scrn->scrnIndex, X_INFO,
+ "Output %s using initial mode %s\n",
+ config->output[o]->name, modes[o]->name);
+ }
+
+ /*
+ * Set the position of each output
+ */
+ if (!xf86InitialOutputPositions (scrn, modes))
+ {
+ xfree (crtcs);
+ xfree (modes);
+ return FALSE;
+ }
+
+ /*
+ * Set initial panning of each output
+ */
+ xf86InitialPanning (scrn);
+
+ /*
+ * Assign CRTCs to fit output configuration
+ */
+ if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height))
+ {
+ xfree (crtcs);
+ xfree (modes);
+ return FALSE;
+ }
+
+ /* XXX override xf86 common frame computation code */
+
+ scrn->display->frameX0 = 0;
+ scrn->display->frameY0 = 0;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->enabled = FALSE;
+ memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
+ /* Set default gamma for all crtc's. */
+ /* This is done to avoid problems later on with cloned outputs. */
+ xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0);
+ }
+
+ if (xf86_crtc_supports_gamma(scrn))
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n");
+
+ /*
+ * Set initial configuration
+ */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr mode = modes[o];
+ xf86CrtcPtr crtc = crtcs[o];
+
+ if (mode && crtc)
+ {
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = output->initial_rotation;
+ crtc->desiredX = output->initial_x;
+ crtc->desiredY = output->initial_y;
+ crtc->desiredTransformPresent = FALSE;
+ crtc->enabled = TRUE;
+ memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec));
+ memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec));
+ memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16));
+ output->crtc = crtc;
+ if (!xf86OutputSetInitialGamma(output))
+ xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name);
+ } else {
+ output->crtc = NULL;
+ }
+ }
+
+ if (scrn->display->virtualX == 0)
+ {
+ /*
+ * Expand virtual size to cover the current config and potential mode
+ * switches, if the driver can't enlarge the screen later.
+ */
+ xf86DefaultScreenLimits (scrn, &width, &height, canGrow);
+
+ scrn->display->virtualX = width;
+ scrn->display->virtualY = height;
+ }
+
+ if (width > scrn->virtualX)
+ scrn->virtualX = width;
+ if (height > scrn->virtualY)
+ scrn->virtualY = height;
+
+ /*
+ * Make sure the configuration isn't too small.
+ */
+ if (width < config->minWidth || height < config->minHeight)
+ return FALSE;
+
+ /*
+ * Limit the crtc config to virtual[XY] if the driver can't grow the
+ * desktop.
+ */
+ if (!canGrow)
+ {
+ xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight,
+ width, height);
+ }
+
+ /* Mirror output modes to scrn mode list */
+ xf86SetScrnInfoModes (scrn);
+
+ xfree (crtcs);
+ xfree (modes);
+ return TRUE;
+}
+
+/*
+ * Check the CRTC we're going to map each output to vs. it's current
+ * CRTC. If they don't match, we have to disable the output and the CRTC
+ * since the driver will have to re-route things.
+ */
+static void
+xf86PrepareOutputs (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ for (o = 0; o < config->num_output; o++) {
+ xf86OutputPtr output = config->output[o];
+#if RANDR_GET_CRTC_INTERFACE
+ /* Disable outputs that are unused or will be re-routed */
+ if (!output->funcs->get_crtc ||
+ output->crtc != (*output->funcs->get_crtc)(output) ||
+ output->crtc == NULL)
+#endif
+ (*output->funcs->dpms)(output, DPMSModeOff);
+ }
+}
+
+static void
+xf86PrepareCrtcs (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < config->num_crtc; c++) {
+#if RANDR_GET_CRTC_INTERFACE
+ xf86CrtcPtr crtc = config->crtc[c];
+ xf86OutputPtr output = NULL;
+ uint32_t desired_outputs = 0, current_outputs = 0;
+ int o;
+
+ for (o = 0; o < config->num_output; o++) {
+ output = config->output[o];
+ if (output->crtc == crtc)
+ desired_outputs |= (1<<o);
+ /* If we can't tell where it's mapped, force it off */
+ if (!output->funcs->get_crtc) {
+ desired_outputs = 0;
+ break;
+ }
+ if ((*output->funcs->get_crtc)(output) == crtc)
+ current_outputs |= (1<<o);
+ }
+
+ /*
+ * If mappings are different or the CRTC is unused,
+ * we need to disable it
+ */
+ if (desired_outputs != current_outputs ||
+ !desired_outputs)
+ (*crtc->funcs->dpms)(crtc, DPMSModeOff);
+#else
+ (*crtc->funcs->dpms)(crtc, DPMSModeOff);
+#endif
+ }
+}
+
+/*
+ * Using the desired mode information in each crtc, set
+ * modes (used in EnterVT functions, or at server startup)
+ */
+
+Bool
+xf86SetDesiredModes (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CrtcPtr crtc = config->crtc[0];
+ int c;
+
+ /* A driver with this hook will take care of this */
+ if (!crtc->funcs->set_mode_major) {
+ xf86PrepareOutputs(scrn);
+ xf86PrepareCrtcs(scrn);
+ }
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86OutputPtr output = NULL;
+ int o;
+ RRTransformPtr transform;
+
+ crtc = config->crtc[c];
+
+ /* Skip disabled CRTCs */
+ if (!crtc->enabled)
+ continue;
+
+ if (config->output[config->compat_output]->crtc == crtc)
+ output = config->output[config->compat_output];
+ else
+ {
+ for (o = 0; o < config->num_output; o++)
+ if (config->output[o]->crtc == crtc)
+ {
+ output = config->output[o];
+ break;
+ }
+ }
+ /* paranoia */
+ if (!output)
+ continue;
+
+ /* Mark that we'll need to re-set the mode for sure */
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ if (!crtc->desiredMode.CrtcHDisplay)
+ {
+ DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode);
+
+ if (!mode)
+ return FALSE;
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = RR_Rotate_0;
+ crtc->desiredTransformPresent = FALSE;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+
+ if (crtc->desiredTransformPresent)
+ transform = &crtc->desiredTransform;
+ else
+ transform = NULL;
+ if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation,
+ transform, crtc->desiredX, crtc->desiredY))
+ return FALSE;
+ }
+
+ xf86DisableUnusedFunctions(scrn);
+ return TRUE;
+}
+
+/**
+ * In the current world order, there are lists of modes per output, which may
+ * or may not include the mode that was asked to be set by XFree86's mode
+ * selection. Find the closest one, in the following preference order:
+ *
+ * - Equality
+ * - Closer in size to the requested mode, but no larger
+ * - Closer in refresh rate to the requested mode.
+ */
+
+DisplayModePtr
+xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired)
+{
+ DisplayModePtr best = NULL, scan = NULL;
+
+ for (scan = output->probed_modes; scan != NULL; scan = scan->next)
+ {
+ /* If there's an exact match, we're done. */
+ if (xf86ModesEqual(scan, desired)) {
+ best = desired;
+ break;
+ }
+
+ /* Reject if it's larger than the desired mode. */
+ if (scan->HDisplay > desired->HDisplay ||
+ scan->VDisplay > desired->VDisplay)
+ {
+ continue;
+ }
+
+ /*
+ * If we haven't picked a best mode yet, use the first
+ * one in the size range
+ */
+ if (best == NULL)
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's closer to the right size than the current best
+ * option.
+ */
+ if ((scan->HDisplay > best->HDisplay &&
+ scan->VDisplay >= best->VDisplay) ||
+ (scan->HDisplay >= best->HDisplay &&
+ scan->VDisplay > best->VDisplay))
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's still closer to the right refresh than the current
+ * best resolution.
+ */
+ if (scan->HDisplay == best->HDisplay &&
+ scan->VDisplay == best->VDisplay &&
+ (fabs(scan->VRefresh - desired->VRefresh) <
+ fabs(best->VRefresh - desired->VRefresh))) {
+ best = scan;
+ }
+ }
+ return best;
+}
+
+/**
+ * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
+ * take the specified mode and apply it to the crtc connected to the compat
+ * output. Then, find similar modes for the other outputs, as with the
+ * InitialConfiguration code above. The goal is to clone the desired
+ * mode across all outputs that are currently active.
+ */
+
+Bool
+xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ Bool ok = TRUE;
+ xf86OutputPtr compat_output = config->output[config->compat_output];
+ DisplayModePtr compat_mode;
+ int c;
+
+ /*
+ * Let the compat output drive the final mode selection
+ */
+ compat_mode = xf86OutputFindClosestMode (compat_output, desired);
+ if (compat_mode)
+ desired = compat_mode;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ DisplayModePtr crtc_mode = NULL;
+ int o;
+
+ if (!crtc->enabled)
+ continue;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr output_mode;
+
+ /* skip outputs not on this crtc */
+ if (output->crtc != crtc)
+ continue;
+
+ if (crtc_mode)
+ {
+ output_mode = xf86OutputFindClosestMode (output, crtc_mode);
+ if (output_mode != crtc_mode)
+ output->crtc = NULL;
+ }
+ else
+ crtc_mode = xf86OutputFindClosestMode (output, desired);
+ }
+ if (!crtc_mode)
+ {
+ crtc->enabled = FALSE;
+ continue;
+ }
+ if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0))
+ ok = FALSE;
+ else
+ {
+ crtc->desiredMode = *crtc_mode;
+ crtc->desiredRotation = rotation;
+ crtc->desiredTransformPresent = FALSE;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+ }
+ xf86DisableUnusedFunctions(pScrn);
+#ifdef RANDR_12_INTERFACE
+ xf86RandR12TellChanged (pScrn->pScreen);
+#endif
+ return ok;
+}
+
+
+/**
+ * Set the DPMS power mode of all outputs and CRTCs.
+ *
+ * If the new mode is off, it will turn off outputs and then CRTCs.
+ * Otherwise, it will affect CRTCs before outputs.
+ */
+void
+xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int i;
+
+ if (!scrn->vtSema)
+ return;
+
+ if (mode == DPMSModeOff) {
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ if (output->crtc != NULL)
+ (*output->funcs->dpms) (output, mode);
+ }
+ }
+
+ for (i = 0; i < config->num_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+ if (crtc->enabled)
+ (*crtc->funcs->dpms) (crtc, mode);
+ }
+
+ if (mode != DPMSModeOff) {
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ if (output->crtc != NULL)
+ (*output->funcs->dpms) (output, mode);
+ }
+ }
+}
+
+/**
+ * Implement the screensaver by just calling down into the driver DPMS hooks.
+ *
+ * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
+ * the outputs will still get disabled (blanked).
+ */
+Bool
+xf86SaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (xf86IsUnblank(mode))
+ xf86DPMSSet(pScrn, DPMSModeOn, 0);
+ else
+ xf86DPMSSet(pScrn, DPMSModeOff, 0);
+
+ return TRUE;
+}
+
+/**
+ * Disable all inactive crtcs and outputs
+ */
+void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o, c;
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ {
+ xf86OutputPtr output = xf86_config->output[o];
+ if (!output->crtc)
+ (*output->funcs->dpms)(output, DPMSModeOff);
+ }
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (!crtc->enabled)
+ {
+ crtc->funcs->dpms(crtc, DPMSModeOff);
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ xf86RotateDestroy(crtc);
+ crtc->active = FALSE;
+ }
+ }
+ if (pScrn->pScreen)
+ xf86_crtc_notify(pScrn->pScreen);
+}
+
+#ifdef RANDR_12_INTERFACE
+
+#define EDID_ATOM_NAME "EDID"
+
+/**
+ * Set the RandR EDID property
+ */
+static void
+xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
+{
+ Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE);
+
+ /* This may get called before the RandR resources have been created */
+ if (output->randr_output == NULL)
+ return;
+
+ if (data_len != 0) {
+ RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
+ PropModeReplace, data_len, data, FALSE, TRUE);
+ } else {
+ RRDeleteOutputProperty(output->randr_output, edid_atom);
+ }
+}
+
+#endif
+
+/* Pull out a phyiscal size from a detailed timing if available. */
+struct det_phySize_parameter {
+ xf86OutputPtr output;
+ ddc_quirk_t quirks;
+ Bool ret;
+};
+
+static void handle_detailed_physical_size(struct detailed_monitor_section
+ *det_mon, void *data)
+{
+ struct det_phySize_parameter *p;
+ p = (struct det_phySize_parameter *)data;
+
+ if (p->ret == TRUE )
+ return ;
+
+ xf86DetTimingApplyQuirks(det_mon, p->quirks,
+ p->output->MonInfo->features.hsize,
+ p->output->MonInfo->features.vsize);
+ if (det_mon->type == DT &&
+ det_mon->section.d_timings.h_size != 0 &&
+ det_mon->section.d_timings.v_size != 0) {
+
+ p->output->mm_width = det_mon->section.d_timings.h_size;
+ p->output->mm_height = det_mon->section.d_timings.v_size;
+ p->ret = TRUE;
+ }
+}
+
+/**
+ * Set the EDID information for the specified output
+ */
+void
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ Bool debug_modes = config->debug_modes || xf86Initialising;
+#ifdef RANDR_12_INTERFACE
+ int size;
+#endif
+
+ if (output->MonInfo != NULL)
+ xfree(output->MonInfo);
+
+ output->MonInfo = edid_mon;
+
+ if (debug_modes) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n",
+ output->name);
+ xf86PrintEDID(edid_mon);
+ }
+
+ /* Set the DDC properties for the 'compat' output */
+ if (output == config->output[config->compat_output])
+ xf86SetDDCproperties(scrn, edid_mon);
+
+#ifdef RANDR_12_INTERFACE
+ /* Set the RandR output properties */
+ size = 0;
+ if (edid_mon)
+ {
+ if (edid_mon->ver.version == 1) {
+ size = 128;
+ if (edid_mon->flags & EDID_COMPLETE_RAWDATA)
+ size += edid_mon->no_sections * 128;
+ } else if (edid_mon->ver.version == 2)
+ size = 256;
+ }
+ xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
+#endif
+
+ if (edid_mon) {
+
+ struct det_phySize_parameter p;
+ p.output = output;
+ p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE);
+ p.ret = FALSE;
+ xf86ForEachDetailedBlock(edid_mon,
+ handle_detailed_physical_size, &p);
+
+ /* if no mm size is available from a detailed timing, check the max size field */
+ if ((!output->mm_width || !output->mm_height) &&
+ (edid_mon->features.hsize && edid_mon->features.vsize))
+ {
+ output->mm_width = edid_mon->features.hsize * 10;
+ output->mm_height = edid_mon->features.vsize * 10;
+ }
+ }
+}
+
+/**
+ * Return the list of modes supported by the EDID information
+ * stored in 'output'
+ */
+DisplayModePtr
+xf86OutputGetEDIDModes (xf86OutputPtr output)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86MonPtr edid_mon = output->MonInfo;
+
+ if (!edid_mon)
+ return NULL;
+ return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
+}
+
+/* maybe we should care about DDC1? meh. */
+xf86MonPtr
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86MonPtr mon;
+
+ mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE);
+ if (mon)
+ xf86DDCApplyQuirks(scrn->scrnIndex, mon);
+
+ return mon;
+}
+
+static char *_xf86ConnectorNames[] = {
+ "None", "VGA", "DVI-I", "DVI-D",
+ "DVI-A", "Composite", "S-Video",
+ "Component", "LFP", "Proprietary",
+ "HDMI", "DisplayPort",
+ };
+char *
+xf86ConnectorGetName(xf86ConnectorType connector)
+{
+ return _xf86ConnectorNames[connector];
+}
+
+static void
+x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
+{
+ dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+ dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+ dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+ dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+
+ if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
+ dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+}
+
+static void
+x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
+{
+ if (crtc->enabled) {
+ crtc_box->x1 = crtc->x;
+ crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
+ crtc_box->y1 = crtc->y;
+ crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
+ } else
+ crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
+static int
+xf86_crtc_box_area(BoxPtr box)
+{
+ return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
+}
+
+/*
+ * Return the crtc covering 'box'. If two crtcs cover a portion of
+ * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
+ * with greater coverage
+ */
+
+static xf86CrtcPtr
+xf86_covering_crtc(ScrnInfoPtr pScrn,
+ BoxPtr box,
+ xf86CrtcPtr desired,
+ BoxPtr crtc_box_ret)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc, best_crtc;
+ int coverage, best_coverage;
+ int c;
+ BoxRec crtc_box, cover_box;
+
+ best_crtc = NULL;
+ best_coverage = 0;
+ crtc_box_ret->x1 = 0;
+ crtc_box_ret->x2 = 0;
+ crtc_box_ret->y1 = 0;
+ crtc_box_ret->y2 = 0;
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ crtc = xf86_config->crtc[c];
+ x86_crtc_box(crtc, &crtc_box);
+ x86_crtc_box_intersect(&cover_box, &crtc_box, box);
+ coverage = xf86_crtc_box_area(&cover_box);
+ if (coverage && crtc == desired) {
+ *crtc_box_ret = crtc_box;
+ return crtc;
+ } else if (coverage > best_coverage) {
+ *crtc_box_ret = crtc_box;
+ best_crtc = crtc;
+ best_coverage = coverage;
+ }
+ }
+ return best_crtc;
+}
+
+/*
+ * For overlay video, compute the relevant CRTC and
+ * clip video to that.
+ *
+ * returning FALSE means there was a memory failure of some kind,
+ * not that the video shouldn't be displayed
+ */
+
+Bool
+xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
+ xf86CrtcPtr *crtc_ret,
+ xf86CrtcPtr desired_crtc,
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height)
+{
+ Bool ret;
+ RegionRec crtc_region_local;
+ RegionPtr crtc_region = reg;
+
+ if (crtc_ret) {
+ BoxRec crtc_box;
+ xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst,
+ desired_crtc,
+ &crtc_box);
+
+ if (crtc) {
+ REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
+ crtc_region = &crtc_region_local;
+ REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
+ }
+ *crtc_ret = crtc;
+ }
+
+ ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb,
+ crtc_region, width, height);
+
+ if (crtc_region != reg)
+ REGION_UNINIT (pScreen, &crtc_region_local);
+
+ return ret;
+}
+
+xf86_crtc_notify_proc_ptr
+xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new)
+{
+ if (xf86CrtcConfigPrivateIndex != -1)
+ {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86_crtc_notify_proc_ptr old;
+
+ old = config->xf86_crtc_notify;
+ config->xf86_crtc_notify = new;
+ return old;
+ }
+ return NULL;
+}
+
+void
+xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old)
+{
+ if (xf86CrtcConfigPrivateIndex != -1)
+ {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ config->xf86_crtc_notify = old;
+ }
+}
+
+void
+xf86_crtc_notify(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ if (config->xf86_crtc_notify)
+ config->xf86_crtc_notify(screen);
+}
+
+Bool
+xf86_crtc_supports_gamma(ScrnInfoPtr pScrn)
+{
+ if (xf86CrtcConfigPrivateIndex != -1) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc;
+
+ /* for multiple drivers loaded we need this */
+ if (!xf86_config)
+ return FALSE;
+ if (xf86_config->num_crtc == 0)
+ return FALSE;
+ crtc = xf86_config->crtc[0];
+
+ return (crtc->funcs->gamma_set != NULL);
+ }
+
+ return FALSE;
+}
diff --git a/xorg-server/hw/xfree86/os-support/bsd/bsd_VTsw.c b/xorg-server/hw/xfree86/os-support/bsd/bsd_VTsw.c
index 476a0e957..90c9c30b1 100644
--- a/xorg-server/hw/xfree86/os-support/bsd/bsd_VTsw.c
+++ b/xorg-server/hw/xfree86/os-support/bsd/bsd_VTsw.c
@@ -1,94 +1,103 @@
-/*
- * Derived from VTsw_usl.c which is
- * Copyright 1993 by David Wexelblat <dwex@goblin.org>
- * by S_ren Schmidt (sos@login.dkuug.dk)
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of David Wexelblat not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. David Wexelblat makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-
-/*
- * Handle the VT-switching interface for OSs that use USL-style ioctl()s
- * (the bsd, sysv, sco, and linux subdirs).
- */
-
-/*
- * This function is the signal handler for the VT-switching signal. It
- * is only referenced inside the OS-support layer.
- */
-void
-xf86VTRequest(int sig)
-{
-#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
- if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
- xf86Info.vtRequestsPending = TRUE;
- }
-#endif
- return;
-}
-
-Bool
-xf86VTSwitchPending()
-{
-#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
- if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
- return(xf86Info.vtRequestsPending ? TRUE : FALSE);
- }
-#endif
- return FALSE;
-}
-
-Bool
-xf86VTSwitchAway()
-{
-#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
- if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
- xf86Info.vtRequestsPending = FALSE;
- if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0)
- return(FALSE);
- else
- return(TRUE);
- }
-#endif
- return FALSE;
-}
-
-Bool
-xf86VTSwitchTo()
-{
-#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
- if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
- xf86Info.vtRequestsPending = FALSE;
- if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
- return(FALSE);
- else
- return(TRUE);
- }
-#endif
- return(TRUE);
-}
+/*
+ * Derived from VTsw_usl.c which is
+ * Copyright 1993 by David Wexelblat <dwex@goblin.org>
+ * by S_ren Schmidt (sos@login.dkuug.dk)
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of David Wexelblat not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. David Wexelblat makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+
+/*
+ * Handle the VT-switching interface for OSs that use USL-style ioctl()s
+ * (the bsd, sysv, sco, and linux subdirs).
+ */
+
+/*
+ * This function is the signal handler for the VT-switching signal. It
+ * is only referenced inside the OS-support layer.
+ */
+void
+xf86VTRequest(int sig)
+{
+#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
+ if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
+ xf86Info.vtRequestsPending = TRUE;
+ }
+#endif
+ return;
+}
+
+Bool
+xf86VTSwitchPending()
+{
+#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
+ if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
+ return(xf86Info.vtRequestsPending ? TRUE : FALSE);
+ }
+#endif
+ return FALSE;
+}
+
+Bool
+xf86VTSwitchAway()
+{
+#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
+ if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
+ xf86Info.vtRequestsPending = FALSE;
+ if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0)
+ return(FALSE);
+ else
+ return(TRUE);
+ }
+#endif
+ return FALSE;
+}
+
+Bool
+xf86VTSwitchTo()
+{
+#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
+ if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) {
+ xf86Info.vtRequestsPending = FALSE;
+ if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
+ return(FALSE);
+ else
+ return(TRUE);
+ }
+#endif
+ return(TRUE);
+}
+
+Bool
+xf86VTActivate(int vtno)
+{
+ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vtno) < 0) {
+ return(FALSE);
+ }
+ return(TRUE);
+}
diff --git a/xorg-server/hw/xfree86/os-support/sco/VTsw_sco.c b/xorg-server/hw/xfree86/os-support/sco/VTsw_sco.c
index d126e7869..9300b13b9 100644
--- a/xorg-server/hw/xfree86/os-support/sco/VTsw_sco.c
+++ b/xorg-server/hw/xfree86/os-support/sco/VTsw_sco.c
@@ -1,117 +1,127 @@
-/*
- * Copyright 1993 by David Wexelblat <dwex@goblin.org>
- * Copyright 1993 by David McCullough <davidm@stallion.oz.au>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of David Wexelblat not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. David Wexelblat makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-
-/* For the event driver prototypes */
-#include <sys/event.h>
-#include <mouse.h>
-
-/*
- * Handle the VT-switching interface for SCO
- */
-
-/*
- * This function is the signal handler for the VT-switching signal. It
- * is only referenced inside the OS-support layer. NOTE: we do NOT need
- * to re-arm the signal here, since we used sigaction() to set the signal
- * disposition in sco_init.c. If we had used signal(), we would need to
- * re-arm the signal here. All we need to do now is record the fact that
- * we got the signal. XFree86 handles the rest.
- */
-void
-xf86VTRequest(int sig)
-{
- xf86Info.vtRequestsPending = TRUE;
- return;
-}
-
-Bool
-xf86VTSwitchPending(void)
-{
- return(xf86Info.vtRequestsPending ? TRUE : FALSE);
-}
-
-/*
- * When we switch away, we need to flush and suspend the event driver
- * before the VT_RELDISP. We also need to get the current LED status
- * and preserve it, so that we can restore it when we come back.
- */
-static int sco_ledstatus = -1;
-static unsigned int sco_ledstate = 0;
-
-Bool
-xf86VTSwitchAway(void)
-{
- ev_flush();
- ev_suspend();
-
- sco_ledstatus = ioctl(xf86Info.consoleFd, KDGETLED, &sco_ledstate);
-
- xf86Info.vtRequestsPending = FALSE;
- if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_TRUE) < 0) {
- return(FALSE);
- } else {
- return(TRUE);
- }
-}
-
-/*
- * When we come back to the X server, we need to resume the event driver,
- * and we need to restore the LED settings to what they were when we
- * switched away.
- */
-Bool
-xf86VTSwitchTo(void)
-{
- ev_resume();
-
- xf86Info.vtRequestsPending = FALSE;
- if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) {
- return(FALSE);
- } else {
- if (sco_ledstatus >= 0) {
- ioctl (xf86Info.consoleFd, KDSETLED, sco_ledstate);
- }
- sco_ledstatus = -1;
-
- /*
- * Convince the console driver this screen is in graphics mode,
- * otherwise it assumes it can do more to the screen than it should.
- */
- if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) {
- ErrorF("Failed to set graphics mode (%s)\n", strerror(errno));
- }
-
- return TRUE;
- }
-}
+/*
+ * Copyright 1993 by David Wexelblat <dwex@goblin.org>
+ * Copyright 1993 by David McCullough <davidm@stallion.oz.au>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of David Wexelblat not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. David Wexelblat makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+
+/* For the event driver prototypes */
+#include <sys/event.h>
+#include <mouse.h>
+
+/*
+ * Handle the VT-switching interface for SCO
+ */
+
+/*
+ * This function is the signal handler for the VT-switching signal. It
+ * is only referenced inside the OS-support layer. NOTE: we do NOT need
+ * to re-arm the signal here, since we used sigaction() to set the signal
+ * disposition in sco_init.c. If we had used signal(), we would need to
+ * re-arm the signal here. All we need to do now is record the fact that
+ * we got the signal. XFree86 handles the rest.
+ */
+void
+xf86VTRequest(int sig)
+{
+ xf86Info.vtRequestsPending = TRUE;
+ return;
+}
+
+Bool
+xf86VTSwitchPending(void)
+{
+ return(xf86Info.vtRequestsPending ? TRUE : FALSE);
+}
+
+/*
+ * When we switch away, we need to flush and suspend the event driver
+ * before the VT_RELDISP. We also need to get the current LED status
+ * and preserve it, so that we can restore it when we come back.
+ */
+static int sco_ledstatus = -1;
+static unsigned int sco_ledstate = 0;
+
+Bool
+xf86VTSwitchAway(void)
+{
+ ev_flush();
+ ev_suspend();
+
+ sco_ledstatus = ioctl(xf86Info.consoleFd, KDGETLED, &sco_ledstate);
+
+ xf86Info.vtRequestsPending = FALSE;
+ if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_TRUE) < 0) {
+ return(FALSE);
+ } else {
+ return(TRUE);
+ }
+}
+
+/*
+ * When we come back to the X server, we need to resume the event driver,
+ * and we need to restore the LED settings to what they were when we
+ * switched away.
+ */
+Bool
+xf86VTSwitchTo(void)
+{
+ ev_resume();
+
+ xf86Info.vtRequestsPending = FALSE;
+ if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) {
+ return(FALSE);
+ } else {
+ if (sco_ledstatus >= 0) {
+ ioctl (xf86Info.consoleFd, KDSETLED, sco_ledstate);
+ }
+ sco_ledstatus = -1;
+
+ /*
+ * Convince the console driver this screen is in graphics mode,
+ * otherwise it assumes it can do more to the screen than it should.
+ */
+ if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) {
+ ErrorF("Failed to set graphics mode (%s)\n", strerror(errno));
+ }
+
+ return TRUE;
+ }
+}
+
+Bool
+xf86VTActivate(int vtno)
+{
+ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vtno - 1) < 0) {
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
diff --git a/xorg-server/hw/xfree86/os-support/shared/VTsw_noop.c b/xorg-server/hw/xfree86/os-support/shared/VTsw_noop.c
index 78cbe0e34..f3ddb29c9 100644
--- a/xorg-server/hw/xfree86/os-support/shared/VTsw_noop.c
+++ b/xorg-server/hw/xfree86/os-support/shared/VTsw_noop.c
@@ -1,54 +1,60 @@
-/*
- * Copyright 1993 by David Wexelblat <dwex@XFree86.org>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of David Wexelblat not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. David Wexelblat makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-
-/*
- * No-op functions for OSs without VTs
- */
-
-Bool
-xf86VTSwitchPending(void)
-{
- return(FALSE);
-}
-
-Bool
-xf86VTSwitchAway(void)
-{
- return(FALSE);
-}
-
-Bool
-xf86VTSwitchTo(void)
-{
- return(TRUE);
-}
+/*
+ * Copyright 1993 by David Wexelblat <dwex@XFree86.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of David Wexelblat not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. David Wexelblat makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+
+/*
+ * No-op functions for OSs without VTs
+ */
+
+Bool
+xf86VTSwitchPending(void)
+{
+ return(FALSE);
+}
+
+Bool
+xf86VTSwitchAway(void)
+{
+ return(FALSE);
+}
+
+Bool
+xf86VTSwitchTo(void)
+{
+ return(TRUE);
+}
+
+Bool
+xf86VTActivate(int vtno)
+{
+ return(TRUE);
+}
diff --git a/xorg-server/hw/xfree86/os-support/shared/VTsw_usl.c b/xorg-server/hw/xfree86/os-support/shared/VTsw_usl.c
index 9308640e2..34bca7ae2 100644
--- a/xorg-server/hw/xfree86/os-support/shared/VTsw_usl.c
+++ b/xorg-server/hw/xfree86/os-support/shared/VTsw_usl.c
@@ -1,90 +1,101 @@
-/*
- * Copyright 1993 by David Wexelblat <dwex@XFree86.org>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of David Wexelblat not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. David Wexelblat makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-
-#ifdef OSHEADER
-# include OSHEADER
-#endif
-
-/*
- * Handle the VT-switching interface for OSs that use USL-style ioctl()s
- * (the sysv, sco, and linux subdirs).
- */
-
-/*
- * This function is the signal handler for the VT-switching signal. It
- * is only referenced inside the OS-support layer.
- */
-void
-xf86VTRequest(int sig)
-{
- signal(sig, (void(*)(int))xf86VTRequest);
- xf86Info.vtRequestsPending = TRUE;
- return;
-}
-
-Bool
-xf86VTSwitchPending(void)
-{
- return(xf86Info.vtRequestsPending ? TRUE : FALSE);
-}
-
-Bool
-xf86VTSwitchAway(void)
-{
- xf86Info.vtRequestsPending = FALSE;
- if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0)
- {
- return(FALSE);
- }
- else
- {
-#ifdef OSSWITCHAWAY
- OSSWITCHAWAY;
-#endif
- return(TRUE);
- }
-}
-
-Bool
-xf86VTSwitchTo(void)
-{
- xf86Info.vtRequestsPending = FALSE;
- if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
- {
- return(FALSE);
- }
- else
- {
- return(TRUE);
- }
-}
+/*
+ * Copyright 1993 by David Wexelblat <dwex@XFree86.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of David Wexelblat not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. David Wexelblat makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+
+#ifdef OSHEADER
+# include OSHEADER
+#endif
+
+/*
+ * Handle the VT-switching interface for OSs that use USL-style ioctl()s
+ * (the sysv, sco, and linux subdirs).
+ */
+
+/*
+ * This function is the signal handler for the VT-switching signal. It
+ * is only referenced inside the OS-support layer.
+ */
+void
+xf86VTRequest(int sig)
+{
+ signal(sig, (void(*)(int))xf86VTRequest);
+ xf86Info.vtRequestsPending = TRUE;
+ return;
+}
+
+Bool
+xf86VTSwitchPending(void)
+{
+ return(xf86Info.vtRequestsPending ? TRUE : FALSE);
+}
+
+Bool
+xf86VTSwitchAway(void)
+{
+ xf86Info.vtRequestsPending = FALSE;
+ if (ioctl(xf86Info.consoleFd, VT_RELDISP, 1) < 0)
+ {
+ return(FALSE);
+ }
+ else
+ {
+#ifdef OSSWITCHAWAY
+ OSSWITCHAWAY;
+#endif
+ return(TRUE);
+ }
+}
+
+Bool
+xf86VTSwitchTo(void)
+{
+ xf86Info.vtRequestsPending = FALSE;
+ if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
+ {
+ return(FALSE);
+ }
+ else
+ {
+ return(TRUE);
+ }
+}
+
+Bool
+xf86VTActivate(int vtno)
+{
+#ifdef VT_ACTIVATE
+ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vtno) < 0) {
+ return(FALSE);
+ }
+#endif
+ return(TRUE);
+}
diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_VTsw.c b/xorg-server/hw/xfree86/os-support/solaris/sun_VTsw.c
index ded2f271e..ee5c7c064 100644
--- a/xorg-server/hw/xfree86/os-support/solaris/sun_VTsw.c
+++ b/xorg-server/hw/xfree86/os-support/solaris/sun_VTsw.c
@@ -1,104 +1,137 @@
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-
-#include <door.h>
-#include <sys/vtdaemon.h>
-
-/*
- * Handle the VT-switching interface for Solaris/OpenSolaris
- */
-
-void
-xf86VTRequest(int sig)
-{
- if (xf86Info.vtPendingNum != -1)
- {
- ioctl(xf86Info.consoleFd, VT_RELDISP, 1);
- xf86Info.vtPendingNum = -1;
-
- return;
- }
-
- xf86Info.vtRequestsPending = TRUE;
- return;
-}
-
-Bool
-xf86VTSwitchPending(void)
-{
- return(xf86Info.vtRequestsPending ? TRUE : FALSE);
-}
-
-Bool
-xf86VTSwitchAway(void)
-{
- int door_fd;
- vt_cmd_arg_t vt_door_arg;
- door_arg_t door_arg;
-
- xf86Info.vtRequestsPending = FALSE;
-
- vt_door_arg.vt_ev = VT_EV_HOTKEYS;
- vt_door_arg.vt_num = xf86Info.vtPendingNum;
- door_arg.data_ptr = (char *)&vt_door_arg;
- door_arg.data_size = sizeof (vt_cmd_arg_t);
- door_arg.rbuf = NULL;
- door_arg.rsize = 0;
- door_arg.desc_ptr = NULL;
- door_arg.desc_num = 0;
-
- if ((door_fd = open(VT_DAEMON_DOOR_FILE, O_RDONLY)) < 0)
- return (FALSE);
-
- if (door_call(door_fd, &door_arg) != 0) {
- close(door_fd);
- return (FALSE);
- }
-
- close(door_fd);
- return (TRUE);
-}
-
-Bool
-xf86VTSwitchTo(void)
-{
- xf86Info.vtRequestsPending = FALSE;
- if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
- {
- return(FALSE);
- }
- else
- {
- return(TRUE);
- }
-}
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+
+#include <door.h>
+#include <sys/vtdaemon.h>
+
+/*
+ * Handle the VT-switching interface for Solaris/OpenSolaris
+ */
+
+static int xf86VTPruneDoor = 0;
+
+void
+xf86VTRelease(int sig)
+{
+ if (xf86Info.vtPendingNum == -1)
+ {
+ xf86VTPruneDoor = 1;
+ xf86Info.vtRequestsPending = TRUE;
+ return;
+ }
+
+ ioctl(xf86Info.consoleFd, VT_RELDISP, 1);
+ xf86Info.vtPendingNum = -1;
+
+ return;
+}
+
+void
+xf86VTAcquire(int sig)
+{
+ xf86Info.vtRequestsPending = TRUE;
+ return;
+}
+
+Bool
+xf86VTSwitchPending(void)
+{
+ return(xf86Info.vtRequestsPending ? TRUE : FALSE);
+}
+
+Bool
+xf86VTSwitchAway(void)
+{
+ int door_fd;
+ vt_cmd_arg_t vt_door_arg;
+ door_arg_t door_arg;
+
+ xf86Info.vtRequestsPending = FALSE;
+
+ if (xf86VTPruneDoor) {
+ xf86VTPruneDoor = 0;
+ ioctl(xf86Info.consoleFd, VT_RELDISP, 1);
+ return (TRUE);
+ }
+
+ vt_door_arg.vt_ev = VT_EV_HOTKEYS;
+ vt_door_arg.vt_num = xf86Info.vtPendingNum;
+ door_arg.data_ptr = (char *)&vt_door_arg;
+ door_arg.data_size = sizeof (vt_cmd_arg_t);
+ door_arg.rbuf = NULL;
+ door_arg.rsize = 0;
+ door_arg.desc_ptr = NULL;
+ door_arg.desc_num = 0;
+
+ if ((door_fd = open(VT_DAEMON_DOOR_FILE, O_RDONLY)) < 0)
+ return (FALSE);
+
+ if (door_call(door_fd, &door_arg) != 0) {
+ close(door_fd);
+ return (FALSE);
+ }
+
+ close(door_fd);
+ return (TRUE);
+}
+
+Bool
+xf86VTSwitchTo(void)
+{
+ xf86Info.vtRequestsPending = FALSE;
+ if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0)
+ {
+ return(FALSE);
+ }
+ else
+ {
+ return(TRUE);
+ }
+}
+
+Bool
+xf86VTActivate(int vtno)
+{
+ struct vt_stat state;
+
+ if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &state) < 0)
+ return(FALSE);
+
+ if ((state.v_state & (1 << vtno)) == 0)
+ return(FALSE);
+
+ xf86Info.vtRequestsPending = TRUE;
+ xf86Info.vtPendingNum = vtno;
+
+ return(TRUE);
+}
diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
index 2c569f02c..82df2e9dd 100644
--- a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
+++ b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
@@ -1,360 +1,367 @@
-/*
- * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
- * Copyright 1993 by David Wexelblat <dwex@goblin.org>
- * Copyright 1999 by David Holland <davidh@iquest.net>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the names of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-#ifdef HAVE_SYS_KD_H
-# include <sys/kd.h>
-#endif
-
-static Bool KeepTty = FALSE;
-static Bool Protect0 = FALSE;
-#ifdef HAS_USL_VTS
-static int VTnum = -1;
-static int xf86StartVT = -1;
-static int vtEnabled = 0;
-#endif
-
-/* Device to open as xf86Info.consoleFd */
-static char consoleDev[PATH_MAX] = "/dev/fb";
-
-/* Set by -dev argument on CLI
- Used by hw/xfree86/common/xf86AutoConfig.c for VIS_GETIDENTIFIER */
-_X_HIDDEN char xf86SolarisFbDev[PATH_MAX] = "/dev/fb";
-
-void
-xf86OpenConsole(void)
-{
- int i;
-#ifdef HAS_USL_VTS
- int fd;
- struct vt_mode VT;
- struct vt_stat vtinfo;
- int FreeVTslot;
- MessageType from = X_PROBED;
-#endif
-
- if (serverGeneration == 1)
- {
- /* Check if we're run with euid==0 */
- if (geteuid() != 0)
- FatalError("xf86OpenConsole: Server must be suid root\n");
-
- /* Protect page 0 to help find NULL dereferencing */
- /* mprotect() doesn't seem to work */
- if (Protect0)
- {
- int fd = -1;
-
- if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0)
- {
- xf86Msg(X_WARNING,
- "xf86OpenConsole: cannot open /dev/zero (%s)\n",
- strerror(errno));
- }
- else
- {
- if ((int)mmap(0, 0x1000, PROT_NONE,
- MAP_FIXED | MAP_SHARED, fd, 0) == -1)
- xf86Msg(X_WARNING,
- "xf86OpenConsole: failed to protect page 0 (%s)\n",
- strerror(errno));
-
- close(fd);
- }
- }
-
-#ifdef HAS_USL_VTS
-
- /*
- * Setup the virtual terminal manager
- */
- if ((fd = open("/dev/vt/0",O_RDWR,0)) == -1)
- {
- xf86ErrorF("xf86OpenConsole: Cannot open /dev/vt/0 (%s)\n",
- strerror(errno));
- vtEnabled = 0;
- }
- else
- {
- if (ioctl(fd, VT_ENABLED, &vtEnabled) < 0)
- {
- xf86ErrorF("xf86OpenConsole: VT_ENABLED failed (%s)\n",
- strerror(errno));
- vtEnabled = 0;
- }
- }
-
-
- if (vtEnabled == 0)
- {
- /* VT not enabled - kernel too old or Sparc platforms
- without visual_io support */
- xf86Msg(from, "VT infrastructure is not available\n");
-
- xf86StartVT = 0;
- xf86Info.vtno = 0;
- strlcpy(consoleDev, xf86SolarisFbDev, sizeof(consoleDev));
- }
- else
- {
- if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
- FatalError("xf86OpenConsole: Cannot determine current VT\n");
-
- xf86StartVT = vtinfo.v_active;
-
- if (VTnum != -1)
- {
- xf86Info.vtno = VTnum;
- from = X_CMDLINE;
- }
- else
- {
- if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
- (xf86Info.vtno == -1)) {
- FatalError("xf86OpenConsole: Cannot find a free VT\n");
- }
- }
-
- xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
- snprintf(consoleDev, PATH_MAX, "/dev/vt/%d", xf86Info.vtno);
- }
-
- if (fd != -1) {
- close(fd);
- }
-
-#endif /* HAS_USL_VTS */
-
- if (!KeepTty)
- setpgrp();
-
- if (((xf86Info.consoleFd = open(consoleDev, O_RDWR | O_NDELAY, 0)) < 0))
- FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
- consoleDev, strerror(errno));
-
-#ifdef HAS_USL_VTS
-
- /* Change ownership of the vt */
- chown(consoleDev, getuid(), getgid());
-
- if (vtEnabled)
- {
- /*
- * Now get the VT
- */
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
-
- if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
-
- if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
- FatalError("xf86OpenConsole: VT_GETMODE failed\n");
-
- OsSignal(SIGUSR1, xf86VTRequest);
-
- VT.mode = VT_PROCESS;
- VT.relsig = SIGUSR1;
- VT.acqsig = SIGUSR1;
-
- if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
- FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
-
- if (ioctl(xf86Info.consoleFd, VT_SETDISPINFO, atoi(display)) < 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_SETDISPINFO failed\n");
- }
-#endif
-
-#ifdef KDSETMODE
- SYSCALL(i = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
- if (i < 0) {
- xf86Msg(X_WARNING,
- "xf86OpenConsole: KDSETMODE KD_GRAPHICS failed on %s (%s)\n",
- consoleDev, strerror(errno));
- }
-#endif
- }
- else /* serverGeneration != 1 */
- {
-#ifdef HAS_USL_VTS
- if (vtEnabled) {
- /*
- * Now re-get the VT
- */
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
-
- if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
-
- /*
- * If the server doesn't have the VT when the reset occurs,
- * this is to make sure we don't continue until the activate
- * signal is received.
- */
- if (!xf86Screens[0]->vtSema)
- sleep(5);
- }
-#endif /* HAS_USL_VTS */
-
- }
-}
-
-void
-xf86CloseConsole(void)
-{
-#ifdef HAS_USL_VTS
- struct vt_mode VT;
-#endif
-
-#if !defined(__i386__) && !defined(__i386) && !defined(__x86)
-
- if (!xf86DoConfigure) {
- int fd;
-
- /*
- * Wipe out framebuffer just like the non-SI Xsun server does. This
- * could be improved by saving framebuffer contents in
- * xf86OpenConsole() above and restoring them here. Also, it's unclear
- * at this point whether this should be done for all framebuffers in
- * the system, rather than only the console.
- */
- if ((fd = open(xf86SolarisFbDev, O_RDWR, 0)) < 0) {
- xf86Msg(X_WARNING,
- "xf86CloseConsole(): unable to open framebuffer (%s)\n",
- strerror(errno));
- } else {
- struct fbgattr fbattr;
-
- if ((ioctl(fd, FBIOGATTR, &fbattr) < 0) &&
- (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0)) {
- xf86Msg(X_WARNING,
- "xf86CloseConsole(): unable to retrieve framebuffer"
- " attributes (%s)\n", strerror(errno));
- } else {
- pointer fbdata;
-
- fbdata = mmap(NULL, fbattr.fbtype.fb_size,
- PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (fbdata == MAP_FAILED) {
- xf86Msg(X_WARNING,
- "xf86CloseConsole(): unable to mmap framebuffer"
- " (%s)\n", strerror(errno));
- } else {
- memset(fbdata, 0, fbattr.fbtype.fb_size);
- munmap(fbdata, fbattr.fbtype.fb_size);
- }
- }
-
- close(fd);
- }
- }
-
-#endif
-
-#ifdef KDSETMODE
- /* Reset the display back to text mode */
- SYSCALL(ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
-#endif
-
-#ifdef HAS_USL_VTS
- if (vtEnabled == 1) {
- if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
- {
- VT.mode = VT_AUTO; /* Set default vt handling */
- ioctl(xf86Info.consoleFd, VT_SETMODE, &VT);
- }
-
- /* Activate the VT that X was started on */
- ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86StartVT);
- }
-#endif /* HAS_USL_VTS */
-
- close(xf86Info.consoleFd);
-}
-
-int
-xf86ProcessArgument(int argc, char **argv, int i)
-{
- /*
- * Keep server from detaching from controlling tty. This is useful when
- * debugging, so the server can receive keyboard signals.
- */
- if (!strcmp(argv[i], "-keeptty"))
- {
- KeepTty = TRUE;
- return 1;
- }
-
- /*
- * Undocumented flag to protect page 0 from read/write to help catch NULL
- * pointer dereferences. This is purely a debugging flag.
- */
- if (!strcmp(argv[i], "-protect0"))
- {
- Protect0 = TRUE;
- return 1;
- }
-
-#ifdef HAS_USL_VTS
-
- if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
- {
- if (sscanf(argv[i], "vt%d", &VTnum) == 0)
- {
- UseMsg();
- VTnum = -1;
- return 0;
- }
-
- return 1;
- }
-
-#endif /* HAS_USL_VTS */
-
- if ((i + 1) < argc) {
- if (!strcmp(argv[i], "-dev")) {
- strlcpy(xf86SolarisFbDev, argv[i+1], sizeof(xf86SolarisFbDev));
- return 2;
- }
- }
-
- return 0;
-}
-
-void xf86UseMsg()
-{
-#ifdef HAS_USL_VTS
- ErrorF("vtX Use the specified VT number\n");
-#endif
- ErrorF("-dev <fb> Framebuffer device\n");
- ErrorF("-keeptty Don't detach controlling tty\n");
- ErrorF(" (for debugging only)\n");
-}
+/*
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
+ * Copyright 1993 by David Wexelblat <dwex@goblin.org>
+ * Copyright 1999 by David Holland <davidh@iquest.net>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the names of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+#ifdef HAVE_SYS_KD_H
+# include <sys/kd.h>
+#endif
+
+static Bool KeepTty = FALSE;
+static Bool Protect0 = FALSE;
+#ifdef HAS_USL_VTS
+static int VTnum = -1;
+static int xf86StartVT = -1;
+static int vtEnabled = 0;
+extern void xf86VTAcquire(int);
+extern void xf86VTRelease(int);
+#endif
+
+/* Device to open as xf86Info.consoleFd */
+static char consoleDev[PATH_MAX] = "/dev/fb";
+
+/* Set by -dev argument on CLI
+ Used by hw/xfree86/common/xf86AutoConfig.c for VIS_GETIDENTIFIER */
+_X_HIDDEN char xf86SolarisFbDev[PATH_MAX] = "/dev/fb";
+
+void
+xf86OpenConsole(void)
+{
+ int i;
+#ifdef HAS_USL_VTS
+ int fd;
+ struct vt_mode VT;
+ struct vt_stat vtinfo;
+ int FreeVTslot;
+ MessageType from = X_PROBED;
+#endif
+
+ if (serverGeneration == 1)
+ {
+ /* Check if we're run with euid==0 */
+ if (geteuid() != 0)
+ FatalError("xf86OpenConsole: Server must be suid root\n");
+
+ /* Protect page 0 to help find NULL dereferencing */
+ /* mprotect() doesn't seem to work */
+ if (Protect0)
+ {
+ int fd = -1;
+
+ if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0)
+ {
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: cannot open /dev/zero (%s)\n",
+ strerror(errno));
+ }
+ else
+ {
+ if ((int)mmap(0, 0x1000, PROT_NONE,
+ MAP_FIXED | MAP_SHARED, fd, 0) == -1)
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: failed to protect page 0 (%s)\n",
+ strerror(errno));
+
+ close(fd);
+ }
+ }
+
+#ifdef HAS_USL_VTS
+
+ /*
+ * Setup the virtual terminal manager
+ */
+ if ((fd = open("/dev/vt/0",O_RDWR,0)) == -1)
+ {
+ xf86ErrorF("xf86OpenConsole: Cannot open /dev/vt/0 (%s)\n",
+ strerror(errno));
+ vtEnabled = 0;
+ }
+ else
+ {
+ if (ioctl(fd, VT_ENABLED, &vtEnabled) < 0)
+ {
+ xf86ErrorF("xf86OpenConsole: VT_ENABLED failed (%s)\n",
+ strerror(errno));
+ vtEnabled = 0;
+ }
+ }
+
+
+ if (vtEnabled == 0)
+ {
+ /* VT not enabled - kernel too old or Sparc platforms
+ without visual_io support */
+ xf86Msg(from, "VT infrastructure is not available\n");
+
+ xf86StartVT = 0;
+ xf86Info.vtno = 0;
+ strlcpy(consoleDev, xf86SolarisFbDev, sizeof(consoleDev));
+ }
+ else
+ {
+ if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
+ FatalError("xf86OpenConsole: Cannot determine current VT\n");
+
+ xf86StartVT = vtinfo.v_active;
+
+ if (VTnum != -1)
+ {
+ xf86Info.vtno = VTnum;
+ from = X_CMDLINE;
+ }
+ else
+ {
+ if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
+ (xf86Info.vtno == -1))
+ {
+ FatalError("xf86OpenConsole: Cannot find a free VT\n");
+ }
+ }
+
+ xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
+ snprintf(consoleDev, PATH_MAX, "/dev/vt/%d", xf86Info.vtno);
+ }
+
+ if (fd != -1)
+ {
+ close(fd);
+ }
+
+#endif /* HAS_USL_VTS */
+
+ if (!KeepTty)
+ setpgrp();
+
+ if (((xf86Info.consoleFd = open(consoleDev, O_RDWR | O_NDELAY, 0)) < 0))
+ FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
+ consoleDev, strerror(errno));
+
+#ifdef HAS_USL_VTS
+
+ /* Change ownership of the vt */
+ chown(consoleDev, getuid(), getgid());
+
+ if (vtEnabled)
+ {
+ /*
+ * Now get the VT
+ */
+ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
+ xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
+
+ if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0)
+ xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
+
+ if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
+ FatalError("xf86OpenConsole: VT_GETMODE failed\n");
+
+ OsSignal(SIGUSR1, xf86VTAcquire);
+ OsSignal(SIGUSR2, xf86VTRelease);
+
+ VT.mode = VT_PROCESS;
+ VT.acqsig = SIGUSR1;
+ VT.relsig = SIGUSR2;
+
+ if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
+ FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
+
+ if (ioctl(xf86Info.consoleFd, VT_SETDISPINFO, atoi(display)) < 0)
+ xf86Msg(X_WARNING, "xf86OpenConsole: VT_SETDISPINFO failed\n");
+ }
+#endif
+
+#ifdef KDSETMODE
+ SYSCALL(i = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
+ if (i < 0) {
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: KDSETMODE KD_GRAPHICS failed on %s (%s)\n",
+ consoleDev, strerror(errno));
+ }
+#endif
+ }
+ else /* serverGeneration != 1 */
+ {
+#ifdef HAS_USL_VTS
+ if (vtEnabled)
+ {
+ /*
+ * Now re-get the VT
+ */
+ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
+ xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
+
+ if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0)
+ xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
+
+ /*
+ * If the server doesn't have the VT when the reset occurs,
+ * this is to make sure we don't continue until the activate
+ * signal is received.
+ */
+ if (!xf86Screens[0]->vtSema)
+ sleep(5);
+ }
+#endif /* HAS_USL_VTS */
+
+ }
+}
+
+void
+xf86CloseConsole(void)
+{
+#ifdef HAS_USL_VTS
+ struct vt_mode VT;
+#endif
+
+#if !defined(__i386__) && !defined(__i386) && !defined(__x86)
+
+ if (!xf86DoConfigure) {
+ int fd;
+
+ /*
+ * Wipe out framebuffer just like the non-SI Xsun server does. This
+ * could be improved by saving framebuffer contents in
+ * xf86OpenConsole() above and restoring them here. Also, it's unclear
+ * at this point whether this should be done for all framebuffers in
+ * the system, rather than only the console.
+ */
+ if ((fd = open(xf86SolarisFbDev, O_RDWR, 0)) < 0) {
+ xf86Msg(X_WARNING,
+ "xf86CloseConsole(): unable to open framebuffer (%s)\n",
+ strerror(errno));
+ } else {
+ struct fbgattr fbattr;
+
+ if ((ioctl(fd, FBIOGATTR, &fbattr) < 0) &&
+ (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0)) {
+ xf86Msg(X_WARNING,
+ "xf86CloseConsole(): unable to retrieve framebuffer"
+ " attributes (%s)\n", strerror(errno));
+ } else {
+ pointer fbdata;
+
+ fbdata = mmap(NULL, fbattr.fbtype.fb_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (fbdata == MAP_FAILED) {
+ xf86Msg(X_WARNING,
+ "xf86CloseConsole(): unable to mmap framebuffer"
+ " (%s)\n", strerror(errno));
+ } else {
+ memset(fbdata, 0, fbattr.fbtype.fb_size);
+ munmap(fbdata, fbattr.fbtype.fb_size);
+ }
+ }
+
+ close(fd);
+ }
+ }
+
+#endif
+
+#ifdef KDSETMODE
+ /* Reset the display back to text mode */
+ SYSCALL(ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
+#endif
+
+#ifdef HAS_USL_VTS
+ if (vtEnabled)
+ {
+ if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
+ {
+ VT.mode = VT_AUTO; /* Set default vt handling */
+ ioctl(xf86Info.consoleFd, VT_SETMODE, &VT);
+ }
+
+ /* Activate the VT that X was started on */
+ ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86StartVT);
+ }
+#endif /* HAS_USL_VTS */
+
+ close(xf86Info.consoleFd);
+}
+
+int
+xf86ProcessArgument(int argc, char **argv, int i)
+{
+ /*
+ * Keep server from detaching from controlling tty. This is useful when
+ * debugging, so the server can receive keyboard signals.
+ */
+ if (!strcmp(argv[i], "-keeptty"))
+ {
+ KeepTty = TRUE;
+ return 1;
+ }
+
+ /*
+ * Undocumented flag to protect page 0 from read/write to help catch NULL
+ * pointer dereferences. This is purely a debugging flag.
+ */
+ if (!strcmp(argv[i], "-protect0"))
+ {
+ Protect0 = TRUE;
+ return 1;
+ }
+
+#ifdef HAS_USL_VTS
+
+ if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
+ {
+ if (sscanf(argv[i], "vt%d", &VTnum) == 0)
+ {
+ UseMsg();
+ VTnum = -1;
+ return 0;
+ }
+
+ return 1;
+ }
+
+#endif /* HAS_USL_VTS */
+
+ if ((i + 1) < argc) {
+ if (!strcmp(argv[i], "-dev")) {
+ strlcpy(xf86SolarisFbDev, argv[i+1], sizeof(xf86SolarisFbDev));
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+void xf86UseMsg()
+{
+#ifdef HAS_USL_VTS
+ ErrorF("vtX Use the specified VT number\n");
+#endif
+ ErrorF("-dev <fb> Framebuffer device\n");
+ ErrorF("-keeptty Don't detach controlling tty\n");
+ ErrorF(" (for debugging only)\n");
+}
diff --git a/xorg-server/hw/xfree86/os-support/xf86_OSproc.h b/xorg-server/hw/xfree86/os-support/xf86_OSproc.h
index c1a117334..3fc332e13 100644
--- a/xorg-server/hw/xfree86/os-support/xf86_OSproc.h
+++ b/xorg-server/hw/xfree86/os-support/xf86_OSproc.h
@@ -1,219 +1,220 @@
-/*
- * Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany
- * Copyright 1992 by David Dawes <dawes@XFree86.org>
- * Copyright 1992 by Jim Tsillas <jtsilla@damon.ccs.northeastern.edu>
- * Copyright 1992 by Rich Murphey <Rich@Rice.edu>
- * Copyright 1992 by Robert Baron <Robert.Baron@ernst.mach.cs.cmu.edu>
- * Copyright 1992 by Orest Zborowski <obz@eskimo.com>
- * Copyright 1993 by Vrije Universiteit, The Netherlands
- * Copyright 1993 by David Wexelblat <dwex@XFree86.org>
- * Copyright 1994, 1996 by Holger Veit <Holger.Veit@gmd.de>
- * Copyright 1994-2003 by The XFree86 Project, Inc
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the names of the above listed copyright holders
- * not be used in advertising or publicity pertaining to distribution of
- * the software without specific, written prior permission. The above listed
- * copyright holders make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
- * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*
- * The ARM32 code here carries the following copyright:
- *
- * Copyright 1997
- * Digital Equipment Corporation. All rights reserved.
- * This software is furnished under license and may be used and copied only in
- * accordance with the following terms and conditions. Subject to these
- * conditions, you may download, copy, install, use, modify and distribute
- * this software in source and/or binary form. No title or ownership is
- * transferred hereby.
- *
- * 1) Any source code used, modified or distributed must reproduce and retain
- * this copyright notice and list of conditions as they appear in the
- * source file.
- *
- * 2) No right is granted to use any trade name, trademark, or logo of Digital
- * Equipment Corporation. Neither the "Digital Equipment Corporation"
- * name nor any trademark or logo of Digital Equipment Corporation may be
- * used to endorse or promote products derived from this software without
- * the prior written permission of Digital Equipment Corporation.
- *
- * 3) This software is provided "AS-IS" and any express or implied warranties,
- * including but not limited to, any implied warranties of merchantability,
- * fitness for a particular purpose, or non-infringement are disclaimed.
- * In no event shall DIGITAL be liable for any damages whatsoever, and in
- * particular, DIGITAL shall not be liable for special, indirect,
- * consequential, or incidental damages or damages for lost profits, loss
- * of revenue or loss of use, whether such damages arise in contract,
- * negligence, tort, under statute, in equity, at law or otherwise, even
- * if advised of the possibility of such damage.
- *
- */
-
-
-#ifndef _XF86_OSPROC_H
-#define _XF86_OSPROC_H
-
-/*
- * The actual prototypes have been pulled into this seperate file so
- * that they can can be used without pulling in all of the OS specific
- * stuff like sys/stat.h, etc. This casues problem for loadable modules.
- */
-
-/*
- * Flags for xf86MapVidMem(). Multiple flags can be or'd together. The
- * flags may be used as hints. For example it would be permissible to
- * enable write combining for memory marked only for framebuffer use.
- */
-
-#define VIDMEM_FRAMEBUFFER 0x01 /* memory for framebuffer use */
-#define VIDMEM_MMIO 0x02 /* memory for I/O use */
-#define VIDMEM_MMIO_32BIT 0x04 /* memory accesses >= 32bit */
-#define VIDMEM_READSIDEEFFECT 0x08 /* reads can have side-effects */
-#define VIDMEM_SPARSE 0x10 /* sparse mapping required
- * assumed when VIDMEM_MMIO is
- * set. May be used with
- * VIDMEM_FRAMEBUFFER) */
-#define VIDMEM_READONLY 0x20 /* read-only mapping
- * used when reading BIOS images
- * through xf86MapVidMem() */
-
-/*
- * OS-independent modem state flags for xf86SetSerialModemState() and
- * xf86GetSerialModemState().
- */
-#define XF86_M_LE 0x001 /* line enable */
-#define XF86_M_DTR 0x002 /* data terminal ready */
-#define XF86_M_RTS 0x004 /* request to send */
-#define XF86_M_ST 0x008 /* secondary transmit */
-#define XF86_M_SR 0x010 /* secondary receive */
-#define XF86_M_CTS 0x020 /* clear to send */
-#define XF86_M_CAR 0x040 /* carrier detect */
-#define XF86_M_RNG 0x080 /* ring */
-#define XF86_M_DSR 0x100 /* data set ready */
-
-#ifndef NO_OSLIB_PROTOTYPES
-/*
- * This is to prevent re-entrancy to FatalError() when aborting.
- * Anything that can be called as a result of AbortDDX() should use this
- * instead of FatalError().
- */
-
-#define xf86FatalError(a, b) \
- if (dispatchException & DE_TERMINATE) { \
- ErrorF(a, b); \
- ErrorF("\n"); \
- return; \
- } else FatalError(a, b)
-
-/***************************************************************************/
-/* Prototypes */
-/***************************************************************************/
-
-#include <X11/Xfuncproto.h>
-#include "opaque.h"
-
-_XFUNCPROTOBEGIN
-
-/* public functions */
-extern _X_EXPORT Bool xf86LinearVidMem(void);
-extern _X_EXPORT Bool xf86CheckMTRR(int);
-extern _X_EXPORT pointer xf86MapVidMem(int, int, unsigned long, unsigned long);
-extern _X_EXPORT void xf86UnMapVidMem(int, pointer, unsigned long);
-extern _X_EXPORT void xf86MapReadSideEffects(int, int, pointer, unsigned long);
-extern _X_EXPORT int xf86ReadBIOS(unsigned long, unsigned long, unsigned char *, int);
-extern _X_EXPORT Bool xf86EnableIO(void);
-extern _X_EXPORT void xf86DisableIO(void);
-#ifdef __NetBSD__
-extern _X_EXPORT void xf86SetTVOut(int);
-extern _X_EXPORT void xf86SetRGBOut(void);
-#endif
-extern _X_EXPORT void xf86OSRingBell(int, int, int);
-extern _X_EXPORT void xf86SetReallySlowBcopy(void);
-extern _X_EXPORT void xf86SlowBcopy(unsigned char *, unsigned char *, int);
-extern _X_EXPORT int xf86OpenSerial(pointer options);
-extern _X_EXPORT int xf86SetSerial(int fd, pointer options);
-extern _X_EXPORT int xf86SetSerialSpeed(int fd, int speed);
-extern _X_EXPORT int xf86ReadSerial(int fd, void *buf, int count);
-extern _X_EXPORT int xf86WriteSerial(int fd, const void *buf, int count);
-extern _X_EXPORT int xf86CloseSerial(int fd);
-extern _X_EXPORT int xf86FlushInput(int fd);
-extern _X_EXPORT int xf86WaitForInput(int fd, int timeout);
-extern _X_EXPORT int xf86SerialSendBreak(int fd, int duration);
-extern _X_EXPORT int xf86SetSerialModemState(int fd, int state);
-extern _X_EXPORT int xf86GetSerialModemState(int fd);
-extern _X_EXPORT int xf86SerialModemSetBits(int fd, int bits);
-extern _X_EXPORT int xf86SerialModemClearBits(int fd, int bits);
-extern _X_EXPORT int xf86LoadKernelModule(const char *pathname);
-
-/* AGP GART interface */
-
-typedef struct _AgpInfo {
- CARD32 bridgeId;
- CARD32 agpMode;
- unsigned long base;
- unsigned long size;
- unsigned long totalPages;
- unsigned long systemPages;
- unsigned long usedPages;
-} AgpInfo, *AgpInfoPtr;
-
-extern _X_EXPORT Bool xf86AgpGARTSupported(void);
-extern _X_EXPORT AgpInfoPtr xf86GetAGPInfo(int screenNum);
-extern _X_EXPORT Bool xf86AcquireGART(int screenNum);
-extern _X_EXPORT Bool xf86ReleaseGART(int screenNum);
-extern _X_EXPORT int xf86AllocateGARTMemory(int screenNum, unsigned long size, int type,
- unsigned long *physical);
-extern _X_EXPORT Bool xf86DeallocateGARTMemory(int screenNum, int key);
-extern _X_EXPORT Bool xf86BindGARTMemory(int screenNum, int key, unsigned long offset);
-extern _X_EXPORT Bool xf86UnbindGARTMemory(int screenNum, int key);
-extern _X_EXPORT Bool xf86EnableAGP(int screenNum, CARD32 mode);
-extern _X_EXPORT Bool xf86GARTCloseScreen(int screenNum);
-
-/* These routines are in shared/sigio.c and are not loaded as part of the
- module. These routines are small, and the code if very POSIX-signal (or
- OS-signal) specific, so it seemed better to provide more complex
- wrappers than to wrap each individual function called. */
-extern _X_EXPORT int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *);
-extern _X_EXPORT int xf86RemoveSIGIOHandler(int fd);
-extern _X_EXPORT int xf86BlockSIGIO (void);
-extern _X_EXPORT void xf86UnblockSIGIO (int);
-extern _X_EXPORT void xf86AssertBlockedSIGIO (char *);
-extern _X_EXPORT Bool xf86SIGIOSupported (void);
-
-#ifdef XF86_OS_PRIVS
-typedef void (*PMClose)(void);
-extern _X_EXPORT void xf86OpenConsole(void);
-extern _X_EXPORT void xf86CloseConsole(void);
-extern _X_EXPORT Bool xf86VTSwitchPending(void);
-extern _X_EXPORT Bool xf86VTSwitchAway(void);
-extern _X_EXPORT Bool xf86VTSwitchTo(void);
-extern _X_EXPORT void xf86VTRequest(int sig);
-extern _X_EXPORT int xf86ProcessArgument(int, char **, int);
-extern _X_EXPORT void xf86UseMsg(void);
-extern _X_EXPORT PMClose xf86OSPMOpen(void);
-
-extern _X_EXPORT void xf86MakeNewMapping(int, int, unsigned long, unsigned long, pointer);
-extern _X_EXPORT void xf86InitVidMem(void);
-
-#endif /* XF86_OS_PRIVS */
-
-
-_XFUNCPROTOEND
-#endif /* NO_OSLIB_PROTOTYPES */
-
-#endif /* _XF86_OSPROC_H */
+/*
+ * Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany
+ * Copyright 1992 by David Dawes <dawes@XFree86.org>
+ * Copyright 1992 by Jim Tsillas <jtsilla@damon.ccs.northeastern.edu>
+ * Copyright 1992 by Rich Murphey <Rich@Rice.edu>
+ * Copyright 1992 by Robert Baron <Robert.Baron@ernst.mach.cs.cmu.edu>
+ * Copyright 1992 by Orest Zborowski <obz@eskimo.com>
+ * Copyright 1993 by Vrije Universiteit, The Netherlands
+ * Copyright 1993 by David Wexelblat <dwex@XFree86.org>
+ * Copyright 1994, 1996 by Holger Veit <Holger.Veit@gmd.de>
+ * Copyright 1994-2003 by The XFree86 Project, Inc
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of the above listed copyright holders
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission. The above listed
+ * copyright holders make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * The ARM32 code here carries the following copyright:
+ *
+ * Copyright 1997
+ * Digital Equipment Corporation. All rights reserved.
+ * This software is furnished under license and may be used and copied only in
+ * accordance with the following terms and conditions. Subject to these
+ * conditions, you may download, copy, install, use, modify and distribute
+ * this software in source and/or binary form. No title or ownership is
+ * transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce and retain
+ * this copyright notice and list of conditions as they appear in the
+ * source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of Digital
+ * Equipment Corporation. Neither the "Digital Equipment Corporation"
+ * name nor any trademark or logo of Digital Equipment Corporation may be
+ * used to endorse or promote products derived from this software without
+ * the prior written permission of Digital Equipment Corporation.
+ *
+ * 3) This software is provided "AS-IS" and any express or implied warranties,
+ * including but not limited to, any implied warranties of merchantability,
+ * fitness for a particular purpose, or non-infringement are disclaimed.
+ * In no event shall DIGITAL be liable for any damages whatsoever, and in
+ * particular, DIGITAL shall not be liable for special, indirect,
+ * consequential, or incidental damages or damages for lost profits, loss
+ * of revenue or loss of use, whether such damages arise in contract,
+ * negligence, tort, under statute, in equity, at law or otherwise, even
+ * if advised of the possibility of such damage.
+ *
+ */
+
+
+#ifndef _XF86_OSPROC_H
+#define _XF86_OSPROC_H
+
+/*
+ * The actual prototypes have been pulled into this seperate file so
+ * that they can can be used without pulling in all of the OS specific
+ * stuff like sys/stat.h, etc. This casues problem for loadable modules.
+ */
+
+/*
+ * Flags for xf86MapVidMem(). Multiple flags can be or'd together. The
+ * flags may be used as hints. For example it would be permissible to
+ * enable write combining for memory marked only for framebuffer use.
+ */
+
+#define VIDMEM_FRAMEBUFFER 0x01 /* memory for framebuffer use */
+#define VIDMEM_MMIO 0x02 /* memory for I/O use */
+#define VIDMEM_MMIO_32BIT 0x04 /* memory accesses >= 32bit */
+#define VIDMEM_READSIDEEFFECT 0x08 /* reads can have side-effects */
+#define VIDMEM_SPARSE 0x10 /* sparse mapping required
+ * assumed when VIDMEM_MMIO is
+ * set. May be used with
+ * VIDMEM_FRAMEBUFFER) */
+#define VIDMEM_READONLY 0x20 /* read-only mapping
+ * used when reading BIOS images
+ * through xf86MapVidMem() */
+
+/*
+ * OS-independent modem state flags for xf86SetSerialModemState() and
+ * xf86GetSerialModemState().
+ */
+#define XF86_M_LE 0x001 /* line enable */
+#define XF86_M_DTR 0x002 /* data terminal ready */
+#define XF86_M_RTS 0x004 /* request to send */
+#define XF86_M_ST 0x008 /* secondary transmit */
+#define XF86_M_SR 0x010 /* secondary receive */
+#define XF86_M_CTS 0x020 /* clear to send */
+#define XF86_M_CAR 0x040 /* carrier detect */
+#define XF86_M_RNG 0x080 /* ring */
+#define XF86_M_DSR 0x100 /* data set ready */
+
+#ifndef NO_OSLIB_PROTOTYPES
+/*
+ * This is to prevent re-entrancy to FatalError() when aborting.
+ * Anything that can be called as a result of AbortDDX() should use this
+ * instead of FatalError().
+ */
+
+#define xf86FatalError(a, b) \
+ if (dispatchException & DE_TERMINATE) { \
+ ErrorF(a, b); \
+ ErrorF("\n"); \
+ return; \
+ } else FatalError(a, b)
+
+/***************************************************************************/
+/* Prototypes */
+/***************************************************************************/
+
+#include <X11/Xfuncproto.h>
+#include "opaque.h"
+
+_XFUNCPROTOBEGIN
+
+/* public functions */
+extern _X_EXPORT Bool xf86LinearVidMem(void);
+extern _X_EXPORT Bool xf86CheckMTRR(int);
+extern _X_EXPORT pointer xf86MapVidMem(int, int, unsigned long, unsigned long);
+extern _X_EXPORT void xf86UnMapVidMem(int, pointer, unsigned long);
+extern _X_EXPORT void xf86MapReadSideEffects(int, int, pointer, unsigned long);
+extern _X_EXPORT int xf86ReadBIOS(unsigned long, unsigned long, unsigned char *, int);
+extern _X_EXPORT Bool xf86EnableIO(void);
+extern _X_EXPORT void xf86DisableIO(void);
+#ifdef __NetBSD__
+extern _X_EXPORT void xf86SetTVOut(int);
+extern _X_EXPORT void xf86SetRGBOut(void);
+#endif
+extern _X_EXPORT void xf86OSRingBell(int, int, int);
+extern _X_EXPORT void xf86SetReallySlowBcopy(void);
+extern _X_EXPORT void xf86SlowBcopy(unsigned char *, unsigned char *, int);
+extern _X_EXPORT int xf86OpenSerial(pointer options);
+extern _X_EXPORT int xf86SetSerial(int fd, pointer options);
+extern _X_EXPORT int xf86SetSerialSpeed(int fd, int speed);
+extern _X_EXPORT int xf86ReadSerial(int fd, void *buf, int count);
+extern _X_EXPORT int xf86WriteSerial(int fd, const void *buf, int count);
+extern _X_EXPORT int xf86CloseSerial(int fd);
+extern _X_EXPORT int xf86FlushInput(int fd);
+extern _X_EXPORT int xf86WaitForInput(int fd, int timeout);
+extern _X_EXPORT int xf86SerialSendBreak(int fd, int duration);
+extern _X_EXPORT int xf86SetSerialModemState(int fd, int state);
+extern _X_EXPORT int xf86GetSerialModemState(int fd);
+extern _X_EXPORT int xf86SerialModemSetBits(int fd, int bits);
+extern _X_EXPORT int xf86SerialModemClearBits(int fd, int bits);
+extern _X_EXPORT int xf86LoadKernelModule(const char *pathname);
+
+/* AGP GART interface */
+
+typedef struct _AgpInfo {
+ CARD32 bridgeId;
+ CARD32 agpMode;
+ unsigned long base;
+ unsigned long size;
+ unsigned long totalPages;
+ unsigned long systemPages;
+ unsigned long usedPages;
+} AgpInfo, *AgpInfoPtr;
+
+extern _X_EXPORT Bool xf86AgpGARTSupported(void);
+extern _X_EXPORT AgpInfoPtr xf86GetAGPInfo(int screenNum);
+extern _X_EXPORT Bool xf86AcquireGART(int screenNum);
+extern _X_EXPORT Bool xf86ReleaseGART(int screenNum);
+extern _X_EXPORT int xf86AllocateGARTMemory(int screenNum, unsigned long size, int type,
+ unsigned long *physical);
+extern _X_EXPORT Bool xf86DeallocateGARTMemory(int screenNum, int key);
+extern _X_EXPORT Bool xf86BindGARTMemory(int screenNum, int key, unsigned long offset);
+extern _X_EXPORT Bool xf86UnbindGARTMemory(int screenNum, int key);
+extern _X_EXPORT Bool xf86EnableAGP(int screenNum, CARD32 mode);
+extern _X_EXPORT Bool xf86GARTCloseScreen(int screenNum);
+
+/* These routines are in shared/sigio.c and are not loaded as part of the
+ module. These routines are small, and the code if very POSIX-signal (or
+ OS-signal) specific, so it seemed better to provide more complex
+ wrappers than to wrap each individual function called. */
+extern _X_EXPORT int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *);
+extern _X_EXPORT int xf86RemoveSIGIOHandler(int fd);
+extern _X_EXPORT int xf86BlockSIGIO (void);
+extern _X_EXPORT void xf86UnblockSIGIO (int);
+extern _X_EXPORT void xf86AssertBlockedSIGIO (char *);
+extern _X_EXPORT Bool xf86SIGIOSupported (void);
+
+#ifdef XF86_OS_PRIVS
+typedef void (*PMClose)(void);
+extern _X_EXPORT void xf86OpenConsole(void);
+extern _X_EXPORT void xf86CloseConsole(void);
+extern _X_HIDDEN Bool xf86VTActivate(int vtno);
+extern _X_EXPORT Bool xf86VTSwitchPending(void);
+extern _X_EXPORT Bool xf86VTSwitchAway(void);
+extern _X_EXPORT Bool xf86VTSwitchTo(void);
+extern _X_EXPORT void xf86VTRequest(int sig);
+extern _X_EXPORT int xf86ProcessArgument(int, char **, int);
+extern _X_EXPORT void xf86UseMsg(void);
+extern _X_EXPORT PMClose xf86OSPMOpen(void);
+
+extern _X_EXPORT void xf86MakeNewMapping(int, int, unsigned long, unsigned long, pointer);
+extern _X_EXPORT void xf86InitVidMem(void);
+
+#endif /* XF86_OS_PRIVS */
+
+
+_XFUNCPROTOEND
+#endif /* NO_OSLIB_PROTOTYPES */
+
+#endif /* _XF86_OSPROC_H */
diff --git a/xorg-server/hw/xfree86/x86emu/ops.c b/xorg-server/hw/xfree86/x86emu/ops.c
index 37ae2c9c9..740a3a58d 100644
--- a/xorg-server/hw/xfree86/x86emu/ops.c
+++ b/xorg-server/hw/xfree86/x86emu/ops.c
@@ -1,11697 +1,11717 @@
-/****************************************************************************
-*
-* Realmode X86 Emulator Library
-*
-* Copyright (C) 1996-1999 SciTech Software, Inc.
-* Copyright (C) David Mosberger-Tang
-* Copyright (C) 1999 Egbert Eich
-*
-* ========================================================================
-*
-* Permission to use, copy, modify, distribute, and sell this software and
-* its documentation for any purpose is hereby granted without fee,
-* provided that the above copyright notice appear in all copies and that
-* both that copyright notice and this permission notice appear in
-* supporting documentation, and that the name of the authors not be used
-* in advertising or publicity pertaining to distribution of the software
-* without specific, written prior permission. The authors makes no
-* representations about the suitability of this software for any purpose.
-* It is provided "as is" without express or implied warranty.
-*
-* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
-* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-* PERFORMANCE OF THIS SOFTWARE.
-*
-* ========================================================================
-*
-* Language: ANSI C
-* Environment: Any
-* Developer: Kendall Bennett
-*
-* Description: This file includes subroutines to implement the decoding
-* and emulation of all the x86 processor instructions.
-*
-* There are approximately 250 subroutines in here, which correspond
-* to the 256 byte-"opcodes" found on the 8086. The table which
-* dispatches this is found in the files optab.[ch].
-*
-* Each opcode proc has a comment preceeding it which gives it's table
-* address. Several opcodes are missing (undefined) in the table.
-*
-* Each proc includes information for decoding (DECODE_PRINTF and
-* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
-* functions (START_OF_INSTR, END_OF_INSTR).
-*
-* Many of the procedures are *VERY* similar in coding. This has
-* allowed for a very large amount of code to be generated in a fairly
-* short amount of time (i.e. cut, paste, and modify). The result is
-* that much of the code below could have been folded into subroutines
-* for a large reduction in size of this file. The downside would be
-* that there would be a penalty in execution speed. The file could
-* also have been *MUCH* larger by inlining certain functions which
-* were called. This could have resulted even faster execution. The
-* prime directive I used to decide whether to inline the code or to
-* modularize it, was basically: 1) no unnecessary subroutine calls,
-* 2) no routines more than about 200 lines in size, and 3) modularize
-* any code that I might not get right the first time. The fetch_*
-* subroutines fall into the latter category. The The decode_* fall
-* into the second category. The coding of the "switch(mod){ .... }"
-* in many of the subroutines below falls into the first category.
-* Especially, the coding of {add,and,or,sub,...}_{byte,word}
-* subroutines are an especially glaring case of the third guideline.
-* Since so much of the code is cloned from other modules (compare
-* opcode #00 to opcode #01), making the basic operations subroutine
-* calls is especially important; otherwise mistakes in coding an
-* "add" would represent a nightmare in maintenance.
-*
-****************************************************************************/
-
-#include "x86emu/x86emui.h"
-
-/*----------------------------- Implementation ----------------------------*/
-
-/****************************************************************************
-PARAMETERS:
-op1 - Instruction op code
-
-REMARKS:
-Handles illegal opcodes.
-****************************************************************************/
-static void x86emuOp_illegal_op(
- u8 op1)
-{
- START_OF_INSTR();
- if (M.x86.R_SP != 0) {
- DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
- TRACE_REGS();
- DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
- M.x86.R_CS, M.x86.R_IP-1,op1));
- HALT_SYS();
- }
- else {
- /* If we get here, it means the stack pointer is back to zero
- * so we are just returning from an emulator service call
- * so therte is no need to display an error message. We trap
- * the emulator with an 0xF1 opcode to finish the service
- * call.
- */
- X86EMU_halt_sys();
- }
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x00
-****************************************************************************/
-static void x86emuOp_add_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
- u8 *destreg, *srcreg;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADD\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x01
-****************************************************************************/
-static void x86emuOp_add_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADD\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = add_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x02
-****************************************************************************/
-static void x86emuOp_add_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADD\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x03
-****************************************************************************/
-static void x86emuOp_add_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADD\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_word(*destreg, srcval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = add_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x04
-****************************************************************************/
-static void x86emuOp_add_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADD\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- M.x86.R_AL = add_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x05
-****************************************************************************/
-static void x86emuOp_add_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("ADD\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("ADD\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = add_long(M.x86.R_EAX, srcval);
- } else {
- M.x86.R_AX = add_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x06
-****************************************************************************/
-static void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("PUSH\tES\n");
- TRACE_AND_STEP();
- push_word(M.x86.R_ES);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x07
-****************************************************************************/
-static void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("POP\tES\n");
- TRACE_AND_STEP();
- M.x86.R_ES = pop_word();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x08
-****************************************************************************/
-static void x86emuOp_or_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("OR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x09
-****************************************************************************/
-static void x86emuOp_or_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("OR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = or_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x0a
-****************************************************************************/
-static void x86emuOp_or_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("OR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x0b
-****************************************************************************/
-static void x86emuOp_or_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("OR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_word(*destreg, srcval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = or_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x0c
-****************************************************************************/
-static void x86emuOp_or_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("OR\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- M.x86.R_AL = or_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x0d
-****************************************************************************/
-static void x86emuOp_or_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("OR\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("OR\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = or_long(M.x86.R_EAX, srcval);
- } else {
- M.x86.R_AX = or_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x0e
-****************************************************************************/
-static void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("PUSH\tCS\n");
- TRACE_AND_STEP();
- push_word(M.x86.R_CS);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
-****************************************************************************/
-static void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
-{
- u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
- INC_DECODED_INST_LEN(1);
- (*x86emu_optab2[op2])(op2);
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x10
-****************************************************************************/
-static void x86emuOp_adc_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADC\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x11
-****************************************************************************/
-static void x86emuOp_adc_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADC\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = adc_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x12
-****************************************************************************/
-static void x86emuOp_adc_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADC\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x13
-****************************************************************************/
-static void x86emuOp_adc_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADC\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_word(*destreg, srcval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = adc_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x14
-****************************************************************************/
-static void x86emuOp_adc_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("ADC\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- M.x86.R_AL = adc_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x15
-****************************************************************************/
-static void x86emuOp_adc_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("ADC\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("ADC\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = adc_long(M.x86.R_EAX, srcval);
- } else {
- M.x86.R_AX = adc_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x16
-****************************************************************************/
-static void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("PUSH\tSS\n");
- TRACE_AND_STEP();
- push_word(M.x86.R_SS);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x17
-****************************************************************************/
-static void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("POP\tSS\n");
- TRACE_AND_STEP();
- M.x86.R_SS = pop_word();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x18
-****************************************************************************/
-static void x86emuOp_sbb_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("SBB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x19
-****************************************************************************/
-static void x86emuOp_sbb_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("SBB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sbb_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x1a
-****************************************************************************/
-static void x86emuOp_sbb_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("SBB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x1b
-****************************************************************************/
-static void x86emuOp_sbb_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("SBB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_word(*destreg, srcval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sbb_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x1c
-****************************************************************************/
-static void x86emuOp_sbb_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("SBB\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- M.x86.R_AL = sbb_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x1d
-****************************************************************************/
-static void x86emuOp_sbb_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("SBB\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("SBB\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = sbb_long(M.x86.R_EAX, srcval);
- } else {
- M.x86.R_AX = sbb_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x1e
-****************************************************************************/
-static void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("PUSH\tDS\n");
- TRACE_AND_STEP();
- push_word(M.x86.R_DS);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x1f
-****************************************************************************/
-static void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("POP\tDS\n");
- TRACE_AND_STEP();
- M.x86.R_DS = pop_word();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x20
-****************************************************************************/
-static void x86emuOp_and_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("AND\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
-
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
-
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
-
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
-
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x21
-****************************************************************************/
-static void x86emuOp_and_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("AND\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = and_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x22
-****************************************************************************/
-static void x86emuOp_and_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("AND\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x23
-****************************************************************************/
-static void x86emuOp_and_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("AND\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_long(*destreg, srcval);
- break;
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_word(*destreg, srcval);
- break;
- }
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = and_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x24
-****************************************************************************/
-static void x86emuOp_and_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("AND\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- M.x86.R_AL = and_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x25
-****************************************************************************/
-static void x86emuOp_and_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("AND\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("AND\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = and_long(M.x86.R_EAX, srcval);
- } else {
- M.x86.R_AX = and_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x26
-****************************************************************************/
-static void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("ES:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_SEGOVR_ES;
- /*
- * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
- * opcode subroutines we do not want to do this.
- */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x27
-****************************************************************************/
-static void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("DAA\n");
- TRACE_AND_STEP();
- M.x86.R_AL = daa_byte(M.x86.R_AL);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x28
-****************************************************************************/
-static void x86emuOp_sub_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("SUB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x29
-****************************************************************************/
-static void x86emuOp_sub_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("SUB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = sub_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x2a
-****************************************************************************/
-static void x86emuOp_sub_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("SUB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x2b
-****************************************************************************/
-static void x86emuOp_sub_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("SUB\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_word(*destreg, srcval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = sub_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x2c
-****************************************************************************/
-static void x86emuOp_sub_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("SUB\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- M.x86.R_AL = sub_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x2d
-****************************************************************************/
-static void x86emuOp_sub_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("SUB\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("SUB\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = sub_long(M.x86.R_EAX, srcval);
- } else {
- M.x86.R_AX = sub_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x2e
-****************************************************************************/
-static void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("CS:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_SEGOVR_CS;
- /* note no DECODE_CLEAR_SEGOVR here. */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x2f
-****************************************************************************/
-static void x86emuOp_das(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("DAS\n");
- TRACE_AND_STEP();
- M.x86.R_AL = das_byte(M.x86.R_AL);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x30
-****************************************************************************/
-static void x86emuOp_xor_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("XOR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_byte(destval, *srcreg);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x31
-****************************************************************************/
-static void x86emuOp_xor_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("XOR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_long(destval, *srcreg);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = xor_word(destval, *srcreg);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x32
-****************************************************************************/
-static void x86emuOp_xor_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("XOR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x33
-****************************************************************************/
-static void x86emuOp_xor_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("XOR\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_word(*destreg, srcval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = xor_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x34
-****************************************************************************/
-static void x86emuOp_xor_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("XOR\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- M.x86.R_AL = xor_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x35
-****************************************************************************/
-static void x86emuOp_xor_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XOR\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("XOR\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = xor_long(M.x86.R_EAX, srcval);
- } else {
- M.x86.R_AX = xor_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x36
-****************************************************************************/
-static void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("SS:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_SEGOVR_SS;
- /* no DECODE_CLEAR_SEGOVR ! */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x37
-****************************************************************************/
-static void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("AAA\n");
- TRACE_AND_STEP();
- M.x86.R_AX = aaa_word(M.x86.R_AX);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x38
-****************************************************************************/
-static void x86emuOp_cmp_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
- u8 *destreg, *srcreg;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("CMP\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(destval, *srcreg);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(destval, *srcreg);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(destval, *srcreg);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x39
-****************************************************************************/
-static void x86emuOp_cmp_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("CMP\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(destval, *srcreg);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(destval, *srcreg);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(destval, *srcreg);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(destval, *srcreg);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(destval, *srcreg);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(destval, *srcreg);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x3a
-****************************************************************************/
-static void x86emuOp_cmp_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("CMP\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(*destreg, srcval);
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(*destreg, srcval);
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(*destreg, srcval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x3b
-****************************************************************************/
-static void x86emuOp_cmp_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("CMP\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(*destreg, srcval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(*destreg, srcval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(*destreg, srcval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- cmp_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x3c
-****************************************************************************/
-static void x86emuOp_cmp_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("CMP\tAL,");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- cmp_byte(M.x86.R_AL, srcval);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x3d
-****************************************************************************/
-static void x86emuOp_cmp_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("CMP\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("CMP\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- cmp_long(M.x86.R_EAX, srcval);
- } else {
- cmp_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x3e
-****************************************************************************/
-static void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("DS:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_SEGOVR_DS;
- /* NO DECODE_CLEAR_SEGOVR! */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x3f
-****************************************************************************/
-static void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("AAS\n");
- TRACE_AND_STEP();
- M.x86.R_AX = aas_word(M.x86.R_AX);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x40
-****************************************************************************/
-static void x86emuOp_inc_AX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tEAX\n");
- } else {
- DECODE_PRINTF("INC\tAX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = inc_long(M.x86.R_EAX);
- } else {
- M.x86.R_AX = inc_word(M.x86.R_AX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x41
-****************************************************************************/
-static void x86emuOp_inc_CX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tECX\n");
- } else {
- DECODE_PRINTF("INC\tCX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ECX = inc_long(M.x86.R_ECX);
- } else {
- M.x86.R_CX = inc_word(M.x86.R_CX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x42
-****************************************************************************/
-static void x86emuOp_inc_DX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tEDX\n");
- } else {
- DECODE_PRINTF("INC\tDX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDX = inc_long(M.x86.R_EDX);
- } else {
- M.x86.R_DX = inc_word(M.x86.R_DX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x43
-****************************************************************************/
-static void x86emuOp_inc_BX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tEBX\n");
- } else {
- DECODE_PRINTF("INC\tBX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBX = inc_long(M.x86.R_EBX);
- } else {
- M.x86.R_BX = inc_word(M.x86.R_BX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x44
-****************************************************************************/
-static void x86emuOp_inc_SP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tESP\n");
- } else {
- DECODE_PRINTF("INC\tSP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESP = inc_long(M.x86.R_ESP);
- } else {
- M.x86.R_SP = inc_word(M.x86.R_SP);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x45
-****************************************************************************/
-static void x86emuOp_inc_BP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tEBP\n");
- } else {
- DECODE_PRINTF("INC\tBP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBP = inc_long(M.x86.R_EBP);
- } else {
- M.x86.R_BP = inc_word(M.x86.R_BP);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x46
-****************************************************************************/
-static void x86emuOp_inc_SI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tESI\n");
- } else {
- DECODE_PRINTF("INC\tSI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESI = inc_long(M.x86.R_ESI);
- } else {
- M.x86.R_SI = inc_word(M.x86.R_SI);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x47
-****************************************************************************/
-static void x86emuOp_inc_DI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tEDI\n");
- } else {
- DECODE_PRINTF("INC\tDI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDI = inc_long(M.x86.R_EDI);
- } else {
- M.x86.R_DI = inc_word(M.x86.R_DI);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x48
-****************************************************************************/
-static void x86emuOp_dec_AX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tEAX\n");
- } else {
- DECODE_PRINTF("DEC\tAX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = dec_long(M.x86.R_EAX);
- } else {
- M.x86.R_AX = dec_word(M.x86.R_AX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x49
-****************************************************************************/
-static void x86emuOp_dec_CX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tECX\n");
- } else {
- DECODE_PRINTF("DEC\tCX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ECX = dec_long(M.x86.R_ECX);
- } else {
- M.x86.R_CX = dec_word(M.x86.R_CX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x4a
-****************************************************************************/
-static void x86emuOp_dec_DX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tEDX\n");
- } else {
- DECODE_PRINTF("DEC\tDX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDX = dec_long(M.x86.R_EDX);
- } else {
- M.x86.R_DX = dec_word(M.x86.R_DX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x4b
-****************************************************************************/
-static void x86emuOp_dec_BX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tEBX\n");
- } else {
- DECODE_PRINTF("DEC\tBX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBX = dec_long(M.x86.R_EBX);
- } else {
- M.x86.R_BX = dec_word(M.x86.R_BX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x4c
-****************************************************************************/
-static void x86emuOp_dec_SP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tESP\n");
- } else {
- DECODE_PRINTF("DEC\tSP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESP = dec_long(M.x86.R_ESP);
- } else {
- M.x86.R_SP = dec_word(M.x86.R_SP);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x4d
-****************************************************************************/
-static void x86emuOp_dec_BP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tEBP\n");
- } else {
- DECODE_PRINTF("DEC\tBP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBP = dec_long(M.x86.R_EBP);
- } else {
- M.x86.R_BP = dec_word(M.x86.R_BP);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x4e
-****************************************************************************/
-static void x86emuOp_dec_SI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tESI\n");
- } else {
- DECODE_PRINTF("DEC\tSI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESI = dec_long(M.x86.R_ESI);
- } else {
- M.x86.R_SI = dec_word(M.x86.R_SI);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x4f
-****************************************************************************/
-static void x86emuOp_dec_DI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tEDI\n");
- } else {
- DECODE_PRINTF("DEC\tDI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDI = dec_long(M.x86.R_EDI);
- } else {
- M.x86.R_DI = dec_word(M.x86.R_DI);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x50
-****************************************************************************/
-static void x86emuOp_push_AX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tEAX\n");
- } else {
- DECODE_PRINTF("PUSH\tAX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_EAX);
- } else {
- push_word(M.x86.R_AX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x51
-****************************************************************************/
-static void x86emuOp_push_CX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tECX\n");
- } else {
- DECODE_PRINTF("PUSH\tCX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_ECX);
- } else {
- push_word(M.x86.R_CX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x52
-****************************************************************************/
-static void x86emuOp_push_DX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tEDX\n");
- } else {
- DECODE_PRINTF("PUSH\tDX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_EDX);
- } else {
- push_word(M.x86.R_DX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x53
-****************************************************************************/
-static void x86emuOp_push_BX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tEBX\n");
- } else {
- DECODE_PRINTF("PUSH\tBX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_EBX);
- } else {
- push_word(M.x86.R_BX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x54
-****************************************************************************/
-static void x86emuOp_push_SP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tESP\n");
- } else {
- DECODE_PRINTF("PUSH\tSP\n");
- }
- TRACE_AND_STEP();
- /* Always push (E)SP, since we are emulating an i386 and above
- * processor. This is necessary as some BIOS'es use this to check
- * what type of processor is in the system.
- */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_ESP);
- } else {
- push_word((u16)(M.x86.R_SP));
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x55
-****************************************************************************/
-static void x86emuOp_push_BP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tEBP\n");
- } else {
- DECODE_PRINTF("PUSH\tBP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_EBP);
- } else {
- push_word(M.x86.R_BP);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x56
-****************************************************************************/
-static void x86emuOp_push_SI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tESI\n");
- } else {
- DECODE_PRINTF("PUSH\tSI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_ESI);
- } else {
- push_word(M.x86.R_SI);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x57
-****************************************************************************/
-static void x86emuOp_push_DI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSH\tEDI\n");
- } else {
- DECODE_PRINTF("PUSH\tDI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(M.x86.R_EDI);
- } else {
- push_word(M.x86.R_DI);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x58
-****************************************************************************/
-static void x86emuOp_pop_AX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tEAX\n");
- } else {
- DECODE_PRINTF("POP\tAX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = pop_long();
- } else {
- M.x86.R_AX = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x59
-****************************************************************************/
-static void x86emuOp_pop_CX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tECX\n");
- } else {
- DECODE_PRINTF("POP\tCX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ECX = pop_long();
- } else {
- M.x86.R_CX = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x5a
-****************************************************************************/
-static void x86emuOp_pop_DX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tEDX\n");
- } else {
- DECODE_PRINTF("POP\tDX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDX = pop_long();
- } else {
- M.x86.R_DX = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x5b
-****************************************************************************/
-static void x86emuOp_pop_BX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tEBX\n");
- } else {
- DECODE_PRINTF("POP\tBX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBX = pop_long();
- } else {
- M.x86.R_BX = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x5c
-****************************************************************************/
-static void x86emuOp_pop_SP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tESP\n");
- } else {
- DECODE_PRINTF("POP\tSP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESP = pop_long();
- } else {
- M.x86.R_SP = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x5d
-****************************************************************************/
-static void x86emuOp_pop_BP(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tEBP\n");
- } else {
- DECODE_PRINTF("POP\tBP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBP = pop_long();
- } else {
- M.x86.R_BP = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x5e
-****************************************************************************/
-static void x86emuOp_pop_SI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tESI\n");
- } else {
- DECODE_PRINTF("POP\tSI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESI = pop_long();
- } else {
- M.x86.R_SI = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x5f
-****************************************************************************/
-static void x86emuOp_pop_DI(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POP\tEDI\n");
- } else {
- DECODE_PRINTF("POP\tDI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDI = pop_long();
- } else {
- M.x86.R_DI = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x60
-****************************************************************************/
-static void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSHAD\n");
- } else {
- DECODE_PRINTF("PUSHA\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 old_sp = M.x86.R_ESP;
-
- push_long(M.x86.R_EAX);
- push_long(M.x86.R_ECX);
- push_long(M.x86.R_EDX);
- push_long(M.x86.R_EBX);
- push_long(old_sp);
- push_long(M.x86.R_EBP);
- push_long(M.x86.R_ESI);
- push_long(M.x86.R_EDI);
- } else {
- u16 old_sp = M.x86.R_SP;
-
- push_word(M.x86.R_AX);
- push_word(M.x86.R_CX);
- push_word(M.x86.R_DX);
- push_word(M.x86.R_BX);
- push_word(old_sp);
- push_word(M.x86.R_BP);
- push_word(M.x86.R_SI);
- push_word(M.x86.R_DI);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x61
-****************************************************************************/
-static void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POPAD\n");
- } else {
- DECODE_PRINTF("POPA\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDI = pop_long();
- M.x86.R_ESI = pop_long();
- M.x86.R_EBP = pop_long();
- M.x86.R_ESP += 4; /* skip ESP */
- M.x86.R_EBX = pop_long();
- M.x86.R_EDX = pop_long();
- M.x86.R_ECX = pop_long();
- M.x86.R_EAX = pop_long();
- } else {
- M.x86.R_DI = pop_word();
- M.x86.R_SI = pop_word();
- M.x86.R_BP = pop_word();
- M.x86.R_SP += 2; /* skip SP */
- M.x86.R_BX = pop_word();
- M.x86.R_DX = pop_word();
- M.x86.R_CX = pop_word();
- M.x86.R_AX = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
-/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x64
-****************************************************************************/
-static void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("FS:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_SEGOVR_FS;
- /*
- * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
- * opcode subroutines we do not want to do this.
- */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x65
-****************************************************************************/
-static void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("GS:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_SEGOVR_GS;
- /*
- * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
- * opcode subroutines we do not want to do this.
- */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x66 - prefix for 32-bit register
-****************************************************************************/
-static void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("DATA:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_PREFIX_DATA;
- /* note no DECODE_CLEAR_SEGOVR here. */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x67 - prefix for 32-bit address
-****************************************************************************/
-static void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("ADDR:\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_PREFIX_ADDR;
- /* note no DECODE_CLEAR_SEGOVR here. */
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x68
-****************************************************************************/
-static void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 imm;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- imm = fetch_long_imm();
- } else {
- imm = fetch_word_imm();
- }
- DECODE_PRINTF2("PUSH\t%x\n", imm);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(imm);
- } else {
- push_word((u16)imm);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x69
-****************************************************************************/
-static void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("IMUL\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
- u32 res_lo,res_hi;
- s32 imm;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg;
- u16 srcval;
- u32 res;
- s16 imm;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- res = (s16)srcval * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
- u32 res_lo,res_hi;
- s32 imm;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg;
- u16 srcval;
- u32 res;
- s16 imm;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- res = (s16)srcval * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
- u32 res_lo,res_hi;
- s32 imm;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg;
- u16 srcval;
- u32 res;
- s16 imm;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- res = (s16)srcval * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
- u32 res_lo,res_hi;
- s32 imm;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg,*srcreg;
- u32 res;
- s16 imm;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- res = (s16)*srcreg * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x6a
-****************************************************************************/
-static void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
-{
- s16 imm;
-
- START_OF_INSTR();
- imm = (s8)fetch_byte_imm();
- DECODE_PRINTF2("PUSH\t%d\n", imm);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long((s32)imm);
- } else {
- push_word(imm);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x6b
-****************************************************************************/
-static void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
- s8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("IMUL\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
- u32 res_lo,res_hi;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg;
- u16 srcval;
- u32 res;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- res = (s16)srcval * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
- u32 res_lo,res_hi;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg;
- u16 srcval;
- u32 res;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- res = (s16)srcval * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
- u32 res_lo,res_hi;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg;
- u16 srcval;
- u32 res;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- res = (s16)srcval * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
- u32 res_lo,res_hi;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- TRACE_AND_STEP();
- imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
- if (res_hi != 0) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u32)res_lo;
- } else {
- u16 *destreg,*srcreg;
- u32 res;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%d\n", (s32)imm);
- res = (s16)*srcreg * (s16)imm;
- if (res > 0xFFFF) {
- SET_FLAG(F_CF);
- SET_FLAG(F_OF);
- } else {
- CLEAR_FLAG(F_CF);
- CLEAR_FLAG(F_OF);
- }
- *destreg = (u16)res;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x6c
-****************************************************************************/
-static void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("INSB\n");
- ins(1);
- TRACE_AND_STEP();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x6d
-****************************************************************************/
-static void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INSD\n");
- ins(4);
- } else {
- DECODE_PRINTF("INSW\n");
- ins(2);
- }
- TRACE_AND_STEP();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x6e
-****************************************************************************/
-static void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("OUTSB\n");
- outs(1);
- TRACE_AND_STEP();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x6f
-****************************************************************************/
-static void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("OUTSD\n");
- outs(4);
- } else {
- DECODE_PRINTF("OUTSW\n");
- outs(2);
- }
- TRACE_AND_STEP();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x70
-****************************************************************************/
-static void x86emuOp_jump_near_O(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if overflow flag is set */
- START_OF_INSTR();
- DECODE_PRINTF("JO\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_OF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x71
-****************************************************************************/
-static void x86emuOp_jump_near_NO(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if overflow is not set */
- START_OF_INSTR();
- DECODE_PRINTF("JNO\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (!ACCESS_FLAG(F_OF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x72
-****************************************************************************/
-static void x86emuOp_jump_near_B(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if carry flag is set. */
- START_OF_INSTR();
- DECODE_PRINTF("JB\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_CF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x73
-****************************************************************************/
-static void x86emuOp_jump_near_NB(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if carry flag is clear. */
- START_OF_INSTR();
- DECODE_PRINTF("JNB\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (!ACCESS_FLAG(F_CF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x74
-****************************************************************************/
-static void x86emuOp_jump_near_Z(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if zero flag is set. */
- START_OF_INSTR();
- DECODE_PRINTF("JZ\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_ZF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x75
-****************************************************************************/
-static void x86emuOp_jump_near_NZ(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if zero flag is clear. */
- START_OF_INSTR();
- DECODE_PRINTF("JNZ\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (!ACCESS_FLAG(F_ZF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x76
-****************************************************************************/
-static void x86emuOp_jump_near_BE(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if carry flag is set or if the zero
- flag is set. */
- START_OF_INSTR();
- DECODE_PRINTF("JBE\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x77
-****************************************************************************/
-static void x86emuOp_jump_near_NBE(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if carry flag is clear and if the zero
- flag is clear */
- START_OF_INSTR();
- DECODE_PRINTF("JNBE\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x78
-****************************************************************************/
-static void x86emuOp_jump_near_S(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if sign flag is set */
- START_OF_INSTR();
- DECODE_PRINTF("JS\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_SF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x79
-****************************************************************************/
-static void x86emuOp_jump_near_NS(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if sign flag is clear */
- START_OF_INSTR();
- DECODE_PRINTF("JNS\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (!ACCESS_FLAG(F_SF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x7a
-****************************************************************************/
-static void x86emuOp_jump_near_P(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if parity flag is set (even parity) */
- START_OF_INSTR();
- DECODE_PRINTF("JP\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_PF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x7b
-****************************************************************************/
-static void x86emuOp_jump_near_NP(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
-
- /* jump to byte offset if parity flag is clear (odd parity) */
- START_OF_INSTR();
- DECODE_PRINTF("JNP\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (!ACCESS_FLAG(F_PF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x7c
-****************************************************************************/
-static void x86emuOp_jump_near_L(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
- int sf, of;
-
- /* jump to byte offset if sign flag not equal to overflow flag. */
- START_OF_INSTR();
- DECODE_PRINTF("JL\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- sf = ACCESS_FLAG(F_SF) != 0;
- of = ACCESS_FLAG(F_OF) != 0;
- if (sf ^ of)
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x7d
-****************************************************************************/
-static void x86emuOp_jump_near_NL(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
- int sf, of;
-
- /* jump to byte offset if sign flag not equal to overflow flag. */
- START_OF_INSTR();
- DECODE_PRINTF("JNL\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- sf = ACCESS_FLAG(F_SF) != 0;
- of = ACCESS_FLAG(F_OF) != 0;
- /* note: inverse of above, but using == instead of xor. */
- if (sf == of)
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x7e
-****************************************************************************/
-static void x86emuOp_jump_near_LE(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
- int sf, of;
-
- /* jump to byte offset if sign flag not equal to overflow flag
- or the zero flag is set */
- START_OF_INSTR();
- DECODE_PRINTF("JLE\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- sf = ACCESS_FLAG(F_SF) != 0;
- of = ACCESS_FLAG(F_OF) != 0;
- if ((sf ^ of) || ACCESS_FLAG(F_ZF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x7f
-****************************************************************************/
-static void x86emuOp_jump_near_NLE(u8 X86EMU_UNUSED(op1))
-{
- s8 offset;
- u16 target;
- int sf, of;
-
- /* jump to byte offset if sign flag equal to overflow flag.
- and the zero flag is clear */
- START_OF_INSTR();
- DECODE_PRINTF("JNLE\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + (s16)offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- sf = ACCESS_FLAG(F_SF) != 0;
- of = ACCESS_FLAG(F_OF) != 0;
- if ((sf == of) && !ACCESS_FLAG(F_ZF))
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-static u8 (*opc80_byte_operation[])(u8 d, u8 s) =
-{
- add_byte, /* 00 */
- or_byte, /* 01 */
- adc_byte, /* 02 */
- sbb_byte, /* 03 */
- and_byte, /* 04 */
- sub_byte, /* 05 */
- xor_byte, /* 06 */
- cmp_byte, /* 07 */
-};
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x80
-****************************************************************************/
-static void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg;
- uint destoffset;
- u8 imm;
- u8 destval;
-
- /*
- * Weirdo special case instruction format. Part of the opcode
- * held below in "RH". Doubly nested case would result, except
- * that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
-
- switch (rh) {
- case 0:
- DECODE_PRINTF("ADD\t");
- break;
- case 1:
- DECODE_PRINTF("OR\t");
- break;
- case 2:
- DECODE_PRINTF("ADC\t");
- break;
- case 3:
- DECODE_PRINTF("SBB\t");
- break;
- case 4:
- DECODE_PRINTF("AND\t");
- break;
- case 5:
- DECODE_PRINTF("SUB\t");
- break;
- case 6:
- DECODE_PRINTF("XOR\t");
- break;
- case 7:
- DECODE_PRINTF("CMP\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- switch (mod) {
- case 0:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc80_byte_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_byte(destoffset, destval);
- break;
- case 1:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc80_byte_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_byte(destoffset, destval);
- break;
- case 2:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc80_byte_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc80_byte_operation[rh]) (*destreg, imm);
- if (rh != 7)
- *destreg = destval;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-static u16 (*opc81_word_operation[])(u16 d, u16 s) =
-{
- add_word, /*00 */
- or_word, /*01 */
- adc_word, /*02 */
- sbb_word, /*03 */
- and_word, /*04 */
- sub_word, /*05 */
- xor_word, /*06 */
- cmp_word, /*07 */
-};
-
-static u32 (*opc81_long_operation[])(u32 d, u32 s) =
-{
- add_long, /*00 */
- or_long, /*01 */
- adc_long, /*02 */
- sbb_long, /*03 */
- and_long, /*04 */
- sub_long, /*05 */
- xor_long, /*06 */
- cmp_long, /*07 */
-};
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x81
-****************************************************************************/
-static void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- /*
- * Weirdo special case instruction format. Part of the opcode
- * held below in "RH". Doubly nested case would result, except
- * that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
-
- switch (rh) {
- case 0:
- DECODE_PRINTF("ADD\t");
- break;
- case 1:
- DECODE_PRINTF("OR\t");
- break;
- case 2:
- DECODE_PRINTF("ADC\t");
- break;
- case 3:
- DECODE_PRINTF("SBB\t");
- break;
- case 4:
- DECODE_PRINTF("AND\t");
- break;
- case 5:
- DECODE_PRINTF("SUB\t");
- break;
- case 6:
- DECODE_PRINTF("XOR\t");
- break;
- case 7:
- DECODE_PRINTF("CMP\t");
- break;
- }
- }
-#endif
- /*
- * Know operation, decode the mod byte to find the addressing
- * mode.
- */
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- imm = fetch_long_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_long_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_long(destoffset, destval);
- } else {
- u16 destval,imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- imm = fetch_word_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_word_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- imm = fetch_long_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_long_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_long(destoffset, destval);
- } else {
- u16 destval,imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- imm = fetch_word_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_word_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- imm = fetch_long_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_long_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_long(destoffset, destval);
- } else {
- u16 destval,imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- imm = fetch_word_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_word_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 destval,imm;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- imm = fetch_long_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_long_operation[rh]) (*destreg, imm);
- if (rh != 7)
- *destreg = destval;
- } else {
- u16 *destreg;
- u16 destval,imm;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- imm = fetch_word_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc81_word_operation[rh]) (*destreg, imm);
- if (rh != 7)
- *destreg = destval;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-static u8 (*opc82_byte_operation[])(u8 s, u8 d) =
-{
- add_byte, /*00 */
- or_byte, /*01 *//*YYY UNUSED ???? */
- adc_byte, /*02 */
- sbb_byte, /*03 */
- and_byte, /*04 *//*YYY UNUSED ???? */
- sub_byte, /*05 */
- xor_byte, /*06 *//*YYY UNUSED ???? */
- cmp_byte, /*07 */
-};
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x82
-****************************************************************************/
-static void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg;
- uint destoffset;
- u8 imm;
- u8 destval;
-
- /*
- * Weirdo special case instruction format. Part of the opcode
- * held below in "RH". Doubly nested case would result, except
- * that the decoded instruction Similar to opcode 81, except that
- * the immediate byte is sign extended to a word length.
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
- switch (rh) {
- case 0:
- DECODE_PRINTF("ADD\t");
- break;
- case 1:
- DECODE_PRINTF("OR\t");
- break;
- case 2:
- DECODE_PRINTF("ADC\t");
- break;
- case 3:
- DECODE_PRINTF("SBB\t");
- break;
- case 4:
- DECODE_PRINTF("AND\t");
- break;
- case 5:
- DECODE_PRINTF("SUB\t");
- break;
- case 6:
- DECODE_PRINTF("XOR\t");
- break;
- case 7:
- DECODE_PRINTF("CMP\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- switch (mod) {
- case 0:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm00_address(rl);
- destval = fetch_data_byte(destoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc82_byte_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_byte(destoffset, destval);
- break;
- case 1:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm01_address(rl);
- destval = fetch_data_byte(destoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc82_byte_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_byte(destoffset, destval);
- break;
- case 2:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- destval = fetch_data_byte(destoffset);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc82_byte_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc82_byte_operation[rh]) (*destreg, imm);
- if (rh != 7)
- *destreg = destval;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-static u16 (*opc83_word_operation[])(u16 s, u16 d) =
-{
- add_word, /*00 */
- or_word, /*01 *//*YYY UNUSED ???? */
- adc_word, /*02 */
- sbb_word, /*03 */
- and_word, /*04 *//*YYY UNUSED ???? */
- sub_word, /*05 */
- xor_word, /*06 *//*YYY UNUSED ???? */
- cmp_word, /*07 */
-};
-
-static u32 (*opc83_long_operation[])(u32 s, u32 d) =
-{
- add_long, /*00 */
- or_long, /*01 *//*YYY UNUSED ???? */
- adc_long, /*02 */
- sbb_long, /*03 */
- and_long, /*04 *//*YYY UNUSED ???? */
- sub_long, /*05 */
- xor_long, /*06 *//*YYY UNUSED ???? */
- cmp_long, /*07 */
-};
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x83
-****************************************************************************/
-static void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- /*
- * Weirdo special case instruction format. Part of the opcode
- * held below in "RH". Doubly nested case would result, except
- * that the decoded instruction Similar to opcode 81, except that
- * the immediate byte is sign extended to a word length.
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
- switch (rh) {
- case 0:
- DECODE_PRINTF("ADD\t");
- break;
- case 1:
- DECODE_PRINTF("OR\t");
- break;
- case 2:
- DECODE_PRINTF("ADC\t");
- break;
- case 3:
- DECODE_PRINTF("SBB\t");
- break;
- case 4:
- DECODE_PRINTF("AND\t");
- break;
- case 5:
- DECODE_PRINTF("SUB\t");
- break;
- case 6:
- DECODE_PRINTF("XOR\t");
- break;
- case 7:
- DECODE_PRINTF("CMP\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm00_address(rl);
- destval = fetch_data_long(destoffset);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_long_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_long(destoffset, destval);
- } else {
- u16 destval,imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm00_address(rl);
- destval = fetch_data_word(destoffset);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_word_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm01_address(rl);
- destval = fetch_data_long(destoffset);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_long_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_long(destoffset, destval);
- } else {
- u16 destval,imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm01_address(rl);
- destval = fetch_data_word(destoffset);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_word_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm10_address(rl);
- destval = fetch_data_long(destoffset);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_long_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_long(destoffset, destval);
- } else {
- u16 destval,imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm10_address(rl);
- destval = fetch_data_word(destoffset);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_word_operation[rh]) (destval, imm);
- if (rh != 7)
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 destval,imm;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_long_operation[rh]) (*destreg, imm);
- if (rh != 7)
- *destreg = destval;
- } else {
- u16 *destreg;
- u16 destval,imm;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- imm = (s8) fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- destval = (*opc83_word_operation[rh]) (*destreg, imm);
- if (rh != 7)
- *destreg = destval;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x84
-****************************************************************************/
-static void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("TEST\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_byte(destval, *srcreg);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_byte(destval, *srcreg);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_byte(destval, *srcreg);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_byte(*destreg, *srcreg);
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x85
-****************************************************************************/
-static void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("TEST\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_long(destval, *srcreg);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_word(destval, *srcreg);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_long(destval, *srcreg);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_word(destval, *srcreg);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_long(destval, *srcreg);
- } else {
- u16 destval;
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_word(destval, *srcreg);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_long(*destreg, *srcreg);
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- test_word(*destreg, *srcreg);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x86
-****************************************************************************/
-static void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
- u8 destval;
- u8 tmp;
-
- START_OF_INSTR();
- DECODE_PRINTF("XCHG\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_byte(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_byte(destoffset);
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = *destreg;
- *destreg = tmp;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x87
-****************************************************************************/
-static void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("XCHG\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *srcreg;
- u32 destval,tmp;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_long(destoffset, destval);
- } else {
- u16 *srcreg;
- u16 destval,tmp;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *srcreg;
- u32 destval,tmp;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_long(destoffset, destval);
- } else {
- u16 *srcreg;
- u16 destval,tmp;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *srcreg;
- u32 destval,tmp;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_long(destoffset);
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_long(destoffset, destval);
- } else {
- u16 *srcreg;
- u16 destval,tmp;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- destval = fetch_data_word(destoffset);
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = destval;
- destval = tmp;
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
- u32 tmp;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = *destreg;
- *destreg = tmp;
- } else {
- u16 *destreg,*srcreg;
- u16 tmp;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- tmp = *srcreg;
- *srcreg = *destreg;
- *destreg = tmp;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x88
-****************************************************************************/
-static void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_byte(destoffset, *srcreg);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_byte(destoffset, *srcreg);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_byte(destoffset, *srcreg);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x89
-****************************************************************************/
-static void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u32 destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_long(destoffset, *srcreg);
- } else {
- u16 *srcreg;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_word(destoffset, *srcreg);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_long(destoffset, *srcreg);
- } else {
- u16 *srcreg;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_word(destoffset, *srcreg);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_long(destoffset, *srcreg);
- } else {
- u16 *srcreg;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- store_data_word(destoffset, *srcreg);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg,*srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- } else {
- u16 *destreg,*srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x8a
-****************************************************************************/
-static void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg, *srcreg;
- uint srcoffset;
- u8 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- break;
- case 1:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- break;
- case 2:
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_byte(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x8b
-****************************************************************************/
-static void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_long(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- } else {
- u16 *destreg;
- u16 srcval;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg, *srcreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- } else {
- u16 *destreg, *srcreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x8c
-****************************************************************************/
-static void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u16 *destreg, *srcreg;
- uint destoffset;
- u16 destval;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- srcreg = decode_rm_seg_register(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = *srcreg;
- store_data_word(destoffset, destval);
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- srcreg = decode_rm_seg_register(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = *srcreg;
- store_data_word(destoffset, destval);
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- srcreg = decode_rm_seg_register(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = *srcreg;
- store_data_word(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcreg = decode_rm_seg_register(rh);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x8d
-****************************************************************************/
-static void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u16 *srcreg;
- uint destoffset;
-
-/*
- * TODO: Need to handle address size prefix!
- *
- * lea eax,[eax+ebx*2] ??
- */
-
- START_OF_INSTR();
- DECODE_PRINTF("LEA\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *srcreg = (u16)destoffset;
- break;
- case 1:
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *srcreg = (u16)destoffset;
- break;
- case 2:
- srcreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *srcreg = (u16)destoffset;
- break;
- case 3: /* register to register */
- /* undefined. Do nothing. */
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x8e
-****************************************************************************/
-static void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u16 *destreg, *srcreg;
- uint srcoffset;
- u16 srcval;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- destreg = decode_rm_seg_register(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- break;
- case 1:
- destreg = decode_rm_seg_register(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- break;
- case 2:
- destreg = decode_rm_seg_register(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- srcval = fetch_data_word(srcoffset);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = srcval;
- break;
- case 3: /* register to register */
- destreg = decode_rm_seg_register(rh);
- DECODE_PRINTF(",");
- srcreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = *srcreg;
- break;
- }
- /*
- * Clean up, and reset all the R_xSP pointers to the correct
- * locations. This is about 3x too much overhead (doing all the
- * segreg ptrs when only one is needed, but this instruction
- * *cannot* be that common, and this isn't too much work anyway.
- */
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x8f
-****************************************************************************/
-static void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("POP\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- if (rh != 0) {
- DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
- HALT_SYS();
- }
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = pop_long();
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = pop_word();
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = pop_long();
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = pop_word();
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = pop_long();
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- destval = pop_word();
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = pop_long();
- } else {
- u16 *destreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = pop_word();
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x90
-****************************************************************************/
-static void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("NOP\n");
- TRACE_AND_STEP();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x91
-****************************************************************************/
-static void x86emuOp_xchg_word_AX_CX(u8 X86EMU_UNUSED(op1))
-{
- u32 tmp;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XCHG\tEAX,ECX\n");
- } else {
- DECODE_PRINTF("XCHG\tAX,CX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- tmp = M.x86.R_EAX;
- M.x86.R_EAX = M.x86.R_ECX;
- M.x86.R_ECX = tmp;
- } else {
- tmp = M.x86.R_AX;
- M.x86.R_AX = M.x86.R_CX;
- M.x86.R_CX = (u16)tmp;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x92
-****************************************************************************/
-static void x86emuOp_xchg_word_AX_DX(u8 X86EMU_UNUSED(op1))
-{
- u32 tmp;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XCHG\tEAX,EDX\n");
- } else {
- DECODE_PRINTF("XCHG\tAX,DX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- tmp = M.x86.R_EAX;
- M.x86.R_EAX = M.x86.R_EDX;
- M.x86.R_EDX = tmp;
- } else {
- tmp = M.x86.R_AX;
- M.x86.R_AX = M.x86.R_DX;
- M.x86.R_DX = (u16)tmp;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x93
-****************************************************************************/
-static void x86emuOp_xchg_word_AX_BX(u8 X86EMU_UNUSED(op1))
-{
- u32 tmp;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XCHG\tEAX,EBX\n");
- } else {
- DECODE_PRINTF("XCHG\tAX,BX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- tmp = M.x86.R_EAX;
- M.x86.R_EAX = M.x86.R_EBX;
- M.x86.R_EBX = tmp;
- } else {
- tmp = M.x86.R_AX;
- M.x86.R_AX = M.x86.R_BX;
- M.x86.R_BX = (u16)tmp;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x94
-****************************************************************************/
-static void x86emuOp_xchg_word_AX_SP(u8 X86EMU_UNUSED(op1))
-{
- u32 tmp;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XCHG\tEAX,ESP\n");
- } else {
- DECODE_PRINTF("XCHG\tAX,SP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- tmp = M.x86.R_EAX;
- M.x86.R_EAX = M.x86.R_ESP;
- M.x86.R_ESP = tmp;
- } else {
- tmp = M.x86.R_AX;
- M.x86.R_AX = M.x86.R_SP;
- M.x86.R_SP = (u16)tmp;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x95
-****************************************************************************/
-static void x86emuOp_xchg_word_AX_BP(u8 X86EMU_UNUSED(op1))
-{
- u32 tmp;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XCHG\tEAX,EBP\n");
- } else {
- DECODE_PRINTF("XCHG\tAX,BP\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- tmp = M.x86.R_EAX;
- M.x86.R_EAX = M.x86.R_EBP;
- M.x86.R_EBP = tmp;
- } else {
- tmp = M.x86.R_AX;
- M.x86.R_AX = M.x86.R_BP;
- M.x86.R_BP = (u16)tmp;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x96
-****************************************************************************/
-static void x86emuOp_xchg_word_AX_SI(u8 X86EMU_UNUSED(op1))
-{
- u32 tmp;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XCHG\tEAX,ESI\n");
- } else {
- DECODE_PRINTF("XCHG\tAX,SI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- tmp = M.x86.R_EAX;
- M.x86.R_EAX = M.x86.R_ESI;
- M.x86.R_ESI = tmp;
- } else {
- tmp = M.x86.R_AX;
- M.x86.R_AX = M.x86.R_SI;
- M.x86.R_SI = (u16)tmp;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x97
-****************************************************************************/
-static void x86emuOp_xchg_word_AX_DI(u8 X86EMU_UNUSED(op1))
-{
- u32 tmp;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("XCHG\tEAX,EDI\n");
- } else {
- DECODE_PRINTF("XCHG\tAX,DI\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- tmp = M.x86.R_EAX;
- M.x86.R_EAX = M.x86.R_EDI;
- M.x86.R_EDI = tmp;
- } else {
- tmp = M.x86.R_AX;
- M.x86.R_AX = M.x86.R_DI;
- M.x86.R_DI = (u16)tmp;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x98
-****************************************************************************/
-static void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("CWDE\n");
- } else {
- DECODE_PRINTF("CBW\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- if (M.x86.R_AX & 0x8000) {
- M.x86.R_EAX |= 0xffff0000;
- } else {
- M.x86.R_EAX &= 0x0000ffff;
- }
- } else {
- if (M.x86.R_AL & 0x80) {
- M.x86.R_AH = 0xff;
- } else {
- M.x86.R_AH = 0x0;
- }
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x99
-****************************************************************************/
-static void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("CDQ\n");
- } else {
- DECODE_PRINTF("CWD\n");
- }
- DECODE_PRINTF("CWD\n");
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- if (M.x86.R_EAX & 0x80000000) {
- M.x86.R_EDX = 0xffffffff;
- } else {
- M.x86.R_EDX = 0x0;
- }
- } else {
- if (M.x86.R_AX & 0x8000) {
- M.x86.R_DX = 0xffff;
- } else {
- M.x86.R_DX = 0x0;
- }
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x9a
-****************************************************************************/
-static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 farseg, faroff;
-
- START_OF_INSTR();
- DECODE_PRINTF("CALL\t");
- faroff = fetch_word_imm();
- farseg = fetch_word_imm();
- DECODE_PRINTF2("%04x:", farseg);
- DECODE_PRINTF2("%04x\n", faroff);
- CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
-
- /* XXX
- *
- * Hooked interrupt vectors calling into our "BIOS" will cause
- * problems unless all intersegment stuff is checked for BIOS
- * access. Check needed here. For moment, let it alone.
- */
- TRACE_AND_STEP();
- push_word(M.x86.R_CS);
- M.x86.R_CS = farseg;
- push_word(M.x86.R_IP);
- M.x86.R_IP = faroff;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x9b
-****************************************************************************/
-static void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("WAIT");
- TRACE_AND_STEP();
- /* NADA. */
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x9c
-****************************************************************************/
-static void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
-{
- u32 flags;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("PUSHFD\n");
- } else {
- DECODE_PRINTF("PUSHF\n");
- }
- TRACE_AND_STEP();
-
- /* clear out *all* bits not representing flags, and turn on real bits */
- flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- push_long(flags);
- } else {
- push_word((u16)flags);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x9d
-****************************************************************************/
-static void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("POPFD\n");
- } else {
- DECODE_PRINTF("POPF\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EFLG = pop_long();
- } else {
- M.x86.R_FLG = pop_word();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x9e
-****************************************************************************/
-static void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("SAHF\n");
- TRACE_AND_STEP();
- /* clear the lower bits of the flag register */
- M.x86.R_FLG &= 0xffffff00;
- /* or in the AH register into the flags register */
- M.x86.R_FLG |= M.x86.R_AH;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0x9f
-****************************************************************************/
-static void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("LAHF\n");
- TRACE_AND_STEP();
- M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
- /*undocumented TC++ behavior??? Nope. It's documented, but
- you have too look real hard to notice it. */
- M.x86.R_AH |= 0x2;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa0
-****************************************************************************/
-static void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 offset;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tAL,");
- offset = fetch_word_imm();
- DECODE_PRINTF2("[%04x]\n", offset);
- TRACE_AND_STEP();
- M.x86.R_AL = fetch_data_byte(offset);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa1
-****************************************************************************/
-static void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 offset;
-
- START_OF_INSTR();
- offset = fetch_word_imm();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
- } else {
- DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = fetch_data_long(offset);
- } else {
- M.x86.R_AX = fetch_data_word(offset);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa2
-****************************************************************************/
-static void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 offset;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- offset = fetch_word_imm();
- DECODE_PRINTF2("[%04x],AL\n", offset);
- TRACE_AND_STEP();
- store_data_byte(offset, M.x86.R_AL);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa3
-****************************************************************************/
-static void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 offset;
-
- START_OF_INSTR();
- offset = fetch_word_imm();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
- } else {
- DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- store_data_long(offset, M.x86.R_EAX);
- } else {
- store_data_word(offset, M.x86.R_AX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa4
-****************************************************************************/
-static void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
-{
- u8 val;
- u32 count;
- int inc;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOVS\tBYTE\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -1;
- else
- inc = 1;
- TRACE_AND_STEP();
- count = 1;
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
- M.x86.R_CX = 0;
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- }
- while (count--) {
- val = fetch_data_byte(M.x86.R_SI);
- store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa5
-****************************************************************************/
-static void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
-{
- u32 val;
- int inc;
- u32 count;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOVS\tDWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -4;
- else
- inc = 4;
- } else {
- DECODE_PRINTF("MOVS\tWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -2;
- else
- inc = 2;
- }
- TRACE_AND_STEP();
- count = 1;
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
- M.x86.R_CX = 0;
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- }
- while (count--) {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- val = fetch_data_long(M.x86.R_SI);
- store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
- } else {
- val = fetch_data_word(M.x86.R_SI);
- store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
- }
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa6
-****************************************************************************/
-static void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
-{
- s8 val1, val2;
- int inc;
-
- START_OF_INSTR();
- DECODE_PRINTF("CMPS\tBYTE\n");
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -1;
- else
- inc = 1;
-
- if (M.x86.mode & SYSMODE_PREFIX_REPE) {
- /* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- val1 = fetch_data_byte(M.x86.R_SI);
- val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_byte(val1, val2);
- M.x86.R_CX -= 1;
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF) == 0)
- break;
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPE;
- } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
- /* REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- val1 = fetch_data_byte(M.x86.R_SI);
- val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_byte(val1, val2);
- M.x86.R_CX -= 1;
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF))
- break; /* zero flag set means equal */
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
- } else {
- val1 = fetch_data_byte(M.x86.R_SI);
- val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_byte(val1, val2);
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa7
-****************************************************************************/
-static void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
-{
- u32 val1,val2;
- int inc;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("CMPS\tDWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -4;
- else
- inc = 4;
- } else {
- DECODE_PRINTF("CMPS\tWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -2;
- else
- inc = 2;
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_REPE) {
- /* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- val1 = fetch_data_long(M.x86.R_SI);
- val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_long(val1, val2);
- } else {
- val1 = fetch_data_word(M.x86.R_SI);
- val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_word((u16)val1, (u16)val2);
- }
- M.x86.R_CX -= 1;
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF) == 0)
- break;
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPE;
- } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
- /* REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- val1 = fetch_data_long(M.x86.R_SI);
- val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_long(val1, val2);
- } else {
- val1 = fetch_data_word(M.x86.R_SI);
- val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_word((u16)val1, (u16)val2);
- }
- M.x86.R_CX -= 1;
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF))
- break; /* zero flag set means equal */
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
- } else {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- val1 = fetch_data_long(M.x86.R_SI);
- val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_long(val1, val2);
- } else {
- val1 = fetch_data_word(M.x86.R_SI);
- val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_word((u16)val1, (u16)val2);
- }
- M.x86.R_SI += inc;
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa8
-****************************************************************************/
-static void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- int imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("TEST\tAL,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%04x\n", imm);
- TRACE_AND_STEP();
- test_byte(M.x86.R_AL, (u8)imm);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xa9
-****************************************************************************/
-static void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("TEST\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("TEST\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- test_long(M.x86.R_EAX, srcval);
- } else {
- test_word(M.x86.R_AX, (u16)srcval);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xaa
-****************************************************************************/
-static void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
-{
- int inc;
-
- START_OF_INSTR();
- DECODE_PRINTF("STOS\tBYTE\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -1;
- else
- inc = 1;
- TRACE_AND_STEP();
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
- M.x86.R_CX -= 1;
- M.x86.R_DI += inc;
- }
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- } else {
- store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xab
-****************************************************************************/
-static void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
-{
- int inc;
- u32 count;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("STOS\tDWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -4;
- else
- inc = 4;
- } else {
- DECODE_PRINTF("STOS\tWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -2;
- else
- inc = 2;
- }
- TRACE_AND_STEP();
- count = 1;
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
- M.x86.R_CX = 0;
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- }
- while (count--) {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
- } else {
- store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
- }
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xac
-****************************************************************************/
-static void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
-{
- int inc;
-
- START_OF_INSTR();
- DECODE_PRINTF("LODS\tBYTE\n");
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -1;
- else
- inc = 1;
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
- M.x86.R_CX -= 1;
- M.x86.R_SI += inc;
- }
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- } else {
- M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
- M.x86.R_SI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xad
-****************************************************************************/
-static void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
-{
- int inc;
- u32 count;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("LODS\tDWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -4;
- else
- inc = 4;
- } else {
- DECODE_PRINTF("LODS\tWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -2;
- else
- inc = 2;
- }
- TRACE_AND_STEP();
- count = 1;
- if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
- /* dont care whether REPE or REPNE */
- /* move them until CX is ZERO. */
- count = M.x86.R_CX;
- M.x86.R_CX = 0;
- M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
- }
- while (count--) {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
- } else {
- M.x86.R_AX = fetch_data_word(M.x86.R_SI);
- }
- M.x86.R_SI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xae
-****************************************************************************/
-static void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
-{
- s8 val2;
- int inc;
-
- START_OF_INSTR();
- DECODE_PRINTF("SCAS\tBYTE\n");
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -1;
- else
- inc = 1;
- if (M.x86.mode & SYSMODE_PREFIX_REPE) {
- /* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_byte(M.x86.R_AL, val2);
- M.x86.R_CX -= 1;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF) == 0)
- break;
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPE;
- } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
- /* REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_byte(M.x86.R_AL, val2);
- M.x86.R_CX -= 1;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF))
- break; /* zero flag set means equal */
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
- } else {
- val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_byte(M.x86.R_AL, val2);
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xaf
-****************************************************************************/
-static void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
-{
- int inc;
- u32 val;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("SCAS\tDWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -4;
- else
- inc = 4;
- } else {
- DECODE_PRINTF("SCAS\tWORD\n");
- if (ACCESS_FLAG(F_DF)) /* down */
- inc = -2;
- else
- inc = 2;
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_REPE) {
- /* REPE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_long(M.x86.R_EAX, val);
- } else {
- val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_word(M.x86.R_AX, (u16)val);
- }
- M.x86.R_CX -= 1;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF) == 0)
- break;
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPE;
- } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
- /* REPNE */
- /* move them until CX is ZERO. */
- while (M.x86.R_CX != 0) {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_long(M.x86.R_EAX, val);
- } else {
- val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_word(M.x86.R_AX, (u16)val);
- }
- M.x86.R_CX -= 1;
- M.x86.R_DI += inc;
- if (ACCESS_FLAG(F_ZF))
- break; /* zero flag set means equal */
- }
- M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
- } else {
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_long(M.x86.R_EAX, val);
- } else {
- val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
- cmp_word(M.x86.R_AX, (u16)val);
- }
- M.x86.R_DI += inc;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb0
-****************************************************************************/
-static void x86emuOp_mov_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tAL,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_AL = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb1
-****************************************************************************/
-static void x86emuOp_mov_byte_CL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tCL,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_CL = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb2
-****************************************************************************/
-static void x86emuOp_mov_byte_DL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tDL,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_DL = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb3
-****************************************************************************/
-static void x86emuOp_mov_byte_BL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tBL,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_BL = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb4
-****************************************************************************/
-static void x86emuOp_mov_byte_AH_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tAH,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_AH = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb5
-****************************************************************************/
-static void x86emuOp_mov_byte_CH_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tCH,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_CH = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb6
-****************************************************************************/
-static void x86emuOp_mov_byte_DH_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tDH,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_DH = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb7
-****************************************************************************/
-static void x86emuOp_mov_byte_BH_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\tBH,");
- imm = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", imm);
- TRACE_AND_STEP();
- M.x86.R_BH = imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb8
-****************************************************************************/
-static void x86emuOp_mov_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tEAX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tAX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = srcval;
- } else {
- M.x86.R_AX = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xb9
-****************************************************************************/
-static void x86emuOp_mov_word_CX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tECX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tCX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ECX = srcval;
- } else {
- M.x86.R_CX = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xba
-****************************************************************************/
-static void x86emuOp_mov_word_DX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tEDX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tDX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDX = srcval;
- } else {
- M.x86.R_DX = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xbb
-****************************************************************************/
-static void x86emuOp_mov_word_BX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tEBX,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tBX,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBX = srcval;
- } else {
- M.x86.R_BX = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xbc
-****************************************************************************/
-static void x86emuOp_mov_word_SP_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tESP,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tSP,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESP = srcval;
- } else {
- M.x86.R_SP = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xbd
-****************************************************************************/
-static void x86emuOp_mov_word_BP_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tEBP,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tBP,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EBP = srcval;
- } else {
- M.x86.R_BP = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xbe
-****************************************************************************/
-static void x86emuOp_mov_word_SI_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tESI,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tSI,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_ESI = srcval;
- } else {
- M.x86.R_SI = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xbf
-****************************************************************************/
-static void x86emuOp_mov_word_DI_IMM(u8 X86EMU_UNUSED(op1))
-{
- u32 srcval;
-
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("MOV\tEDI,");
- srcval = fetch_long_imm();
- } else {
- DECODE_PRINTF("MOV\tDI,");
- srcval = fetch_word_imm();
- }
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EDI = srcval;
- } else {
- M.x86.R_DI = (u16)srcval;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/* used by opcodes c0, d0, and d2. */
-static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
-{
- rol_byte,
- ror_byte,
- rcl_byte,
- rcr_byte,
- shl_byte,
- shr_byte,
- shl_byte, /* sal_byte === shl_byte by definition */
- sar_byte,
-};
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc0
-****************************************************************************/
-static void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg;
- uint destoffset;
- u8 destval;
- u8 amt;
-
- /*
- * Yet another weirdo special case instruction format. Part of
- * the opcode held below in "RH". Doubly nested case would
- * result, except that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
-
- switch (rh) {
- case 0:
- DECODE_PRINTF("ROL\t");
- break;
- case 1:
- DECODE_PRINTF("ROR\t");
- break;
- case 2:
- DECODE_PRINTF("RCL\t");
- break;
- case 3:
- DECODE_PRINTF("RCR\t");
- break;
- case 4:
- DECODE_PRINTF("SHL\t");
- break;
- case 5:
- DECODE_PRINTF("SHR\t");
- break;
- case 6:
- DECODE_PRINTF("SAL\t");
- break;
- case 7:
- DECODE_PRINTF("SAR\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- switch (mod) {
- case 0:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm00_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, amt);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm01_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, amt);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, amt);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
- *destreg = destval;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/* used by opcodes c1, d1, and d3. */
-static u16(*opcD1_word_operation[])(u16 s, u8 d) =
-{
- rol_word,
- ror_word,
- rcl_word,
- rcr_word,
- shl_word,
- shr_word,
- shl_word, /* sal_byte === shl_byte by definition */
- sar_word,
-};
-
-/* used by opcodes c1, d1, and d3. */
-static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
-{
- rol_long,
- ror_long,
- rcl_long,
- rcr_long,
- shl_long,
- shr_long,
- shl_long, /* sal_byte === shl_byte by definition */
- sar_long,
-};
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc1
-****************************************************************************/
-static void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
- u8 amt;
-
- /*
- * Yet another weirdo special case instruction format. Part of
- * the opcode held below in "RH". Doubly nested case would
- * result, except that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
-
- switch (rh) {
- case 0:
- DECODE_PRINTF("ROL\t");
- break;
- case 1:
- DECODE_PRINTF("ROR\t");
- break;
- case 2:
- DECODE_PRINTF("RCL\t");
- break;
- case 3:
- DECODE_PRINTF("RCR\t");
- break;
- case 4:
- DECODE_PRINTF("SHL\t");
- break;
- case 5:
- DECODE_PRINTF("SHR\t");
- break;
- case 6:
- DECODE_PRINTF("SAL\t");
- break;
- case 7:
- DECODE_PRINTF("SAR\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm00_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, amt);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm00_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, amt);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm01_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, amt);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm01_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, amt);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm10_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, amt);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm10_address(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, amt);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- TRACE_AND_STEP();
- *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
- } else {
- u16 *destreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- amt = fetch_byte_imm();
- DECODE_PRINTF2(",%x\n", amt);
- TRACE_AND_STEP();
- *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc2
-****************************************************************************/
-static void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("RET\t");
- imm = fetch_word_imm();
- DECODE_PRINTF2("%x\n", imm);
- RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
- TRACE_AND_STEP();
- M.x86.R_IP = pop_word();
- M.x86.R_SP += imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc3
-****************************************************************************/
-static void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("RET\n");
- RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
- TRACE_AND_STEP();
- M.x86.R_IP = pop_word();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc4
-****************************************************************************/
-static void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rh, rl;
- u16 *dstreg;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("LES\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- dstreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *dstreg = fetch_data_word(srcoffset);
- M.x86.R_ES = fetch_data_word(srcoffset + 2);
- break;
- case 1:
- dstreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *dstreg = fetch_data_word(srcoffset);
- M.x86.R_ES = fetch_data_word(srcoffset + 2);
- break;
- case 2:
- dstreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *dstreg = fetch_data_word(srcoffset);
- M.x86.R_ES = fetch_data_word(srcoffset + 2);
- break;
- case 3: /* register to register */
- /* UNDEFINED! */
- TRACE_AND_STEP();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc5
-****************************************************************************/
-static void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rh, rl;
- u16 *dstreg;
- uint srcoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("LDS\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0:
- dstreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *dstreg = fetch_data_word(srcoffset);
- M.x86.R_DS = fetch_data_word(srcoffset + 2);
- break;
- case 1:
- dstreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *dstreg = fetch_data_word(srcoffset);
- M.x86.R_DS = fetch_data_word(srcoffset + 2);
- break;
- case 2:
- dstreg = DECODE_RM_WORD_REGISTER(rh);
- DECODE_PRINTF(",");
- srcoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *dstreg = fetch_data_word(srcoffset);
- M.x86.R_DS = fetch_data_word(srcoffset + 2);
- break;
- case 3: /* register to register */
- /* UNDEFINED! */
- TRACE_AND_STEP();
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc6
-****************************************************************************/
-static void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg;
- uint destoffset;
- u8 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- if (rh != 0) {
- DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
- HALT_SYS();
- }
- switch (mod) {
- case 0:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm00_address(rl);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%2x\n", imm);
- TRACE_AND_STEP();
- store_data_byte(destoffset, imm);
- break;
- case 1:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm01_address(rl);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%2x\n", imm);
- TRACE_AND_STEP();
- store_data_byte(destoffset, imm);
- break;
- case 2:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%2x\n", imm);
- TRACE_AND_STEP();
- store_data_byte(destoffset, imm);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- imm = fetch_byte_imm();
- DECODE_PRINTF2(",%2x\n", imm);
- TRACE_AND_STEP();
- *destreg = imm;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc7
-****************************************************************************/
-static void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- START_OF_INSTR();
- DECODE_PRINTF("MOV\t");
- FETCH_DECODE_MODRM(mod, rh, rl);
- if (rh != 0) {
- DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
- HALT_SYS();
- }
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm00_address(rl);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- store_data_long(destoffset, imm);
- } else {
- u16 imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm00_address(rl);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- store_data_word(destoffset, imm);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm01_address(rl);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- store_data_long(destoffset, imm);
- } else {
- u16 imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm01_address(rl);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- store_data_word(destoffset, imm);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 imm;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm10_address(rl);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- store_data_long(destoffset, imm);
- } else {
- u16 imm;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm10_address(rl);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- store_data_word(destoffset, imm);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 imm;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- imm = fetch_long_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- *destreg = imm;
- } else {
- u16 *destreg;
- u16 imm;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- imm = fetch_word_imm();
- DECODE_PRINTF2(",%x\n", imm);
- TRACE_AND_STEP();
- *destreg = imm;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc8
-****************************************************************************/
-static void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
-{
- u16 local,frame_pointer;
- u8 nesting;
- int i;
-
- START_OF_INSTR();
- local = fetch_word_imm();
- nesting = fetch_byte_imm();
- DECODE_PRINTF2("ENTER %x\n", local);
- DECODE_PRINTF2(",%x\n", nesting);
- TRACE_AND_STEP();
- push_word(M.x86.R_BP);
- frame_pointer = M.x86.R_SP;
- if (nesting > 0) {
- for (i = 1; i < nesting; i++) {
- M.x86.R_BP -= 2;
- push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
- }
- push_word(frame_pointer);
- }
- M.x86.R_BP = frame_pointer;
- M.x86.R_SP = (u16)(M.x86.R_SP - local);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xc9
-****************************************************************************/
-static void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("LEAVE\n");
- TRACE_AND_STEP();
- M.x86.R_SP = M.x86.R_BP;
- M.x86.R_BP = pop_word();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xca
-****************************************************************************/
-static void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 imm;
-
- START_OF_INSTR();
- DECODE_PRINTF("RETF\t");
- imm = fetch_word_imm();
- DECODE_PRINTF2("%x\n", imm);
- RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
- TRACE_AND_STEP();
- M.x86.R_IP = pop_word();
- M.x86.R_CS = pop_word();
- M.x86.R_SP += imm;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xcb
-****************************************************************************/
-static void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("RETF\n");
- RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
- TRACE_AND_STEP();
- M.x86.R_IP = pop_word();
- M.x86.R_CS = pop_word();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xcc
-****************************************************************************/
-static void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("INT 3\n");
- TRACE_AND_STEP();
- if (_X86EMU_intrTab[3]) {
- (*_X86EMU_intrTab[3])(3);
- } else {
- push_word((u16)M.x86.R_FLG);
- CLEAR_FLAG(F_IF);
- CLEAR_FLAG(F_TF);
- push_word(M.x86.R_CS);
- M.x86.R_CS = mem_access_word(3 * 4 + 2);
- push_word(M.x86.R_IP);
- M.x86.R_IP = mem_access_word(3 * 4);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xcd
-****************************************************************************/
-static void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 intnum;
-
- START_OF_INSTR();
- DECODE_PRINTF("INT\t");
- intnum = fetch_byte_imm();
- DECODE_PRINTF2("%x\n", intnum);
- TRACE_AND_STEP();
- if (_X86EMU_intrTab[intnum]) {
- (*_X86EMU_intrTab[intnum])(intnum);
- } else {
- push_word((u16)M.x86.R_FLG);
- CLEAR_FLAG(F_IF);
- CLEAR_FLAG(F_TF);
- push_word(M.x86.R_CS);
- M.x86.R_CS = mem_access_word(intnum * 4 + 2);
- push_word(M.x86.R_IP);
- M.x86.R_IP = mem_access_word(intnum * 4);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xce
-****************************************************************************/
-static void x86emuOp_into(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("INTO\n");
- TRACE_AND_STEP();
- if (ACCESS_FLAG(F_OF)) {
- if (_X86EMU_intrTab[4]) {
- (*_X86EMU_intrTab[4])(4);
- } else {
- push_word((u16)M.x86.R_FLG);
- CLEAR_FLAG(F_IF);
- CLEAR_FLAG(F_TF);
- push_word(M.x86.R_CS);
- M.x86.R_CS = mem_access_word(4 * 4 + 2);
- push_word(M.x86.R_IP);
- M.x86.R_IP = mem_access_word(4 * 4);
- }
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xcf
-****************************************************************************/
-static void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("IRET\n");
-
- TRACE_AND_STEP();
-
- M.x86.R_IP = pop_word();
- M.x86.R_CS = pop_word();
- M.x86.R_FLG = pop_word();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xd0
-****************************************************************************/
-static void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg;
- uint destoffset;
- u8 destval;
-
- /*
- * Yet another weirdo special case instruction format. Part of
- * the opcode held below in "RH". Doubly nested case would
- * result, except that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
- switch (rh) {
- case 0:
- DECODE_PRINTF("ROL\t");
- break;
- case 1:
- DECODE_PRINTF("ROR\t");
- break;
- case 2:
- DECODE_PRINTF("RCL\t");
- break;
- case 3:
- DECODE_PRINTF("RCR\t");
- break;
- case 4:
- DECODE_PRINTF("SHL\t");
- break;
- case 5:
- DECODE_PRINTF("SHR\t");
- break;
- case 6:
- DECODE_PRINTF("SAL\t");
- break;
- case 7:
- DECODE_PRINTF("SAR\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- switch (mod) {
- case 0:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, 1);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, 1);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, 1);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",1\n");
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
- *destreg = destval;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xd1
-****************************************************************************/
-static void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- /*
- * Yet another weirdo special case instruction format. Part of
- * the opcode held below in "RH". Doubly nested case would
- * result, except that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
- switch (rh) {
- case 0:
- DECODE_PRINTF("ROL\t");
- break;
- case 1:
- DECODE_PRINTF("ROR\t");
- break;
- case 2:
- DECODE_PRINTF("RCL\t");
- break;
- case 3:
- DECODE_PRINTF("RCR\t");
- break;
- case 4:
- DECODE_PRINTF("SHL\t");
- break;
- case 5:
- DECODE_PRINTF("SHR\t");
- break;
- case 6:
- DECODE_PRINTF("SAL\t");
- break;
- case 7:
- DECODE_PRINTF("SAR\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, 1);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, 1);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, 1);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, 1);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, 1);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",1\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, 1);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
- u32 *destreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",1\n");
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (*destreg, 1);
- *destreg = destval;
- } else {
- u16 destval;
- u16 *destreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",1\n");
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (*destreg, 1);
- *destreg = destval;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xd2
-****************************************************************************/
-static void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg;
- uint destoffset;
- u8 destval;
- u8 amt;
-
- /*
- * Yet another weirdo special case instruction format. Part of
- * the opcode held below in "RH". Doubly nested case would
- * result, except that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
- switch (rh) {
- case 0:
- DECODE_PRINTF("ROL\t");
- break;
- case 1:
- DECODE_PRINTF("ROR\t");
- break;
- case 2:
- DECODE_PRINTF("RCL\t");
- break;
- case 3:
- DECODE_PRINTF("RCR\t");
- break;
- case 4:
- DECODE_PRINTF("SHL\t");
- break;
- case 5:
- DECODE_PRINTF("SHR\t");
- break;
- case 6:
- DECODE_PRINTF("SAL\t");
- break;
- case 7:
- DECODE_PRINTF("SAR\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- amt = M.x86.R_CL;
- switch (mod) {
- case 0:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, amt);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, amt);
- store_data_byte(destoffset, destval);
- break;
- case 2:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (destval, amt);
- store_data_byte(destoffset, destval);
- break;
- case 3: /* register to register */
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",CL\n");
- TRACE_AND_STEP();
- destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
- *destreg = destval;
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xd3
-****************************************************************************/
-static void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
- u8 amt;
-
- /*
- * Yet another weirdo special case instruction format. Part of
- * the opcode held below in "RH". Doubly nested case would
- * result, except that the decoded instruction
- */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
- switch (rh) {
- case 0:
- DECODE_PRINTF("ROL\t");
- break;
- case 1:
- DECODE_PRINTF("ROR\t");
- break;
- case 2:
- DECODE_PRINTF("RCL\t");
- break;
- case 3:
- DECODE_PRINTF("RCR\t");
- break;
- case 4:
- DECODE_PRINTF("SHL\t");
- break;
- case 5:
- DECODE_PRINTF("SHR\t");
- break;
- case 6:
- DECODE_PRINTF("SAL\t");
- break;
- case 7:
- DECODE_PRINTF("SAR\t");
- break;
- }
- }
-#endif
- /* know operation, decode the mod byte to find the addressing
- mode. */
- amt = M.x86.R_CL;
- switch (mod) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, amt);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, amt);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, amt);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, amt);
- store_data_word(destoffset, destval);
- }
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_long_operation[rh]) (destval, amt);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("WORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",CL\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = (*opcD1_word_operation[rh]) (destval, amt);
- store_data_word(destoffset, destval);
- }
- break;
- case 3: /* register to register */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",CL\n");
- TRACE_AND_STEP();
- *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
- } else {
- u16 *destreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",CL\n");
- TRACE_AND_STEP();
- *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xd4
-****************************************************************************/
-static void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
-{
- u8 a;
-
- START_OF_INSTR();
- DECODE_PRINTF("AAM\n");
- a = fetch_byte_imm(); /* this is a stupid encoding. */
- if (a != 10) {
- /* fix: add base decoding
- aam_word(u8 val, int base a) */
- DECODE_PRINTF("ERROR DECODING AAM\n");
- TRACE_REGS();
- HALT_SYS();
- }
- TRACE_AND_STEP();
- /* note the type change here --- returning AL and AH in AX. */
- M.x86.R_AX = aam_word(M.x86.R_AL);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xd5
-****************************************************************************/
-static void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
-{
- u8 a;
-
- START_OF_INSTR();
- DECODE_PRINTF("AAD\n");
- a = fetch_byte_imm();
- if (a != 10) {
- /* fix: add base decoding
- aad_word(u16 val, int base a) */
- DECODE_PRINTF("ERROR DECODING AAM\n");
- TRACE_REGS();
- HALT_SYS();
- }
- TRACE_AND_STEP();
- M.x86.R_AX = aad_word(M.x86.R_AX);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/* opcode 0xd6 ILLEGAL OPCODE */
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xd7
-****************************************************************************/
-static void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
-{
- u16 addr;
-
- START_OF_INSTR();
- DECODE_PRINTF("XLAT\n");
- TRACE_AND_STEP();
- addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
- M.x86.R_AL = fetch_data_byte(addr);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/* instuctions D8 .. DF are in i87_ops.c */
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe0
-****************************************************************************/
-static void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
-{
- s16 ip;
-
- START_OF_INSTR();
- DECODE_PRINTF("LOOPNE\t");
- ip = (s8) fetch_byte_imm();
- ip += (s16) M.x86.R_IP;
- DECODE_PRINTF2("%04x\n", ip);
- TRACE_AND_STEP();
- M.x86.R_CX -= 1;
- if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
- M.x86.R_IP = ip;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe1
-****************************************************************************/
-static void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
-{
- s16 ip;
-
- START_OF_INSTR();
- DECODE_PRINTF("LOOPE\t");
- ip = (s8) fetch_byte_imm();
- ip += (s16) M.x86.R_IP;
- DECODE_PRINTF2("%04x\n", ip);
- TRACE_AND_STEP();
- M.x86.R_CX -= 1;
- if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
- M.x86.R_IP = ip;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe2
-****************************************************************************/
-static void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
-{
- s16 ip;
-
- START_OF_INSTR();
- DECODE_PRINTF("LOOP\t");
- ip = (s8) fetch_byte_imm();
- ip += (s16) M.x86.R_IP;
- DECODE_PRINTF2("%04x\n", ip);
- TRACE_AND_STEP();
- M.x86.R_CX -= 1;
- if (M.x86.R_CX != 0)
- M.x86.R_IP = ip;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe3
-****************************************************************************/
-static void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
-{
- u16 target;
- s8 offset;
-
- /* jump to byte offset if overflow flag is set */
- START_OF_INSTR();
- DECODE_PRINTF("JCXZ\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- if (M.x86.R_CX == 0)
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe4
-****************************************************************************/
-static void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 port;
-
- START_OF_INSTR();
- DECODE_PRINTF("IN\t");
- port = (u8) fetch_byte_imm();
- DECODE_PRINTF2("%x,AL\n", port);
- TRACE_AND_STEP();
- M.x86.R_AL = (*sys_inb)(port);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe5
-****************************************************************************/
-static void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
-{
- u8 port;
-
- START_OF_INSTR();
- DECODE_PRINTF("IN\t");
- port = (u8) fetch_byte_imm();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF2("EAX,%x\n", port);
- } else {
- DECODE_PRINTF2("AX,%x\n", port);
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = (*sys_inl)(port);
- } else {
- M.x86.R_AX = (*sys_inw)(port);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe6
-****************************************************************************/
-static void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
-{
- u8 port;
-
- START_OF_INSTR();
- DECODE_PRINTF("OUT\t");
- port = (u8) fetch_byte_imm();
- DECODE_PRINTF2("%x,AL\n", port);
- TRACE_AND_STEP();
- (*sys_outb)(port, M.x86.R_AL);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe7
-****************************************************************************/
-static void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
-{
- u8 port;
-
- START_OF_INSTR();
- DECODE_PRINTF("OUT\t");
- port = (u8) fetch_byte_imm();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF2("%x,EAX\n", port);
- } else {
- DECODE_PRINTF2("%x,AX\n", port);
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- (*sys_outl)(port, M.x86.R_EAX);
- } else {
- (*sys_outw)(port, M.x86.R_AX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe8
-****************************************************************************/
-static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
-{
- s16 ip;
-
- START_OF_INSTR();
- DECODE_PRINTF("CALL\t");
- ip = (s16) fetch_word_imm();
- ip += (s16) M.x86.R_IP; /* CHECK SIGN */
- DECODE_PRINTF2("%04x\n", (u16)ip);
- CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
- TRACE_AND_STEP();
- push_word(M.x86.R_IP);
- M.x86.R_IP = ip;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xe9
-****************************************************************************/
-static void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
-{
- int ip;
-
- START_OF_INSTR();
- DECODE_PRINTF("JMP\t");
- ip = (s16)fetch_word_imm();
- ip += (s16)M.x86.R_IP;
- DECODE_PRINTF2("%04x\n", (u16)ip);
- TRACE_AND_STEP();
- M.x86.R_IP = (u16)ip;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xea
-****************************************************************************/
-static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 cs, ip;
-
- START_OF_INSTR();
- DECODE_PRINTF("JMP\tFAR ");
- ip = fetch_word_imm();
- cs = fetch_word_imm();
- DECODE_PRINTF2("%04x:", cs);
- DECODE_PRINTF2("%04x\n", ip);
- TRACE_AND_STEP();
- M.x86.R_IP = ip;
- M.x86.R_CS = cs;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xeb
-****************************************************************************/
-static void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
-{
- u16 target;
- s8 offset;
-
- START_OF_INSTR();
- DECODE_PRINTF("JMP\t");
- offset = (s8)fetch_byte_imm();
- target = (u16)(M.x86.R_IP + offset);
- DECODE_PRINTF2("%x\n", target);
- TRACE_AND_STEP();
- M.x86.R_IP = target;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xec
-****************************************************************************/
-static void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("IN\tAL,DX\n");
- TRACE_AND_STEP();
- M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xed
-****************************************************************************/
-static void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("IN\tEAX,DX\n");
- } else {
- DECODE_PRINTF("IN\tAX,DX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
- } else {
- M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xee
-****************************************************************************/
-static void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("OUT\tDX,AL\n");
- TRACE_AND_STEP();
- (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xef
-****************************************************************************/
-static void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("OUT\tDX,EAX\n");
- } else {
- DECODE_PRINTF("OUT\tDX,AX\n");
- }
- TRACE_AND_STEP();
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
- } else {
- (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf0
-****************************************************************************/
-static void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("LOCK:\n");
- TRACE_AND_STEP();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/*opcode 0xf1 ILLEGAL OPERATION */
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf2
-****************************************************************************/
-static void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("REPNE\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_PREFIX_REPNE;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf3
-****************************************************************************/
-static void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("REPE\n");
- TRACE_AND_STEP();
- M.x86.mode |= SYSMODE_PREFIX_REPE;
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf4
-****************************************************************************/
-static void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
-{
- START_OF_INSTR();
- DECODE_PRINTF("HALT\n");
- TRACE_AND_STEP();
- HALT_SYS();
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf5
-****************************************************************************/
-static void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
-{
- /* complement the carry flag. */
- START_OF_INSTR();
- DECODE_PRINTF("CMC\n");
- TRACE_AND_STEP();
- TOGGLE_FLAG(F_CF);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf6
-****************************************************************************/
-static void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- u8 *destreg;
- uint destoffset;
- u8 destval, srcval;
-
- /* long, drawn out code follows. Double switch for a total
- of 32 cases. */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0: /* mod=00 */
- switch (rh) {
- case 0: /* test byte imm */
- DECODE_PRINTF("TEST\tBYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%02x\n", srcval);
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- test_byte(destval, srcval);
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
- HALT_SYS();
- break;
- case 2:
- DECODE_PRINTF("NOT\tBYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = not_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 3:
- DECODE_PRINTF("NEG\tBYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = neg_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 4:
- DECODE_PRINTF("MUL\tBYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- mul_byte(destval);
- break;
- case 5:
- DECODE_PRINTF("IMUL\tBYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- imul_byte(destval);
- break;
- case 6:
- DECODE_PRINTF("DIV\tBYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- div_byte(destval);
- break;
- case 7:
- DECODE_PRINTF("IDIV\tBYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- idiv_byte(destval);
- break;
- }
- break; /* end mod==00 */
- case 1: /* mod=01 */
- switch (rh) {
- case 0: /* test byte imm */
- DECODE_PRINTF("TEST\tBYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%02x\n", srcval);
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- test_byte(destval, srcval);
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
- HALT_SYS();
- break;
- case 2:
- DECODE_PRINTF("NOT\tBYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = not_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 3:
- DECODE_PRINTF("NEG\tBYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = neg_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 4:
- DECODE_PRINTF("MUL\tBYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- mul_byte(destval);
- break;
- case 5:
- DECODE_PRINTF("IMUL\tBYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- imul_byte(destval);
- break;
- case 6:
- DECODE_PRINTF("DIV\tBYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- div_byte(destval);
- break;
- case 7:
- DECODE_PRINTF("IDIV\tBYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- idiv_byte(destval);
- break;
- }
- break; /* end mod==01 */
- case 2: /* mod=10 */
- switch (rh) {
- case 0: /* test byte imm */
- DECODE_PRINTF("TEST\tBYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%02x\n", srcval);
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- test_byte(destval, srcval);
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
- HALT_SYS();
- break;
- case 2:
- DECODE_PRINTF("NOT\tBYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = not_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 3:
- DECODE_PRINTF("NEG\tBYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = neg_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 4:
- DECODE_PRINTF("MUL\tBYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- mul_byte(destval);
- break;
- case 5:
- DECODE_PRINTF("IMUL\tBYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- imul_byte(destval);
- break;
- case 6:
- DECODE_PRINTF("DIV\tBYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- div_byte(destval);
- break;
- case 7:
- DECODE_PRINTF("IDIV\tBYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- idiv_byte(destval);
- break;
- }
- break; /* end mod==10 */
- case 3: /* mod=11 */
- switch (rh) {
- case 0: /* test byte imm */
- DECODE_PRINTF("TEST\t");
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF(",");
- srcval = fetch_byte_imm();
- DECODE_PRINTF2("%02x\n", srcval);
- TRACE_AND_STEP();
- test_byte(*destreg, srcval);
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
- HALT_SYS();
- break;
- case 2:
- DECODE_PRINTF("NOT\t");
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = not_byte(*destreg);
- break;
- case 3:
- DECODE_PRINTF("NEG\t");
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = neg_byte(*destreg);
- break;
- case 4:
- DECODE_PRINTF("MUL\t");
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- mul_byte(*destreg); /*!!! */
- break;
- case 5:
- DECODE_PRINTF("IMUL\t");
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- imul_byte(*destreg);
- break;
- case 6:
- DECODE_PRINTF("DIV\t");
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- div_byte(*destreg);
- break;
- case 7:
- DECODE_PRINTF("IDIV\t");
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- idiv_byte(*destreg);
- break;
- }
- break; /* end mod==11 */
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf7
-****************************************************************************/
-static void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rl, rh;
- uint destoffset;
-
- /* long, drawn out code follows. Double switch for a total
- of 32 cases. */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
- switch (mod) {
- case 0: /* mod=00 */
- switch (rh) {
- case 0: /* test word imm */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,srcval;
-
- DECODE_PRINTF("TEST\tDWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_long_imm();
- DECODE_PRINTF2("%x\n", srcval);
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- test_long(destval, srcval);
- } else {
- u16 destval,srcval;
-
- DECODE_PRINTF("TEST\tWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_word_imm();
- DECODE_PRINTF2("%x\n", srcval);
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- test_word(destval, srcval);
- }
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
- HALT_SYS();
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("NOT\tDWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = not_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("NOT\tWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = not_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 3:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("NEG\tDWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = neg_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("NEG\tWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = neg_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 4:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("MUL\tDWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- mul_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("MUL\tWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- mul_word(destval);
- }
- break;
- case 5:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("IMUL\tDWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- imul_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("IMUL\tWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- imul_word(destval);
- }
- break;
- case 6:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DIV\tDWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- div_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("DIV\tWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- div_word(destval);
- }
- break;
- case 7:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("IDIV\tDWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- idiv_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("IDIV\tWORD PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- idiv_word(destval);
- }
- break;
- }
- break; /* end mod==00 */
- case 1: /* mod=01 */
- switch (rh) {
- case 0: /* test word imm */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,srcval;
-
- DECODE_PRINTF("TEST\tDWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_long_imm();
- DECODE_PRINTF2("%x\n", srcval);
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- test_long(destval, srcval);
- } else {
- u16 destval,srcval;
-
- DECODE_PRINTF("TEST\tWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_word_imm();
- DECODE_PRINTF2("%x\n", srcval);
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- test_word(destval, srcval);
- }
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
- HALT_SYS();
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("NOT\tDWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = not_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("NOT\tWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = not_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 3:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("NEG\tDWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = neg_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("NEG\tWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = neg_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 4:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("MUL\tDWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- mul_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("MUL\tWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- mul_word(destval);
- }
- break;
- case 5:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("IMUL\tDWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- imul_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("IMUL\tWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- imul_word(destval);
- }
- break;
- case 6:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DIV\tDWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- div_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("DIV\tWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- div_word(destval);
- }
- break;
- case 7:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("IDIV\tDWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- idiv_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("IDIV\tWORD PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- idiv_word(destval);
- }
- break;
- }
- break; /* end mod==01 */
- case 2: /* mod=10 */
- switch (rh) {
- case 0: /* test word imm */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval,srcval;
-
- DECODE_PRINTF("TEST\tDWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_long_imm();
- DECODE_PRINTF2("%x\n", srcval);
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- test_long(destval, srcval);
- } else {
- u16 destval,srcval;
-
- DECODE_PRINTF("TEST\tWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF(",");
- srcval = fetch_word_imm();
- DECODE_PRINTF2("%x\n", srcval);
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- test_word(destval, srcval);
- }
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
- HALT_SYS();
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("NOT\tDWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = not_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("NOT\tWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = not_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 3:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("NEG\tDWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = neg_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("NEG\tWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = neg_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 4:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("MUL\tDWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- mul_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("MUL\tWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- mul_word(destval);
- }
- break;
- case 5:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("IMUL\tDWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- imul_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("IMUL\tWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- imul_word(destval);
- }
- break;
- case 6:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("DIV\tDWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- div_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("DIV\tWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- div_word(destval);
- }
- break;
- case 7:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- DECODE_PRINTF("IDIV\tDWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- idiv_long(destval);
- } else {
- u16 destval;
-
- DECODE_PRINTF("IDIV\tWORD PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- idiv_word(destval);
- }
- break;
- }
- break; /* end mod==10 */
- case 3: /* mod=11 */
- switch (rh) {
- case 0: /* test word imm */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
- u32 srcval;
-
- DECODE_PRINTF("TEST\t");
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF(",");
- srcval = fetch_long_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- test_long(*destreg, srcval);
- } else {
- u16 *destreg;
- u16 srcval;
-
- DECODE_PRINTF("TEST\t");
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF(",");
- srcval = fetch_word_imm();
- DECODE_PRINTF2("%x\n", srcval);
- TRACE_AND_STEP();
- test_word(*destreg, srcval);
- }
- break;
- case 1:
- DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
- HALT_SYS();
- break;
- case 2:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- DECODE_PRINTF("NOT\t");
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = not_long(*destreg);
- } else {
- u16 *destreg;
-
- DECODE_PRINTF("NOT\t");
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = not_word(*destreg);
- }
- break;
- case 3:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- DECODE_PRINTF("NEG\t");
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = neg_long(*destreg);
- } else {
- u16 *destreg;
-
- DECODE_PRINTF("NEG\t");
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = neg_word(*destreg);
- }
- break;
- case 4:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- DECODE_PRINTF("MUL\t");
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- mul_long(*destreg); /*!!! */
- } else {
- u16 *destreg;
-
- DECODE_PRINTF("MUL\t");
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- mul_word(*destreg); /*!!! */
- }
- break;
- case 5:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- DECODE_PRINTF("IMUL\t");
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- imul_long(*destreg);
- } else {
- u16 *destreg;
-
- DECODE_PRINTF("IMUL\t");
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- imul_word(*destreg);
- }
- break;
- case 6:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- DECODE_PRINTF("DIV\t");
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- div_long(*destreg);
- } else {
- u16 *destreg;
-
- DECODE_PRINTF("DIV\t");
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- div_word(*destreg);
- }
- break;
- case 7:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- DECODE_PRINTF("IDIV\t");
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- idiv_long(*destreg);
- } else {
- u16 *destreg;
-
- DECODE_PRINTF("IDIV\t");
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- idiv_word(*destreg);
- }
- break;
- }
- break; /* end mod==11 */
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf8
-****************************************************************************/
-static void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
-{
- /* clear the carry flag. */
- START_OF_INSTR();
- DECODE_PRINTF("CLC\n");
- TRACE_AND_STEP();
- CLEAR_FLAG(F_CF);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xf9
-****************************************************************************/
-static void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
-{
- /* set the carry flag. */
- START_OF_INSTR();
- DECODE_PRINTF("STC\n");
- TRACE_AND_STEP();
- SET_FLAG(F_CF);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xfa
-****************************************************************************/
-static void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
-{
- /* clear interrupts. */
- START_OF_INSTR();
- DECODE_PRINTF("CLI\n");
- TRACE_AND_STEP();
- CLEAR_FLAG(F_IF);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xfb
-****************************************************************************/
-static void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
-{
- /* enable interrupts. */
- START_OF_INSTR();
- DECODE_PRINTF("STI\n");
- TRACE_AND_STEP();
- SET_FLAG(F_IF);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xfc
-****************************************************************************/
-static void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
-{
- /* clear interrupts. */
- START_OF_INSTR();
- DECODE_PRINTF("CLD\n");
- TRACE_AND_STEP();
- CLEAR_FLAG(F_DF);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xfd
-****************************************************************************/
-static void x86emuOp_std(u8 X86EMU_UNUSED(op1))
-{
- /* clear interrupts. */
- START_OF_INSTR();
- DECODE_PRINTF("STD\n");
- TRACE_AND_STEP();
- SET_FLAG(F_DF);
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xfe
-****************************************************************************/
-static void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rh, rl;
- u8 destval;
- uint destoffset;
- u8 *destreg;
-
- /* Yet another special case instruction. */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
-
- switch (rh) {
- case 0:
- DECODE_PRINTF("INC\t");
- break;
- case 1:
- DECODE_PRINTF("DEC\t");
- break;
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
- HALT_SYS();
- break;
- }
- }
-#endif
- switch (mod) {
- case 0:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- switch (rh) {
- case 0: /* inc word ptr ... */
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = inc_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 1: /* dec word ptr ... */
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = dec_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- }
- break;
- case 1:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- switch (rh) {
- case 0:
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = inc_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = dec_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- }
- break;
- case 2:
- DECODE_PRINTF("BYTE PTR ");
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- switch (rh) {
- case 0:
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = inc_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- case 1:
- destval = fetch_data_byte(destoffset);
- TRACE_AND_STEP();
- destval = dec_byte(destval);
- store_data_byte(destoffset, destval);
- break;
- }
- break;
- case 3:
- destreg = DECODE_RM_BYTE_REGISTER(rl);
- DECODE_PRINTF("\n");
- switch (rh) {
- case 0:
- TRACE_AND_STEP();
- *destreg = inc_byte(*destreg);
- break;
- case 1:
- TRACE_AND_STEP();
- *destreg = dec_byte(*destreg);
- break;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/****************************************************************************
-REMARKS:
-Handles opcode 0xff
-****************************************************************************/
-static void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
-{
- int mod, rh, rl;
- uint destoffset = 0;
- u16 *destreg;
- u16 destval,destval2;
-
- /* Yet another special case instruction. */
- START_OF_INSTR();
- FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
- if (DEBUG_DECODE()) {
- /* XXX DECODE_PRINTF may be changed to something more
- general, so that it is important to leave the strings
- in the same format, even though the result is that the
- above test is done twice. */
-
- switch (rh) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("INC\tDWORD PTR ");
- } else {
- DECODE_PRINTF("INC\tWORD PTR ");
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- DECODE_PRINTF("DEC\tDWORD PTR ");
- } else {
- DECODE_PRINTF("DEC\tWORD PTR ");
- }
- break;
- case 2:
- DECODE_PRINTF("CALL\t");
- break;
- case 3:
- DECODE_PRINTF("CALL\tFAR ");
- break;
- case 4:
- DECODE_PRINTF("JMP\t");
- break;
- case 5:
- DECODE_PRINTF("JMP\tFAR ");
- break;
- case 6:
- DECODE_PRINTF("PUSH\t");
- break;
- case 7:
- DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
- HALT_SYS();
- break;
- }
- }
-#endif
- switch (mod) {
- case 0:
- destoffset = decode_rm00_address(rl);
- DECODE_PRINTF("\n");
- switch (rh) {
- case 0: /* inc word ptr ... */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = inc_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = inc_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 1: /* dec word ptr ... */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = dec_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = dec_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 2: /* call word ptr ... */
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- push_word(M.x86.R_IP);
- M.x86.R_IP = destval;
- break;
- case 3: /* call far ptr ... */
- destval = fetch_data_word(destoffset);
- destval2 = fetch_data_word(destoffset + 2);
- TRACE_AND_STEP();
- push_word(M.x86.R_CS);
- M.x86.R_CS = destval2;
- push_word(M.x86.R_IP);
- M.x86.R_IP = destval;
- break;
- case 4: /* jmp word ptr ... */
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- M.x86.R_IP = destval;
- break;
- case 5: /* jmp far ptr ... */
- destval = fetch_data_word(destoffset);
- destval2 = fetch_data_word(destoffset + 2);
- TRACE_AND_STEP();
- M.x86.R_IP = destval;
- M.x86.R_CS = destval2;
- break;
- case 6: /* push word ptr ... */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- push_long(destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- push_word(destval);
- }
- break;
- }
- break;
- case 1:
- destoffset = decode_rm01_address(rl);
- DECODE_PRINTF("\n");
- switch (rh) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = inc_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = inc_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = dec_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = dec_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 2: /* call word ptr ... */
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- push_word(M.x86.R_IP);
- M.x86.R_IP = destval;
- break;
- case 3: /* call far ptr ... */
- destval = fetch_data_word(destoffset);
- destval2 = fetch_data_word(destoffset + 2);
- TRACE_AND_STEP();
- push_word(M.x86.R_CS);
- M.x86.R_CS = destval2;
- push_word(M.x86.R_IP);
- M.x86.R_IP = destval;
- break;
- case 4: /* jmp word ptr ... */
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- M.x86.R_IP = destval;
- break;
- case 5: /* jmp far ptr ... */
- destval = fetch_data_word(destoffset);
- destval2 = fetch_data_word(destoffset + 2);
- TRACE_AND_STEP();
- M.x86.R_IP = destval;
- M.x86.R_CS = destval2;
- break;
- case 6: /* push word ptr ... */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- push_long(destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- push_word(destval);
- }
- break;
- }
- break;
- case 2:
- destoffset = decode_rm10_address(rl);
- DECODE_PRINTF("\n");
- switch (rh) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = inc_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = inc_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- destval = dec_long(destval);
- store_data_long(destoffset, destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- destval = dec_word(destval);
- store_data_word(destoffset, destval);
- }
- break;
- case 2: /* call word ptr ... */
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- push_word(M.x86.R_IP);
- M.x86.R_IP = destval;
- break;
- case 3: /* call far ptr ... */
- destval = fetch_data_word(destoffset);
- destval2 = fetch_data_word(destoffset + 2);
- TRACE_AND_STEP();
- push_word(M.x86.R_CS);
- M.x86.R_CS = destval2;
- push_word(M.x86.R_IP);
- M.x86.R_IP = destval;
- break;
- case 4: /* jmp word ptr ... */
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- M.x86.R_IP = destval;
- break;
- case 5: /* jmp far ptr ... */
- destval = fetch_data_word(destoffset);
- destval2 = fetch_data_word(destoffset + 2);
- TRACE_AND_STEP();
- M.x86.R_IP = destval;
- M.x86.R_CS = destval2;
- break;
- case 6: /* push word ptr ... */
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 destval;
-
- destval = fetch_data_long(destoffset);
- TRACE_AND_STEP();
- push_long(destval);
- } else {
- u16 destval;
-
- destval = fetch_data_word(destoffset);
- TRACE_AND_STEP();
- push_word(destval);
- }
- break;
- }
- break;
- case 3:
- switch (rh) {
- case 0:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = inc_long(*destreg);
- } else {
- u16 *destreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = inc_word(*destreg);
- }
- break;
- case 1:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = dec_long(*destreg);
- } else {
- u16 *destreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- *destreg = dec_word(*destreg);
- }
- break;
- case 2: /* call word ptr ... */
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- push_word(M.x86.R_IP);
- M.x86.R_IP = *destreg;
- break;
- case 3: /* jmp far ptr ... */
- DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
- TRACE_AND_STEP();
- HALT_SYS();
- break;
-
- case 4: /* jmp ... */
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- M.x86.R_IP = (u16) (*destreg);
- break;
- case 5: /* jmp far ptr ... */
- DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
- TRACE_AND_STEP();
- HALT_SYS();
- break;
- case 6:
- if (M.x86.mode & SYSMODE_PREFIX_DATA) {
- u32 *destreg;
-
- destreg = DECODE_RM_LONG_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- push_long(*destreg);
- } else {
- u16 *destreg;
-
- destreg = DECODE_RM_WORD_REGISTER(rl);
- DECODE_PRINTF("\n");
- TRACE_AND_STEP();
- push_word(*destreg);
- }
- break;
- }
- break;
- }
- DECODE_CLEAR_SEGOVR();
- END_OF_INSTR();
-}
-
-/***************************************************************************
- * Single byte operation code table:
- **************************************************************************/
-void (*x86emu_optab[256])(u8) =
-{
-/* 0x00 */ x86emuOp_add_byte_RM_R,
-/* 0x01 */ x86emuOp_add_word_RM_R,
-/* 0x02 */ x86emuOp_add_byte_R_RM,
-/* 0x03 */ x86emuOp_add_word_R_RM,
-/* 0x04 */ x86emuOp_add_byte_AL_IMM,
-/* 0x05 */ x86emuOp_add_word_AX_IMM,
-/* 0x06 */ x86emuOp_push_ES,
-/* 0x07 */ x86emuOp_pop_ES,
-
-/* 0x08 */ x86emuOp_or_byte_RM_R,
-/* 0x09 */ x86emuOp_or_word_RM_R,
-/* 0x0a */ x86emuOp_or_byte_R_RM,
-/* 0x0b */ x86emuOp_or_word_R_RM,
-/* 0x0c */ x86emuOp_or_byte_AL_IMM,
-/* 0x0d */ x86emuOp_or_word_AX_IMM,
-/* 0x0e */ x86emuOp_push_CS,
-/* 0x0f */ x86emuOp_two_byte,
-
-/* 0x10 */ x86emuOp_adc_byte_RM_R,
-/* 0x11 */ x86emuOp_adc_word_RM_R,
-/* 0x12 */ x86emuOp_adc_byte_R_RM,
-/* 0x13 */ x86emuOp_adc_word_R_RM,
-/* 0x14 */ x86emuOp_adc_byte_AL_IMM,
-/* 0x15 */ x86emuOp_adc_word_AX_IMM,
-/* 0x16 */ x86emuOp_push_SS,
-/* 0x17 */ x86emuOp_pop_SS,
-
-/* 0x18 */ x86emuOp_sbb_byte_RM_R,
-/* 0x19 */ x86emuOp_sbb_word_RM_R,
-/* 0x1a */ x86emuOp_sbb_byte_R_RM,
-/* 0x1b */ x86emuOp_sbb_word_R_RM,
-/* 0x1c */ x86emuOp_sbb_byte_AL_IMM,
-/* 0x1d */ x86emuOp_sbb_word_AX_IMM,
-/* 0x1e */ x86emuOp_push_DS,
-/* 0x1f */ x86emuOp_pop_DS,
-
-/* 0x20 */ x86emuOp_and_byte_RM_R,
-/* 0x21 */ x86emuOp_and_word_RM_R,
-/* 0x22 */ x86emuOp_and_byte_R_RM,
-/* 0x23 */ x86emuOp_and_word_R_RM,
-/* 0x24 */ x86emuOp_and_byte_AL_IMM,
-/* 0x25 */ x86emuOp_and_word_AX_IMM,
-/* 0x26 */ x86emuOp_segovr_ES,
-/* 0x27 */ x86emuOp_daa,
-
-/* 0x28 */ x86emuOp_sub_byte_RM_R,
-/* 0x29 */ x86emuOp_sub_word_RM_R,
-/* 0x2a */ x86emuOp_sub_byte_R_RM,
-/* 0x2b */ x86emuOp_sub_word_R_RM,
-/* 0x2c */ x86emuOp_sub_byte_AL_IMM,
-/* 0x2d */ x86emuOp_sub_word_AX_IMM,
-/* 0x2e */ x86emuOp_segovr_CS,
-/* 0x2f */ x86emuOp_das,
-
-/* 0x30 */ x86emuOp_xor_byte_RM_R,
-/* 0x31 */ x86emuOp_xor_word_RM_R,
-/* 0x32 */ x86emuOp_xor_byte_R_RM,
-/* 0x33 */ x86emuOp_xor_word_R_RM,
-/* 0x34 */ x86emuOp_xor_byte_AL_IMM,
-/* 0x35 */ x86emuOp_xor_word_AX_IMM,
-/* 0x36 */ x86emuOp_segovr_SS,
-/* 0x37 */ x86emuOp_aaa,
-
-/* 0x38 */ x86emuOp_cmp_byte_RM_R,
-/* 0x39 */ x86emuOp_cmp_word_RM_R,
-/* 0x3a */ x86emuOp_cmp_byte_R_RM,
-/* 0x3b */ x86emuOp_cmp_word_R_RM,
-/* 0x3c */ x86emuOp_cmp_byte_AL_IMM,
-/* 0x3d */ x86emuOp_cmp_word_AX_IMM,
-/* 0x3e */ x86emuOp_segovr_DS,
-/* 0x3f */ x86emuOp_aas,
-
-/* 0x40 */ x86emuOp_inc_AX,
-/* 0x41 */ x86emuOp_inc_CX,
-/* 0x42 */ x86emuOp_inc_DX,
-/* 0x43 */ x86emuOp_inc_BX,
-/* 0x44 */ x86emuOp_inc_SP,
-/* 0x45 */ x86emuOp_inc_BP,
-/* 0x46 */ x86emuOp_inc_SI,
-/* 0x47 */ x86emuOp_inc_DI,
-
-/* 0x48 */ x86emuOp_dec_AX,
-/* 0x49 */ x86emuOp_dec_CX,
-/* 0x4a */ x86emuOp_dec_DX,
-/* 0x4b */ x86emuOp_dec_BX,
-/* 0x4c */ x86emuOp_dec_SP,
-/* 0x4d */ x86emuOp_dec_BP,
-/* 0x4e */ x86emuOp_dec_SI,
-/* 0x4f */ x86emuOp_dec_DI,
-
-/* 0x50 */ x86emuOp_push_AX,
-/* 0x51 */ x86emuOp_push_CX,
-/* 0x52 */ x86emuOp_push_DX,
-/* 0x53 */ x86emuOp_push_BX,
-/* 0x54 */ x86emuOp_push_SP,
-/* 0x55 */ x86emuOp_push_BP,
-/* 0x56 */ x86emuOp_push_SI,
-/* 0x57 */ x86emuOp_push_DI,
-
-/* 0x58 */ x86emuOp_pop_AX,
-/* 0x59 */ x86emuOp_pop_CX,
-/* 0x5a */ x86emuOp_pop_DX,
-/* 0x5b */ x86emuOp_pop_BX,
-/* 0x5c */ x86emuOp_pop_SP,
-/* 0x5d */ x86emuOp_pop_BP,
-/* 0x5e */ x86emuOp_pop_SI,
-/* 0x5f */ x86emuOp_pop_DI,
-
-/* 0x60 */ x86emuOp_push_all,
-/* 0x61 */ x86emuOp_pop_all,
-/* 0x62 */ x86emuOp_illegal_op, /* bound */
-/* 0x63 */ x86emuOp_illegal_op, /* arpl */
-/* 0x64 */ x86emuOp_segovr_FS,
-/* 0x65 */ x86emuOp_segovr_GS,
-/* 0x66 */ x86emuOp_prefix_data,
-/* 0x67 */ x86emuOp_prefix_addr,
-
-/* 0x68 */ x86emuOp_push_word_IMM,
-/* 0x69 */ x86emuOp_imul_word_IMM,
-/* 0x6a */ x86emuOp_push_byte_IMM,
-/* 0x6b */ x86emuOp_imul_byte_IMM,
-/* 0x6c */ x86emuOp_ins_byte,
-/* 0x6d */ x86emuOp_ins_word,
-/* 0x6e */ x86emuOp_outs_byte,
-/* 0x6f */ x86emuOp_outs_word,
-
-/* 0x70 */ x86emuOp_jump_near_O,
-/* 0x71 */ x86emuOp_jump_near_NO,
-/* 0x72 */ x86emuOp_jump_near_B,
-/* 0x73 */ x86emuOp_jump_near_NB,
-/* 0x74 */ x86emuOp_jump_near_Z,
-/* 0x75 */ x86emuOp_jump_near_NZ,
-/* 0x76 */ x86emuOp_jump_near_BE,
-/* 0x77 */ x86emuOp_jump_near_NBE,
-
-/* 0x78 */ x86emuOp_jump_near_S,
-/* 0x79 */ x86emuOp_jump_near_NS,
-/* 0x7a */ x86emuOp_jump_near_P,
-/* 0x7b */ x86emuOp_jump_near_NP,
-/* 0x7c */ x86emuOp_jump_near_L,
-/* 0x7d */ x86emuOp_jump_near_NL,
-/* 0x7e */ x86emuOp_jump_near_LE,
-/* 0x7f */ x86emuOp_jump_near_NLE,
-
-/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
-/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
-/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
-/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
-/* 0x84 */ x86emuOp_test_byte_RM_R,
-/* 0x85 */ x86emuOp_test_word_RM_R,
-/* 0x86 */ x86emuOp_xchg_byte_RM_R,
-/* 0x87 */ x86emuOp_xchg_word_RM_R,
-
-/* 0x88 */ x86emuOp_mov_byte_RM_R,
-/* 0x89 */ x86emuOp_mov_word_RM_R,
-/* 0x8a */ x86emuOp_mov_byte_R_RM,
-/* 0x8b */ x86emuOp_mov_word_R_RM,
-/* 0x8c */ x86emuOp_mov_word_RM_SR,
-/* 0x8d */ x86emuOp_lea_word_R_M,
-/* 0x8e */ x86emuOp_mov_word_SR_RM,
-/* 0x8f */ x86emuOp_pop_RM,
-
-/* 0x90 */ x86emuOp_nop,
-/* 0x91 */ x86emuOp_xchg_word_AX_CX,
-/* 0x92 */ x86emuOp_xchg_word_AX_DX,
-/* 0x93 */ x86emuOp_xchg_word_AX_BX,
-/* 0x94 */ x86emuOp_xchg_word_AX_SP,
-/* 0x95 */ x86emuOp_xchg_word_AX_BP,
-/* 0x96 */ x86emuOp_xchg_word_AX_SI,
-/* 0x97 */ x86emuOp_xchg_word_AX_DI,
-
-/* 0x98 */ x86emuOp_cbw,
-/* 0x99 */ x86emuOp_cwd,
-/* 0x9a */ x86emuOp_call_far_IMM,
-/* 0x9b */ x86emuOp_wait,
-/* 0x9c */ x86emuOp_pushf_word,
-/* 0x9d */ x86emuOp_popf_word,
-/* 0x9e */ x86emuOp_sahf,
-/* 0x9f */ x86emuOp_lahf,
-
-/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
-/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
-/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
-/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
-/* 0xa4 */ x86emuOp_movs_byte,
-/* 0xa5 */ x86emuOp_movs_word,
-/* 0xa6 */ x86emuOp_cmps_byte,
-/* 0xa7 */ x86emuOp_cmps_word,
-/* 0xa8 */ x86emuOp_test_AL_IMM,
-/* 0xa9 */ x86emuOp_test_AX_IMM,
-/* 0xaa */ x86emuOp_stos_byte,
-/* 0xab */ x86emuOp_stos_word,
-/* 0xac */ x86emuOp_lods_byte,
-/* 0xad */ x86emuOp_lods_word,
-/* 0xac */ x86emuOp_scas_byte,
-/* 0xad */ x86emuOp_scas_word,
-
-
-/* 0xb0 */ x86emuOp_mov_byte_AL_IMM,
-/* 0xb1 */ x86emuOp_mov_byte_CL_IMM,
-/* 0xb2 */ x86emuOp_mov_byte_DL_IMM,
-/* 0xb3 */ x86emuOp_mov_byte_BL_IMM,
-/* 0xb4 */ x86emuOp_mov_byte_AH_IMM,
-/* 0xb5 */ x86emuOp_mov_byte_CH_IMM,
-/* 0xb6 */ x86emuOp_mov_byte_DH_IMM,
-/* 0xb7 */ x86emuOp_mov_byte_BH_IMM,
-
-/* 0xb8 */ x86emuOp_mov_word_AX_IMM,
-/* 0xb9 */ x86emuOp_mov_word_CX_IMM,
-/* 0xba */ x86emuOp_mov_word_DX_IMM,
-/* 0xbb */ x86emuOp_mov_word_BX_IMM,
-/* 0xbc */ x86emuOp_mov_word_SP_IMM,
-/* 0xbd */ x86emuOp_mov_word_BP_IMM,
-/* 0xbe */ x86emuOp_mov_word_SI_IMM,
-/* 0xbf */ x86emuOp_mov_word_DI_IMM,
-
-/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
-/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
-/* 0xc2 */ x86emuOp_ret_near_IMM,
-/* 0xc3 */ x86emuOp_ret_near,
-/* 0xc4 */ x86emuOp_les_R_IMM,
-/* 0xc5 */ x86emuOp_lds_R_IMM,
-/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
-/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
-/* 0xc8 */ x86emuOp_enter,
-/* 0xc9 */ x86emuOp_leave,
-/* 0xca */ x86emuOp_ret_far_IMM,
-/* 0xcb */ x86emuOp_ret_far,
-/* 0xcc */ x86emuOp_int3,
-/* 0xcd */ x86emuOp_int_IMM,
-/* 0xce */ x86emuOp_into,
-/* 0xcf */ x86emuOp_iret,
-
-/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
-/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
-/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
-/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
-/* 0xd4 */ x86emuOp_aam,
-/* 0xd5 */ x86emuOp_aad,
-/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
-/* 0xd7 */ x86emuOp_xlat,
-/* 0xd8 */ x86emuOp_esc_coprocess_d8,
-/* 0xd9 */ x86emuOp_esc_coprocess_d9,
-/* 0xda */ x86emuOp_esc_coprocess_da,
-/* 0xdb */ x86emuOp_esc_coprocess_db,
-/* 0xdc */ x86emuOp_esc_coprocess_dc,
-/* 0xdd */ x86emuOp_esc_coprocess_dd,
-/* 0xde */ x86emuOp_esc_coprocess_de,
-/* 0xdf */ x86emuOp_esc_coprocess_df,
-
-/* 0xe0 */ x86emuOp_loopne,
-/* 0xe1 */ x86emuOp_loope,
-/* 0xe2 */ x86emuOp_loop,
-/* 0xe3 */ x86emuOp_jcxz,
-/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
-/* 0xe5 */ x86emuOp_in_word_AX_IMM,
-/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
-/* 0xe7 */ x86emuOp_out_word_IMM_AX,
-
-/* 0xe8 */ x86emuOp_call_near_IMM,
-/* 0xe9 */ x86emuOp_jump_near_IMM,
-/* 0xea */ x86emuOp_jump_far_IMM,
-/* 0xeb */ x86emuOp_jump_byte_IMM,
-/* 0xec */ x86emuOp_in_byte_AL_DX,
-/* 0xed */ x86emuOp_in_word_AX_DX,
-/* 0xee */ x86emuOp_out_byte_DX_AL,
-/* 0xef */ x86emuOp_out_word_DX_AX,
-
-/* 0xf0 */ x86emuOp_lock,
-/* 0xf1 */ x86emuOp_illegal_op,
-/* 0xf2 */ x86emuOp_repne,
-/* 0xf3 */ x86emuOp_repe,
-/* 0xf4 */ x86emuOp_halt,
-/* 0xf5 */ x86emuOp_cmc,
-/* 0xf6 */ x86emuOp_opcF6_byte_RM,
-/* 0xf7 */ x86emuOp_opcF7_word_RM,
-
-/* 0xf8 */ x86emuOp_clc,
-/* 0xf9 */ x86emuOp_stc,
-/* 0xfa */ x86emuOp_cli,
-/* 0xfb */ x86emuOp_sti,
-/* 0xfc */ x86emuOp_cld,
-/* 0xfd */ x86emuOp_std,
-/* 0xfe */ x86emuOp_opcFE_byte_RM,
-/* 0xff */ x86emuOp_opcFF_word_RM,
-};
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines to implement the decoding
+* and emulation of all the x86 processor instructions.
+*
+* There are approximately 250 subroutines in here, which correspond
+* to the 256 byte-"opcodes" found on the 8086. The table which
+* dispatches this is found in the files optab.[ch].
+*
+* Each opcode proc has a comment preceeding it which gives it's table
+* address. Several opcodes are missing (undefined) in the table.
+*
+* Each proc includes information for decoding (DECODE_PRINTF and
+* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
+* functions (START_OF_INSTR, END_OF_INSTR).
+*
+* Many of the procedures are *VERY* similar in coding. This has
+* allowed for a very large amount of code to be generated in a fairly
+* short amount of time (i.e. cut, paste, and modify). The result is
+* that much of the code below could have been folded into subroutines
+* for a large reduction in size of this file. The downside would be
+* that there would be a penalty in execution speed. The file could
+* also have been *MUCH* larger by inlining certain functions which
+* were called. This could have resulted even faster execution. The
+* prime directive I used to decide whether to inline the code or to
+* modularize it, was basically: 1) no unnecessary subroutine calls,
+* 2) no routines more than about 200 lines in size, and 3) modularize
+* any code that I might not get right the first time. The fetch_*
+* subroutines fall into the latter category. The The decode_* fall
+* into the second category. The coding of the "switch(mod){ .... }"
+* in many of the subroutines below falls into the first category.
+* Especially, the coding of {add,and,or,sub,...}_{byte,word}
+* subroutines are an especially glaring case of the third guideline.
+* Since so much of the code is cloned from other modules (compare
+* opcode #00 to opcode #01), making the basic operations subroutine
+* calls is especially important; otherwise mistakes in coding an
+* "add" would represent a nightmare in maintenance.
+*
+****************************************************************************/
+
+#include "x86emu/x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+static void x86emuOp_illegal_op(
+ u8 op1)
+{
+ START_OF_INSTR();
+ if (M.x86.R_SP != 0) {
+ DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
+ TRACE_REGS();
+ DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
+ M.x86.R_CS, M.x86.R_IP-1,op1));
+ HALT_SYS();
+ }
+ else {
+ /* If we get here, it means the stack pointer is back to zero
+ * so we are just returning from an emulator service call
+ * so therte is no need to display an error message. We trap
+ * the emulator with an 0xF1 opcode to finish the service
+ * call.
+ */
+ X86EMU_halt_sys();
+ }
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x00
+****************************************************************************/
+static void x86emuOp_add_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 *destreg, *srcreg;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x01
+****************************************************************************/
+static void x86emuOp_add_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x02
+****************************************************************************/
+static void x86emuOp_add_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x03
+****************************************************************************/
+static void x86emuOp_add_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x04
+****************************************************************************/
+static void x86emuOp_add_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = add_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x05
+****************************************************************************/
+static void x86emuOp_add_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("ADD\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("ADD\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = add_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = add_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x06
+****************************************************************************/
+static void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tES\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_ES);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x07
+****************************************************************************/
+static void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tES\n");
+ TRACE_AND_STEP();
+ M.x86.R_ES = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x08
+****************************************************************************/
+static void x86emuOp_or_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x09
+****************************************************************************/
+static void x86emuOp_or_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0a
+****************************************************************************/
+static void x86emuOp_or_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0b
+****************************************************************************/
+static void x86emuOp_or_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0c
+****************************************************************************/
+static void x86emuOp_or_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = or_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0d
+****************************************************************************/
+static void x86emuOp_or_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OR\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("OR\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = or_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = or_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0e
+****************************************************************************/
+static void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tCS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
+****************************************************************************/
+static void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
+{
+ u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ (*x86emu_optab2[op2])(op2);
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x10
+****************************************************************************/
+static void x86emuOp_adc_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x11
+****************************************************************************/
+static void x86emuOp_adc_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x12
+****************************************************************************/
+static void x86emuOp_adc_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x13
+****************************************************************************/
+static void x86emuOp_adc_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x14
+****************************************************************************/
+static void x86emuOp_adc_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = adc_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x15
+****************************************************************************/
+static void x86emuOp_adc_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("ADC\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("ADC\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = adc_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = adc_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x16
+****************************************************************************/
+static void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tSS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_SS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x17
+****************************************************************************/
+static void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tSS\n");
+ TRACE_AND_STEP();
+ M.x86.R_SS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x18
+****************************************************************************/
+static void x86emuOp_sbb_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x19
+****************************************************************************/
+static void x86emuOp_sbb_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1a
+****************************************************************************/
+static void x86emuOp_sbb_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1b
+****************************************************************************/
+static void x86emuOp_sbb_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1c
+****************************************************************************/
+static void x86emuOp_sbb_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = sbb_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1d
+****************************************************************************/
+static void x86emuOp_sbb_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("SBB\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("SBB\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = sbb_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = sbb_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1e
+****************************************************************************/
+static void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tDS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_DS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1f
+****************************************************************************/
+static void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tDS\n");
+ TRACE_AND_STEP();
+ M.x86.R_DS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x20
+****************************************************************************/
+static void x86emuOp_and_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x21
+****************************************************************************/
+static void x86emuOp_and_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x22
+****************************************************************************/
+static void x86emuOp_and_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x23
+****************************************************************************/
+static void x86emuOp_and_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, srcval);
+ break;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, srcval);
+ break;
+ }
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x24
+****************************************************************************/
+static void x86emuOp_and_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = and_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x25
+****************************************************************************/
+static void x86emuOp_and_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("AND\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("AND\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = and_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = and_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x26
+****************************************************************************/
+static void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ES:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_ES;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x27
+****************************************************************************/
+static void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DAA\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = daa_byte(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x28
+****************************************************************************/
+static void x86emuOp_sub_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x29
+****************************************************************************/
+static void x86emuOp_sub_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2a
+****************************************************************************/
+static void x86emuOp_sub_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2b
+****************************************************************************/
+static void x86emuOp_sub_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2c
+****************************************************************************/
+static void x86emuOp_sub_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = sub_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2d
+****************************************************************************/
+static void x86emuOp_sub_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("SUB\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("SUB\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = sub_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = sub_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2e
+****************************************************************************/
+static void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("CS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_CS;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2f
+****************************************************************************/
+static void x86emuOp_das(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DAS\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = das_byte(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x30
+****************************************************************************/
+static void x86emuOp_xor_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x31
+****************************************************************************/
+static void x86emuOp_xor_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x32
+****************************************************************************/
+static void x86emuOp_xor_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x33
+****************************************************************************/
+static void x86emuOp_xor_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x34
+****************************************************************************/
+static void x86emuOp_xor_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = xor_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x35
+****************************************************************************/
+static void x86emuOp_xor_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XOR\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("XOR\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = xor_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = xor_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x36
+****************************************************************************/
+static void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("SS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_SS;
+ /* no DECODE_CLEAR_SEGOVR ! */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x37
+****************************************************************************/
+static void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("AAA\n");
+ TRACE_AND_STEP();
+ M.x86.R_AX = aaa_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x38
+****************************************************************************/
+static void x86emuOp_cmp_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 *destreg, *srcreg;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(destval, *srcreg);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(destval, *srcreg);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(destval, *srcreg);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x39
+****************************************************************************/
+static void x86emuOp_cmp_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(destval, *srcreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(destval, *srcreg);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(destval, *srcreg);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3a
+****************************************************************************/
+static void x86emuOp_cmp_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3b
+****************************************************************************/
+static void x86emuOp_cmp_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3c
+****************************************************************************/
+static void x86emuOp_cmp_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ cmp_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3d
+****************************************************************************/
+static void x86emuOp_cmp_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CMP\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("CMP\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ cmp_long(M.x86.R_EAX, srcval);
+ } else {
+ cmp_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3e
+****************************************************************************/
+static void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_DS;
+ /* NO DECODE_CLEAR_SEGOVR! */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3f
+****************************************************************************/
+static void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("AAS\n");
+ TRACE_AND_STEP();
+ M.x86.R_AX = aas_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x40
+****************************************************************************/
+static void x86emuOp_inc_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEAX\n");
+ } else {
+ DECODE_PRINTF("INC\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = inc_long(M.x86.R_EAX);
+ } else {
+ M.x86.R_AX = inc_word(M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x41
+****************************************************************************/
+static void x86emuOp_inc_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tECX\n");
+ } else {
+ DECODE_PRINTF("INC\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = inc_long(M.x86.R_ECX);
+ } else {
+ M.x86.R_CX = inc_word(M.x86.R_CX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x42
+****************************************************************************/
+static void x86emuOp_inc_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEDX\n");
+ } else {
+ DECODE_PRINTF("INC\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = inc_long(M.x86.R_EDX);
+ } else {
+ M.x86.R_DX = inc_word(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x43
+****************************************************************************/
+static void x86emuOp_inc_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEBX\n");
+ } else {
+ DECODE_PRINTF("INC\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = inc_long(M.x86.R_EBX);
+ } else {
+ M.x86.R_BX = inc_word(M.x86.R_BX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x44
+****************************************************************************/
+static void x86emuOp_inc_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tESP\n");
+ } else {
+ DECODE_PRINTF("INC\tSP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = inc_long(M.x86.R_ESP);
+ } else {
+ M.x86.R_SP = inc_word(M.x86.R_SP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x45
+****************************************************************************/
+static void x86emuOp_inc_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEBP\n");
+ } else {
+ DECODE_PRINTF("INC\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = inc_long(M.x86.R_EBP);
+ } else {
+ M.x86.R_BP = inc_word(M.x86.R_BP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x46
+****************************************************************************/
+static void x86emuOp_inc_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tESI\n");
+ } else {
+ DECODE_PRINTF("INC\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = inc_long(M.x86.R_ESI);
+ } else {
+ M.x86.R_SI = inc_word(M.x86.R_SI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x47
+****************************************************************************/
+static void x86emuOp_inc_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEDI\n");
+ } else {
+ DECODE_PRINTF("INC\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = inc_long(M.x86.R_EDI);
+ } else {
+ M.x86.R_DI = inc_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x48
+****************************************************************************/
+static void x86emuOp_dec_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEAX\n");
+ } else {
+ DECODE_PRINTF("DEC\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = dec_long(M.x86.R_EAX);
+ } else {
+ M.x86.R_AX = dec_word(M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x49
+****************************************************************************/
+static void x86emuOp_dec_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tECX\n");
+ } else {
+ DECODE_PRINTF("DEC\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = dec_long(M.x86.R_ECX);
+ } else {
+ M.x86.R_CX = dec_word(M.x86.R_CX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4a
+****************************************************************************/
+static void x86emuOp_dec_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEDX\n");
+ } else {
+ DECODE_PRINTF("DEC\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = dec_long(M.x86.R_EDX);
+ } else {
+ M.x86.R_DX = dec_word(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4b
+****************************************************************************/
+static void x86emuOp_dec_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEBX\n");
+ } else {
+ DECODE_PRINTF("DEC\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = dec_long(M.x86.R_EBX);
+ } else {
+ M.x86.R_BX = dec_word(M.x86.R_BX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4c
+****************************************************************************/
+static void x86emuOp_dec_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tESP\n");
+ } else {
+ DECODE_PRINTF("DEC\tSP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = dec_long(M.x86.R_ESP);
+ } else {
+ M.x86.R_SP = dec_word(M.x86.R_SP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4d
+****************************************************************************/
+static void x86emuOp_dec_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEBP\n");
+ } else {
+ DECODE_PRINTF("DEC\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = dec_long(M.x86.R_EBP);
+ } else {
+ M.x86.R_BP = dec_word(M.x86.R_BP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4e
+****************************************************************************/
+static void x86emuOp_dec_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tESI\n");
+ } else {
+ DECODE_PRINTF("DEC\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = dec_long(M.x86.R_ESI);
+ } else {
+ M.x86.R_SI = dec_word(M.x86.R_SI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4f
+****************************************************************************/
+static void x86emuOp_dec_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEDI\n");
+ } else {
+ DECODE_PRINTF("DEC\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = dec_long(M.x86.R_EDI);
+ } else {
+ M.x86.R_DI = dec_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x50
+****************************************************************************/
+static void x86emuOp_push_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEAX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EAX);
+ } else {
+ push_word(M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x51
+****************************************************************************/
+static void x86emuOp_push_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tECX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_ECX);
+ } else {
+ push_word(M.x86.R_CX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x52
+****************************************************************************/
+static void x86emuOp_push_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEDX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EDX);
+ } else {
+ push_word(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x53
+****************************************************************************/
+static void x86emuOp_push_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEBX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EBX);
+ } else {
+ push_word(M.x86.R_BX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x54
+****************************************************************************/
+static void x86emuOp_push_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tESP\n");
+ } else {
+ DECODE_PRINTF("PUSH\tSP\n");
+ }
+ TRACE_AND_STEP();
+ /* Always push (E)SP, since we are emulating an i386 and above
+ * processor. This is necessary as some BIOS'es use this to check
+ * what type of processor is in the system.
+ */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_ESP);
+ } else {
+ push_word((u16)(M.x86.R_SP));
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x55
+****************************************************************************/
+static void x86emuOp_push_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEBP\n");
+ } else {
+ DECODE_PRINTF("PUSH\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EBP);
+ } else {
+ push_word(M.x86.R_BP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x56
+****************************************************************************/
+static void x86emuOp_push_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tESI\n");
+ } else {
+ DECODE_PRINTF("PUSH\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_ESI);
+ } else {
+ push_word(M.x86.R_SI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x57
+****************************************************************************/
+static void x86emuOp_push_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEDI\n");
+ } else {
+ DECODE_PRINTF("PUSH\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EDI);
+ } else {
+ push_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x58
+****************************************************************************/
+static void x86emuOp_pop_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEAX\n");
+ } else {
+ DECODE_PRINTF("POP\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = pop_long();
+ } else {
+ M.x86.R_AX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x59
+****************************************************************************/
+static void x86emuOp_pop_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tECX\n");
+ } else {
+ DECODE_PRINTF("POP\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = pop_long();
+ } else {
+ M.x86.R_CX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5a
+****************************************************************************/
+static void x86emuOp_pop_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEDX\n");
+ } else {
+ DECODE_PRINTF("POP\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = pop_long();
+ } else {
+ M.x86.R_DX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5b
+****************************************************************************/
+static void x86emuOp_pop_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEBX\n");
+ } else {
+ DECODE_PRINTF("POP\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = pop_long();
+ } else {
+ M.x86.R_BX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5c
+****************************************************************************/
+static void x86emuOp_pop_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tESP\n");
+ } else {
+ DECODE_PRINTF("POP\tSP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = pop_long();
+ } else {
+ M.x86.R_SP = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5d
+****************************************************************************/
+static void x86emuOp_pop_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEBP\n");
+ } else {
+ DECODE_PRINTF("POP\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = pop_long();
+ } else {
+ M.x86.R_BP = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5e
+****************************************************************************/
+static void x86emuOp_pop_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tESI\n");
+ } else {
+ DECODE_PRINTF("POP\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = pop_long();
+ } else {
+ M.x86.R_SI = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5f
+****************************************************************************/
+static void x86emuOp_pop_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEDI\n");
+ } else {
+ DECODE_PRINTF("POP\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = pop_long();
+ } else {
+ M.x86.R_DI = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x60
+****************************************************************************/
+static void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSHAD\n");
+ } else {
+ DECODE_PRINTF("PUSHA\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 old_sp = M.x86.R_ESP;
+
+ push_long(M.x86.R_EAX);
+ push_long(M.x86.R_ECX);
+ push_long(M.x86.R_EDX);
+ push_long(M.x86.R_EBX);
+ push_long(old_sp);
+ push_long(M.x86.R_EBP);
+ push_long(M.x86.R_ESI);
+ push_long(M.x86.R_EDI);
+ } else {
+ u16 old_sp = M.x86.R_SP;
+
+ push_word(M.x86.R_AX);
+ push_word(M.x86.R_CX);
+ push_word(M.x86.R_DX);
+ push_word(M.x86.R_BX);
+ push_word(old_sp);
+ push_word(M.x86.R_BP);
+ push_word(M.x86.R_SI);
+ push_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x61
+****************************************************************************/
+static void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POPAD\n");
+ } else {
+ DECODE_PRINTF("POPA\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = pop_long();
+ M.x86.R_ESI = pop_long();
+ M.x86.R_EBP = pop_long();
+ M.x86.R_ESP += 4; /* skip ESP */
+ M.x86.R_EBX = pop_long();
+ M.x86.R_EDX = pop_long();
+ M.x86.R_ECX = pop_long();
+ M.x86.R_EAX = pop_long();
+ } else {
+ M.x86.R_DI = pop_word();
+ M.x86.R_SI = pop_word();
+ M.x86.R_BP = pop_word();
+ M.x86.R_SP += 2; /* skip SP */
+ M.x86.R_BX = pop_word();
+ M.x86.R_DX = pop_word();
+ M.x86.R_CX = pop_word();
+ M.x86.R_AX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
+/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x64
+****************************************************************************/
+static void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("FS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_FS;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x65
+****************************************************************************/
+static void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("GS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_GS;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x66 - prefix for 32-bit register
+****************************************************************************/
+static void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DATA:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_DATA;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x67 - prefix for 32-bit address
+****************************************************************************/
+static void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ADDR:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_ADDR;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x68
+****************************************************************************/
+static void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 imm;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ imm = fetch_long_imm();
+ } else {
+ imm = fetch_word_imm();
+ }
+ DECODE_PRINTF2("PUSH\t%x\n", imm);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(imm);
+ } else {
+ push_word((u16)imm);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x69
+****************************************************************************/
+static void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ res = (s16)*srcreg * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6a
+****************************************************************************/
+static void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ s16 imm;
+
+ START_OF_INSTR();
+ imm = (s8)fetch_byte_imm();
+ DECODE_PRINTF2("PUSH\t%d\n", imm);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long((s32)imm);
+ } else {
+ push_word(imm);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6b
+****************************************************************************/
+static void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ s8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ res = (s16)*srcreg * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6c
+****************************************************************************/
+static void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("INSB\n");
+ ins(1);
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6d
+****************************************************************************/
+static void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INSD\n");
+ ins(4);
+ } else {
+ DECODE_PRINTF("INSW\n");
+ ins(2);
+ }
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6e
+****************************************************************************/
+static void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("OUTSB\n");
+ outs(1);
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6f
+****************************************************************************/
+static void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OUTSD\n");
+ outs(4);
+ } else {
+ DECODE_PRINTF("OUTSW\n");
+ outs(2);
+ }
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x70
+****************************************************************************/
+static void x86emuOp_jump_near_O(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if overflow flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JO\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_OF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x71
+****************************************************************************/
+static void x86emuOp_jump_near_NO(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if overflow is not set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNO\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_OF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x72
+****************************************************************************/
+static void x86emuOp_jump_near_B(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is set. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JB\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_CF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x73
+****************************************************************************/
+static void x86emuOp_jump_near_NB(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is clear. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNB\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_CF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x74
+****************************************************************************/
+static void x86emuOp_jump_near_Z(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if zero flag is set. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JZ\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x75
+****************************************************************************/
+static void x86emuOp_jump_near_NZ(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if zero flag is clear. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNZ\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x76
+****************************************************************************/
+static void x86emuOp_jump_near_BE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is set or if the zero
+ flag is set. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JBE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x77
+****************************************************************************/
+static void x86emuOp_jump_near_NBE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is clear and if the zero
+ flag is clear */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNBE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x78
+****************************************************************************/
+static void x86emuOp_jump_near_S(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if sign flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JS\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_SF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x79
+****************************************************************************/
+static void x86emuOp_jump_near_NS(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if sign flag is clear */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNS\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_SF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7a
+****************************************************************************/
+static void x86emuOp_jump_near_P(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if parity flag is set (even parity) */
+ START_OF_INSTR();
+ DECODE_PRINTF("JP\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_PF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7b
+****************************************************************************/
+static void x86emuOp_jump_near_NP(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if parity flag is clear (odd parity) */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNP\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_PF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7c
+****************************************************************************/
+static void x86emuOp_jump_near_L(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag not equal to overflow flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JL\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ if (sf ^ of)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7d
+****************************************************************************/
+static void x86emuOp_jump_near_NL(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag not equal to overflow flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNL\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ /* note: inverse of above, but using == instead of xor. */
+ if (sf == of)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7e
+****************************************************************************/
+static void x86emuOp_jump_near_LE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag not equal to overflow flag
+ or the zero flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JLE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ if ((sf ^ of) || ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7f
+****************************************************************************/
+static void x86emuOp_jump_near_NLE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag equal to overflow flag.
+ and the zero flag is clear */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNLE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ if ((sf == of) && !ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u8 (*opc80_byte_operation[])(u8 d, u8 s) =
+{
+ add_byte, /* 00 */
+ or_byte, /* 01 */
+ adc_byte, /* 02 */
+ sbb_byte, /* 03 */
+ and_byte, /* 04 */
+ sub_byte, /* 05 */
+ xor_byte, /* 06 */
+ cmp_byte, /* 07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x80
+****************************************************************************/
+static void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+ u8 destval;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u16 (*opc81_word_operation[])(u16 d, u16 s) =
+{
+ add_word, /*00 */
+ or_word, /*01 */
+ adc_word, /*02 */
+ sbb_word, /*03 */
+ and_word, /*04 */
+ sub_word, /*05 */
+ xor_word, /*06 */
+ cmp_word, /*07 */
+};
+
+static u32 (*opc81_long_operation[])(u32 d, u32 s) =
+{
+ add_long, /*00 */
+ or_long, /*01 */
+ adc_long, /*02 */
+ sbb_long, /*03 */
+ and_long, /*04 */
+ sub_long, /*05 */
+ xor_long, /*06 */
+ cmp_long, /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x81
+****************************************************************************/
+static void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /*
+ * Know operation, decode the mod byte to find the addressing
+ * mode.
+ */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 destval,imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ } else {
+ u16 *destreg;
+ u16 destval,imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u8 (*opc82_byte_operation[])(u8 s, u8 d) =
+{
+ add_byte, /*00 */
+ or_byte, /*01 *//*YYY UNUSED ???? */
+ adc_byte, /*02 */
+ sbb_byte, /*03 */
+ and_byte, /*04 *//*YYY UNUSED ???? */
+ sub_byte, /*05 */
+ xor_byte, /*06 *//*YYY UNUSED ???? */
+ cmp_byte, /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x82
+****************************************************************************/
+static void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+ u8 destval;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction Similar to opcode 81, except that
+ * the immediate byte is sign extended to a word length.
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u16 (*opc83_word_operation[])(u16 s, u16 d) =
+{
+ add_word, /*00 */
+ or_word, /*01 *//*YYY UNUSED ???? */
+ adc_word, /*02 */
+ sbb_word, /*03 */
+ and_word, /*04 *//*YYY UNUSED ???? */
+ sub_word, /*05 */
+ xor_word, /*06 *//*YYY UNUSED ???? */
+ cmp_word, /*07 */
+};
+
+static u32 (*opc83_long_operation[])(u32 s, u32 d) =
+{
+ add_long, /*00 */
+ or_long, /*01 *//*YYY UNUSED ???? */
+ adc_long, /*02 */
+ sbb_long, /*03 */
+ and_long, /*04 *//*YYY UNUSED ???? */
+ sub_long, /*05 */
+ xor_long, /*06 *//*YYY UNUSED ???? */
+ cmp_long, /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x83
+****************************************************************************/
+static void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction Similar to opcode 81, except that
+ * the immediate byte is sign extended to a word length.
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ destval = fetch_data_long(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ destval = fetch_data_word(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ destval = fetch_data_long(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ destval = fetch_data_word(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ destval = fetch_data_long(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ destval = fetch_data_word(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 destval,imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ } else {
+ u16 *destreg;
+ u16 destval,imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x84
+****************************************************************************/
+static void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(destval, *srcreg);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(destval, *srcreg);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(destval, *srcreg);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x85
+****************************************************************************/
+static void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(destval, *srcreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(destval, *srcreg);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(destval, *srcreg);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x86
+****************************************************************************/
+static void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+ u8 tmp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XCHG\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x87
+****************************************************************************/
+static void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XCHG\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 destval,tmp;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_long(destoffset, destval);
+ } else {
+ u16 *srcreg;
+ u16 destval,tmp;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 destval,tmp;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_long(destoffset, destval);
+ } else {
+ u16 *srcreg;
+ u16 destval,tmp;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 destval,tmp;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_long(destoffset, destval);
+ } else {
+ u16 *srcreg;
+ u16 destval,tmp;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 tmp;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ } else {
+ u16 *destreg,*srcreg;
+ u16 tmp;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x88
+****************************************************************************/
+static void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, *srcreg);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, *srcreg);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, *srcreg);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x89
+****************************************************************************/
+static void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u32 destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_long(destoffset, *srcreg);
+ } else {
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_word(destoffset, *srcreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_long(destoffset, *srcreg);
+ } else {
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_word(destoffset, *srcreg);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_long(destoffset, *srcreg);
+ } else {
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_word(destoffset, *srcreg);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8a
+****************************************************************************/
+static void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8b
+****************************************************************************/
+static void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg, *srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg, *srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8c
+****************************************************************************/
+static void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *destreg, *srcreg;
+ uint destoffset;
+ u16 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = *srcreg;
+ store_data_word(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = *srcreg;
+ store_data_word(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = *srcreg;
+ store_data_word(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8d
+****************************************************************************/
+static void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LEA\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+ u32 *srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u32)destoffset;
+ } else {
+ u16 *srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u16)destoffset;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+ u32 *srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u32)destoffset;
+ } else {
+ u16 *srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u16)destoffset;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+ u32 *srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u32)destoffset;
+ } else {
+ u16 *srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u16)destoffset;
+ }
+ break;
+ case 3: /* register to register */
+ /* undefined. Do nothing. */
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8e
+****************************************************************************/
+static void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *destreg, *srcreg;
+ uint srcoffset;
+ u16 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 1:
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 2:
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 3: /* register to register */
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ /*
+ * Clean up, and reset all the R_xSP pointers to the correct
+ * locations. This is about 3x too much overhead (doing all the
+ * segreg ptrs when only one is needed, but this instruction
+ * *cannot* be that common, and this isn't too much work anyway.
+ */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8f
+****************************************************************************/
+static void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+ HALT_SYS();
+ }
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_long();
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_word();
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_long();
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_word();
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_long();
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_word();
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = pop_long();
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = pop_word();
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x90
+****************************************************************************/
+static void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("NOP\n");
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x91
+****************************************************************************/
+static void x86emuOp_xchg_word_AX_CX(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,ECX\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,CX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_ECX;
+ M.x86.R_ECX = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_CX;
+ M.x86.R_CX = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x92
+****************************************************************************/
+static void x86emuOp_xchg_word_AX_DX(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EDX\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,DX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EDX;
+ M.x86.R_EDX = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_DX;
+ M.x86.R_DX = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x93
+****************************************************************************/
+static void x86emuOp_xchg_word_AX_BX(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EBX\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,BX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EBX;
+ M.x86.R_EBX = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_BX;
+ M.x86.R_BX = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x94
+****************************************************************************/
+static void x86emuOp_xchg_word_AX_SP(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,ESP\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,SP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_ESP;
+ M.x86.R_ESP = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_SP;
+ M.x86.R_SP = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x95
+****************************************************************************/
+static void x86emuOp_xchg_word_AX_BP(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EBP\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,BP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EBP;
+ M.x86.R_EBP = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_BP;
+ M.x86.R_BP = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x96
+****************************************************************************/
+static void x86emuOp_xchg_word_AX_SI(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,ESI\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,SI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_ESI;
+ M.x86.R_ESI = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_SI;
+ M.x86.R_SI = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x97
+****************************************************************************/
+static void x86emuOp_xchg_word_AX_DI(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EDI\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,DI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EDI;
+ M.x86.R_EDI = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_DI;
+ M.x86.R_DI = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x98
+****************************************************************************/
+static void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CWDE\n");
+ } else {
+ DECODE_PRINTF("CBW\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.R_AX & 0x8000) {
+ M.x86.R_EAX |= 0xffff0000;
+ } else {
+ M.x86.R_EAX &= 0x0000ffff;
+ }
+ } else {
+ if (M.x86.R_AL & 0x80) {
+ M.x86.R_AH = 0xff;
+ } else {
+ M.x86.R_AH = 0x0;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x99
+****************************************************************************/
+static void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CDQ\n");
+ } else {
+ DECODE_PRINTF("CWD\n");
+ }
+ DECODE_PRINTF("CWD\n");
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.R_EAX & 0x80000000) {
+ M.x86.R_EDX = 0xffffffff;
+ } else {
+ M.x86.R_EDX = 0x0;
+ }
+ } else {
+ if (M.x86.R_AX & 0x8000) {
+ M.x86.R_DX = 0xffff;
+ } else {
+ M.x86.R_DX = 0x0;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9a
+****************************************************************************/
+static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 farseg, faroff;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CALL\t");
+ faroff = fetch_word_imm();
+ farseg = fetch_word_imm();
+ DECODE_PRINTF2("%04x:", farseg);
+ DECODE_PRINTF2("%04x\n", faroff);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
+
+ /* XXX
+ *
+ * Hooked interrupt vectors calling into our "BIOS" will cause
+ * problems unless all intersegment stuff is checked for BIOS
+ * access. Check needed here. For moment, let it alone.
+ */
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = farseg;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = faroff;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9b
+****************************************************************************/
+static void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("WAIT");
+ TRACE_AND_STEP();
+ /* NADA. */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9c
+****************************************************************************/
+static void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 flags;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSHFD\n");
+ } else {
+ DECODE_PRINTF("PUSHF\n");
+ }
+ TRACE_AND_STEP();
+
+ /* clear out *all* bits not representing flags, and turn on real bits */
+ flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(flags);
+ } else {
+ push_word((u16)flags);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9d
+****************************************************************************/
+static void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POPFD\n");
+ } else {
+ DECODE_PRINTF("POPF\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EFLG = pop_long();
+ } else {
+ M.x86.R_FLG = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9e
+****************************************************************************/
+static void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("SAHF\n");
+ TRACE_AND_STEP();
+ /* clear the lower bits of the flag register */
+ M.x86.R_FLG &= 0xffffff00;
+ /* or in the AH register into the flags register */
+ M.x86.R_FLG |= M.x86.R_AH;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9f
+****************************************************************************/
+static void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LAHF\n");
+ TRACE_AND_STEP();
+ M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
+ /*undocumented TC++ behavior??? Nope. It's documented, but
+ you have too look real hard to notice it. */
+ M.x86.R_AH |= 0x2;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa0
+****************************************************************************/
+static void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tAL,");
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x]\n", offset);
+ TRACE_AND_STEP();
+ M.x86.R_AL = fetch_data_byte(offset);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa1
+****************************************************************************/
+static void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ offset = fetch_word_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
+ } else {
+ DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = fetch_data_long(offset);
+ } else {
+ M.x86.R_AX = fetch_data_word(offset);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa2
+****************************************************************************/
+static void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x],AL\n", offset);
+ TRACE_AND_STEP();
+ store_data_byte(offset, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa3
+****************************************************************************/
+static void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ offset = fetch_word_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
+ } else {
+ DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ store_data_long(offset, M.x86.R_EAX);
+ } else {
+ store_data_word(offset, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa4
+****************************************************************************/
+static void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
+{
+ u8 val;
+ u32 count;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVS\tBYTE\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ val = fetch_data_byte(M.x86.R_SI);
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa5
+****************************************************************************/
+static void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 val;
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOVS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("MOVS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long(M.x86.R_SI);
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
+ } else {
+ val = fetch_data_word(M.x86.R_SI);
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
+ }
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa6
+****************************************************************************/
+static void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
+{
+ s8 val1, val2;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMPS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa7
+****************************************************************************/
+static void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 val1,val2;
+ int inc;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CMPS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("CMPS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa8
+****************************************************************************/
+static void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\tAL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%04x\n", imm);
+ TRACE_AND_STEP();
+ test_byte(M.x86.R_AL, (u8)imm);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa9
+****************************************************************************/
+static void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("TEST\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("TEST\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ test_long(M.x86.R_EAX, srcval);
+ } else {
+ test_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaa
+****************************************************************************/
+static void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("STOS\tBYTE\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ TRACE_AND_STEP();
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xab
+****************************************************************************/
+static void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("STOS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("STOS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
+ } else {
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
+ }
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xac
+****************************************************************************/
+static void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LODS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+ M.x86.R_SI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xad
+****************************************************************************/
+static void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("LODS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("LODS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
+ } else {
+ M.x86.R_AX = fetch_data_word(M.x86.R_SI);
+ }
+ M.x86.R_SI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xae
+****************************************************************************/
+static void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
+{
+ s8 val2;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SCAS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaf
+****************************************************************************/
+static void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 val;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("SCAS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("SCAS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb0
+****************************************************************************/
+static void x86emuOp_mov_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tAL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_AL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb1
+****************************************************************************/
+static void x86emuOp_mov_byte_CL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tCL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_CL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb2
+****************************************************************************/
+static void x86emuOp_mov_byte_DL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tDL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_DL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb3
+****************************************************************************/
+static void x86emuOp_mov_byte_BL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tBL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_BL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb4
+****************************************************************************/
+static void x86emuOp_mov_byte_AH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tAH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_AH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb5
+****************************************************************************/
+static void x86emuOp_mov_byte_CH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tCH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_CH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb6
+****************************************************************************/
+static void x86emuOp_mov_byte_DH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tDH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_DH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb7
+****************************************************************************/
+static void x86emuOp_mov_byte_BH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tBH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_BH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb8
+****************************************************************************/
+static void x86emuOp_mov_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = srcval;
+ } else {
+ M.x86.R_AX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb9
+****************************************************************************/
+static void x86emuOp_mov_word_CX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tECX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tCX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = srcval;
+ } else {
+ M.x86.R_CX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xba
+****************************************************************************/
+static void x86emuOp_mov_word_DX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEDX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tDX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = srcval;
+ } else {
+ M.x86.R_DX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbb
+****************************************************************************/
+static void x86emuOp_mov_word_BX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEBX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tBX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = srcval;
+ } else {
+ M.x86.R_BX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbc
+****************************************************************************/
+static void x86emuOp_mov_word_SP_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tESP,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tSP,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = srcval;
+ } else {
+ M.x86.R_SP = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbd
+****************************************************************************/
+static void x86emuOp_mov_word_BP_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEBP,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tBP,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = srcval;
+ } else {
+ M.x86.R_BP = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbe
+****************************************************************************/
+static void x86emuOp_mov_word_SI_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tESI,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tSI,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = srcval;
+ } else {
+ M.x86.R_SI = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbf
+****************************************************************************/
+static void x86emuOp_mov_word_DI_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEDI,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tDI,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = srcval;
+ } else {
+ M.x86.R_DI = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* used by opcodes c0, d0, and d2. */
+static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
+{
+ rol_byte,
+ ror_byte,
+ rcl_byte,
+ rcr_byte,
+ shl_byte,
+ shr_byte,
+ shl_byte, /* sal_byte === shl_byte by definition */
+ sar_byte,
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc0
+****************************************************************************/
+static void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* used by opcodes c1, d1, and d3. */
+static u16(*opcD1_word_operation[])(u16 s, u8 d) =
+{
+ rol_word,
+ ror_word,
+ rcl_word,
+ rcr_word,
+ shl_word,
+ shr_word,
+ shl_word, /* sal_byte === shl_byte by definition */
+ sar_word,
+};
+
+/* used by opcodes c1, d1, and d3. */
+static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
+{
+ rol_long,
+ ror_long,
+ rcl_long,
+ rcr_long,
+ shl_long,
+ shr_long,
+ shl_long, /* sal_byte === shl_byte by definition */
+ sar_long,
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc1
+****************************************************************************/
+static void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc2
+****************************************************************************/
+static void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("RET\t");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_SP += imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc3
+****************************************************************************/
+static void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("RET\n");
+ RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc4
+****************************************************************************/
+static void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LES\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_ES = fetch_data_word(srcoffset + 2);
+ break;
+ case 1:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_ES = fetch_data_word(srcoffset + 2);
+ break;
+ case 2:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_ES = fetch_data_word(srcoffset + 2);
+ break;
+ case 3: /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc5
+****************************************************************************/
+static void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LDS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_DS = fetch_data_word(srcoffset + 2);
+ break;
+ case 1:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_DS = fetch_data_word(srcoffset + 2);
+ break;
+ case 2:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_DS = fetch_data_word(srcoffset + 2);
+ break;
+ case 3: /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc6
+****************************************************************************/
+static void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
+ HALT_SYS();
+ }
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, imm);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, imm);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, imm);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc7
+****************************************************************************/
+static void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+ HALT_SYS();
+ }
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_long(destoffset, imm);
+ } else {
+ u16 imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_word(destoffset, imm);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_long(destoffset, imm);
+ } else {
+ u16 imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_word(destoffset, imm);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_long(destoffset, imm);
+ } else {
+ u16 imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_word(destoffset, imm);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ } else {
+ u16 *destreg;
+ u16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc8
+****************************************************************************/
+static void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
+{
+ u16 local,frame_pointer;
+ u8 nesting;
+ int i;
+
+ START_OF_INSTR();
+ local = fetch_word_imm();
+ nesting = fetch_byte_imm();
+ DECODE_PRINTF2("ENTER %x\n", local);
+ DECODE_PRINTF2(",%x\n", nesting);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_BP);
+ frame_pointer = M.x86.R_SP;
+ if (nesting > 0) {
+ for (i = 1; i < nesting; i++) {
+ M.x86.R_BP -= 2;
+ push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
+ }
+ push_word(frame_pointer);
+ }
+ M.x86.R_BP = frame_pointer;
+ M.x86.R_SP = (u16)(M.x86.R_SP - local);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc9
+****************************************************************************/
+static void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LEAVE\n");
+ TRACE_AND_STEP();
+ M.x86.R_SP = M.x86.R_BP;
+ M.x86.R_BP = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xca
+****************************************************************************/
+static void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("RETF\t");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ M.x86.R_SP += imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcb
+****************************************************************************/
+static void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("RETF\n");
+ RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcc
+****************************************************************************/
+static void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("INT 3\n");
+ TRACE_AND_STEP();
+ if (_X86EMU_intrTab[3]) {
+ (*_X86EMU_intrTab[3])(3);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(3 * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(3 * 4);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcd
+****************************************************************************/
+static void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 intnum;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("INT\t");
+ intnum = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", intnum);
+ TRACE_AND_STEP();
+ if (_X86EMU_intrTab[intnum]) {
+ (*_X86EMU_intrTab[intnum])(intnum);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(intnum * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(intnum * 4);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xce
+****************************************************************************/
+static void x86emuOp_into(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("INTO\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_OF)) {
+ if (_X86EMU_intrTab[4]) {
+ (*_X86EMU_intrTab[4])(4);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(4 * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(4 * 4);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcf
+****************************************************************************/
+static void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("IRET\n");
+
+ TRACE_AND_STEP();
+
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ M.x86.R_FLG = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd0
+****************************************************************************/
+static void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, 1);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, 1);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, 1);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd1
+****************************************************************************/
+static void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, 1);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, 1);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, 1);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, 1);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, 1);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, 1);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ } else {
+ u16 destval;
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd2
+****************************************************************************/
+static void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ amt = M.x86.R_CL;
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd3
+****************************************************************************/
+static void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ amt = M.x86.R_CL;
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd4
+****************************************************************************/
+static void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
+{
+ u8 a;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AAM\n");
+ a = fetch_byte_imm(); /* this is a stupid encoding. */
+ if (a != 10) {
+ /* fix: add base decoding
+ aam_word(u8 val, int base a) */
+ DECODE_PRINTF("ERROR DECODING AAM\n");
+ TRACE_REGS();
+ HALT_SYS();
+ }
+ TRACE_AND_STEP();
+ /* note the type change here --- returning AL and AH in AX. */
+ M.x86.R_AX = aam_word(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd5
+****************************************************************************/
+static void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
+{
+ u8 a;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AAD\n");
+ a = fetch_byte_imm();
+ if (a != 10) {
+ /* fix: add base decoding
+ aad_word(u16 val, int base a) */
+ DECODE_PRINTF("ERROR DECODING AAM\n");
+ TRACE_REGS();
+ HALT_SYS();
+ }
+ TRACE_AND_STEP();
+ M.x86.R_AX = aad_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* opcode 0xd6 ILLEGAL OPCODE */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd7
+****************************************************************************/
+static void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
+{
+ u16 addr;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XLAT\n");
+ TRACE_AND_STEP();
+ addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
+ M.x86.R_AL = fetch_data_byte(addr);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* instuctions D8 .. DF are in i87_ops.c */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe0
+****************************************************************************/
+static void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOPNE\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe1
+****************************************************************************/
+static void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOPE\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe2
+****************************************************************************/
+static void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOP\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0)
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe3
+****************************************************************************/
+static void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
+{
+ u16 target;
+ s8 offset;
+
+ /* jump to byte offset if overflow flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JCXZ\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (M.x86.R_CX == 0)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe4
+****************************************************************************/
+static void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\t");
+ port = (u8) fetch_byte_imm();
+ DECODE_PRINTF2("%x,AL\n", port);
+ TRACE_AND_STEP();
+ M.x86.R_AL = (*sys_inb)(port);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe5
+****************************************************************************/
+static void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\t");
+ port = (u8) fetch_byte_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("EAX,%x\n", port);
+ } else {
+ DECODE_PRINTF2("AX,%x\n", port);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = (*sys_inl)(port);
+ } else {
+ M.x86.R_AX = (*sys_inw)(port);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe6
+****************************************************************************/
+static void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\t");
+ port = (u8) fetch_byte_imm();
+ DECODE_PRINTF2("%x,AL\n", port);
+ TRACE_AND_STEP();
+ (*sys_outb)(port, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe7
+****************************************************************************/
+static void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\t");
+ port = (u8) fetch_byte_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("%x,EAX\n", port);
+ } else {
+ DECODE_PRINTF2("%x,AX\n", port);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ (*sys_outl)(port, M.x86.R_EAX);
+ } else {
+ (*sys_outw)(port, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe8
+****************************************************************************/
+static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CALL\t");
+ ip = (s16) fetch_word_imm();
+ ip += (s16) M.x86.R_IP; /* CHECK SIGN */
+ DECODE_PRINTF2("%04x\n", (u16)ip);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe9
+****************************************************************************/
+static void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\t");
+ ip = (s16)fetch_word_imm();
+ ip += (s16)M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", (u16)ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = (u16)ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xea
+****************************************************************************/
+static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 cs, ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\tFAR ");
+ ip = fetch_word_imm();
+ cs = fetch_word_imm();
+ DECODE_PRINTF2("%04x:", cs);
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = ip;
+ M.x86.R_CS = cs;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xeb
+****************************************************************************/
+static void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 target;
+ s8 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xec
+****************************************************************************/
+static void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\tAL,DX\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xed
+****************************************************************************/
+static void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("IN\tEAX,DX\n");
+ } else {
+ DECODE_PRINTF("IN\tAX,DX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
+ } else {
+ M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xee
+****************************************************************************/
+static void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\tDX,AL\n");
+ TRACE_AND_STEP();
+ (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xef
+****************************************************************************/
+static void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OUT\tDX,EAX\n");
+ } else {
+ DECODE_PRINTF("OUT\tDX,AX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
+ } else {
+ (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf0
+****************************************************************************/
+static void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LOCK:\n");
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/*opcode 0xf1 ILLEGAL OPERATION */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf2
+****************************************************************************/
+static void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("REPNE\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_REPNE;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf3
+****************************************************************************/
+static void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("REPE\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_REPE;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf4
+****************************************************************************/
+static void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("HALT\n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf5
+****************************************************************************/
+static void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
+{
+ /* complement the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CMC\n");
+ TRACE_AND_STEP();
+ TOGGLE_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf6
+****************************************************************************/
+static void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval, srcval;
+
+ /* long, drawn out code follows. Double switch for a total
+ of 32 cases. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0: /* mod=00 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ test_byte(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = not_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ mul_byte(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ imul_byte(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ div_byte(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ idiv_byte(destval);
+ break;
+ }
+ break; /* end mod==00 */
+ case 1: /* mod=01 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ test_byte(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = not_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ mul_byte(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ imul_byte(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ div_byte(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ idiv_byte(destval);
+ break;
+ }
+ break; /* end mod==01 */
+ case 2: /* mod=10 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ test_byte(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = not_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ mul_byte(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ imul_byte(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ div_byte(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ idiv_byte(destval);
+ break;
+ }
+ break; /* end mod==10 */
+ case 3: /* mod=11 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ TRACE_AND_STEP();
+ test_byte(*destreg, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_byte(*destreg);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_byte(*destreg);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_byte(*destreg); /*!!! */
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_byte(*destreg);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_byte(*destreg);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_byte(*destreg);
+ break;
+ }
+ break; /* end mod==11 */
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf7
+****************************************************************************/
+static void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /* long, drawn out code follows. Double switch for a total
+ of 32 cases. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0: /* mod=00 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,srcval;
+
+ DECODE_PRINTF("TEST\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ test_long(destval, srcval);
+ } else {
+ u16 destval,srcval;
+
+ DECODE_PRINTF("TEST\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ test_word(destval, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NOT\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = not_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NOT\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = not_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NEG\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NEG\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("MUL\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ mul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("MUL\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ mul_word(destval);
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IMUL\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ imul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IMUL\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ imul_word(destval);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DIV\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ div_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("DIV\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ div_word(destval);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IDIV\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ idiv_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IDIV\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ idiv_word(destval);
+ }
+ break;
+ }
+ break; /* end mod==00 */
+ case 1: /* mod=01 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,srcval;
+
+ DECODE_PRINTF("TEST\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ test_long(destval, srcval);
+ } else {
+ u16 destval,srcval;
+
+ DECODE_PRINTF("TEST\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ test_word(destval, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NOT\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = not_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NOT\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = not_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NEG\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NEG\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("MUL\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ mul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("MUL\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ mul_word(destval);
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IMUL\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ imul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IMUL\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ imul_word(destval);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DIV\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ div_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("DIV\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ div_word(destval);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IDIV\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ idiv_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IDIV\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ idiv_word(destval);
+ }
+ break;
+ }
+ break; /* end mod==01 */
+ case 2: /* mod=10 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,srcval;
+
+ DECODE_PRINTF("TEST\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ test_long(destval, srcval);
+ } else {
+ u16 destval,srcval;
+
+ DECODE_PRINTF("TEST\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ test_word(destval, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NOT\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = not_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NOT\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = not_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NEG\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NEG\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("MUL\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ mul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("MUL\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ mul_word(destval);
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IMUL\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ imul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IMUL\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ imul_word(destval);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DIV\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ div_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("DIV\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ div_word(destval);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IDIV\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ idiv_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IDIV\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ idiv_word(destval);
+ }
+ break;
+ }
+ break; /* end mod==10 */
+ case 3: /* mod=11 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ DECODE_PRINTF("TEST\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ DECODE_PRINTF("TEST\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("NOT\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("NOT\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_word(*destreg);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("NEG\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("NEG\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_word(*destreg);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("MUL\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_long(*destreg); /*!!! */
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("MUL\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_word(*destreg); /*!!! */
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("IMUL\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("IMUL\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_word(*destreg);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("DIV\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("DIV\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_word(*destreg);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("IDIV\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("IDIV\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_word(*destreg);
+ }
+ break;
+ }
+ break; /* end mod==11 */
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf8
+****************************************************************************/
+static void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
+{
+ /* clear the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLC\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf9
+****************************************************************************/
+static void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
+{
+ /* set the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STC\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfa
+****************************************************************************/
+static void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLI\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_IF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfb
+****************************************************************************/
+static void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
+{
+ /* enable interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STI\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_IF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfc
+****************************************************************************/
+static void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLD\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_DF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfd
+****************************************************************************/
+static void x86emuOp_std(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STD\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_DF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfe
+****************************************************************************/
+static void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u8 destval;
+ uint destoffset;
+ u8 *destreg;
+
+ /* Yet another special case instruction. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("INC\t");
+ break;
+ case 1:
+ DECODE_PRINTF("DEC\t");
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
+ HALT_SYS();
+ break;
+ }
+ }
+#endif
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0: /* inc word ptr ... */
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1: /* dec word ptr ... */
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ }
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ }
+ break;
+ case 3:
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ TRACE_AND_STEP();
+ *destreg = inc_byte(*destreg);
+ break;
+ case 1:
+ TRACE_AND_STEP();
+ *destreg = dec_byte(*destreg);
+ break;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xff
+****************************************************************************/
+static void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ uint destoffset = 0;
+ u16 *destreg;
+ u16 destval,destval2;
+
+ /* Yet another special case instruction. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tDWORD PTR ");
+ } else {
+ DECODE_PRINTF("INC\tWORD PTR ");
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tDWORD PTR ");
+ } else {
+ DECODE_PRINTF("DEC\tWORD PTR ");
+ }
+ break;
+ case 2:
+ DECODE_PRINTF("CALL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("CALL\tFAR ");
+ break;
+ case 4:
+ DECODE_PRINTF("JMP\t");
+ break;
+ case 5:
+ DECODE_PRINTF("JMP\tFAR ");
+ break;
+ case 6:
+ DECODE_PRINTF("PUSH\t");
+ break;
+ case 7:
+ DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
+ HALT_SYS();
+ break;
+ }
+ }
+#endif
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0: /* inc word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1: /* dec word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 3: /* call far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = destval2;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 4: /* jmp word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ break;
+ case 5: /* jmp far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ M.x86.R_CS = destval2;
+ break;
+ case 6: /* push word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ push_long(destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(destval);
+ }
+ break;
+ }
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 3: /* call far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = destval2;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 4: /* jmp word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ break;
+ case 5: /* jmp far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ M.x86.R_CS = destval2;
+ break;
+ case 6: /* push word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ push_long(destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(destval);
+ }
+ break;
+ }
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 3: /* call far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = destval2;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 4: /* jmp word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ break;
+ case 5: /* jmp far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ M.x86.R_CS = destval2;
+ break;
+ case 6: /* push word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ push_long(destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(destval);
+ }
+ break;
+ }
+ break;
+ case 3:
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = inc_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = inc_word(*destreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = dec_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = dec_word(*destreg);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = *destreg;
+ break;
+ case 3: /* jmp far ptr ... */
+ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ break;
+
+ case 4: /* jmp ... */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ M.x86.R_IP = (u16) (*destreg);
+ break;
+ case 5: /* jmp far ptr ... */
+ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_word(*destreg);
+ }
+ break;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Single byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab[256])(u8) =
+{
+/* 0x00 */ x86emuOp_add_byte_RM_R,
+/* 0x01 */ x86emuOp_add_word_RM_R,
+/* 0x02 */ x86emuOp_add_byte_R_RM,
+/* 0x03 */ x86emuOp_add_word_R_RM,
+/* 0x04 */ x86emuOp_add_byte_AL_IMM,
+/* 0x05 */ x86emuOp_add_word_AX_IMM,
+/* 0x06 */ x86emuOp_push_ES,
+/* 0x07 */ x86emuOp_pop_ES,
+
+/* 0x08 */ x86emuOp_or_byte_RM_R,
+/* 0x09 */ x86emuOp_or_word_RM_R,
+/* 0x0a */ x86emuOp_or_byte_R_RM,
+/* 0x0b */ x86emuOp_or_word_R_RM,
+/* 0x0c */ x86emuOp_or_byte_AL_IMM,
+/* 0x0d */ x86emuOp_or_word_AX_IMM,
+/* 0x0e */ x86emuOp_push_CS,
+/* 0x0f */ x86emuOp_two_byte,
+
+/* 0x10 */ x86emuOp_adc_byte_RM_R,
+/* 0x11 */ x86emuOp_adc_word_RM_R,
+/* 0x12 */ x86emuOp_adc_byte_R_RM,
+/* 0x13 */ x86emuOp_adc_word_R_RM,
+/* 0x14 */ x86emuOp_adc_byte_AL_IMM,
+/* 0x15 */ x86emuOp_adc_word_AX_IMM,
+/* 0x16 */ x86emuOp_push_SS,
+/* 0x17 */ x86emuOp_pop_SS,
+
+/* 0x18 */ x86emuOp_sbb_byte_RM_R,
+/* 0x19 */ x86emuOp_sbb_word_RM_R,
+/* 0x1a */ x86emuOp_sbb_byte_R_RM,
+/* 0x1b */ x86emuOp_sbb_word_R_RM,
+/* 0x1c */ x86emuOp_sbb_byte_AL_IMM,
+/* 0x1d */ x86emuOp_sbb_word_AX_IMM,
+/* 0x1e */ x86emuOp_push_DS,
+/* 0x1f */ x86emuOp_pop_DS,
+
+/* 0x20 */ x86emuOp_and_byte_RM_R,
+/* 0x21 */ x86emuOp_and_word_RM_R,
+/* 0x22 */ x86emuOp_and_byte_R_RM,
+/* 0x23 */ x86emuOp_and_word_R_RM,
+/* 0x24 */ x86emuOp_and_byte_AL_IMM,
+/* 0x25 */ x86emuOp_and_word_AX_IMM,
+/* 0x26 */ x86emuOp_segovr_ES,
+/* 0x27 */ x86emuOp_daa,
+
+/* 0x28 */ x86emuOp_sub_byte_RM_R,
+/* 0x29 */ x86emuOp_sub_word_RM_R,
+/* 0x2a */ x86emuOp_sub_byte_R_RM,
+/* 0x2b */ x86emuOp_sub_word_R_RM,
+/* 0x2c */ x86emuOp_sub_byte_AL_IMM,
+/* 0x2d */ x86emuOp_sub_word_AX_IMM,
+/* 0x2e */ x86emuOp_segovr_CS,
+/* 0x2f */ x86emuOp_das,
+
+/* 0x30 */ x86emuOp_xor_byte_RM_R,
+/* 0x31 */ x86emuOp_xor_word_RM_R,
+/* 0x32 */ x86emuOp_xor_byte_R_RM,
+/* 0x33 */ x86emuOp_xor_word_R_RM,
+/* 0x34 */ x86emuOp_xor_byte_AL_IMM,
+/* 0x35 */ x86emuOp_xor_word_AX_IMM,
+/* 0x36 */ x86emuOp_segovr_SS,
+/* 0x37 */ x86emuOp_aaa,
+
+/* 0x38 */ x86emuOp_cmp_byte_RM_R,
+/* 0x39 */ x86emuOp_cmp_word_RM_R,
+/* 0x3a */ x86emuOp_cmp_byte_R_RM,
+/* 0x3b */ x86emuOp_cmp_word_R_RM,
+/* 0x3c */ x86emuOp_cmp_byte_AL_IMM,
+/* 0x3d */ x86emuOp_cmp_word_AX_IMM,
+/* 0x3e */ x86emuOp_segovr_DS,
+/* 0x3f */ x86emuOp_aas,
+
+/* 0x40 */ x86emuOp_inc_AX,
+/* 0x41 */ x86emuOp_inc_CX,
+/* 0x42 */ x86emuOp_inc_DX,
+/* 0x43 */ x86emuOp_inc_BX,
+/* 0x44 */ x86emuOp_inc_SP,
+/* 0x45 */ x86emuOp_inc_BP,
+/* 0x46 */ x86emuOp_inc_SI,
+/* 0x47 */ x86emuOp_inc_DI,
+
+/* 0x48 */ x86emuOp_dec_AX,
+/* 0x49 */ x86emuOp_dec_CX,
+/* 0x4a */ x86emuOp_dec_DX,
+/* 0x4b */ x86emuOp_dec_BX,
+/* 0x4c */ x86emuOp_dec_SP,
+/* 0x4d */ x86emuOp_dec_BP,
+/* 0x4e */ x86emuOp_dec_SI,
+/* 0x4f */ x86emuOp_dec_DI,
+
+/* 0x50 */ x86emuOp_push_AX,
+/* 0x51 */ x86emuOp_push_CX,
+/* 0x52 */ x86emuOp_push_DX,
+/* 0x53 */ x86emuOp_push_BX,
+/* 0x54 */ x86emuOp_push_SP,
+/* 0x55 */ x86emuOp_push_BP,
+/* 0x56 */ x86emuOp_push_SI,
+/* 0x57 */ x86emuOp_push_DI,
+
+/* 0x58 */ x86emuOp_pop_AX,
+/* 0x59 */ x86emuOp_pop_CX,
+/* 0x5a */ x86emuOp_pop_DX,
+/* 0x5b */ x86emuOp_pop_BX,
+/* 0x5c */ x86emuOp_pop_SP,
+/* 0x5d */ x86emuOp_pop_BP,
+/* 0x5e */ x86emuOp_pop_SI,
+/* 0x5f */ x86emuOp_pop_DI,
+
+/* 0x60 */ x86emuOp_push_all,
+/* 0x61 */ x86emuOp_pop_all,
+/* 0x62 */ x86emuOp_illegal_op, /* bound */
+/* 0x63 */ x86emuOp_illegal_op, /* arpl */
+/* 0x64 */ x86emuOp_segovr_FS,
+/* 0x65 */ x86emuOp_segovr_GS,
+/* 0x66 */ x86emuOp_prefix_data,
+/* 0x67 */ x86emuOp_prefix_addr,
+
+/* 0x68 */ x86emuOp_push_word_IMM,
+/* 0x69 */ x86emuOp_imul_word_IMM,
+/* 0x6a */ x86emuOp_push_byte_IMM,
+/* 0x6b */ x86emuOp_imul_byte_IMM,
+/* 0x6c */ x86emuOp_ins_byte,
+/* 0x6d */ x86emuOp_ins_word,
+/* 0x6e */ x86emuOp_outs_byte,
+/* 0x6f */ x86emuOp_outs_word,
+
+/* 0x70 */ x86emuOp_jump_near_O,
+/* 0x71 */ x86emuOp_jump_near_NO,
+/* 0x72 */ x86emuOp_jump_near_B,
+/* 0x73 */ x86emuOp_jump_near_NB,
+/* 0x74 */ x86emuOp_jump_near_Z,
+/* 0x75 */ x86emuOp_jump_near_NZ,
+/* 0x76 */ x86emuOp_jump_near_BE,
+/* 0x77 */ x86emuOp_jump_near_NBE,
+
+/* 0x78 */ x86emuOp_jump_near_S,
+/* 0x79 */ x86emuOp_jump_near_NS,
+/* 0x7a */ x86emuOp_jump_near_P,
+/* 0x7b */ x86emuOp_jump_near_NP,
+/* 0x7c */ x86emuOp_jump_near_L,
+/* 0x7d */ x86emuOp_jump_near_NL,
+/* 0x7e */ x86emuOp_jump_near_LE,
+/* 0x7f */ x86emuOp_jump_near_NLE,
+
+/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
+/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
+/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
+/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
+/* 0x84 */ x86emuOp_test_byte_RM_R,
+/* 0x85 */ x86emuOp_test_word_RM_R,
+/* 0x86 */ x86emuOp_xchg_byte_RM_R,
+/* 0x87 */ x86emuOp_xchg_word_RM_R,
+
+/* 0x88 */ x86emuOp_mov_byte_RM_R,
+/* 0x89 */ x86emuOp_mov_word_RM_R,
+/* 0x8a */ x86emuOp_mov_byte_R_RM,
+/* 0x8b */ x86emuOp_mov_word_R_RM,
+/* 0x8c */ x86emuOp_mov_word_RM_SR,
+/* 0x8d */ x86emuOp_lea_word_R_M,
+/* 0x8e */ x86emuOp_mov_word_SR_RM,
+/* 0x8f */ x86emuOp_pop_RM,
+
+/* 0x90 */ x86emuOp_nop,
+/* 0x91 */ x86emuOp_xchg_word_AX_CX,
+/* 0x92 */ x86emuOp_xchg_word_AX_DX,
+/* 0x93 */ x86emuOp_xchg_word_AX_BX,
+/* 0x94 */ x86emuOp_xchg_word_AX_SP,
+/* 0x95 */ x86emuOp_xchg_word_AX_BP,
+/* 0x96 */ x86emuOp_xchg_word_AX_SI,
+/* 0x97 */ x86emuOp_xchg_word_AX_DI,
+
+/* 0x98 */ x86emuOp_cbw,
+/* 0x99 */ x86emuOp_cwd,
+/* 0x9a */ x86emuOp_call_far_IMM,
+/* 0x9b */ x86emuOp_wait,
+/* 0x9c */ x86emuOp_pushf_word,
+/* 0x9d */ x86emuOp_popf_word,
+/* 0x9e */ x86emuOp_sahf,
+/* 0x9f */ x86emuOp_lahf,
+
+/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
+/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
+/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
+/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
+/* 0xa4 */ x86emuOp_movs_byte,
+/* 0xa5 */ x86emuOp_movs_word,
+/* 0xa6 */ x86emuOp_cmps_byte,
+/* 0xa7 */ x86emuOp_cmps_word,
+/* 0xa8 */ x86emuOp_test_AL_IMM,
+/* 0xa9 */ x86emuOp_test_AX_IMM,
+/* 0xaa */ x86emuOp_stos_byte,
+/* 0xab */ x86emuOp_stos_word,
+/* 0xac */ x86emuOp_lods_byte,
+/* 0xad */ x86emuOp_lods_word,
+/* 0xac */ x86emuOp_scas_byte,
+/* 0xad */ x86emuOp_scas_word,
+
+
+/* 0xb0 */ x86emuOp_mov_byte_AL_IMM,
+/* 0xb1 */ x86emuOp_mov_byte_CL_IMM,
+/* 0xb2 */ x86emuOp_mov_byte_DL_IMM,
+/* 0xb3 */ x86emuOp_mov_byte_BL_IMM,
+/* 0xb4 */ x86emuOp_mov_byte_AH_IMM,
+/* 0xb5 */ x86emuOp_mov_byte_CH_IMM,
+/* 0xb6 */ x86emuOp_mov_byte_DH_IMM,
+/* 0xb7 */ x86emuOp_mov_byte_BH_IMM,
+
+/* 0xb8 */ x86emuOp_mov_word_AX_IMM,
+/* 0xb9 */ x86emuOp_mov_word_CX_IMM,
+/* 0xba */ x86emuOp_mov_word_DX_IMM,
+/* 0xbb */ x86emuOp_mov_word_BX_IMM,
+/* 0xbc */ x86emuOp_mov_word_SP_IMM,
+/* 0xbd */ x86emuOp_mov_word_BP_IMM,
+/* 0xbe */ x86emuOp_mov_word_SI_IMM,
+/* 0xbf */ x86emuOp_mov_word_DI_IMM,
+
+/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
+/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
+/* 0xc2 */ x86emuOp_ret_near_IMM,
+/* 0xc3 */ x86emuOp_ret_near,
+/* 0xc4 */ x86emuOp_les_R_IMM,
+/* 0xc5 */ x86emuOp_lds_R_IMM,
+/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
+/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
+/* 0xc8 */ x86emuOp_enter,
+/* 0xc9 */ x86emuOp_leave,
+/* 0xca */ x86emuOp_ret_far_IMM,
+/* 0xcb */ x86emuOp_ret_far,
+/* 0xcc */ x86emuOp_int3,
+/* 0xcd */ x86emuOp_int_IMM,
+/* 0xce */ x86emuOp_into,
+/* 0xcf */ x86emuOp_iret,
+
+/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
+/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
+/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
+/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
+/* 0xd4 */ x86emuOp_aam,
+/* 0xd5 */ x86emuOp_aad,
+/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
+/* 0xd7 */ x86emuOp_xlat,
+/* 0xd8 */ x86emuOp_esc_coprocess_d8,
+/* 0xd9 */ x86emuOp_esc_coprocess_d9,
+/* 0xda */ x86emuOp_esc_coprocess_da,
+/* 0xdb */ x86emuOp_esc_coprocess_db,
+/* 0xdc */ x86emuOp_esc_coprocess_dc,
+/* 0xdd */ x86emuOp_esc_coprocess_dd,
+/* 0xde */ x86emuOp_esc_coprocess_de,
+/* 0xdf */ x86emuOp_esc_coprocess_df,
+
+/* 0xe0 */ x86emuOp_loopne,
+/* 0xe1 */ x86emuOp_loope,
+/* 0xe2 */ x86emuOp_loop,
+/* 0xe3 */ x86emuOp_jcxz,
+/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
+/* 0xe5 */ x86emuOp_in_word_AX_IMM,
+/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
+/* 0xe7 */ x86emuOp_out_word_IMM_AX,
+
+/* 0xe8 */ x86emuOp_call_near_IMM,
+/* 0xe9 */ x86emuOp_jump_near_IMM,
+/* 0xea */ x86emuOp_jump_far_IMM,
+/* 0xeb */ x86emuOp_jump_byte_IMM,
+/* 0xec */ x86emuOp_in_byte_AL_DX,
+/* 0xed */ x86emuOp_in_word_AX_DX,
+/* 0xee */ x86emuOp_out_byte_DX_AL,
+/* 0xef */ x86emuOp_out_word_DX_AX,
+
+/* 0xf0 */ x86emuOp_lock,
+/* 0xf1 */ x86emuOp_illegal_op,
+/* 0xf2 */ x86emuOp_repne,
+/* 0xf3 */ x86emuOp_repe,
+/* 0xf4 */ x86emuOp_halt,
+/* 0xf5 */ x86emuOp_cmc,
+/* 0xf6 */ x86emuOp_opcF6_byte_RM,
+/* 0xf7 */ x86emuOp_opcF7_word_RM,
+
+/* 0xf8 */ x86emuOp_clc,
+/* 0xf9 */ x86emuOp_stc,
+/* 0xfa */ x86emuOp_cli,
+/* 0xfb */ x86emuOp_sti,
+/* 0xfc */ x86emuOp_cld,
+/* 0xfd */ x86emuOp_std,
+/* 0xfe */ x86emuOp_opcFE_byte_RM,
+/* 0xff */ x86emuOp_opcFF_word_RM,
+};