mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-19 07:38:28 +00:00
Imported Genode release 11.11
This commit is contained in:
committed by
Christian Helmuth
parent
6bcc9aef0e
commit
da4e1feaa5
129
os/src/drivers/framebuffer/fiasco_ux/framebuffer.cc
Normal file
129
os/src/drivers/framebuffer/fiasco_ux/framebuffer.cc
Normal file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* \brief Fiasco-UX Framebuffer driver
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-08-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/stdint.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/snprintf.h>
|
||||
|
||||
#include <rom_session/connection.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/vhw.h>
|
||||
}
|
||||
|
||||
#include "framebuffer.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Framebuffer area
|
||||
*/
|
||||
static Dataspace_capability io_mem_cap;
|
||||
|
||||
|
||||
/****************
|
||||
** Driver API **
|
||||
****************/
|
||||
|
||||
Dataspace_capability Framebuffer_drv::hw_framebuffer()
|
||||
{
|
||||
return io_mem_cap;
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** Driver startup **
|
||||
********************/
|
||||
|
||||
/**
|
||||
* Configure Fiasco kernel info page
|
||||
*/
|
||||
static void *map_kip()
|
||||
{
|
||||
/* request KIP dataspace */
|
||||
Rom_connection rom("l4v2_kip");
|
||||
rom.on_destruction(Rom_connection::KEEP_OPEN);
|
||||
|
||||
/* attach KIP dataspace */
|
||||
return env()->rm_session()->attach(rom.dataspace());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read virtual hardware descriptor from kernel info page
|
||||
*/
|
||||
static int init_framebuffer_vhw(void *kip, addr_t *base, size_t *size)
|
||||
{
|
||||
Fiasco::l4_kernel_info_t *kip_ptr = (Fiasco::l4_kernel_info_t *)kip;
|
||||
struct Fiasco::l4_vhw_descriptor *vhw = Fiasco::l4_vhw_get(kip_ptr);
|
||||
if (!vhw) return -1;
|
||||
|
||||
struct Fiasco::l4_vhw_entry *e = Fiasco::l4_vhw_get_entry_type(vhw, Fiasco::L4_TYPE_VHW_FRAMEBUFFER);
|
||||
if (!e) return -2;
|
||||
|
||||
*base = e->mem_start;
|
||||
*size = e->mem_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure io_mem area containing Fiasco-UX framebuffer
|
||||
*/
|
||||
Dataspace_capability map_framebuffer_area(addr_t base, size_t size, void **framebuffer)
|
||||
{
|
||||
/* request io_mem dataspace */
|
||||
Io_mem_connection io_mem(base, size);
|
||||
io_mem.on_destruction(Io_mem_connection::KEEP_OPEN);
|
||||
Io_mem_dataspace_capability io_mem_ds = io_mem.dataspace();
|
||||
if (!io_mem_ds.valid()) return Dataspace_capability();
|
||||
|
||||
/* attach io_mem dataspace */
|
||||
*framebuffer = env()->rm_session()->attach(io_mem_ds);
|
||||
return io_mem_ds;
|
||||
}
|
||||
|
||||
|
||||
int Framebuffer_drv::init()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
void *kip = 0;
|
||||
try { kip = map_kip(); }
|
||||
catch (...) {
|
||||
PERR("KIP mapping failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr_t base; size_t size;
|
||||
if (init_framebuffer_vhw(kip, &base, &size)) {
|
||||
PERR("VHW framebuffer init failed");
|
||||
return 2;
|
||||
}
|
||||
|
||||
PDBG("--- framebuffer area is [%lx,%lx) ---", base, base + size);
|
||||
|
||||
void *framebuffer = 0;
|
||||
io_mem_cap = map_framebuffer_area(base, size, &framebuffer);
|
||||
if (!io_mem_cap.valid()) {
|
||||
PERR("VHW framebuffer area mapping failed");
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
32
os/src/drivers/framebuffer/fiasco_ux/framebuffer.h
Normal file
32
os/src/drivers/framebuffer/fiasco_ux/framebuffer.h
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* \brief Framebuffer driver interface
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-08-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _FRAMEBUFFER_H
|
||||
#define _FRAMEBUFFER_H
|
||||
|
||||
#include <dataspace/capability.h>
|
||||
|
||||
namespace Framebuffer_drv {
|
||||
|
||||
/**
|
||||
* Return capability for h/w framebuffer dataspace
|
||||
*/
|
||||
Genode::Dataspace_capability hw_framebuffer();
|
||||
|
||||
/**
|
||||
* Initialize driver
|
||||
*/
|
||||
int init();
|
||||
}
|
||||
|
||||
#endif
|
125
os/src/drivers/framebuffer/fiasco_ux/main.cc
Normal file
125
os/src/drivers/framebuffer/fiasco_ux/main.cc
Normal file
@ -0,0 +1,125 @@
|
||||
/**
|
||||
* \brief Framebuffer driver front-end
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-08-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <root/component.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <framebuffer_session/framebuffer_session.h>
|
||||
|
||||
/* Local */
|
||||
#include "framebuffer.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/***********************************************
|
||||
** Implementation of the framebuffer service **
|
||||
***********************************************/
|
||||
|
||||
/*
|
||||
* Screen configuration
|
||||
*
|
||||
* FIXME currently it's 640x480@16 and not configurable
|
||||
*/
|
||||
static int scr_width = 640, scr_height = 480, scr_mode = 16;
|
||||
|
||||
namespace Framebuffer {
|
||||
|
||||
class Session_component : public Genode::Rpc_object<Session>
|
||||
{
|
||||
public:
|
||||
|
||||
Dataspace_capability dataspace() { return Framebuffer_drv::hw_framebuffer(); }
|
||||
|
||||
void info(int *out_w, int *out_h, Mode *out_mode)
|
||||
{
|
||||
*out_w = scr_width;
|
||||
*out_h = scr_height;
|
||||
|
||||
switch (scr_mode) {
|
||||
case 16: *out_mode = RGB565; break;
|
||||
default: *out_mode = INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
void refresh(int x, int y, int w, int h)
|
||||
{
|
||||
#if 0
|
||||
/* clip refresh area to screen boundaries */
|
||||
int x1 = max(x, 0);
|
||||
int y1 = max(y, 0);
|
||||
int x2 = min(x + w - 1, scr_width - 1);
|
||||
int y2 = min(y + h - 1, scr_height - 1);
|
||||
|
||||
if (x1 > x2 || y1 > y2) return;
|
||||
|
||||
/* copy pixels from shared dataspace to sdl surface */
|
||||
const int start_offset = bytes_per_pixel()*(y1*scr_width + x1);
|
||||
const int line_len = bytes_per_pixel()*(x2 - x1 + 1);
|
||||
const int pitch = bytes_per_pixel()*scr_width;
|
||||
|
||||
char *src = (char *)fb_ds_addr + start_offset;
|
||||
char *dst = (char *)screen->pixels + start_offset;
|
||||
|
||||
for (int i = y1; i <= y2; i++, src += pitch, dst += pitch)
|
||||
Genode::memcpy(dst, src, line_len);
|
||||
|
||||
/* flush pixels in sdl window */
|
||||
SDL_UpdateRect(screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Root : public Root_component<Session_component>
|
||||
{
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) {
|
||||
return new (md_alloc()) Session_component(); }
|
||||
|
||||
public:
|
||||
|
||||
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc)
|
||||
: Root_component<Session_component>(session_ep, md_alloc) { }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* initialize server entry point */
|
||||
enum { STACK_SIZE = 4096 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep");
|
||||
|
||||
/* init driver back-end */
|
||||
if (Framebuffer_drv::init()) {
|
||||
PERR("H/W driver init failed");
|
||||
return 3;
|
||||
}
|
||||
|
||||
static Framebuffer::Root fb_root(&ep, env()->heap());
|
||||
|
||||
/* tell parent about the service */
|
||||
env()->parent()->announce(ep.manage(&fb_root));
|
||||
|
||||
/* main's done - go to sleep */
|
||||
|
||||
sleep_forever();
|
||||
return 0;
|
||||
}
|
4
os/src/drivers/framebuffer/fiasco_ux/target.mk
Normal file
4
os/src/drivers/framebuffer/fiasco_ux/target.mk
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = framebuffer_ux_drv
|
||||
REQUIRES = fiasco x86
|
||||
SRC_CC = main.cc framebuffer.cc
|
||||
LIBS = cxx env server
|
236
os/src/drivers/framebuffer/pl11x/main.cc
Normal file
236
os/src/drivers/framebuffer/pl11x/main.cc
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* \brief PL11x frame-buffer driver
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-02-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <framebuffer_session/framebuffer_session.h>
|
||||
#include <root/component.h>
|
||||
#include <os/ring_buffer.h>
|
||||
|
||||
/* device configuration */
|
||||
#include <pl11x_defs.h>
|
||||
#include <sp810_defs.h>
|
||||
#include <video_memory.h>
|
||||
|
||||
|
||||
/***********************************************
|
||||
** Implementation of the framebuffer service **
|
||||
***********************************************/
|
||||
|
||||
namespace Framebuffer
|
||||
{
|
||||
|
||||
enum {
|
||||
SCR_WIDTH = 640,
|
||||
SCR_HEIGHT = 480,
|
||||
LEFT_MARGIN = 64,
|
||||
RIGHT_MARGIN = 32,
|
||||
UPPER_MARGIN = 9,
|
||||
LOWER_MARGIN = 11,
|
||||
HSYNC_LEN = 64,
|
||||
VSYNC_LEN = 25,
|
||||
|
||||
BYTES_PER_PIXEL = 2,
|
||||
FRAMEBUFFER_SIZE = SCR_WIDTH*SCR_HEIGHT*BYTES_PER_PIXEL,
|
||||
};
|
||||
|
||||
class Session_component : public Genode::Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Dataspace_capability _fb_ds_cap;
|
||||
Genode::Dataspace_client _fb_ds;
|
||||
Genode::addr_t _regs_base;
|
||||
Genode::addr_t _sys_regs_base;
|
||||
Timer::Connection _timer;
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Bit definitions of the lcd control register
|
||||
*/
|
||||
CTRL_ENABLED = 1 << 0,
|
||||
CTRL_BPP16 = 4 << 1,
|
||||
CTRL_BPP16_565 = 6 << 1,
|
||||
CTRL_TFT = 1 << 5,
|
||||
CTRL_BGR = 1 << 8,
|
||||
CTRL_POWER = 1 << 11,
|
||||
CTRL_VCOMP = 1 << 12,
|
||||
|
||||
/**
|
||||
* Bit definitions for CLCDC timing.
|
||||
*/
|
||||
CLCDC_IVS = 1 << 11,
|
||||
CLCDC_IHS = 1 << 12,
|
||||
CLCDC_BCD = 1 << 26,
|
||||
};
|
||||
|
||||
void sys_reg_write(unsigned reg, long value) {
|
||||
*(volatile long *)(_sys_regs_base + sizeof(long)*reg) = value; }
|
||||
|
||||
long sys_reg_read(unsigned reg) {
|
||||
return *(volatile long *)(_sys_regs_base + sizeof(long)*reg); }
|
||||
|
||||
void reg_write(unsigned reg, long value) {
|
||||
*(volatile long *)(_regs_base + sizeof(long)*reg) = value; }
|
||||
|
||||
long reg_read(unsigned reg) {
|
||||
return *(volatile long *)(_regs_base + sizeof(long)*reg); }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(void *regs_base, void *sys_regs_base,
|
||||
Genode::Dataspace_capability fb_ds_cap)
|
||||
: _fb_ds_cap(fb_ds_cap), _fb_ds(_fb_ds_cap),
|
||||
_regs_base((Genode::addr_t)regs_base),
|
||||
_sys_regs_base((Genode::addr_t)sys_regs_base)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
uint32_t tim0 = (SCR_WIDTH/16 - 1) << 2
|
||||
| (HSYNC_LEN - 1) << 8
|
||||
| (RIGHT_MARGIN - 1) << 16
|
||||
| (LEFT_MARGIN - 1) << 24;
|
||||
uint32_t tim1 = (SCR_HEIGHT - 1)
|
||||
| (VSYNC_LEN - 1) << 10
|
||||
| LOWER_MARGIN << 16
|
||||
| UPPER_MARGIN << 24;
|
||||
uint32_t tim2 = ((SCR_WIDTH - 1) << 16)
|
||||
| CLCDC_IVS | CLCDC_IHS | CLCDC_BCD;
|
||||
uint32_t tim3 = 0;
|
||||
uint32_t ctrl = reg_read(PL11X_REG_CTRL);
|
||||
|
||||
/* reset video if already enabled */
|
||||
if (ctrl & CTRL_POWER) {
|
||||
ctrl &= ~CTRL_POWER;
|
||||
reg_write(PL11X_REG_CTRL, ctrl);
|
||||
_timer.msleep(100);
|
||||
}
|
||||
if (ctrl & CTRL_ENABLED) {
|
||||
ctrl &= ~CTRL_ENABLED;
|
||||
reg_write(PL11X_REG_CTRL, ctrl);
|
||||
_timer.msleep(100);
|
||||
}
|
||||
|
||||
ctrl = CTRL_BGR | CTRL_ENABLED | CTRL_TFT | CTRL_VCOMP;
|
||||
|
||||
/*
|
||||
* QEmu (version <= 14.x) doesn't emulate pl11x properly,
|
||||
* set bpp16 although we actually use bbp16_565.
|
||||
* It doesn't set the system's identity register,
|
||||
* so we can detect it.
|
||||
*/
|
||||
ctrl |= (sys_reg_read(SP810_REG_ID) == 0) ? CTRL_BPP16 : CTRL_BPP16_565;
|
||||
|
||||
/* init color-lcd oscillator */
|
||||
sys_reg_write(SP810_REG_LOCK, 0xa05f);
|
||||
sys_reg_write(SP810_REG_OSCCLCD, 0x2c77);
|
||||
sys_reg_write(SP810_REG_LOCK, 0);
|
||||
|
||||
/* init video timing */
|
||||
reg_write(PL11X_REG_TIMING0, tim0);
|
||||
reg_write(PL11X_REG_TIMING1, tim1);
|
||||
reg_write(PL11X_REG_TIMING2, tim2);
|
||||
reg_write(PL11X_REG_TIMING3, tim3);
|
||||
|
||||
/* set framebuffer address and ctrl register */
|
||||
reg_write(PL11X_REG_UPBASE, _fb_ds.phys_addr());
|
||||
reg_write(PL11X_REG_LPBASE, 0);
|
||||
reg_write(PL11X_REG_IMSC, 0);
|
||||
reg_write(PL11X_REG_CTRL, ctrl);
|
||||
_timer.msleep(100);
|
||||
|
||||
/* power on */
|
||||
reg_write(PL11X_REG_CTRL, ctrl | CTRL_POWER);
|
||||
}
|
||||
|
||||
Genode::Dataspace_capability dataspace() { return _fb_ds_cap; }
|
||||
|
||||
void info(int *out_w, int *out_h, Mode *out_mode)
|
||||
{
|
||||
*out_w = SCR_WIDTH;
|
||||
*out_h = SCR_HEIGHT;
|
||||
*out_mode = RGB565;
|
||||
}
|
||||
|
||||
void refresh(int x, int y, int w, int h) { }
|
||||
};
|
||||
|
||||
|
||||
class Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
void *_lcd_regs_base;
|
||||
void *_sys_regs_base;
|
||||
Genode::Dataspace_capability _fb_ds_cap;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) {
|
||||
return new (md_alloc()) Session_component(_lcd_regs_base,
|
||||
_sys_regs_base,
|
||||
_fb_ds_cap); }
|
||||
|
||||
public:
|
||||
|
||||
Root(Genode::Rpc_entrypoint *session_ep, Genode::Allocator *md_alloc,
|
||||
void *lcd_regs_base, void *sys_regs_base,
|
||||
Genode::Dataspace_capability fb_ds_cap)
|
||||
: Genode::Root_component<Session_component>(session_ep, md_alloc),
|
||||
_lcd_regs_base(lcd_regs_base), _sys_regs_base(sys_regs_base),
|
||||
_fb_ds_cap(fb_ds_cap) { }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
printf("--- pl11x framebuffer driver ---\n");
|
||||
|
||||
/* locally map LCD control registers */
|
||||
Io_mem_connection lcd_io_mem(PL11X_LCD_PHYS, PL11X_LCD_SIZE);
|
||||
void *lcd_base = env()->rm_session()->attach(lcd_io_mem.dataspace());
|
||||
|
||||
/* locally map system control registers */
|
||||
Io_mem_connection sys_mem(SP810_PHYS, SP810_SIZE);
|
||||
void *sys_base = env()->rm_session()->attach(sys_mem.dataspace());
|
||||
|
||||
enum { STACK_SIZE = 4096 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep");
|
||||
|
||||
Dataspace_capability fb_ds_cap =
|
||||
Framebuffer::alloc_video_memory(Framebuffer::FRAMEBUFFER_SIZE);
|
||||
|
||||
/*
|
||||
* Let the entry point serve the framebuffer and input root interfaces
|
||||
*/
|
||||
static Framebuffer::Root fb_root(&ep, env()->heap(), lcd_base, sys_base, fb_ds_cap);
|
||||
env()->parent()->announce(ep.manage(&fb_root));
|
||||
|
||||
sleep_forever();
|
||||
|
||||
return 0;
|
||||
}
|
7
os/src/drivers/framebuffer/pl11x/pbxa9/target.mk
Normal file
7
os/src/drivers/framebuffer/pl11x/pbxa9/target.mk
Normal file
@ -0,0 +1,7 @@
|
||||
TARGET = pl11x_drv
|
||||
REQUIRES = pl11x platform_pbxa9
|
||||
SRC_CC = main.cc video_memory.cc
|
||||
LIBS = cxx env server
|
||||
INC_DIR += $(PRG_DIR)/..
|
||||
|
||||
vpath %.cc $(PRG_DIR)/..
|
0
os/src/drivers/framebuffer/pl11x/target.mk
Normal file
0
os/src/drivers/framebuffer/pl11x/target.mk
Normal file
7
os/src/drivers/framebuffer/pl11x/vea9x4/target.mk
Normal file
7
os/src/drivers/framebuffer/pl11x/vea9x4/target.mk
Normal file
@ -0,0 +1,7 @@
|
||||
TARGET = pl11x_drv
|
||||
REQUIRES = pl11x platform_vea9x4
|
||||
SRC_CC = main.cc video_memory.cc
|
||||
LIBS = cxx env server
|
||||
INC_DIR += $(PRG_DIR)/..
|
||||
|
||||
vpath main.cc $(PRG_DIR)/..
|
27
os/src/drivers/framebuffer/pl11x/vea9x4/video_memory.cc
Normal file
27
os/src/drivers/framebuffer/pl11x/vea9x4/video_memory.cc
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* \brief PL11x video memory function for versatile express A9x4.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-11-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
|
||||
#include <pl11x_defs.h>
|
||||
#include <video_memory.h>
|
||||
|
||||
Genode::Dataspace_capability Framebuffer::alloc_video_memory(Genode::size_t sz) {
|
||||
using namespace Genode;
|
||||
|
||||
Io_mem_connection *fb_mem =
|
||||
new (env()->heap()) Io_mem_connection(PL11X_VIDEO_RAM, sz);
|
||||
return fb_mem->dataspace();
|
||||
}
|
22
os/src/drivers/framebuffer/pl11x/video_memory.cc
Normal file
22
os/src/drivers/framebuffer/pl11x/video_memory.cc
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* \brief PL11x video memory function for platform baseboard cortex-A9.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-11-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
|
||||
#include <pl11x_defs.h>
|
||||
#include <video_memory.h>
|
||||
|
||||
Genode::Dataspace_capability Framebuffer::alloc_video_memory(Genode::size_t sz) {
|
||||
return Genode::env()->ram_session()->alloc(sz);
|
||||
}
|
26
os/src/drivers/framebuffer/pl11x/video_memory.h
Normal file
26
os/src/drivers/framebuffer/pl11x/video_memory.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* \brief Video memory allocator.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-11-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__VIDEOMEM_ALLOCATOR_H_
|
||||
#define _INCLUDE__VIDEOMEM_ALLOCATOR_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
#include <dataspace/capability.h>
|
||||
|
||||
namespace Framebuffer {
|
||||
|
||||
Genode::Dataspace_capability alloc_video_memory(Genode::size_t size);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__VIDEOMEM_ALLOCATOR_H_ */
|
7
os/src/drivers/framebuffer/pl11x/vpb926/target.mk
Normal file
7
os/src/drivers/framebuffer/pl11x/vpb926/target.mk
Normal file
@ -0,0 +1,7 @@
|
||||
TARGET = pl11x_drv
|
||||
REQUIRES = pl11x platform_vpb926
|
||||
SRC_CC = main.cc video_memory.cc
|
||||
LIBS = cxx env server
|
||||
INC_DIR += $(PRG_DIR)/..
|
||||
|
||||
vpath %.cc $(PRG_DIR)/..
|
181
os/src/drivers/framebuffer/sdl/fb_sdl.cc
Normal file
181
os/src/drivers/framebuffer/sdl/fb_sdl.cc
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* \brief SDL-based implementation of the Genode framebuffer
|
||||
* \author Norman Feske
|
||||
* \date 2006-07-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Linux */
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
/* Genode */
|
||||
#include <util/misc_math.h>
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <root/component.h>
|
||||
#include <framebuffer_session/framebuffer_session.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <input/component.h>
|
||||
|
||||
|
||||
/*
|
||||
* Variables for the libSDL output window
|
||||
*/
|
||||
static SDL_Surface *screen;
|
||||
static int scr_width = 1024, scr_height = 768;
|
||||
static Framebuffer::Session::Mode scr_mode = Framebuffer::Session::RGB565;
|
||||
|
||||
/*
|
||||
* Dataspace capability and local address of virtual frame buffer
|
||||
* that is shared with the client.
|
||||
*/
|
||||
static Genode::Dataspace_capability fb_ds_cap;
|
||||
static void *fb_ds_addr;
|
||||
|
||||
|
||||
/***********************************************
|
||||
** Implementation of the framebuffer service **
|
||||
***********************************************/
|
||||
|
||||
namespace Framebuffer {
|
||||
|
||||
class Session_component : public Genode::Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Mode _mode;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component() : _mode(RGB565) { }
|
||||
|
||||
Genode::Dataspace_capability dataspace() { return fb_ds_cap; }
|
||||
|
||||
void info(int *out_w, int *out_h, Mode *out_mode)
|
||||
{
|
||||
*out_w = scr_width;
|
||||
*out_h = scr_height;
|
||||
*out_mode = _mode;
|
||||
}
|
||||
|
||||
void refresh(int x, int y, int w, int h)
|
||||
{
|
||||
/* clip refresh area to screen boundaries */
|
||||
int x1 = Genode::max(x, 0);
|
||||
int y1 = Genode::max(y, 0);
|
||||
int x2 = Genode::min(x + w - 1, scr_width - 1);
|
||||
int y2 = Genode::min(y + h - 1, scr_height - 1);
|
||||
|
||||
if (x1 > x2 || y1 > y2) return;
|
||||
|
||||
/* copy pixels from shared dataspace to sdl surface */
|
||||
const int start_offset = bytes_per_pixel(_mode)*(y1*scr_width + x1);
|
||||
const int line_len = bytes_per_pixel(_mode)*(x2 - x1 + 1);
|
||||
const int pitch = bytes_per_pixel(_mode)*scr_width;
|
||||
|
||||
char *src = (char *)fb_ds_addr + start_offset;
|
||||
char *dst = (char *)screen->pixels + start_offset;
|
||||
|
||||
for (int i = y1; i <= y2; i++, src += pitch, dst += pitch)
|
||||
Genode::memcpy(dst, src, line_len);
|
||||
|
||||
/* flush pixels in sdl window */
|
||||
SDL_UpdateRect(screen, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shortcut for single-client root component
|
||||
*/
|
||||
typedef Genode::Root_component<Session_component, Genode::Single_client> Root_component;
|
||||
|
||||
|
||||
class Root : public Root_component
|
||||
{
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) {
|
||||
return new (md_alloc()) Session_component(); }
|
||||
|
||||
public:
|
||||
|
||||
Root(Genode::Rpc_entrypoint *session_ep,
|
||||
Genode::Allocator *md_alloc)
|
||||
: Root_component(session_ep, md_alloc) { }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main program
|
||||
*/
|
||||
extern "C" int main(int, char**)
|
||||
{
|
||||
using namespace Genode;
|
||||
using namespace Framebuffer;
|
||||
|
||||
/*
|
||||
* FIXME: Read configuration (screen parameters)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize libSDL window
|
||||
*/
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||
{
|
||||
PERR("SDL_Init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Genode::size_t bpp = Framebuffer::Session::bytes_per_pixel(scr_mode);
|
||||
screen = SDL_SetVideoMode(scr_width, scr_height, bpp*8, SDL_SWSURFACE);
|
||||
SDL_ShowCursor(0);
|
||||
|
||||
Genode::printf("creating virtual framebuffer for mode %dx%d@%zd\n", scr_width, scr_height, bpp*8);
|
||||
|
||||
/*
|
||||
* Create dataspace representing the virtual frame buffer
|
||||
*/
|
||||
try {
|
||||
static Attached_ram_dataspace fb_ds(env()->ram_session(), scr_width*scr_height*bpp);
|
||||
fb_ds_cap = fb_ds.cap();
|
||||
fb_ds_addr = fb_ds.local_addr<void>();
|
||||
} catch (...) {
|
||||
PERR("Could not allocate dataspace for virtual frame buffer");
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize server entry point
|
||||
*/
|
||||
enum { STACK_SIZE = 16*1024 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep");
|
||||
|
||||
/*
|
||||
* Let the entry point serve the framebuffer and input root interfaces
|
||||
*/
|
||||
static Framebuffer::Root framebuffer_root(&ep, env()->heap());
|
||||
static Input::Root input_root(&ep, env()->heap());
|
||||
|
||||
/*
|
||||
* Now, the root interfaces are ready to accept requests.
|
||||
* This is the right time to tell mummy about our services.
|
||||
*/
|
||||
env()->parent()->announce(ep.manage(&framebuffer_root));
|
||||
env()->parent()->announce(ep.manage(&input_root));
|
||||
|
||||
sleep_forever();
|
||||
return 0;
|
||||
}
|
204
os/src/drivers/framebuffer/sdl/input.cc
Normal file
204
os/src/drivers/framebuffer/sdl/input.cc
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* \brief SDL input support
|
||||
* \author Norman Feske
|
||||
* \date 2006-08-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Linux */
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
/* Genode */
|
||||
#include <input/keycodes.h>
|
||||
|
||||
/* Local */
|
||||
#include <input/component.h>
|
||||
|
||||
#include <base/printf.h>
|
||||
|
||||
/**
|
||||
* Convert SDL keycode to Genode keycode
|
||||
*/
|
||||
static long convert_keycode(int sdl_keycode)
|
||||
{
|
||||
using namespace Input;
|
||||
|
||||
switch (sdl_keycode) {
|
||||
|
||||
case SDLK_BACKSPACE: return KEY_BACKSPACE;
|
||||
case SDLK_TAB: return KEY_TAB;
|
||||
case SDLK_RETURN: return KEY_ENTER;
|
||||
case SDLK_PAUSE: return KEY_PAUSE;
|
||||
case SDLK_ESCAPE: return KEY_ESC;
|
||||
case SDLK_SPACE: return KEY_SPACE;
|
||||
case SDLK_QUOTE: return KEY_APOSTROPHE;
|
||||
case SDLK_HASH: return KEY_APOSTROPHE;
|
||||
case SDLK_COMMA: return KEY_COMMA;
|
||||
case SDLK_MINUS: return KEY_MINUS;
|
||||
case SDLK_PERIOD: return KEY_DOT;
|
||||
case SDLK_SLASH: return KEY_SLASH;
|
||||
case SDLK_0: return KEY_0;
|
||||
case SDLK_1: return KEY_1;
|
||||
case SDLK_2: return KEY_2;
|
||||
case SDLK_3: return KEY_3;
|
||||
case SDLK_4: return KEY_4;
|
||||
case SDLK_5: return KEY_5;
|
||||
case SDLK_6: return KEY_6;
|
||||
case SDLK_7: return KEY_7;
|
||||
case SDLK_8: return KEY_8;
|
||||
case SDLK_9: return KEY_9;
|
||||
case SDLK_SEMICOLON: return KEY_SEMICOLON;
|
||||
case SDLK_LESS: return KEY_BACKSLASH;
|
||||
case SDLK_EQUALS: return KEY_EQUAL;
|
||||
case SDLK_QUESTION: return KEY_QUESTION;
|
||||
case SDLK_LEFTBRACKET: return KEY_LEFTBRACE;
|
||||
case SDLK_BACKSLASH: return KEY_BACKSLASH;
|
||||
case SDLK_RIGHTBRACKET: return KEY_RIGHTBRACE;
|
||||
case SDLK_BACKQUOTE: return KEY_GRAVE;
|
||||
case SDLK_a: return KEY_A;
|
||||
case SDLK_b: return KEY_B;
|
||||
case SDLK_c: return KEY_C;
|
||||
case SDLK_d: return KEY_D;
|
||||
case SDLK_e: return KEY_E;
|
||||
case SDLK_f: return KEY_F;
|
||||
case SDLK_g: return KEY_G;
|
||||
case SDLK_h: return KEY_H;
|
||||
case SDLK_i: return KEY_I;
|
||||
case SDLK_j: return KEY_J;
|
||||
case SDLK_k: return KEY_K;
|
||||
case SDLK_l: return KEY_L;
|
||||
case SDLK_m: return KEY_M;
|
||||
case SDLK_n: return KEY_N;
|
||||
case SDLK_o: return KEY_O;
|
||||
case SDLK_p: return KEY_P;
|
||||
case SDLK_q: return KEY_Q;
|
||||
case SDLK_r: return KEY_R;
|
||||
case SDLK_s: return KEY_S;
|
||||
case SDLK_t: return KEY_T;
|
||||
case SDLK_u: return KEY_U;
|
||||
case SDLK_v: return KEY_V;
|
||||
case SDLK_w: return KEY_W;
|
||||
case SDLK_x: return KEY_X;
|
||||
case SDLK_y: return KEY_Y;
|
||||
case SDLK_z: return KEY_Z;
|
||||
case SDLK_DELETE: return KEY_DELETE;
|
||||
|
||||
/* arrows + home/end pad */
|
||||
case SDLK_UP: return KEY_UP;
|
||||
case SDLK_DOWN: return KEY_DOWN;
|
||||
case SDLK_RIGHT: return KEY_RIGHT;
|
||||
case SDLK_LEFT: return KEY_LEFT;
|
||||
case SDLK_INSERT: return KEY_INSERT;
|
||||
case SDLK_HOME: return KEY_HOME;
|
||||
case SDLK_END: return KEY_END;
|
||||
case SDLK_PAGEUP: return KEY_PAGEUP;
|
||||
case SDLK_PAGEDOWN: return KEY_PAGEDOWN;
|
||||
|
||||
/* function keys */
|
||||
case SDLK_F1: return KEY_F1;
|
||||
case SDLK_F2: return KEY_F2;
|
||||
case SDLK_F3: return KEY_F3;
|
||||
case SDLK_F4: return KEY_F4;
|
||||
case SDLK_F5: return KEY_F5;
|
||||
case SDLK_F6: return KEY_F6;
|
||||
case SDLK_F7: return KEY_F7;
|
||||
case SDLK_F8: return KEY_F8;
|
||||
case SDLK_F9: return KEY_F9;
|
||||
case SDLK_F10: return KEY_F10;
|
||||
case SDLK_F11: return KEY_F11;
|
||||
case SDLK_F12: return KEY_F12;
|
||||
case SDLK_F13: return KEY_F13;
|
||||
case SDLK_F14: return KEY_F14;
|
||||
case SDLK_F15: return KEY_F15;
|
||||
|
||||
/* special keys */
|
||||
case SDLK_PRINT: return KEY_PRINT;
|
||||
case SDLK_SCROLLOCK: return KEY_SCROLLLOCK;
|
||||
case SDLK_MENU: return KEY_MENU;
|
||||
|
||||
/* key state modifier keys */
|
||||
case SDLK_NUMLOCK: return KEY_NUMLOCK;
|
||||
case SDLK_CAPSLOCK: return KEY_CAPSLOCK;
|
||||
case SDLK_RSHIFT: return KEY_RIGHTSHIFT;
|
||||
case SDLK_LSHIFT: return KEY_LEFTSHIFT;
|
||||
case SDLK_RCTRL: return KEY_RIGHTCTRL;
|
||||
case SDLK_LCTRL: return KEY_LEFTCTRL;
|
||||
case SDLK_RALT: return KEY_RIGHTALT;
|
||||
case SDLK_LALT: return KEY_LEFTALT;
|
||||
case SDLK_RMETA: return KEY_RIGHTMETA;
|
||||
case SDLK_LMETA: return KEY_LEFTMETA;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Input::event_handling(bool enable) { }
|
||||
bool Input::event_pending() { return SDL_PollEvent(0); }
|
||||
|
||||
|
||||
/**
|
||||
* Wait for an event, Zzz...zz..
|
||||
*/
|
||||
Input::Event Input::get_event()
|
||||
{
|
||||
using namespace Input;
|
||||
|
||||
SDL_Event event;
|
||||
static int mx, my;
|
||||
static int ox, oy;
|
||||
|
||||
SDL_WaitEvent(&event);
|
||||
|
||||
/* query new mouse position */
|
||||
ox = mx; oy = my;
|
||||
if (event.type == SDL_MOUSEMOTION)
|
||||
SDL_GetMouseState(&mx, &my);
|
||||
|
||||
/* determine keycode */
|
||||
long keycode = 0;
|
||||
switch (event.type) {
|
||||
case SDL_KEYUP:
|
||||
case SDL_KEYDOWN:
|
||||
|
||||
keycode = convert_keycode(event.key.keysym.sym);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
|
||||
switch (event.button.button) {
|
||||
case SDL_BUTTON_LEFT: keycode = BTN_LEFT; break;
|
||||
case SDL_BUTTON_RIGHT: keycode = BTN_RIGHT; break;
|
||||
default: keycode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* determine event type */
|
||||
Event::Type type;
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEMOTION: type = Event::MOTION; break;
|
||||
case SDL_KEYUP:
|
||||
case SDL_MOUSEBUTTONUP: type = Event::RELEASE; break;
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button == SDL_BUTTON_WHEELUP) {
|
||||
type = Event::WHEEL;
|
||||
return Event(type, 0, 0, 0, 0, 1);
|
||||
} else if (event.button.button == SDL_BUTTON_WHEELDOWN) {
|
||||
type = Event::WHEEL;
|
||||
return Event(type, 0, 0, 0, 0, -1);
|
||||
}
|
||||
type = Event::PRESS;
|
||||
break;
|
||||
default: type = Event::INVALID;
|
||||
}
|
||||
|
||||
return Event(type, keycode, mx, my, mx - ox, my - oy);
|
||||
}
|
6
os/src/drivers/framebuffer/sdl/target.mk
Normal file
6
os/src/drivers/framebuffer/sdl/target.mk
Normal file
@ -0,0 +1,6 @@
|
||||
TARGET = fb_sdl
|
||||
LIBS = lx_hybrid server
|
||||
REQUIRES = linux sdl
|
||||
SRC_CC = fb_sdl.cc input.cc
|
||||
LX_LIBS = sdl
|
||||
|
79
os/src/drivers/framebuffer/vesa/README
Normal file
79
os/src/drivers/framebuffer/vesa/README
Normal file
@ -0,0 +1,79 @@
|
||||
This driver for x86 VBE 2.0 flat framebuffers was implemented by Sebastian
|
||||
Sumpf.
|
||||
|
||||
|
||||
Building instructions
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* 'specs.conf': set 'SPECS' variable, enable at least the following specs:
|
||||
'genode' 'fiasco' 'fiasco_x86'. Also, add the location of the
|
||||
'framebuffer_session' include files to your include search path, e.g.,
|
||||
'INC_DIR += <genode dir>/demo/include'
|
||||
|
||||
* Compile; the target will be called 'vesa_drv' --> Good luck
|
||||
|
||||
Config arguments
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, the driver sets up a resolution of 1024x768 at 16 bit color
|
||||
depth. This behaviour can be overridden by supplying the following
|
||||
arguments via Genode's config mechanism:
|
||||
|
||||
! <config width="1024"
|
||||
! height="768"
|
||||
! depth="16"
|
||||
! buffered="no" />
|
||||
|
||||
The 'depth' attribute is specified in bits per pixel. If setting the
|
||||
'buffered' attribute to 'yes', the VESA driver hands out a plain
|
||||
memory buffer to its client and flushes the pixels to the physical
|
||||
frame buffer each time, 'refresh' is called by the client. Buffered
|
||||
output should be used if the client tends to read from the frame
|
||||
buffer (i.e., the client performs output with alpha channel).
|
||||
|
||||
Note that only VESA modes but no arbitrary combination of values are
|
||||
supported. To find out which graphics modes exist on your platform,
|
||||
you might use the 'vbeprobe' command of the GRUB boot loader. Also,
|
||||
the driver will print a list of supported modes if the specified
|
||||
values are invalid.
|
||||
|
||||
As an alternative to letting the VESA driver set up a screen mode, the
|
||||
driver is able to reuse an already initialized mode, which becomes useful
|
||||
if the VESA mode is already initialized by the boot loader. If the screen
|
||||
is initialized that way, the 'preinit' attribute of the 'config' node can
|
||||
be set to '"yes"' to prevent the driver from changing the mode. This way,
|
||||
the driver will just query the current mode and make the already
|
||||
initialized framebuffer available to its client.
|
||||
|
||||
|
||||
Options and usage from clients
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Example:
|
||||
|
||||
! #include <framebuffer_session/connection.h>
|
||||
!
|
||||
! ...
|
||||
!
|
||||
! /* create session to frame-buffer service */
|
||||
! Framebuffer::Connection framebuffer(1024, 768, Framebuffer::Session::RGB565);
|
||||
!
|
||||
! /* retrieve frame buffer dataspace */
|
||||
! Dataspace_capability fb_ds_cap = framebuffer.dataspace();
|
||||
!
|
||||
! /* map dataspace to local address space */
|
||||
! void *local_addr = env()->rm_session()->attach(fb_ds_cap);
|
||||
|
||||
:Session-creation arguments:
|
||||
|
||||
:'fb_width': resolution width in pixel
|
||||
|
||||
:'fb_height': resolution height in pixel
|
||||
|
||||
:'fb_mode ': bits per pixel
|
||||
|
||||
:Supported modes:
|
||||
|
||||
'640x480', '800x600', '1024x786', '1280x1024' at 15, 16, 24, 32 bits per pixel
|
||||
Buffered output is only supported for modes using 16 bits per pixel.
|
||||
|
17
os/src/drivers/framebuffer/vesa/contrib/LICENSE
Normal file
17
os/src/drivers/framebuffer/vesa/contrib/LICENSE
Normal file
@ -0,0 +1,17 @@
|
||||
License information
|
||||
-------------------
|
||||
|
||||
The x86emu library is under a BSD style license, comaptible
|
||||
with the XFree86 1.0 and X licenses used by XFree86. The
|
||||
original x86emu libraries were under the GNU General Public
|
||||
License. Due to license incompatibilities between the GPL
|
||||
and the XFree86 1.0 license, the original authors of the code
|
||||
decided to allow a license change. If you have submitted
|
||||
code to the original x86emu project, and you don't agree
|
||||
with the license change, please contact us and let you
|
||||
know. Your code will be removed to comply with your wishes.
|
||||
|
||||
If you have any questions about this, please send email to
|
||||
x86emu@linuxlabs.com or KendallB@scitechsoft.com for
|
||||
clarification.
|
||||
|
19
os/src/drivers/framebuffer/vesa/contrib/Makefile.old
Normal file
19
os/src/drivers/framebuffer/vesa/contrib/Makefile.old
Normal file
@ -0,0 +1,19 @@
|
||||
PKGDIR ?= ../..
|
||||
L4DIR ?= $(PKGDIR)/../..
|
||||
|
||||
TARGET = libx86emu.a
|
||||
MODE = sigma0
|
||||
SYSTEMS = x86-l4v2 amd64-l4v2
|
||||
|
||||
SRC_C = decode.c fpu.c ops.c ops2.c prim_ops.c sys.c
|
||||
CPPFLAGS = -DNO_LONG_LONG
|
||||
CFLAGS = -fomit-frame-pointer
|
||||
PRIVATE_INCDIR = $(PKGDIR)/lib/src
|
||||
WARNINGS = -Wall -Wstrict-prototypes
|
||||
|
||||
DEBUG = 0
|
||||
ifeq ($(DEBUG),1)
|
||||
SRC_C += debug.c
|
||||
endif
|
||||
|
||||
include $(L4DIR)/mk/lib.mk
|
432
os/src/drivers/framebuffer/vesa/contrib/debug.c
Normal file
432
os/src/drivers/framebuffer/vesa/contrib/debug.c
Normal file
@ -0,0 +1,432 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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 contains the code to handle debugging of the
|
||||
* emulator.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "x86emu/x86emui.h"
|
||||
#ifndef NO_SYS_HEADERS
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static void print_encoded_bytes (u16 s, u16 o);
|
||||
static void print_decoded_instruction (void);
|
||||
//static int parse_line (char *s, int *ps, int *n);
|
||||
|
||||
/* should look something like debug's output. */
|
||||
void X86EMU_trace_regs (void)
|
||||
{
|
||||
if (DEBUG_TRACE()) {
|
||||
x86emu_dump_regs();
|
||||
}
|
||||
if (DEBUG_DECODE() && ! DEBUG_DECODE_NOPRINT()) {
|
||||
printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
|
||||
print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
|
||||
print_decoded_instruction();
|
||||
}
|
||||
}
|
||||
|
||||
void X86EMU_trace_xregs (void)
|
||||
{
|
||||
if (DEBUG_TRACE()) {
|
||||
x86emu_dump_xregs();
|
||||
}
|
||||
}
|
||||
|
||||
void x86emu_just_disassemble (void)
|
||||
{
|
||||
/*
|
||||
* This routine called if the flag DEBUG_DISASSEMBLE is set kind
|
||||
* of a hack!
|
||||
*/
|
||||
printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
|
||||
print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
|
||||
print_decoded_instruction();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) disassemble_forward (u16 seg, u16 off, int n)
|
||||
{
|
||||
X86EMU_sysEnv tregs;
|
||||
int i;
|
||||
u8 op1;
|
||||
/*
|
||||
* hack, hack, hack. What we do is use the exact machinery set up
|
||||
* for execution, except that now there is an additional state
|
||||
* flag associated with the "execution", and we are using a copy
|
||||
* of the register struct. All the major opcodes, once fully
|
||||
* decoded, have the following two steps: TRACE_REGS(r,m);
|
||||
* SINGLE_STEP(r,m); which disappear if DEBUG is not defined to
|
||||
* the preprocessor. The TRACE_REGS macro expands to:
|
||||
*
|
||||
* if (debug&DEBUG_DISASSEMBLE)
|
||||
* {just_disassemble(); goto EndOfInstruction;}
|
||||
* if (debug&DEBUG_TRACE) trace_regs(r,m);
|
||||
*
|
||||
* ...... and at the last line of the routine.
|
||||
*
|
||||
* EndOfInstruction: end_instr();
|
||||
*
|
||||
* Up to the point where TRACE_REG is expanded, NO modifications
|
||||
* are done to any register EXCEPT the IP register, for fetch and
|
||||
* decoding purposes.
|
||||
*
|
||||
* This was done for an entirely different reason, but makes a
|
||||
* nice way to get the system to help debug codes.
|
||||
*/
|
||||
tregs = M;
|
||||
tregs.x86.R_IP = off;
|
||||
tregs.x86.R_CS = seg;
|
||||
|
||||
/* reset the decoding buffers */
|
||||
tregs.x86.enc_str_pos = 0;
|
||||
tregs.x86.enc_pos = 0;
|
||||
|
||||
/* turn on the "disassemble only, no execute" flag */
|
||||
tregs.x86.debug |= DEBUG_DISASSEMBLE_F;
|
||||
|
||||
/* DUMP NEXT n instructions to screen in straight_line fashion */
|
||||
/*
|
||||
* This looks like the regular instruction fetch stream, except
|
||||
* that when this occurs, each fetched opcode, upon seeing the
|
||||
* DEBUG_DISASSEMBLE flag set, exits immediately after decoding
|
||||
* the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!!
|
||||
* Note the use of a copy of the register structure...
|
||||
*/
|
||||
for (i=0; i<n; i++) {
|
||||
op1 = (*sys_rdb)(((u32)M.x86.R_CS<<4) + (M.x86.R_IP++));
|
||||
(x86emu_optab[op1])(op1);
|
||||
}
|
||||
/* end major hack mode. */
|
||||
}
|
||||
|
||||
void x86emu_check_ip_access (void)
|
||||
{
|
||||
/* NULL as of now */
|
||||
}
|
||||
|
||||
void x86emu_check_sp_access (void)
|
||||
{
|
||||
}
|
||||
|
||||
void x86emu_check_mem_access (u32 dummy)
|
||||
{
|
||||
/* check bounds, etc */
|
||||
}
|
||||
|
||||
void x86emu_check_data_access (uint dummy1, uint dummy2)
|
||||
{
|
||||
/* check bounds, etc */
|
||||
}
|
||||
|
||||
void x86emu_inc_decoded_inst_len (int x)
|
||||
{
|
||||
M.x86.enc_pos += x;
|
||||
}
|
||||
|
||||
void x86emu_decode_printf (char *x)
|
||||
{
|
||||
sprintf(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",x);
|
||||
M.x86.enc_str_pos += strlen(x);
|
||||
}
|
||||
|
||||
void x86emu_decode_printf2 (char *x, int y)
|
||||
{
|
||||
char temp[100];
|
||||
sprintf(temp,x,y);
|
||||
sprintf(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",temp);
|
||||
M.x86.enc_str_pos += strlen(temp);
|
||||
}
|
||||
|
||||
void x86emu_end_instr (void)
|
||||
{
|
||||
M.x86.enc_str_pos = 0;
|
||||
M.x86.enc_pos = 0;
|
||||
}
|
||||
|
||||
static void print_encoded_bytes (u16 s, u16 o)
|
||||
{
|
||||
int i;
|
||||
char buf1[64];
|
||||
for (i=0; i< M.x86.enc_pos; i++) {
|
||||
sprintf(buf1+2*i,"%02x", fetch_data_byte_abs(s,o+i));
|
||||
}
|
||||
printk("%-20s",buf1);
|
||||
}
|
||||
|
||||
static void print_decoded_instruction (void)
|
||||
{
|
||||
printk("%s", M.x86.decoded_buf);
|
||||
}
|
||||
|
||||
void x86emu_print_int_vect (u16 iv)
|
||||
{
|
||||
u16 seg,off;
|
||||
|
||||
if (iv > 256) return;
|
||||
seg = fetch_data_word_abs(0,iv*4);
|
||||
off = fetch_data_word_abs(0,iv*4+2);
|
||||
printk("%04x:%04x ", seg, off);
|
||||
}
|
||||
|
||||
void X86EMU_dump_memory (u16 seg, u16 off, u32 amt)
|
||||
{
|
||||
u32 start = off & 0xfffffff0;
|
||||
u32 end = (off+16) & 0xfffffff0;
|
||||
u32 i;
|
||||
u32 current;
|
||||
|
||||
current = start;
|
||||
while (end <= off + amt) {
|
||||
printk("%04x:%04x ", seg, start);
|
||||
for (i=start; i< off; i++)
|
||||
printk(" ");
|
||||
for ( ; i< end; i++)
|
||||
printk("%02x ", fetch_data_byte_abs(seg,i));
|
||||
printk("\n");
|
||||
start = end;
|
||||
end = start + 16;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void x86emu_single_step (void)
|
||||
{
|
||||
char s[1024];
|
||||
int ps[10];
|
||||
int ntok;
|
||||
int cmd;
|
||||
int done;
|
||||
int segment;
|
||||
int offset;
|
||||
static int breakpoint;
|
||||
static int noDecode = 1;
|
||||
|
||||
char *p;
|
||||
|
||||
if (DEBUG_BREAK()) {
|
||||
if (M.x86.saved_ip != breakpoint) {
|
||||
return;
|
||||
} else {
|
||||
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
|
||||
M.x86.debug |= DEBUG_TRACE_F;
|
||||
M.x86.debug &= ~DEBUG_BREAK_F;
|
||||
print_decoded_instruction ();
|
||||
X86EMU_trace_regs();
|
||||
}
|
||||
}
|
||||
done=0;
|
||||
offset = M.x86.saved_ip;
|
||||
while (!done) {
|
||||
printk("-");
|
||||
p = fgets(s, 1023, stdin);
|
||||
cmd = parse_line(s, ps, &ntok);
|
||||
switch(cmd) {
|
||||
case 'u':
|
||||
disassemble_forward(M.x86.saved_cs,(u16)offset,10);
|
||||
break;
|
||||
case 'd':
|
||||
if (ntok == 2) {
|
||||
segment = M.x86.saved_cs;
|
||||
offset = ps[1];
|
||||
X86EMU_dump_memory(segment,(u16)offset,16);
|
||||
offset += 16;
|
||||
} else if (ntok == 3) {
|
||||
segment = ps[1];
|
||||
offset = ps[2];
|
||||
X86EMU_dump_memory(segment,(u16)offset,16);
|
||||
offset += 16;
|
||||
} else {
|
||||
segment = M.x86.saved_cs;
|
||||
X86EMU_dump_memory(segment,(u16)offset,16);
|
||||
offset += 16;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
M.x86.debug ^= DEBUG_TRACECALL_F;
|
||||
break;
|
||||
case 's':
|
||||
M.x86.debug ^= DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F;
|
||||
break;
|
||||
case 'r':
|
||||
X86EMU_trace_regs();
|
||||
break;
|
||||
case 'x':
|
||||
X86EMU_trace_xregs();
|
||||
break;
|
||||
case 'g':
|
||||
if (ntok == 2) {
|
||||
breakpoint = ps[1];
|
||||
if (noDecode) {
|
||||
M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
|
||||
} else {
|
||||
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
|
||||
}
|
||||
M.x86.debug &= ~DEBUG_TRACE_F;
|
||||
M.x86.debug |= DEBUG_BREAK_F;
|
||||
done = 1;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
M.x86.debug |= DEBUG_EXIT;
|
||||
return;
|
||||
case 'P':
|
||||
noDecode = (noDecode)?0:1;
|
||||
printk("Toggled decoding to %s\n",(noDecode)?"FALSE":"TRUE");
|
||||
break;
|
||||
case 't':
|
||||
case 0:
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int X86EMU_trace_on(void)
|
||||
{
|
||||
return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
|
||||
}
|
||||
|
||||
int X86EMU_trace_off(void)
|
||||
{
|
||||
return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int parse_line (char *s, int *ps, int *n)
|
||||
{
|
||||
int cmd;
|
||||
|
||||
*n = 0;
|
||||
while(*s == ' ' || *s == '\t') s++;
|
||||
ps[*n] = *s;
|
||||
switch (*s) {
|
||||
case '\n':
|
||||
*n += 1;
|
||||
return 0;
|
||||
default:
|
||||
cmd = *s;
|
||||
*n += 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (*s != ' ' && *s != '\t' && *s != '\n') s++;
|
||||
|
||||
if (*s == '\n')
|
||||
return cmd;
|
||||
|
||||
while(*s == ' ' || *s == '\t') s++;
|
||||
|
||||
sscanf(s,"%x",&ps[*n]);
|
||||
*n += 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
void x86emu_dump_regs (void)
|
||||
{
|
||||
printk("\tAX=%04x ", M.x86.R_AX );
|
||||
printk("BX=%04x ", M.x86.R_BX );
|
||||
printk("CX=%04x ", M.x86.R_CX );
|
||||
printk("DX=%04x ", M.x86.R_DX );
|
||||
printk("SP=%04x ", M.x86.R_SP );
|
||||
printk("BP=%04x ", M.x86.R_BP );
|
||||
printk("SI=%04x ", M.x86.R_SI );
|
||||
printk("DI=%04x\n", M.x86.R_DI );
|
||||
printk("\tDS=%04x ", M.x86.R_DS );
|
||||
printk("ES=%04x ", M.x86.R_ES );
|
||||
printk("SS=%04x ", M.x86.R_SS );
|
||||
printk("CS=%04x ", M.x86.R_CS );
|
||||
printk("IP=%04x ", M.x86.R_IP );
|
||||
if (ACCESS_FLAG(F_OF)) printk("OV "); /* CHECKED... */
|
||||
else printk("NV ");
|
||||
if (ACCESS_FLAG(F_DF)) printk("DN ");
|
||||
else printk("UP ");
|
||||
if (ACCESS_FLAG(F_IF)) printk("EI ");
|
||||
else printk("DI ");
|
||||
if (ACCESS_FLAG(F_SF)) printk("NG ");
|
||||
else printk("PL ");
|
||||
if (ACCESS_FLAG(F_ZF)) printk("ZR ");
|
||||
else printk("NZ ");
|
||||
if (ACCESS_FLAG(F_AF)) printk("AC ");
|
||||
else printk("NA ");
|
||||
if (ACCESS_FLAG(F_PF)) printk("PE ");
|
||||
else printk("PO ");
|
||||
if (ACCESS_FLAG(F_CF)) printk("CY ");
|
||||
else printk("NC ");
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
void x86emu_dump_xregs (void)
|
||||
{
|
||||
printk("\tEAX=%08x ", M.x86.R_EAX );
|
||||
printk("EBX=%08x ", M.x86.R_EBX );
|
||||
printk("ECX=%08x ", M.x86.R_ECX );
|
||||
printk("EDX=%08x \n", M.x86.R_EDX );
|
||||
printk("\tESP=%08x ", M.x86.R_ESP );
|
||||
printk("EBP=%08x ", M.x86.R_EBP );
|
||||
printk("ESI=%08x ", M.x86.R_ESI );
|
||||
printk("EDI=%08x\n", M.x86.R_EDI );
|
||||
printk("\tDS=%04x ", M.x86.R_DS );
|
||||
printk("ES=%04x ", M.x86.R_ES );
|
||||
printk("SS=%04x ", M.x86.R_SS );
|
||||
printk("CS=%04x ", M.x86.R_CS );
|
||||
printk("EIP=%08x\n\t", M.x86.R_EIP );
|
||||
if (ACCESS_FLAG(F_OF)) printk("OV "); /* CHECKED... */
|
||||
else printk("NV ");
|
||||
if (ACCESS_FLAG(F_DF)) printk("DN ");
|
||||
else printk("UP ");
|
||||
if (ACCESS_FLAG(F_IF)) printk("EI ");
|
||||
else printk("DI ");
|
||||
if (ACCESS_FLAG(F_SF)) printk("NG ");
|
||||
else printk("PL ");
|
||||
if (ACCESS_FLAG(F_ZF)) printk("ZR ");
|
||||
else printk("NZ ");
|
||||
if (ACCESS_FLAG(F_AF)) printk("AC ");
|
||||
else printk("NA ");
|
||||
if (ACCESS_FLAG(F_PF)) printk("PE ");
|
||||
else printk("PO ");
|
||||
if (ACCESS_FLAG(F_CF)) printk("CY ");
|
||||
else printk("NC ");
|
||||
printk("\n");
|
||||
}
|
1092
os/src/drivers/framebuffer/vesa/contrib/decode.c
Normal file
1092
os/src/drivers/framebuffer/vesa/contrib/decode.c
Normal file
File diff suppressed because it is too large
Load Diff
56
os/src/drivers/framebuffer/vesa/contrib/fgets.c
Normal file
56
os/src/drivers/framebuffer/vesa/contrib/fgets.c
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <flux/x86/pc/direct_cons.h>
|
||||
|
||||
char *fgets(char *str, int size, FILE *stream);
|
||||
|
||||
char
|
||||
*fgets(char *str, int size, FILE *stream)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
if (size <= 0)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while (i < size)
|
||||
{
|
||||
c = direct_cons_getchar();
|
||||
if (c == '\r')
|
||||
{
|
||||
putchar('\n');
|
||||
putchar('\r');
|
||||
if (i == 0)
|
||||
{
|
||||
str[0] = '\n';
|
||||
str[1] = '\0';
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (c == 8)
|
||||
{
|
||||
if (i>0)
|
||||
{
|
||||
putchar(c);
|
||||
putchar(' ');
|
||||
putchar(c);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
putchar(c);
|
||||
str[i++] = c;
|
||||
}
|
||||
}
|
||||
if (++i < size)
|
||||
str[i] = '\n';
|
||||
if (i < size)
|
||||
str[i] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
965
os/src/drivers/framebuffer/vesa/contrib/fpu.c
Normal file
965
os/src/drivers/framebuffer/vesa/contrib/fpu.c
Normal file
@ -0,0 +1,965 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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 contains the code to implement the decoding and
|
||||
* emulation of the FPU instructions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "x86emu/x86emui.h"
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
|
||||
/* opcode=0xd8 */
|
||||
void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
START_OF_INSTR();
|
||||
DECODE_PRINTF("ESC D8\n");
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_d9_tab[] = {
|
||||
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
|
||||
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
|
||||
|
||||
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
|
||||
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
|
||||
|
||||
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
|
||||
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
|
||||
};
|
||||
|
||||
static char *x86emu_fpu_op_d9_tab1[] = {
|
||||
"FLD\t", "FLD\t", "FLD\t", "FLD\t",
|
||||
"FLD\t", "FLD\t", "FLD\t", "FLD\t",
|
||||
|
||||
"FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
|
||||
"FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
|
||||
|
||||
"FNOP", "ESC_D9", "ESC_D9", "ESC_D9",
|
||||
"ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9",
|
||||
|
||||
"FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
|
||||
"FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
|
||||
|
||||
"FCHS", "FABS", "ESC_D9", "ESC_D9",
|
||||
"FTST", "FXAM", "ESC_D9", "ESC_D9",
|
||||
|
||||
"FLD1", "FLDL2T", "FLDL2E", "FLDPI",
|
||||
"FLDLG2", "FLDLN2", "FLDZ", "ESC_D9",
|
||||
|
||||
"F2XM1", "FYL2X", "FPTAN", "FPATAN",
|
||||
"FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP",
|
||||
|
||||
"FPREM", "FYL2XP1", "FSQRT", "ESC_D9",
|
||||
"FRNDINT", "FSCALE", "ESC_D9", "ESC_D9",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xd9 */
|
||||
void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset = 0;
|
||||
u8 stkelem = 0;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
#ifdef DEBUG
|
||||
if (mod != 3) {
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl);
|
||||
} else {
|
||||
DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]);
|
||||
}
|
||||
#endif
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8)rl;
|
||||
if (rh < 4) {
|
||||
DECODE_PRINTF2("ST(%d)\n", stkelem);
|
||||
} else {
|
||||
DECODE_PRINTF("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
/* execute */
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem);
|
||||
break;
|
||||
case 2:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_nop();
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem);
|
||||
break;
|
||||
case 4:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
default:
|
||||
/* 2,3,6,7 */
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
default:
|
||||
/* 7 */
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_decstp();
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_R_incstp();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)destoffset;
|
||||
(void)stkelem;
|
||||
#endif /* X86EMU_FPU_PRESENT */
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
char *x86emu_fpu_op_da_tab[] = {
|
||||
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
|
||||
"FICOMP\tDWORD PTR ",
|
||||
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
|
||||
"FIDIVR\tDWORD PTR ",
|
||||
|
||||
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
|
||||
"FICOMP\tDWORD PTR ",
|
||||
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
|
||||
"FIDIVR\tDWORD PTR ",
|
||||
|
||||
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
|
||||
"FICOMP\tDWORD PTR ",
|
||||
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
|
||||
"FIDIVR\tDWORD PTR ",
|
||||
|
||||
"ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
|
||||
"ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xda */
|
||||
void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset = 0;
|
||||
u8 stkelem = 0;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)destoffset;
|
||||
(void)stkelem;
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
char *x86emu_fpu_op_db_tab[] = {
|
||||
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
|
||||
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
|
||||
|
||||
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
|
||||
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
|
||||
|
||||
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
|
||||
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdb */
|
||||
void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset = 0;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
#ifdef DEBUG
|
||||
if (mod != 3) {
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl);
|
||||
} else if (rh == 4) { /* === 11 10 0 nnn */
|
||||
switch (rl) {
|
||||
case 0:
|
||||
DECODE_PRINTF("FENI\n");
|
||||
break;
|
||||
case 1:
|
||||
DECODE_PRINTF("FDISI\n");
|
||||
break;
|
||||
case 2:
|
||||
DECODE_PRINTF("FCLEX\n");
|
||||
break;
|
||||
case 3:
|
||||
DECODE_PRINTF("FINIT\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
/* execute */
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 4:
|
||||
switch (rl) {
|
||||
case 0:
|
||||
x86emu_fpu_R_feni();
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fdisi();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fclex();
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_finit();
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)destoffset;
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
char *x86emu_fpu_op_dc_tab[] = {
|
||||
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
|
||||
"FCOMP\tQWORD PTR ",
|
||||
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
|
||||
"FDIVR\tQWORD PTR ",
|
||||
|
||||
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
|
||||
"FCOMP\tQWORD PTR ",
|
||||
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
|
||||
"FDIVR\tQWORD PTR ",
|
||||
|
||||
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
|
||||
"FCOMP\tQWORD PTR ",
|
||||
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
|
||||
"FDIVR\tQWORD PTR ",
|
||||
|
||||
"FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t",
|
||||
"FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t",
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdc */
|
||||
void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset = 0;
|
||||
u8 stkelem = 0;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
/* execute */
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)destoffset;
|
||||
(void)stkelem;
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_dd_tab[] = {
|
||||
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
|
||||
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
|
||||
|
||||
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
|
||||
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
|
||||
|
||||
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
|
||||
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
|
||||
|
||||
"FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
|
||||
"ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdd */
|
||||
void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset = 0;
|
||||
u8 stkelem = 0;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_ffree(stkelem);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fxch(stkelem);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fst(stkelem); /* register version */
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fstp(stkelem); /* register version */
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)destoffset;
|
||||
(void)stkelem;
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_de_tab[] =
|
||||
{
|
||||
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
|
||||
"FICOMP\tWORD PTR ",
|
||||
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
|
||||
"FIDIVR\tWORD PTR ",
|
||||
|
||||
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
|
||||
"FICOMP\tWORD PTR ",
|
||||
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
|
||||
"FIDIVR\tWORD PTR ",
|
||||
|
||||
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
|
||||
"FICOMP\tWORD PTR ",
|
||||
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
|
||||
"FIDIVR\tWORD PTR ",
|
||||
|
||||
"FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t",
|
||||
"FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t",
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xde */
|
||||
void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset = 0;
|
||||
u8 stkelem = 0;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8)rl;
|
||||
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 3:
|
||||
if (stkelem == 1)
|
||||
x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP);
|
||||
else
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)destoffset;
|
||||
(void)stkelem;
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static char *x86emu_fpu_op_df_tab[] = {
|
||||
/* mod == 00 */
|
||||
"FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
|
||||
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
|
||||
"FISTP\tQWORD PTR ",
|
||||
|
||||
/* mod == 01 */
|
||||
"FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
|
||||
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
|
||||
"FISTP\tQWORD PTR ",
|
||||
|
||||
/* mod == 10 */
|
||||
"FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
|
||||
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
|
||||
"FISTP\tQWORD PTR ",
|
||||
|
||||
/* mod == 11 */
|
||||
"FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
|
||||
"ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F,"
|
||||
};
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* opcode=0xdf */
|
||||
void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
|
||||
{
|
||||
int mod, rl, rh;
|
||||
uint destoffset = 0;
|
||||
u8 stkelem = 0;
|
||||
|
||||
START_OF_INSTR();
|
||||
FETCH_DECODE_MODRM(mod, rh, rl);
|
||||
DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl);
|
||||
switch (mod) {
|
||||
case 0:
|
||||
destoffset = decode_rm00_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 1:
|
||||
destoffset = decode_rm01_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 2:
|
||||
destoffset = decode_rm10_address(rl);
|
||||
DECODE_PRINTF("\n");
|
||||
break;
|
||||
case 3: /* register to register */
|
||||
stkelem = (u8)rl;
|
||||
DECODE_PRINTF2("\tST(%d)\n", stkelem);
|
||||
break;
|
||||
}
|
||||
#ifdef X86EMU_FPU_PRESENT
|
||||
switch (mod) {
|
||||
case 3:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_R_ffree(stkelem);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_R_fxch(stkelem);
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_R_fst(stkelem); /* register version */
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_R_fstp(stkelem); /* register version */
|
||||
break;
|
||||
default:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rh) {
|
||||
case 0:
|
||||
x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 1:
|
||||
x86emu_fpu_illegal();
|
||||
break;
|
||||
case 2:
|
||||
x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 3:
|
||||
x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset);
|
||||
break;
|
||||
case 4:
|
||||
x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset);
|
||||
break;
|
||||
case 5:
|
||||
x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset);
|
||||
break;
|
||||
case 6:
|
||||
x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset);
|
||||
break;
|
||||
case 7:
|
||||
x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)destoffset;
|
||||
(void)stkelem;
|
||||
#endif
|
||||
DECODE_CLEAR_SEGOVR();
|
||||
END_OF_INSTR_NO_TRACE();
|
||||
}
|
11697
os/src/drivers/framebuffer/vesa/contrib/ops.c
Normal file
11697
os/src/drivers/framebuffer/vesa/contrib/ops.c
Normal file
File diff suppressed because it is too large
Load Diff
2805
os/src/drivers/framebuffer/vesa/contrib/ops2.c
Normal file
2805
os/src/drivers/framebuffer/vesa/contrib/ops2.c
Normal file
File diff suppressed because it is too large
Load Diff
2655
os/src/drivers/framebuffer/vesa/contrib/prim_ops.c
Normal file
2655
os/src/drivers/framebuffer/vesa/contrib/prim_ops.c
Normal file
File diff suppressed because it is too large
Load Diff
12
os/src/drivers/framebuffer/vesa/contrib/printk.c
Normal file
12
os/src/drivers/framebuffer/vesa/contrib/printk.c
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
printk(const char *format,...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
vprintf(format, list);
|
||||
va_end(list);
|
||||
}
|
661
os/src/drivers/framebuffer/vesa/contrib/sys.c
Normal file
661
os/src/drivers/framebuffer/vesa/contrib/sys.c
Normal file
@ -0,0 +1,661 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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 which are related to
|
||||
* programmed I/O and memory access. Included in this module
|
||||
* are default functions with limited usefulness. For real
|
||||
* uses these functions will most likely be overriden by the
|
||||
* user library.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "x86emu/x86emui.h"
|
||||
#include "x86emu/debug.h"
|
||||
#include "x86emu/prim_ops.h"
|
||||
#ifndef NO_SYS_HEADERS
|
||||
#include <string.h>
|
||||
#endif
|
||||
/*------------------------- Global Variables ------------------------------*/
|
||||
|
||||
X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
|
||||
X86EMU_intrFuncs _X86EMU_intrTab[256];
|
||||
|
||||
/*----------------------------- Implementation ----------------------------*/
|
||||
#if defined(__alpha__) || defined(__alpha)
|
||||
/* to cope with broken egcs-1.1.2 :-(((( */
|
||||
|
||||
#define ALPHA_UALOADS
|
||||
/*
|
||||
* inline functions to do unaligned accesses
|
||||
* from linux/include/asm-alpha/unaligned.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* EGCS 1.1 knows about arbitrary unaligned loads. Define some
|
||||
* packed structures to talk about such things with.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91))
|
||||
struct __una_u64 { unsigned long x __attribute__((packed)); };
|
||||
struct __una_u32 { unsigned int x __attribute__((packed)); };
|
||||
struct __una_u16 { unsigned short x __attribute__((packed)); };
|
||||
#endif
|
||||
|
||||
static __inline__ unsigned long ldq_u(unsigned long * r11)
|
||||
{
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91))
|
||||
const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
|
||||
return ptr->x;
|
||||
#else
|
||||
unsigned long r1,r2;
|
||||
__asm__("ldq_u %0,%3\n\t"
|
||||
"ldq_u %1,%4\n\t"
|
||||
"extql %0,%2,%0\n\t"
|
||||
"extqh %1,%2,%1"
|
||||
:"=&r" (r1), "=&r" (r2)
|
||||
:"r" (r11),
|
||||
"m" (*r11),
|
||||
"m" (*(const unsigned long *)(7+(char *) r11)));
|
||||
return r1 | r2;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ unsigned long ldl_u(unsigned int * r11)
|
||||
{
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91))
|
||||
const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
|
||||
return ptr->x;
|
||||
#else
|
||||
unsigned long r1,r2;
|
||||
__asm__("ldq_u %0,%3\n\t"
|
||||
"ldq_u %1,%4\n\t"
|
||||
"extll %0,%2,%0\n\t"
|
||||
"extlh %1,%2,%1"
|
||||
:"=&r" (r1), "=&r" (r2)
|
||||
:"r" (r11),
|
||||
"m" (*r11),
|
||||
"m" (*(const unsigned long *)(3+(char *) r11)));
|
||||
return r1 | r2;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ unsigned long ldw_u(unsigned short * r11)
|
||||
{
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91))
|
||||
const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
|
||||
return ptr->x;
|
||||
#else
|
||||
unsigned long r1,r2;
|
||||
__asm__("ldq_u %0,%3\n\t"
|
||||
"ldq_u %1,%4\n\t"
|
||||
"extwl %0,%2,%0\n\t"
|
||||
"extwh %1,%2,%1"
|
||||
:"=&r" (r1), "=&r" (r2)
|
||||
:"r" (r11),
|
||||
"m" (*r11),
|
||||
"m" (*(const unsigned long *)(1+(char *) r11)));
|
||||
return r1 | r2;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Elemental unaligned stores
|
||||
*/
|
||||
|
||||
static __inline__ void stq_u(unsigned long r5, unsigned long * r11)
|
||||
{
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91))
|
||||
struct __una_u64 *ptr = (struct __una_u64 *) r11;
|
||||
ptr->x = r5;
|
||||
#else
|
||||
unsigned long r1,r2,r3,r4;
|
||||
|
||||
__asm__("ldq_u %3,%1\n\t"
|
||||
"ldq_u %2,%0\n\t"
|
||||
"insqh %6,%7,%5\n\t"
|
||||
"insql %6,%7,%4\n\t"
|
||||
"mskqh %3,%7,%3\n\t"
|
||||
"mskql %2,%7,%2\n\t"
|
||||
"bis %3,%5,%3\n\t"
|
||||
"bis %2,%4,%2\n\t"
|
||||
"stq_u %3,%1\n\t"
|
||||
"stq_u %2,%0"
|
||||
:"=m" (*r11),
|
||||
"=m" (*(unsigned long *)(7+(char *) r11)),
|
||||
"=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
|
||||
:"r" (r5), "r" (r11));
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void stl_u(unsigned long r5, unsigned int * r11)
|
||||
{
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91))
|
||||
struct __una_u32 *ptr = (struct __una_u32 *) r11;
|
||||
ptr->x = r5;
|
||||
#else
|
||||
unsigned long r1,r2,r3,r4;
|
||||
|
||||
__asm__("ldq_u %3,%1\n\t"
|
||||
"ldq_u %2,%0\n\t"
|
||||
"inslh %6,%7,%5\n\t"
|
||||
"insll %6,%7,%4\n\t"
|
||||
"msklh %3,%7,%3\n\t"
|
||||
"mskll %2,%7,%2\n\t"
|
||||
"bis %3,%5,%3\n\t"
|
||||
"bis %2,%4,%2\n\t"
|
||||
"stq_u %3,%1\n\t"
|
||||
"stq_u %2,%0"
|
||||
:"=m" (*r11),
|
||||
"=m" (*(unsigned long *)(3+(char *) r11)),
|
||||
"=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
|
||||
:"r" (r5), "r" (r11));
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void stw_u(unsigned long r5, unsigned short * r11)
|
||||
{
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC_MINOR__ >= 91))
|
||||
struct __una_u16 *ptr = (struct __una_u16 *) r11;
|
||||
ptr->x = r5;
|
||||
#else
|
||||
unsigned long r1,r2,r3,r4;
|
||||
|
||||
__asm__("ldq_u %3,%1\n\t"
|
||||
"ldq_u %2,%0\n\t"
|
||||
"inswh %6,%7,%5\n\t"
|
||||
"inswl %6,%7,%4\n\t"
|
||||
"mskwh %3,%7,%3\n\t"
|
||||
"mskwl %2,%7,%2\n\t"
|
||||
"bis %3,%5,%3\n\t"
|
||||
"bis %2,%4,%2\n\t"
|
||||
"stq_u %3,%1\n\t"
|
||||
"stq_u %2,%0"
|
||||
:"=m" (*r11),
|
||||
"=m" (*(unsigned long *)(1+(char *) r11)),
|
||||
"=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
|
||||
:"r" (r5), "r" (r11));
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && ((__GNUC__ < 3)) && \
|
||||
(defined (__ia64__) || defined (ia64__))
|
||||
#define IA64_UALOADS
|
||||
/*
|
||||
* EGCS 1.1 knows about arbitrary unaligned loads. Define some
|
||||
* packed structures to talk about such things with.
|
||||
*/
|
||||
struct __una_u64 { unsigned long x __attribute__((packed)); };
|
||||
struct __una_u32 { unsigned int x __attribute__((packed)); };
|
||||
struct __una_u16 { unsigned short x __attribute__((packed)); };
|
||||
|
||||
static __inline__ unsigned long
|
||||
__uldq (const unsigned long * r11)
|
||||
{
|
||||
const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
|
||||
return ptr->x;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
uldl (const unsigned int * r11)
|
||||
{
|
||||
const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
|
||||
return ptr->x;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
uldw (const unsigned short * r11)
|
||||
{
|
||||
const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
|
||||
return ptr->x;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
ustq (unsigned long r5, unsigned long * r11)
|
||||
{
|
||||
struct __una_u64 *ptr = (struct __una_u64 *) r11;
|
||||
ptr->x = r5;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
ustl (unsigned long r5, unsigned int * r11)
|
||||
{
|
||||
struct __una_u32 *ptr = (struct __una_u32 *) r11;
|
||||
ptr->x = r5;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
ustw (unsigned long r5, unsigned short * r11)
|
||||
{
|
||||
struct __una_u16 *ptr = (struct __una_u16 *) r11;
|
||||
ptr->x = r5;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - Emulator memory address to read
|
||||
|
||||
RETURNS:
|
||||
Byte value read from emulator memory.
|
||||
|
||||
REMARKS:
|
||||
Reads a byte value from the emulator memory.
|
||||
****************************************************************************/
|
||||
u8 X86API rdb(
|
||||
u32 addr)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
if (addr > M.mem_size - 1) {
|
||||
DB(printk("mem_read: address %#lx out of range!\n", addr);)
|
||||
HALT_SYS();
|
||||
}
|
||||
val = *(u8*)(M.mem_base + addr);
|
||||
DB( if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 1 -> %#x\n", addr, val);)
|
||||
return val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - Emulator memory address to read
|
||||
|
||||
RETURNS:
|
||||
Word value read from emulator memory.
|
||||
|
||||
REMARKS:
|
||||
Reads a word value from the emulator memory.
|
||||
****************************************************************************/
|
||||
u16 X86API rdw(
|
||||
u32 addr)
|
||||
{
|
||||
u16 val = 0;
|
||||
|
||||
if (addr > M.mem_size - 2) {
|
||||
DB(printk("mem_read: address %#lx out of range!\n", addr);)
|
||||
HALT_SYS();
|
||||
}
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x1) {
|
||||
val = (*(u8*)(M.mem_base + addr) |
|
||||
(*(u8*)(M.mem_base + addr + 1) << 8));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(ALPHA_UALOADS)
|
||||
val = ldw_u((u16*)(M.mem_base + addr));
|
||||
#elif defined(IA64_UALOADS)
|
||||
val = uldw((u16*)(M.mem_base + addr));
|
||||
#else
|
||||
val = *(u16*)(M.mem_base + addr);
|
||||
#endif
|
||||
DB( if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 2 -> %#x\n", addr, val);)
|
||||
return val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - Emulator memory address to read
|
||||
|
||||
RETURNS:
|
||||
Long value read from emulator memory.
|
||||
REMARKS:
|
||||
Reads a long value from the emulator memory.
|
||||
****************************************************************************/
|
||||
u32 X86API rdl(
|
||||
u32 addr)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
if (addr > M.mem_size - 4) {
|
||||
DB(printk("mem_read: address %#lx out of range!\n", addr);)
|
||||
HALT_SYS();
|
||||
}
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x3) {
|
||||
val = (*(u8*)(M.mem_base + addr + 0) |
|
||||
(*(u8*)(M.mem_base + addr + 1) << 8) |
|
||||
(*(u8*)(M.mem_base + addr + 2) << 16) |
|
||||
(*(u8*)(M.mem_base + addr + 3) << 24));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(ALPHA_UALOADS)
|
||||
val = ldl_u((u32*)(M.mem_base + addr));
|
||||
#elif defined(IA64_UALOADS)
|
||||
val = uldl((u32*)(M.mem_base + addr));
|
||||
#else
|
||||
val = *(u32*)(M.mem_base + addr);
|
||||
#endif
|
||||
DB( if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 4 -> %#x\n", addr, val);)
|
||||
return val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - Emulator memory address to read
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a byte value to emulator memory.
|
||||
****************************************************************************/
|
||||
void X86API wrb(
|
||||
u32 addr,
|
||||
u8 val)
|
||||
{
|
||||
DB( if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 1 <- %#x\n", addr, val);)
|
||||
if (addr > M.mem_size - 1) {
|
||||
DB(printk("mem_write: address %#lx out of range!\n", addr);)
|
||||
HALT_SYS();
|
||||
}
|
||||
*(u8*)(M.mem_base + addr) = val;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - Emulator memory address to read
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a word value to emulator memory.
|
||||
****************************************************************************/
|
||||
void X86API wrw(
|
||||
u32 addr,
|
||||
u16 val)
|
||||
{
|
||||
DB( if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 2 <- %#x\n", addr, val);)
|
||||
if (addr > M.mem_size - 2) {
|
||||
DB(printk("mem_write: address %#lx out of range!\n", addr);)
|
||||
HALT_SYS();
|
||||
}
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x1) {
|
||||
*(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
|
||||
*(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(ALPHA_UALOADS)
|
||||
stw_u(val,(u16*)(M.mem_base + addr));
|
||||
#elif defined(IA64_UALOADS)
|
||||
ustw(val,(u16*)(M.mem_base + addr));
|
||||
#else
|
||||
*(u16*)(M.mem_base + addr) = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - Emulator memory address to read
|
||||
val - Value to store
|
||||
|
||||
REMARKS:
|
||||
Writes a long value to emulator memory.
|
||||
****************************************************************************/
|
||||
void X86API wrl(
|
||||
u32 addr,
|
||||
u32 val)
|
||||
{
|
||||
DB( if (DEBUG_MEM_TRACE())
|
||||
printk("%#08x 4 <- %#x\n", addr, val);)
|
||||
if (addr > M.mem_size - 4) {
|
||||
DB(printk("mem_write: address %#lx out of range!\n", addr);)
|
||||
HALT_SYS();
|
||||
}
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (addr & 0x1) {
|
||||
*(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
|
||||
*(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
|
||||
*(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff;
|
||||
*(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(ALPHA_UALOADS)
|
||||
stl_u(val,(u32*)(M.mem_base + addr));
|
||||
#elif defined(IA64_UALOADS)
|
||||
ustl(val,(u32*)(M.mem_base + addr));
|
||||
#else
|
||||
*(u32*)(M.mem_base + addr) = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - PIO address to read
|
||||
RETURN:
|
||||
0
|
||||
REMARKS:
|
||||
Default PIO byte read function. Doesn't perform real inb.
|
||||
****************************************************************************/
|
||||
static u8 X86API p_inb(
|
||||
X86EMU_pioAddr addr)
|
||||
{
|
||||
DB( if (DEBUG_IO_TRACE())
|
||||
printk("inb %#04x \n", addr);)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - PIO address to read
|
||||
RETURN:
|
||||
0
|
||||
REMARKS:
|
||||
Default PIO word read function. Doesn't perform real inw.
|
||||
****************************************************************************/
|
||||
static u16 X86API p_inw(
|
||||
X86EMU_pioAddr addr)
|
||||
{
|
||||
DB( if (DEBUG_IO_TRACE())
|
||||
printk("inw %#04x \n", addr);)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - PIO address to read
|
||||
RETURN:
|
||||
0
|
||||
REMARKS:
|
||||
Default PIO long read function. Doesn't perform real inl.
|
||||
****************************************************************************/
|
||||
static u32 X86API p_inl(
|
||||
X86EMU_pioAddr addr)
|
||||
{
|
||||
DB( if (DEBUG_IO_TRACE())
|
||||
printk("inl %#04x \n", addr);)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - PIO address to write
|
||||
val - Value to store
|
||||
REMARKS:
|
||||
Default PIO byte write function. Doesn't perform real outb.
|
||||
****************************************************************************/
|
||||
static void X86API p_outb(
|
||||
X86EMU_pioAddr addr,
|
||||
u8 val)
|
||||
{
|
||||
DB( if (DEBUG_IO_TRACE())
|
||||
printk("outb %#02x -> %#04x \n", val, addr);)
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - PIO address to write
|
||||
val - Value to store
|
||||
REMARKS:
|
||||
Default PIO word write function. Doesn't perform real outw.
|
||||
****************************************************************************/
|
||||
static void X86API p_outw(
|
||||
X86EMU_pioAddr addr,
|
||||
u16 val)
|
||||
{
|
||||
DB( if (DEBUG_IO_TRACE())
|
||||
printk("outw %#04x -> %#04x \n", val, addr);)
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
addr - PIO address to write
|
||||
val - Value to store
|
||||
REMARKS:
|
||||
Default PIO ;ong write function. Doesn't perform real outl.
|
||||
****************************************************************************/
|
||||
static void X86API p_outl(
|
||||
X86EMU_pioAddr addr,
|
||||
u32 val)
|
||||
{
|
||||
DB( if (DEBUG_IO_TRACE())
|
||||
printk("outl %#08x -> %#04x \n", val, addr);)
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------- Global Variables ------------------------------*/
|
||||
|
||||
u8 (X86APIP sys_rdb)(u32 addr) = rdb;
|
||||
u16 (X86APIP sys_rdw)(u32 addr) = rdw;
|
||||
u32 (X86APIP sys_rdl)(u32 addr) = rdl;
|
||||
void (X86APIP sys_wrb)(u32 addr,u8 val) = wrb;
|
||||
void (X86APIP sys_wrw)(u32 addr,u16 val) = wrw;
|
||||
void (X86APIP sys_wrl)(u32 addr,u32 val) = wrl;
|
||||
u8 (X86APIP sys_inb)(X86EMU_pioAddr addr) = p_inb;
|
||||
u16 (X86APIP sys_inw)(X86EMU_pioAddr addr) = p_inw;
|
||||
u32 (X86APIP sys_inl)(X86EMU_pioAddr addr) = p_inl;
|
||||
void (X86APIP sys_outb)(X86EMU_pioAddr addr, u8 val) = p_outb;
|
||||
void (X86APIP sys_outw)(X86EMU_pioAddr addr, u16 val) = p_outw;
|
||||
void (X86APIP sys_outl)(X86EMU_pioAddr addr, u32 val) = p_outl;
|
||||
|
||||
/*----------------------------- Setup -------------------------------------*/
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
funcs - New memory function pointers to make active
|
||||
|
||||
REMARKS:
|
||||
This function is used to set the pointers to functions which access
|
||||
memory space, allowing the user application to override these functions
|
||||
and hook them out as necessary for their application.
|
||||
****************************************************************************/
|
||||
void X86EMU_setupMemFuncs(
|
||||
X86EMU_memFuncs *funcs)
|
||||
{
|
||||
sys_rdb = funcs->rdb;
|
||||
sys_rdw = funcs->rdw;
|
||||
sys_rdl = funcs->rdl;
|
||||
sys_wrb = funcs->wrb;
|
||||
sys_wrw = funcs->wrw;
|
||||
sys_wrl = funcs->wrl;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
funcs - New programmed I/O function pointers to make active
|
||||
|
||||
REMARKS:
|
||||
This function is used to set the pointers to functions which access
|
||||
I/O space, allowing the user application to override these functions
|
||||
and hook them out as necessary for their application.
|
||||
****************************************************************************/
|
||||
void X86EMU_setupPioFuncs(
|
||||
X86EMU_pioFuncs *funcs)
|
||||
{
|
||||
sys_inb = funcs->inb;
|
||||
sys_inw = funcs->inw;
|
||||
sys_inl = funcs->inl;
|
||||
sys_outb = funcs->outb;
|
||||
sys_outw = funcs->outw;
|
||||
sys_outl = funcs->outl;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
funcs - New interrupt vector table to make active
|
||||
|
||||
REMARKS:
|
||||
This function is used to set the pointers to functions which handle
|
||||
interrupt processing in the emulator, allowing the user application to
|
||||
hook interrupts as necessary for their application. Any interrupts that
|
||||
are not hooked by the user application, and reflected and handled internally
|
||||
in the emulator via the interrupt vector table. This allows the application
|
||||
to get control when the code being emulated executes specific software
|
||||
interrupts.
|
||||
****************************************************************************/
|
||||
void X86EMU_setupIntrFuncs(
|
||||
X86EMU_intrFuncs funcs[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < 256; i++)
|
||||
_X86EMU_intrTab[i] = NULL;
|
||||
if (funcs) {
|
||||
for (i = 0; i < 256; i++)
|
||||
_X86EMU_intrTab[i] = funcs[i];
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
PARAMETERS:
|
||||
int - New software interrupt to prepare for
|
||||
|
||||
REMARKS:
|
||||
This function is used to set up the emulator state to exceute a software
|
||||
interrupt. This can be used by the user application code to allow an
|
||||
interrupt to be hooked, examined and then reflected back to the emulator
|
||||
so that the code in the emulator will continue processing the software
|
||||
interrupt as per normal. This essentially allows system code to actively
|
||||
hook and handle certain software interrupts as necessary.
|
||||
****************************************************************************/
|
||||
void X86EMU_prepareForInt(
|
||||
int num)
|
||||
{
|
||||
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(num * 4 + 2);
|
||||
push_word(M.x86.R_IP);
|
||||
M.x86.R_IP = mem_access_word(num * 4);
|
||||
M.x86.intr = 0;
|
||||
}
|
210
os/src/drivers/framebuffer/vesa/contrib/x86emu/debug.h
Normal file
210
os/src/drivers/framebuffer/vesa/contrib/x86emu/debug.h
Normal file
@ -0,0 +1,210 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for debug definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_DEBUG_H
|
||||
#define __X86EMU_DEBUG_H
|
||||
|
||||
/*---------------------- Macros and type definitions ----------------------*/
|
||||
|
||||
/* checks to be enabled for "runtime" */
|
||||
|
||||
#define CHECK_IP_FETCH_F 0x1
|
||||
#define CHECK_SP_ACCESS_F 0x2
|
||||
#define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */
|
||||
#define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset*/
|
||||
|
||||
#ifdef DEBUG
|
||||
# define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F)
|
||||
# define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F)
|
||||
# define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F)
|
||||
# define CHECK_DATA_ACCESS() (M.x86.check & CHECK_DATA_ACCESS_F)
|
||||
#else
|
||||
# define CHECK_IP_FETCH()
|
||||
# define CHECK_SP_ACCESS()
|
||||
# define CHECK_MEM_ACCESS()
|
||||
# define CHECK_DATA_ACCESS()
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F)
|
||||
# define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F)
|
||||
# define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F)
|
||||
# define DEBUG_STEP() (M.x86.debug & DEBUG_STEP_F)
|
||||
# define DEBUG_DISASSEMBLE() (M.x86.debug & DEBUG_DISASSEMBLE_F)
|
||||
# define DEBUG_BREAK() (M.x86.debug & DEBUG_BREAK_F)
|
||||
# define DEBUG_SVC() (M.x86.debug & DEBUG_SVC_F)
|
||||
# define DEBUG_SAVE_IP_CS() (M.x86.debug & DEBUG_SAVE_IP_CS_F)
|
||||
|
||||
# define DEBUG_FS() (M.x86.debug & DEBUG_FS_F)
|
||||
# define DEBUG_PROC() (M.x86.debug & DEBUG_PROC_F)
|
||||
# define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F)
|
||||
# define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F)
|
||||
# define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F)
|
||||
# define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F)
|
||||
# define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F)
|
||||
# define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F)
|
||||
# define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F)
|
||||
#else
|
||||
# define DEBUG_INSTRUMENT() 0
|
||||
# define DEBUG_DECODE() 0
|
||||
# define DEBUG_TRACE() 0
|
||||
# define DEBUG_STEP() 0
|
||||
# define DEBUG_DISASSEMBLE() 0
|
||||
# define DEBUG_BREAK() 0
|
||||
# define DEBUG_SVC() 0
|
||||
# define DEBUG_SAVE_IP_CS() 0
|
||||
# define DEBUG_FS() 0
|
||||
# define DEBUG_PROC() 0
|
||||
# define DEBUG_SYSINT() 0
|
||||
# define DEBUG_TRACECALL() 0
|
||||
# define DEBUG_TRACECALLREGS() 0
|
||||
# define DEBUG_SYS() 0
|
||||
# define DEBUG_MEM_TRACE() 0
|
||||
# define DEBUG_IO_TRACE() 0
|
||||
# define DEBUG_DECODE_NOPRINT() 0
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
# define DECODE_PRINTF(x) if (DEBUG_DECODE()) \
|
||||
x86emu_decode_printf(x)
|
||||
# define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \
|
||||
x86emu_decode_printf2(x,y)
|
||||
|
||||
/*
|
||||
* The following allow us to look at the bytes of an instruction. The
|
||||
* first INCR_INSTRN_LEN, is called everytime bytes are consumed in
|
||||
* the decoding process. The SAVE_IP_CS is called initially when the
|
||||
* major opcode of the instruction is accessed.
|
||||
*/
|
||||
#define INC_DECODED_INST_LEN(x) \
|
||||
if (DEBUG_DECODE()) \
|
||||
x86emu_inc_decoded_inst_len(x)
|
||||
|
||||
#define SAVE_IP_CS(x,y) \
|
||||
if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \
|
||||
| DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \
|
||||
M.x86.saved_cs = x; \
|
||||
M.x86.saved_ip = y; \
|
||||
}
|
||||
#else
|
||||
# define INC_DECODED_INST_LEN(x)
|
||||
# define DECODE_PRINTF(x)
|
||||
# define DECODE_PRINTF2(x,y)
|
||||
# define SAVE_IP_CS(x,y)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TRACE_REGS() \
|
||||
if (DEBUG_DISASSEMBLE()) { \
|
||||
x86emu_just_disassemble(); \
|
||||
goto EndOfTheInstructionProcedure; \
|
||||
} \
|
||||
if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs()
|
||||
#else
|
||||
# define TRACE_REGS()
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define SINGLE_STEP() /*if (DEBUG_STEP()) x86emu_single_step()*/
|
||||
#else
|
||||
# define SINGLE_STEP()
|
||||
#endif
|
||||
|
||||
#define TRACE_AND_STEP() \
|
||||
TRACE_REGS(); \
|
||||
SINGLE_STEP()
|
||||
|
||||
#ifdef DEBUG
|
||||
# define START_OF_INSTR()
|
||||
# define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr();
|
||||
# define END_OF_INSTR_NO_TRACE() x86emu_end_instr();
|
||||
#else
|
||||
# define START_OF_INSTR()
|
||||
# define END_OF_INSTR()
|
||||
# define END_OF_INSTR_NO_TRACE()
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define CALL_TRACE(u,v,w,x,s) \
|
||||
if (DEBUG_TRACECALLREGS()) \
|
||||
x86emu_dump_regs(); \
|
||||
if (DEBUG_TRACECALL()) \
|
||||
printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x);
|
||||
# define RETURN_TRACE(n,u,v) \
|
||||
if (DEBUG_TRACECALLREGS()) \
|
||||
x86emu_dump_regs(); \
|
||||
if (DEBUG_TRACECALL()) \
|
||||
printk("%04x:%04x: %s\n",u,v,n);
|
||||
#else
|
||||
# define CALL_TRACE(u,v,w,x,s)
|
||||
# define RETURN_TRACE(n,u,v)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DB(x) x
|
||||
#else
|
||||
#define DB(x)
|
||||
#endif
|
||||
|
||||
/*-------------------------- Function Prototypes --------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
extern void x86emu_inc_decoded_inst_len (int x);
|
||||
extern void x86emu_decode_printf (char *x);
|
||||
extern void x86emu_decode_printf2 (char *x, int y);
|
||||
extern void x86emu_just_disassemble (void);
|
||||
extern void x86emu_single_step (void);
|
||||
extern void x86emu_end_instr (void);
|
||||
extern void x86emu_dump_regs (void);
|
||||
extern void x86emu_dump_xregs (void);
|
||||
extern void x86emu_print_int_vect (u16 iv);
|
||||
extern void x86emu_instrument_instruction (void);
|
||||
extern void x86emu_check_ip_access (void);
|
||||
extern void x86emu_check_sp_access (void);
|
||||
extern void x86emu_check_mem_access (u32 p);
|
||||
extern void x86emu_check_data_access (uint s, uint o);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_DEBUG_H */
|
88
os/src/drivers/framebuffer/vesa/contrib/x86emu/decode.h
Normal file
88
os/src/drivers/framebuffer/vesa/contrib/x86emu/decode.h
Normal file
@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for instruction decoding logic.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_DECODE_H
|
||||
#define __X86EMU_DECODE_H
|
||||
|
||||
/*---------------------- Macros and type definitions ----------------------*/
|
||||
|
||||
/* Instruction Decoding Stuff */
|
||||
|
||||
#define FETCH_DECODE_MODRM(mod,rh,rl) fetch_decode_modrm(&mod,&rh,&rl)
|
||||
#define DECODE_RM_BYTE_REGISTER(r) decode_rm_byte_register(r)
|
||||
#define DECODE_RM_WORD_REGISTER(r) decode_rm_word_register(r)
|
||||
#define DECODE_RM_LONG_REGISTER(r) decode_rm_long_register(r)
|
||||
#define DECODE_CLEAR_SEGOVR() M.x86.mode &= ~SYSMODE_CLRMASK
|
||||
|
||||
/*-------------------------- Function Prototypes --------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
void x86emu_intr_raise (u8 type);
|
||||
void fetch_decode_modrm (int *mod,int *regh,int *regl);
|
||||
u8 fetch_byte_imm (void);
|
||||
u16 fetch_word_imm (void);
|
||||
u32 fetch_long_imm (void);
|
||||
u8 fetch_data_byte (uint offset);
|
||||
u8 fetch_data_byte_abs (uint segment, uint offset);
|
||||
u16 fetch_data_word (uint offset);
|
||||
u16 fetch_data_word_abs (uint segment, uint offset);
|
||||
u32 fetch_data_long (uint offset);
|
||||
u32 fetch_data_long_abs (uint segment, uint offset);
|
||||
void store_data_byte (uint offset, u8 val);
|
||||
void store_data_byte_abs (uint segment, uint offset, u8 val);
|
||||
void store_data_word (uint offset, u16 val);
|
||||
void store_data_word_abs (uint segment, uint offset, u16 val);
|
||||
void store_data_long (uint offset, u32 val);
|
||||
void store_data_long_abs (uint segment, uint offset, u32 val);
|
||||
u8* decode_rm_byte_register(int reg);
|
||||
u16* decode_rm_word_register(int reg);
|
||||
u32* decode_rm_long_register(int reg);
|
||||
u16* decode_rm_seg_register(int reg);
|
||||
u32 decode_rm00_address(int rm);
|
||||
u32 decode_rm01_address(int rm);
|
||||
u32 decode_rm10_address(int rm);
|
||||
u32 decode_sib_address(int sib, int mod);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_DECODE_H */
|
61
os/src/drivers/framebuffer/vesa/contrib/x86emu/fpu.h
Normal file
61
os/src/drivers/framebuffer/vesa/contrib/x86emu/fpu.h
Normal file
@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for FPU instruction decoding.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_FPU_H
|
||||
#define __X86EMU_FPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
/* these have to be defined, whether 8087 support compiled in or not. */
|
||||
|
||||
extern void x86emuOp_esc_coprocess_d8 (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_d9 (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_da (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_db (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_dc (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_dd (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_de (u8 op1);
|
||||
extern void x86emuOp_esc_coprocess_df (u8 op1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_FPU_H */
|
119
os/src/drivers/framebuffer/vesa/contrib/x86emu/fpu_regs.h
Normal file
119
os/src/drivers/framebuffer/vesa/contrib/x86emu/fpu_regs.h
Normal file
@ -0,0 +1,119 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for FPU register definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_FPU_REGS_H
|
||||
#define __X86EMU_FPU_REGS_H
|
||||
|
||||
#ifdef X86_FPU_SUPPORT
|
||||
|
||||
#ifdef PACK
|
||||
# pragma PACK
|
||||
#endif
|
||||
|
||||
/* Basic 8087 register can hold any of the following values: */
|
||||
|
||||
union x86_fpu_reg_u {
|
||||
s8 tenbytes[10];
|
||||
double dval;
|
||||
float fval;
|
||||
s16 sval;
|
||||
s32 lval;
|
||||
};
|
||||
|
||||
struct x86_fpu_reg {
|
||||
union x86_fpu_reg_u reg;
|
||||
char tag;
|
||||
};
|
||||
|
||||
/*
|
||||
* Since we are not going to worry about the problems of aliasing
|
||||
* registers, every time a register is modified, its result type is
|
||||
* set in the tag fields for that register. If some operation
|
||||
* attempts to access the type in a way inconsistent with its current
|
||||
* storage format, then we flag the operation. If common, we'll
|
||||
* attempt the conversion.
|
||||
*/
|
||||
|
||||
#define X86_FPU_VALID 0x80
|
||||
#define X86_FPU_REGTYP(r) ((r) & 0x7F)
|
||||
|
||||
#define X86_FPU_WORD 0x0
|
||||
#define X86_FPU_SHORT 0x1
|
||||
#define X86_FPU_LONG 0x2
|
||||
#define X86_FPU_FLOAT 0x3
|
||||
#define X86_FPU_DOUBLE 0x4
|
||||
#define X86_FPU_LDBL 0x5
|
||||
#define X86_FPU_BSD 0x6
|
||||
|
||||
#define X86_FPU_STKTOP 0
|
||||
|
||||
struct x86_fpu_registers {
|
||||
struct x86_fpu_reg x86_fpu_stack[8];
|
||||
int x86_fpu_flags;
|
||||
int x86_fpu_config; /* rounding modes, etc. */
|
||||
short x86_fpu_tos, x86_fpu_bos;
|
||||
};
|
||||
|
||||
#ifdef END_PACK
|
||||
# pragma END_PACK
|
||||
#endif
|
||||
|
||||
/*
|
||||
* There are two versions of the following macro.
|
||||
*
|
||||
* One version is for opcode D9, for which there are more than 32
|
||||
* instructions encoded in the second byte of the opcode.
|
||||
*
|
||||
* The other version, deals with all the other 7 i87 opcodes, for
|
||||
* which there are only 32 strings needed to describe the
|
||||
* instructions.
|
||||
*/
|
||||
|
||||
#endif /* X86_FPU_SUPPORT */
|
||||
|
||||
#ifdef DEBUG
|
||||
# define DECODE_PRINTINSTR32(t,mod,rh,rl) \
|
||||
DECODE_PRINTF(t[(mod<<3)+(rh)]);
|
||||
# define DECODE_PRINTINSTR256(t,mod,rh,rl) \
|
||||
DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]);
|
||||
#else
|
||||
# define DECODE_PRINTINSTR32(t,mod,rh,rl)
|
||||
# define DECODE_PRINTINSTR256(t,mod,rh,rl)
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_FPU_REGS_H */
|
45
os/src/drivers/framebuffer/vesa/contrib/x86emu/ops.h
Normal file
45
os/src/drivers/framebuffer/vesa/contrib/x86emu/ops.h
Normal file
@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for operand decoding functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_OPS_H
|
||||
#define __X86EMU_OPS_H
|
||||
|
||||
extern void (*x86emu_optab[0x100])(u8 op1);
|
||||
extern void (*x86emu_optab2[0x100])(u8 op2);
|
||||
|
||||
#endif /* __X86EMU_OPS_H */
|
970
os/src/drivers/framebuffer/vesa/contrib/x86emu/prim_asm.h
Normal file
970
os/src/drivers/framebuffer/vesa/contrib/x86emu/prim_asm.h
Normal file
@ -0,0 +1,970 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Watcom C++ 10.6 or later
|
||||
* Environment: Any
|
||||
* Developer: Kendall Bennett
|
||||
*
|
||||
* Description: Inline assembler versions of the primitive operand
|
||||
* functions for faster performance. At the moment this is
|
||||
* x86 inline assembler, but these functions could be replaced
|
||||
* with native inline assembler for each supported processor
|
||||
* platform.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_PRIM_ASM_H
|
||||
#define __X86EMU_PRIM_ASM_H
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
|
||||
#ifndef VALIDATE
|
||||
#define __HAVE_INLINE_ASSEMBLER__
|
||||
#endif
|
||||
|
||||
u32 get_flags_asm(void);
|
||||
#pragma aux get_flags_asm = \
|
||||
"pushf" \
|
||||
"pop eax" \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
|
||||
u16 aaa_word_asm(u32 *flags,u16 d);
|
||||
#pragma aux aaa_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"aaa" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u16 aas_word_asm(u32 *flags,u16 d);
|
||||
#pragma aux aas_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"aas" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u16 aad_word_asm(u32 *flags,u16 d);
|
||||
#pragma aux aad_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"aad" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u16 aam_word_asm(u32 *flags,u8 d);
|
||||
#pragma aux aam_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"aam" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u8 adc_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux adc_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"adc al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 adc_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux adc_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"adc ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 adc_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux adc_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"adc eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
u8 add_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux add_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"add al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 add_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux add_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"add ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 add_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux add_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"add eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
u8 and_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux and_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"and al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 and_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux and_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"and ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 and_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux and_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"and eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
u8 cmp_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux cmp_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"cmp al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 cmp_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux cmp_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"cmp ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 cmp_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux cmp_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"cmp eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
u8 daa_byte_asm(u32 *flags,u8 d);
|
||||
#pragma aux daa_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"daa" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] \
|
||||
value [al] \
|
||||
modify exact [al];
|
||||
|
||||
u8 das_byte_asm(u32 *flags,u8 d);
|
||||
#pragma aux das_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"das" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] \
|
||||
value [al] \
|
||||
modify exact [al];
|
||||
|
||||
u8 dec_byte_asm(u32 *flags,u8 d);
|
||||
#pragma aux dec_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"dec al" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] \
|
||||
value [al] \
|
||||
modify exact [al];
|
||||
|
||||
u16 dec_word_asm(u32 *flags,u16 d);
|
||||
#pragma aux dec_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"dec ax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u32 dec_long_asm(u32 *flags,u32 d);
|
||||
#pragma aux dec_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"dec eax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
|
||||
u8 inc_byte_asm(u32 *flags,u8 d);
|
||||
#pragma aux inc_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"inc al" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] \
|
||||
value [al] \
|
||||
modify exact [al];
|
||||
|
||||
u16 inc_word_asm(u32 *flags,u16 d);
|
||||
#pragma aux inc_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"inc ax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u32 inc_long_asm(u32 *flags,u32 d);
|
||||
#pragma aux inc_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"inc eax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
|
||||
u8 or_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux or_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"or al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 or_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux or_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"or ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 or_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux or_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"or eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
u8 neg_byte_asm(u32 *flags,u8 d);
|
||||
#pragma aux neg_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"neg al" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] \
|
||||
value [al] \
|
||||
modify exact [al];
|
||||
|
||||
u16 neg_word_asm(u32 *flags,u16 d);
|
||||
#pragma aux neg_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"neg ax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u32 neg_long_asm(u32 *flags,u32 d);
|
||||
#pragma aux neg_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"neg eax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
|
||||
u8 not_byte_asm(u32 *flags,u8 d);
|
||||
#pragma aux not_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"not al" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] \
|
||||
value [al] \
|
||||
modify exact [al];
|
||||
|
||||
u16 not_word_asm(u32 *flags,u16 d);
|
||||
#pragma aux not_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"not ax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] \
|
||||
value [ax] \
|
||||
modify exact [ax];
|
||||
|
||||
u32 not_long_asm(u32 *flags,u32 d);
|
||||
#pragma aux not_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"not eax" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
|
||||
u8 rcl_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux rcl_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rcl al,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [cl] \
|
||||
value [al] \
|
||||
modify exact [al cl];
|
||||
|
||||
u16 rcl_word_asm(u32 *flags,u16 d, u8 s);
|
||||
#pragma aux rcl_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rcl ax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax cl];
|
||||
|
||||
u32 rcl_long_asm(u32 *flags,u32 d, u8 s);
|
||||
#pragma aux rcl_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rcl eax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax cl];
|
||||
|
||||
u8 rcr_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux rcr_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rcr al,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [cl] \
|
||||
value [al] \
|
||||
modify exact [al cl];
|
||||
|
||||
u16 rcr_word_asm(u32 *flags,u16 d, u8 s);
|
||||
#pragma aux rcr_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rcr ax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax cl];
|
||||
|
||||
u32 rcr_long_asm(u32 *flags,u32 d, u8 s);
|
||||
#pragma aux rcr_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rcr eax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax cl];
|
||||
|
||||
u8 rol_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux rol_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rol al,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [cl] \
|
||||
value [al] \
|
||||
modify exact [al cl];
|
||||
|
||||
u16 rol_word_asm(u32 *flags,u16 d, u8 s);
|
||||
#pragma aux rol_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rol ax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax cl];
|
||||
|
||||
u32 rol_long_asm(u32 *flags,u32 d, u8 s);
|
||||
#pragma aux rol_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"rol eax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax cl];
|
||||
|
||||
u8 ror_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux ror_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"ror al,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [cl] \
|
||||
value [al] \
|
||||
modify exact [al cl];
|
||||
|
||||
u16 ror_word_asm(u32 *flags,u16 d, u8 s);
|
||||
#pragma aux ror_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"ror ax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax cl];
|
||||
|
||||
u32 ror_long_asm(u32 *flags,u32 d, u8 s);
|
||||
#pragma aux ror_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"ror eax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax cl];
|
||||
|
||||
u8 shl_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux shl_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shl al,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [cl] \
|
||||
value [al] \
|
||||
modify exact [al cl];
|
||||
|
||||
u16 shl_word_asm(u32 *flags,u16 d, u8 s);
|
||||
#pragma aux shl_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shl ax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax cl];
|
||||
|
||||
u32 shl_long_asm(u32 *flags,u32 d, u8 s);
|
||||
#pragma aux shl_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shl eax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax cl];
|
||||
|
||||
u8 shr_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux shr_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shr al,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [cl] \
|
||||
value [al] \
|
||||
modify exact [al cl];
|
||||
|
||||
u16 shr_word_asm(u32 *flags,u16 d, u8 s);
|
||||
#pragma aux shr_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shr ax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax cl];
|
||||
|
||||
u32 shr_long_asm(u32 *flags,u32 d, u8 s);
|
||||
#pragma aux shr_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shr eax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax cl];
|
||||
|
||||
u8 sar_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux sar_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sar al,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [cl] \
|
||||
value [al] \
|
||||
modify exact [al cl];
|
||||
|
||||
u16 sar_word_asm(u32 *flags,u16 d, u8 s);
|
||||
#pragma aux sar_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sar ax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax cl];
|
||||
|
||||
u32 sar_long_asm(u32 *flags,u32 d, u8 s);
|
||||
#pragma aux sar_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sar eax,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax cl];
|
||||
|
||||
u16 shld_word_asm(u32 *flags,u16 d, u16 fill, u8 s);
|
||||
#pragma aux shld_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shld ax,dx,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [dx] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax dx cl];
|
||||
|
||||
u32 shld_long_asm(u32 *flags,u32 d, u32 fill, u8 s);
|
||||
#pragma aux shld_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shld eax,edx,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [edx] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax edx cl];
|
||||
|
||||
u16 shrd_word_asm(u32 *flags,u16 d, u16 fill, u8 s);
|
||||
#pragma aux shrd_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shrd ax,dx,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [dx] [cl] \
|
||||
value [ax] \
|
||||
modify exact [ax dx cl];
|
||||
|
||||
u32 shrd_long_asm(u32 *flags,u32 d, u32 fill, u8 s);
|
||||
#pragma aux shrd_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"shrd eax,edx,cl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [edx] [cl] \
|
||||
value [eax] \
|
||||
modify exact [eax edx cl];
|
||||
|
||||
u8 sbb_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux sbb_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sbb al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 sbb_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux sbb_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sbb ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 sbb_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux sbb_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sbb eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
u8 sub_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux sub_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sub al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 sub_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux sub_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sub ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 sub_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux sub_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"sub eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
void test_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux test_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"test al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
modify exact [al bl];
|
||||
|
||||
void test_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux test_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"test ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
modify exact [ax bx];
|
||||
|
||||
void test_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux test_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"test eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
u8 xor_byte_asm(u32 *flags,u8 d, u8 s);
|
||||
#pragma aux xor_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"xor al,bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [al] [bl] \
|
||||
value [al] \
|
||||
modify exact [al bl];
|
||||
|
||||
u16 xor_word_asm(u32 *flags,u16 d, u16 s);
|
||||
#pragma aux xor_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"xor ax,bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [ax] [bx] \
|
||||
value [ax] \
|
||||
modify exact [ax bx];
|
||||
|
||||
u32 xor_long_asm(u32 *flags,u32 d, u32 s);
|
||||
#pragma aux xor_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"xor eax,ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
parm [edi] [eax] [ebx] \
|
||||
value [eax] \
|
||||
modify exact [eax ebx];
|
||||
|
||||
void imul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s);
|
||||
#pragma aux imul_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"imul bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],ax" \
|
||||
parm [edi] [esi] [al] [bl] \
|
||||
modify exact [esi ax bl];
|
||||
|
||||
void imul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s);
|
||||
#pragma aux imul_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"imul bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],ax" \
|
||||
"mov [ecx],dx" \
|
||||
parm [edi] [esi] [ecx] [ax] [bx]\
|
||||
modify exact [esi edi ax bx dx];
|
||||
|
||||
void imul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s);
|
||||
#pragma aux imul_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"imul ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],eax" \
|
||||
"mov [ecx],edx" \
|
||||
parm [edi] [esi] [ecx] [eax] [ebx] \
|
||||
modify exact [esi edi eax ebx edx];
|
||||
|
||||
void mul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s);
|
||||
#pragma aux mul_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"mul bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],ax" \
|
||||
parm [edi] [esi] [al] [bl] \
|
||||
modify exact [esi ax bl];
|
||||
|
||||
void mul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s);
|
||||
#pragma aux mul_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"mul bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],ax" \
|
||||
"mov [ecx],dx" \
|
||||
parm [edi] [esi] [ecx] [ax] [bx]\
|
||||
modify exact [esi edi ax bx dx];
|
||||
|
||||
void mul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s);
|
||||
#pragma aux mul_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"mul ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],eax" \
|
||||
"mov [ecx],edx" \
|
||||
parm [edi] [esi] [ecx] [eax] [ebx] \
|
||||
modify exact [esi edi eax ebx edx];
|
||||
|
||||
void idiv_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s);
|
||||
#pragma aux idiv_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"idiv bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],al" \
|
||||
"mov [ecx],ah" \
|
||||
parm [edi] [esi] [ecx] [ax] [bl]\
|
||||
modify exact [esi edi ax bl];
|
||||
|
||||
void idiv_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s);
|
||||
#pragma aux idiv_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"idiv bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],ax" \
|
||||
"mov [ecx],dx" \
|
||||
parm [edi] [esi] [ecx] [ax] [dx] [bx]\
|
||||
modify exact [esi edi ax dx bx];
|
||||
|
||||
void idiv_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s);
|
||||
#pragma aux idiv_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"idiv ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],eax" \
|
||||
"mov [ecx],edx" \
|
||||
parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
|
||||
modify exact [esi edi eax edx ebx];
|
||||
|
||||
void div_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s);
|
||||
#pragma aux div_byte_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"div bl" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],al" \
|
||||
"mov [ecx],ah" \
|
||||
parm [edi] [esi] [ecx] [ax] [bl]\
|
||||
modify exact [esi edi ax bl];
|
||||
|
||||
void div_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s);
|
||||
#pragma aux div_word_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"div bx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],ax" \
|
||||
"mov [ecx],dx" \
|
||||
parm [edi] [esi] [ecx] [ax] [dx] [bx]\
|
||||
modify exact [esi edi ax dx bx];
|
||||
|
||||
void div_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s);
|
||||
#pragma aux div_long_asm = \
|
||||
"push [edi]" \
|
||||
"popf" \
|
||||
"div ebx" \
|
||||
"pushf" \
|
||||
"pop [edi]" \
|
||||
"mov [esi],eax" \
|
||||
"mov [ecx],edx" \
|
||||
parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
|
||||
modify exact [esi edi eax edx ebx];
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_PRIM_ASM_H */
|
141
os/src/drivers/framebuffer/vesa/contrib/x86emu/prim_ops.h
Normal file
141
os/src/drivers/framebuffer/vesa/contrib/x86emu/prim_ops.h
Normal file
@ -0,0 +1,141 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for primitive operation functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_PRIM_OPS_H
|
||||
#define __X86EMU_PRIM_OPS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
u16 aaa_word (u16 d);
|
||||
u16 aas_word (u16 d);
|
||||
u16 aad_word (u16 d);
|
||||
u16 aam_word (u8 d);
|
||||
u8 adc_byte (u8 d, u8 s);
|
||||
u16 adc_word (u16 d, u16 s);
|
||||
u32 adc_long (u32 d, u32 s);
|
||||
u8 add_byte (u8 d, u8 s);
|
||||
u16 add_word (u16 d, u16 s);
|
||||
u32 add_long (u32 d, u32 s);
|
||||
u8 and_byte (u8 d, u8 s);
|
||||
u16 and_word (u16 d, u16 s);
|
||||
u32 and_long (u32 d, u32 s);
|
||||
u8 cmp_byte (u8 d, u8 s);
|
||||
u16 cmp_word (u16 d, u16 s);
|
||||
u32 cmp_long (u32 d, u32 s);
|
||||
u8 daa_byte (u8 d);
|
||||
u8 das_byte (u8 d);
|
||||
u8 dec_byte (u8 d);
|
||||
u16 dec_word (u16 d);
|
||||
u32 dec_long (u32 d);
|
||||
u8 inc_byte (u8 d);
|
||||
u16 inc_word (u16 d);
|
||||
u32 inc_long (u32 d);
|
||||
u8 or_byte (u8 d, u8 s);
|
||||
u16 or_word (u16 d, u16 s);
|
||||
u32 or_long (u32 d, u32 s);
|
||||
u8 neg_byte (u8 s);
|
||||
u16 neg_word (u16 s);
|
||||
u32 neg_long (u32 s);
|
||||
u8 not_byte (u8 s);
|
||||
u16 not_word (u16 s);
|
||||
u32 not_long (u32 s);
|
||||
u8 rcl_byte (u8 d, u8 s);
|
||||
u16 rcl_word (u16 d, u8 s);
|
||||
u32 rcl_long (u32 d, u8 s);
|
||||
u8 rcr_byte (u8 d, u8 s);
|
||||
u16 rcr_word (u16 d, u8 s);
|
||||
u32 rcr_long (u32 d, u8 s);
|
||||
u8 rol_byte (u8 d, u8 s);
|
||||
u16 rol_word (u16 d, u8 s);
|
||||
u32 rol_long (u32 d, u8 s);
|
||||
u8 ror_byte (u8 d, u8 s);
|
||||
u16 ror_word (u16 d, u8 s);
|
||||
u32 ror_long (u32 d, u8 s);
|
||||
u8 shl_byte (u8 d, u8 s);
|
||||
u16 shl_word (u16 d, u8 s);
|
||||
u32 shl_long (u32 d, u8 s);
|
||||
u8 shr_byte (u8 d, u8 s);
|
||||
u16 shr_word (u16 d, u8 s);
|
||||
u32 shr_long (u32 d, u8 s);
|
||||
u8 sar_byte (u8 d, u8 s);
|
||||
u16 sar_word (u16 d, u8 s);
|
||||
u32 sar_long (u32 d, u8 s);
|
||||
u16 shld_word (u16 d, u16 fill, u8 s);
|
||||
u32 shld_long (u32 d, u32 fill, u8 s);
|
||||
u16 shrd_word (u16 d, u16 fill, u8 s);
|
||||
u32 shrd_long (u32 d, u32 fill, u8 s);
|
||||
u8 sbb_byte (u8 d, u8 s);
|
||||
u16 sbb_word (u16 d, u16 s);
|
||||
u32 sbb_long (u32 d, u32 s);
|
||||
u8 sub_byte (u8 d, u8 s);
|
||||
u16 sub_word (u16 d, u16 s);
|
||||
u32 sub_long (u32 d, u32 s);
|
||||
void test_byte (u8 d, u8 s);
|
||||
void test_word (u16 d, u16 s);
|
||||
void test_long (u32 d, u32 s);
|
||||
u8 xor_byte (u8 d, u8 s);
|
||||
u16 xor_word (u16 d, u16 s);
|
||||
u32 xor_long (u32 d, u32 s);
|
||||
void imul_byte (u8 s);
|
||||
void imul_word (u16 s);
|
||||
void imul_long (u32 s);
|
||||
void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s);
|
||||
void mul_byte (u8 s);
|
||||
void mul_word (u16 s);
|
||||
void mul_long (u32 s);
|
||||
void idiv_byte (u8 s);
|
||||
void idiv_word (u16 s);
|
||||
void idiv_long (u32 s);
|
||||
void div_byte (u8 s);
|
||||
void div_word (u16 s);
|
||||
void div_long (u32 s);
|
||||
void ins (int size);
|
||||
void outs (int size);
|
||||
u16 mem_access_word (int addr);
|
||||
void push_word (u16 w);
|
||||
void push_long (u32 w);
|
||||
u16 pop_word (void);
|
||||
u32 pop_long (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_PRIM_OPS_H */
|
103
os/src/drivers/framebuffer/vesa/contrib/x86emu/x86emui.h
Normal file
103
os/src/drivers/framebuffer/vesa/contrib/x86emu/x86emui.h
Normal file
@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for system specific functions. These functions
|
||||
* are always compiled and linked in the OS depedent libraries,
|
||||
* and never in a binary portable driver.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __X86EMU_X86EMUI_H
|
||||
#define __X86EMU_X86EMUI_H
|
||||
|
||||
/* If we are compiling in C++ mode, we can compile some functions as
|
||||
* inline to increase performance (however the code size increases quite
|
||||
* dramatically in this case).
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus) && !defined(_NO_INLINE)
|
||||
#define _INLINE inline
|
||||
#else
|
||||
#define _INLINE static
|
||||
#endif
|
||||
|
||||
/* Get rid of unused parameters in C++ compilation mode */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define X86EMU_UNUSED(v)
|
||||
#else
|
||||
#define X86EMU_UNUSED(v) v
|
||||
#endif
|
||||
|
||||
#define NULL (void*)0
|
||||
|
||||
#include <x86emu/x86emu.h>
|
||||
#include "x86emu/debug.h"
|
||||
#include "x86emu/decode.h"
|
||||
#include "x86emu/ops.h"
|
||||
#include "x86emu/prim_ops.h"
|
||||
#include "x86emu/fpu.h"
|
||||
#include "x86emu/fpu_regs.h"
|
||||
|
||||
#ifndef NO_SYS_HEADERS
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
/*--------------------------- Inline Functions ----------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
extern u8 (X86APIP sys_rdb)(u32 addr);
|
||||
extern u16 (X86APIP sys_rdw)(u32 addr);
|
||||
extern u32 (X86APIP sys_rdl)(u32 addr);
|
||||
extern void (X86APIP sys_wrb)(u32 addr,u8 val);
|
||||
extern void (X86APIP sys_wrw)(u32 addr,u16 val);
|
||||
extern void (X86APIP sys_wrl)(u32 addr,u32 val);
|
||||
|
||||
extern u8 (X86APIP sys_inb)(X86EMU_pioAddr addr);
|
||||
extern u16 (X86APIP sys_inw)(X86EMU_pioAddr addr);
|
||||
extern u32 (X86APIP sys_inl)(X86EMU_pioAddr addr);
|
||||
extern void (X86APIP sys_outb)(X86EMU_pioAddr addr,u8 val);
|
||||
extern void (X86APIP sys_outw)(X86EMU_pioAddr addr,u16 val);
|
||||
extern void (X86APIP sys_outl)(X86EMU_pioAddr addr,u32 val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_X86EMUI_H */
|
253
os/src/drivers/framebuffer/vesa/framebuffer.cc
Normal file
253
os/src/drivers/framebuffer/vesa/framebuffer.cc
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* \brief VESA frame buffer driver back end
|
||||
* \author Sebastian Sumpf
|
||||
* \author Christian Helmuth
|
||||
* \date 2007-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/stdint.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include "ifx86emu.h"
|
||||
#include "vesa.h"
|
||||
#include "vbe.h"
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Vesa;
|
||||
|
||||
/**
|
||||
* Frame buffer I/O memory dataspace
|
||||
*/
|
||||
static Dataspace_capability io_mem_cap;
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
/***************
|
||||
** Utilities **
|
||||
***************/
|
||||
|
||||
|
||||
static inline uint32_t to_phys(uint32_t addr)
|
||||
{
|
||||
return (addr & 0xFFFF) + ((addr >> 12) & 0xFFFF0);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t get_vesa_mode(mb_vbe_ctrl_t *ctrl_info, mb_vbe_mode_t *mode_info,
|
||||
unsigned long width, unsigned long height,
|
||||
unsigned long depth, bool verbose)
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
|
||||
if (verbose)
|
||||
printf("Supported mode list\n");
|
||||
|
||||
/*
|
||||
* The virtual address of the ctrl_info mapping may change on x86_cmd
|
||||
* execution. Therefore, we resolve the address on each iteration.
|
||||
*/
|
||||
#define MODE_PTR(off) (X86emu::virt_addr<uint16_t>(to_phys(ctrl_info->video_mode)) + off)
|
||||
for (unsigned off = 0; *MODE_PTR(off) != 0xFFFF; ++off) {
|
||||
if (X86emu::x86emu_cmd(VBE_INFO_FUNC, 0, *MODE_PTR(off), VESA_MODE_OFFS) != VBE_SUPPORTED)
|
||||
continue;
|
||||
|
||||
if (verbose)
|
||||
printf(" 0x%03x %ux%u@%u\n", *MODE_PTR(off), mode_info->x_resolution,
|
||||
mode_info->y_resolution,
|
||||
mode_info->bits_per_pixel);
|
||||
|
||||
if (mode_info->x_resolution == width &&
|
||||
mode_info->y_resolution == height &&
|
||||
mode_info->bits_per_pixel == depth)
|
||||
ret = *MODE_PTR(off);
|
||||
}
|
||||
#undef MODE_PTR
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (verbose)
|
||||
PWRN("Searching in default vesa modes");
|
||||
|
||||
return get_default_vesa_mode(width, height, depth);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
** Driver API **
|
||||
****************/
|
||||
|
||||
Dataspace_capability Framebuffer_drv::hw_framebuffer()
|
||||
{
|
||||
return io_mem_cap;
|
||||
}
|
||||
|
||||
|
||||
int Framebuffer_drv::map_io_mem(addr_t base, size_t size, bool write_combined,
|
||||
void **out_addr, addr_t addr,
|
||||
Dataspace_capability *out_io_ds)
|
||||
{
|
||||
Io_mem_connection io_mem(base, size, write_combined);
|
||||
io_mem.on_destruction(Io_mem_connection::KEEP_OPEN);
|
||||
Io_mem_dataspace_capability io_ds = io_mem.dataspace();
|
||||
if (!io_ds.valid())
|
||||
return -2;
|
||||
|
||||
try {
|
||||
*out_addr = env()->rm_session()->attach(io_ds, size, 0, addr != 0, addr);
|
||||
} catch (Rm_session::Attach_failed) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (out_io_ds)
|
||||
*out_io_ds = io_ds;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Framebuffer_drv::use_current_mode()
|
||||
{
|
||||
mb_vbe_ctrl_t *ctrl_info;
|
||||
mb_vbe_mode_t *mode_info;
|
||||
|
||||
/* set location of data types */
|
||||
ctrl_info = reinterpret_cast<mb_vbe_ctrl_t*>(X86emu::x86_mem.data_addr()
|
||||
+ VESA_CTRL_OFFS);
|
||||
mode_info = reinterpret_cast<mb_vbe_mode_t*>(X86emu::x86_mem.data_addr()
|
||||
+ VESA_MODE_OFFS);
|
||||
|
||||
/* retrieve controller information */
|
||||
if (X86emu::x86emu_cmd(VBE_CONTROL_FUNC, 0, 0, VESA_CTRL_OFFS) != VBE_SUPPORTED) {
|
||||
PWRN("VBE Bios not present");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* retrieve current video mode */
|
||||
uint16_t vesa_mode = 0;
|
||||
if (X86emu::x86emu_cmd(VBE_GMODE_FUNC, 0, 0, 0, &vesa_mode) != VBE_SUPPORTED) {
|
||||
PWRN("VBE Bios not present");
|
||||
return -1;
|
||||
}
|
||||
vesa_mode &= 0x3fff;
|
||||
|
||||
/* retrieve framebuffer info for current mode */
|
||||
if (X86emu::x86emu_cmd(VBE_INFO_FUNC, 0, vesa_mode, VESA_MODE_OFFS) != VBE_SUPPORTED) {
|
||||
PWRN("VBE Info function failed");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (!io_mem_cap.valid()) {
|
||||
printf("Found: physical frame buffer at 0x%08x size: 0x%08x\n",
|
||||
mode_info->phys_base,
|
||||
ctrl_info->total_memory << 16);
|
||||
|
||||
void *fb;
|
||||
map_io_mem(mode_info->phys_base, ctrl_info->total_memory << 16, true,
|
||||
&fb, 0, &io_mem_cap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Framebuffer_drv::set_mode(unsigned long width, unsigned long height,
|
||||
unsigned long mode)
|
||||
{
|
||||
mb_vbe_ctrl_t *ctrl_info;
|
||||
mb_vbe_mode_t *mode_info;
|
||||
char * oem_string;
|
||||
uint16_t vesa_mode;
|
||||
|
||||
/* set location of data types */
|
||||
ctrl_info = reinterpret_cast<mb_vbe_ctrl_t*>(X86emu::x86_mem.data_addr()
|
||||
+ VESA_CTRL_OFFS);
|
||||
mode_info = reinterpret_cast<mb_vbe_mode_t*>(X86emu::x86_mem.data_addr()
|
||||
+ VESA_MODE_OFFS);
|
||||
|
||||
/* retrieve controller information */
|
||||
if (X86emu::x86emu_cmd(VBE_CONTROL_FUNC, 0, 0, VESA_CTRL_OFFS) != VBE_SUPPORTED) {
|
||||
PWRN("VBE Bios not present");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* retrieve vesa mode hex value */
|
||||
if (!(vesa_mode = get_vesa_mode(ctrl_info, mode_info, width, height, mode, verbose))) {
|
||||
PWRN("graphics mode %lux%lu@%lu not found", width, height, mode);
|
||||
get_vesa_mode(ctrl_info, mode_info, 0, 0, 0, true);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* use current refresh rate, set flat framebuffer model */
|
||||
vesa_mode = (vesa_mode & VBE_CUR_REFRESH_MASK) | VBE_SET_FLAT_FB;
|
||||
|
||||
/* determine VBE version and OEM string */
|
||||
oem_string = X86emu::virt_addr<char>(to_phys(ctrl_info->oem_string));
|
||||
|
||||
printf("Found: VESA BIOS version %d.%d\nOEM: %s\n",
|
||||
ctrl_info->version >> 8, ctrl_info->version & 0xFF,
|
||||
ctrl_info->oem_string ? oem_string : "[unknown]");
|
||||
|
||||
if (ctrl_info->version < 0x200) {
|
||||
PWRN("VESA Bios version 2.0 or later required");
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* get mode info */
|
||||
/* 0x91 tests MODE SUPPORTED (0x1) | GRAPHICS MODE (0x10) | LINEAR
|
||||
* FRAME BUFFER (0x80) bits */
|
||||
if (X86emu::x86emu_cmd(VBE_INFO_FUNC, 0, vesa_mode, VESA_MODE_OFFS) != VBE_SUPPORTED
|
||||
|| (mode_info->mode_attributes & 0x91) != 0x91) {
|
||||
PWRN("graphics mode %lux%lu@%lu not supported", width, height, mode);
|
||||
get_vesa_mode(ctrl_info, mode_info, 0, 0, 0, true);
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* set mode */
|
||||
if ((X86emu::x86emu_cmd(VBE_MODE_FUNC, vesa_mode) & 0xFF00) != VBE_SUCCESS) {
|
||||
PDBG("VBE SET error");
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* map framebuffer */
|
||||
void *fb;
|
||||
if (!io_mem_cap.valid()) {
|
||||
X86emu::x86emu_cmd(VBE_INFO_FUNC, 0, vesa_mode, VESA_MODE_OFFS);
|
||||
|
||||
printf("Found: physical frame buffer at 0x%08x size: 0x%08x\n",
|
||||
mode_info->phys_base,
|
||||
ctrl_info->total_memory << 16);
|
||||
map_io_mem(mode_info->phys_base, ctrl_info->total_memory << 16, true,
|
||||
&fb, 0, &io_mem_cap);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
X86emu::print_regions();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** Driver startup **
|
||||
********************/
|
||||
|
||||
int Framebuffer_drv::init()
|
||||
{
|
||||
if (X86emu::init())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
311
os/src/drivers/framebuffer/vesa/hw_emul.cc
Normal file
311
os/src/drivers/framebuffer/vesa/hw_emul.cc
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* \brief Hardware emulation implementation
|
||||
* \author Christian Helmuth
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-06-01
|
||||
*
|
||||
* The emulation comprises:
|
||||
*
|
||||
* - Simple programmable interval timer (PIT)
|
||||
* - Virtual PCI bus with VGA card attached to its physical slot
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/sleep.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
#include "hw_emul.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
/************************
|
||||
** PCI virtualization **
|
||||
************************/
|
||||
|
||||
#include <pci_session/connection.h>
|
||||
#include <pci_device/client.h>
|
||||
|
||||
enum {
|
||||
PCI_ADDR_REG = 0xcf8,
|
||||
PCI_DATA_REG = 0xcfc
|
||||
};
|
||||
|
||||
class Pci_card
|
||||
{
|
||||
private:
|
||||
|
||||
Pci::Connection _pci_drv;
|
||||
Pci::Device_client _device;
|
||||
unsigned short _devfn;
|
||||
|
||||
Pci::Device_capability _find_vga_card()
|
||||
{
|
||||
/*
|
||||
* Iterate through all accessible devices.
|
||||
*/
|
||||
Pci::Device_capability prev_device_cap, device_cap;
|
||||
for (device_cap = _pci_drv.first_device();
|
||||
device_cap.valid();
|
||||
device_cap = _pci_drv.next_device(prev_device_cap)) {
|
||||
|
||||
Pci::Device_client device(device_cap);
|
||||
|
||||
/*
|
||||
* If the device is an VGA compatible controller with base
|
||||
* class 0x03 and sub class 0x00 stop iteration. (We shift out
|
||||
* the interface bits.)
|
||||
*/
|
||||
if ((device.class_code() >> 8) == 0x0300)
|
||||
break;
|
||||
|
||||
prev_device_cap = device_cap;
|
||||
}
|
||||
|
||||
if (!device_cap.valid()) {
|
||||
PERR("PCI VGA card not found. Sleeping...");
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
return device_cap;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Pci_card() : _pci_drv(), _device(_find_vga_card())
|
||||
{
|
||||
unsigned char bus = 0, dev = 0, fn = 0;
|
||||
|
||||
_device.bus_address(&bus, &dev, &fn);
|
||||
_devfn = bus << 8 | dev << 3 | fn;
|
||||
|
||||
if (verbose)
|
||||
PDBG("Found PCI VGA at %x:%x.%x", bus, dev, fn);
|
||||
}
|
||||
|
||||
Pci::Device_client &device() { return _device; }
|
||||
unsigned short devfn() const { return _devfn; }
|
||||
};
|
||||
|
||||
|
||||
static Pci_card *pci_card()
|
||||
{
|
||||
static Pci_card _pci_card;
|
||||
return &_pci_card;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Last address written to address port.
|
||||
*/
|
||||
static unsigned pci_cfg_addr;
|
||||
static bool pci_cfg_addr_valid = false;
|
||||
|
||||
|
||||
template <typename T>
|
||||
static bool handle_pci_port_write(unsigned short port, T val)
|
||||
{
|
||||
switch (port) {
|
||||
|
||||
case PCI_ADDR_REG:
|
||||
/*
|
||||
* The virtual bus has only 1 device - the VGA card - at its physical
|
||||
* bus address.
|
||||
*/
|
||||
{
|
||||
if (sizeof(T) != 4) {
|
||||
PWRN("writing with size %zx not supported", sizeof(T));
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned devfn = (val >> 8) & 0xffff;
|
||||
if (devfn != pci_card()->devfn()) {
|
||||
if (verbose)
|
||||
PWRN("accessing unknown PCI device %x", devfn);
|
||||
pci_cfg_addr_valid = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* remember the configuration address */
|
||||
pci_cfg_addr = val & 0xfc;
|
||||
pci_cfg_addr_valid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case PCI_DATA_REG:
|
||||
PWRN("writing data register not supported (value=0x%x)", (int)val);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static bool handle_pci_port_read(unsigned short port, T *val)
|
||||
{
|
||||
unsigned raw_val;
|
||||
|
||||
*val = 0;
|
||||
|
||||
switch (port & ~3) {
|
||||
|
||||
case PCI_ADDR_REG:
|
||||
*val = pci_cfg_addr;
|
||||
return true;
|
||||
|
||||
case PCI_DATA_REG:
|
||||
{
|
||||
unsigned off_bits = (port & 3) * 8;
|
||||
|
||||
if (!pci_cfg_addr_valid) {
|
||||
/*
|
||||
* XXX returning -1 here for "invalid PCI device" breaks Qemu's
|
||||
* Cirrus VGA BIOS.
|
||||
*/
|
||||
*val = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (pci_cfg_addr) {
|
||||
|
||||
case 0: /* vendor / device ID */
|
||||
raw_val = pci_card()->device().vendor_id() |
|
||||
(pci_card()->device().device_id() << 16);
|
||||
break;
|
||||
|
||||
case 4: /* status and command */
|
||||
case 8: /* class code / revision ID */
|
||||
raw_val = pci_card()->device().config_read(pci_cfg_addr,
|
||||
Pci::Device::ACCESS_32BIT);
|
||||
break;
|
||||
|
||||
case 0x10: /* base address register 0 */
|
||||
case 0x14: /* base address register 1 */
|
||||
case 0x18: /* base address register 2 */
|
||||
case 0x1c: /* base address register 3 */
|
||||
case 0x20: /* base address register 4 */
|
||||
case 0x24: /* base address register 5 */
|
||||
{
|
||||
unsigned bar = (pci_cfg_addr - 0x10) / 4;
|
||||
Pci::Device::Resource res = pci_card()->device().resource(bar);
|
||||
if (res.type() == Pci::Device::Resource::INVALID) {
|
||||
PWRN("requested PCI resource 0x%x invalid", bar);
|
||||
*val = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
raw_val = res.bar();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
PWRN("unexpected configuration address 0x%x", pci_cfg_addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
*val = raw_val >> off_bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
** PIT virtualization **
|
||||
************************/
|
||||
|
||||
/*
|
||||
* Some VESA BIOS implementations use the PIT as time source. However, usually
|
||||
* only the PIT counter is queried by first writing a latch command (0) to the
|
||||
* command register and subsequently reading the data port two times (low word
|
||||
* and high word). Returning non-zero bogus values seems to make (at least
|
||||
* some) VESA BIOS implementations happy.
|
||||
*/
|
||||
|
||||
enum {
|
||||
PIT_DATA_PORT_0 = 0x40,
|
||||
PIT_CMD_PORT = 0x43,
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle port-write access to the PIT
|
||||
*
|
||||
* \return true if the port access referred to the PIT
|
||||
*/
|
||||
template <typename T>
|
||||
static bool handle_pit_port_write(unsigned short port, T val)
|
||||
{
|
||||
if (port >= PIT_DATA_PORT_0 && port <= PIT_CMD_PORT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle port-read access from the PIT registers
|
||||
*
|
||||
* \return true if the port access referred to the PIT
|
||||
*/
|
||||
template <typename T>
|
||||
static bool handle_pit_port_read(unsigned short port, T *val)
|
||||
{
|
||||
if (port >= PIT_DATA_PORT_0 && port <= PIT_CMD_PORT) {
|
||||
*val = 0x15; /* bogus value */
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
** API implementation **
|
||||
************************/
|
||||
|
||||
/* instantiate externally used template funciton */
|
||||
template bool hw_emul_handle_port_read(unsigned short port, unsigned char *val);
|
||||
template bool hw_emul_handle_port_read(unsigned short port, unsigned short *val);
|
||||
template bool hw_emul_handle_port_read(unsigned short port, unsigned long *val);
|
||||
template bool hw_emul_handle_port_read(unsigned short port, unsigned int *val);
|
||||
template bool hw_emul_handle_port_write(unsigned short port, unsigned char val);
|
||||
template bool hw_emul_handle_port_write(unsigned short port, unsigned short val);
|
||||
template bool hw_emul_handle_port_write(unsigned short port, unsigned long val);
|
||||
template bool hw_emul_handle_port_write(unsigned short port, unsigned int val);
|
||||
|
||||
template <typename T>
|
||||
bool hw_emul_handle_port_read(unsigned short port, T *val)
|
||||
{
|
||||
T ret;
|
||||
|
||||
if (handle_pci_port_read(port, &ret)
|
||||
|| handle_pit_port_read(port, &ret)) {
|
||||
*val = ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool hw_emul_handle_port_write(unsigned short port, T val)
|
||||
{
|
||||
if (handle_pci_port_write(port, val)
|
||||
|| handle_pit_port_write(port, val))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
522
os/src/drivers/framebuffer/vesa/ifx86emu.cc
Normal file
522
os/src/drivers/framebuffer/vesa/ifx86emu.cc
Normal file
@ -0,0 +1,522 @@
|
||||
/*
|
||||
* \brief x86 emulation binding and support
|
||||
* \author Sebastian Sumpf
|
||||
* \author Christian Helmuth
|
||||
* \date 2007-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/printf.h>
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <util/avl_tree.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <os/attached_ram_dataspace.h>
|
||||
|
||||
#include <io_port_session/connection.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
|
||||
#include "ifx86emu.h"
|
||||
#include "framebuffer.h"
|
||||
#include "vesa.h"
|
||||
#include "hw_emul.h"
|
||||
|
||||
|
||||
namespace X86emu {
|
||||
#include"x86emu/x86emu.h"
|
||||
}
|
||||
|
||||
using namespace Vesa;
|
||||
using namespace Genode;
|
||||
using X86emu::x86_mem;
|
||||
using X86emu::PAGESIZE;
|
||||
using X86emu::CODESIZE;
|
||||
|
||||
struct X86emu::X86emu_mem X86emu::x86_mem;
|
||||
|
||||
static const bool verbose = false;
|
||||
static const bool verbose_mem = false;
|
||||
static const bool verbose_port = false;
|
||||
|
||||
|
||||
/***************
|
||||
** Utilities **
|
||||
***************/
|
||||
|
||||
class Region : public Avl_node<Region>
|
||||
{
|
||||
private:
|
||||
|
||||
addr_t _base;
|
||||
size_t _size;
|
||||
|
||||
public:
|
||||
|
||||
Region(addr_t base, size_t size) : _base(base), _size(size) { }
|
||||
|
||||
/************************
|
||||
** AVL node interface **
|
||||
************************/
|
||||
|
||||
bool higher(Region *r) { return r->_base >= _base; }
|
||||
|
||||
/**
|
||||
* Find region the given region fits into
|
||||
*/
|
||||
Region * match(addr_t base, size_t size)
|
||||
{
|
||||
Region *r = this;
|
||||
|
||||
do {
|
||||
if (base >= r->_base
|
||||
&& base + size <= r->_base + r->_size)
|
||||
break;
|
||||
|
||||
if (base < r->_base)
|
||||
r = r->child(LEFT);
|
||||
else
|
||||
r = r->child(RIGHT);
|
||||
} while (r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find region the given region meets
|
||||
*
|
||||
* \return Region overlapping or just meeting (can be merged into
|
||||
* super region)
|
||||
*/
|
||||
Region * meet(addr_t base, size_t size)
|
||||
{
|
||||
Region *r = this;
|
||||
|
||||
do {
|
||||
if ((r->_base <= base && r->_base + r->_size >= base)
|
||||
|| (base <= r->_base && base + size >= r->_base))
|
||||
break;
|
||||
|
||||
if (base < r->_base)
|
||||
r = r->child(LEFT);
|
||||
else
|
||||
r = r->child(RIGHT);
|
||||
} while (r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log region
|
||||
*/
|
||||
void print_regions()
|
||||
{
|
||||
if (child(LEFT))
|
||||
child(LEFT)->print_regions();
|
||||
|
||||
printf(" [%08lx,%08lx)\n", _base, _base + _size);
|
||||
|
||||
if (child(RIGHT))
|
||||
child(RIGHT)->print_regions();
|
||||
}
|
||||
|
||||
addr_t base() const { return _base; }
|
||||
size_t size() const { return _size; }
|
||||
};
|
||||
|
||||
|
||||
template <typename TYPE>
|
||||
class Region_database : public Avl_tree<Region>
|
||||
{
|
||||
public:
|
||||
|
||||
TYPE * match(addr_t base, size_t size)
|
||||
{
|
||||
if (!first()) return 0;
|
||||
|
||||
return static_cast<TYPE *>(first()->match(base, size));
|
||||
}
|
||||
|
||||
TYPE * meet(addr_t base, size_t size)
|
||||
{
|
||||
if (!first()) return 0;
|
||||
|
||||
return static_cast<TYPE *>(first()->meet(base, size));
|
||||
}
|
||||
|
||||
TYPE * get_region(addr_t base, size_t size)
|
||||
{
|
||||
TYPE *region;
|
||||
|
||||
/* look for match and return if found */
|
||||
if ((region = match(base, size)))
|
||||
return region;
|
||||
|
||||
/*
|
||||
* We try to create a new port region, but first we look if any overlapping
|
||||
* resp. meeting regions already exist. These are freed and merged into a
|
||||
* new super region including the new port region.
|
||||
*/
|
||||
|
||||
addr_t beg = base, end = base + size;
|
||||
|
||||
while ((region = meet(beg, end - beg))) {
|
||||
/* merge region into super region */
|
||||
beg = min(beg, static_cast<addr_t>(region->base()));
|
||||
end = max(end, static_cast<addr_t>(region->base() + region->size()));
|
||||
|
||||
/* destroy old region */
|
||||
remove(region);
|
||||
destroy(env()->heap(), region);
|
||||
}
|
||||
|
||||
try {
|
||||
region = new (env()->heap()) TYPE(beg, end - beg);
|
||||
insert(region);
|
||||
return region;
|
||||
} catch (...) {
|
||||
PERR("Access to I/O region [%08lx,%08lx) denied", beg, end - beg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void print_regions()
|
||||
{
|
||||
if (!first()) return;
|
||||
|
||||
first()->print_regions();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* I/O port region including corresponding IO_PORT connection
|
||||
*/
|
||||
class Port_region : public Region, public Io_port_connection
|
||||
{
|
||||
public:
|
||||
|
||||
Port_region(unsigned short port_base, size_t port_size)
|
||||
: Region(port_base, port_size), Io_port_connection(port_base, port_size)
|
||||
{
|
||||
if (verbose)
|
||||
PLOG("add port [%04lx,%04lx)", base(), base() + size());
|
||||
}
|
||||
|
||||
~Port_region()
|
||||
{
|
||||
if (verbose)
|
||||
PLOG("del port [%04lx,%04lx)", base(), base() + size());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* I/O memory region including corresponding IO_MEM connection
|
||||
*/
|
||||
class Mem_region : public Region
|
||||
{
|
||||
private:
|
||||
|
||||
class Io_mem_dataspace : public Io_mem_connection
|
||||
{
|
||||
private:
|
||||
|
||||
void *_local_addr;
|
||||
|
||||
public:
|
||||
|
||||
Io_mem_dataspace(addr_t base, size_t size)
|
||||
: Io_mem_connection(base, size)
|
||||
{
|
||||
_local_addr = env()->rm_session()->attach(dataspace());
|
||||
}
|
||||
|
||||
~Io_mem_dataspace()
|
||||
{
|
||||
env()->rm_session()->detach(_local_addr);
|
||||
}
|
||||
|
||||
Io_mem_dataspace_capability cap() { return dataspace(); }
|
||||
|
||||
template <typename T>
|
||||
T * local_addr() { return static_cast<T *>(_local_addr); }
|
||||
};
|
||||
|
||||
Io_mem_dataspace _ds;
|
||||
|
||||
public:
|
||||
|
||||
Mem_region(addr_t mem_base, size_t mem_size)
|
||||
: Region(mem_base, mem_size), _ds(mem_base, mem_size)
|
||||
{
|
||||
if (verbose)
|
||||
PLOG("add mem [%08lx,%08lx) @ %p", base(), base() + size(), _ds.local_addr<void>());
|
||||
}
|
||||
|
||||
~Mem_region()
|
||||
{
|
||||
if (verbose)
|
||||
PLOG("del mem [%08lx,%08lx)", base(), base() + size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T * virt_addr(addr_t addr)
|
||||
{
|
||||
return reinterpret_cast<T *>(_ds.local_addr<char>() + (addr - base()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Region_database<Port_region> port_region_db;
|
||||
static Region_database<Mem_region> mem_region_db;
|
||||
|
||||
|
||||
/**
|
||||
* Setup static memory for x86emu
|
||||
*/
|
||||
static int map_code_area(void)
|
||||
{
|
||||
int err;
|
||||
Ram_dataspace_capability ds_cap;
|
||||
void *dummy;
|
||||
|
||||
/* map page0 */
|
||||
if ((err = Framebuffer_drv::map_io_mem(0x0, PAGESIZE, false, &dummy))) {
|
||||
PERR("Could not map page zero");
|
||||
return err;
|
||||
}
|
||||
x86_mem.bios_addr(dummy);
|
||||
|
||||
/* alloc code pages in RAM */
|
||||
try {
|
||||
static Attached_ram_dataspace ram_ds(env()->ram_session(), CODESIZE);
|
||||
dummy = ram_ds.local_addr<void>();
|
||||
x86_mem.data_addr(dummy);
|
||||
} catch (...) {
|
||||
PERR("Could not allocate dataspace for code");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* build opcode command */
|
||||
uint32_t code = 0;
|
||||
code = 0xcd; /* int opcode */
|
||||
code |= 0x10 << 8; /* 10h */
|
||||
code |= 0xf4 << 16; /* ret opcode */
|
||||
memcpy(dummy, &code, sizeof(code));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
** x86emu memory-access support **
|
||||
**********************************/
|
||||
|
||||
template <typename T>
|
||||
static T X86API read(X86emu::u32 addr)
|
||||
{
|
||||
T ret = *X86emu::virt_addr<T>(addr);
|
||||
|
||||
if (verbose_mem) {
|
||||
unsigned v = ret;
|
||||
PLOG(" io_mem: read [%p,%p) val 0x%ux",
|
||||
reinterpret_cast<void*>(addr),
|
||||
reinterpret_cast<void*>(addr + sizeof(T)), v);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static void X86API write(X86emu::u32 addr, T val)
|
||||
{
|
||||
*X86emu::virt_addr<T>(addr) = val;
|
||||
|
||||
if (verbose_mem) {
|
||||
unsigned v = val;
|
||||
PLOG(" io_mem: write [%p,%p) val 0x%ux",
|
||||
reinterpret_cast<void*>(addr),
|
||||
reinterpret_cast<void*>(addr + sizeof(T)), v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
X86emu::X86EMU_memFuncs mem_funcs = {
|
||||
&read, &read, &read,
|
||||
&write, &write, &write
|
||||
};
|
||||
|
||||
|
||||
/********************************
|
||||
** x86emu port-access support **
|
||||
********************************/
|
||||
|
||||
template <typename T>
|
||||
static T X86API inx(X86emu::X86EMU_pioAddr addr)
|
||||
{
|
||||
T ret;
|
||||
unsigned short port = static_cast<unsigned short>(addr);
|
||||
|
||||
if (hw_emul_handle_port_read(port, &ret))
|
||||
return ret;
|
||||
|
||||
Port_region *region = port_region_db.get_region(port, sizeof(T));
|
||||
|
||||
if (!region) return 0;
|
||||
|
||||
switch (sizeof(T)) {
|
||||
case 1:
|
||||
ret = (T)region->inb(port);
|
||||
break;
|
||||
case 2:
|
||||
ret = (T)region->inw(port);
|
||||
break;
|
||||
default:
|
||||
ret = (T)region->inl(port);
|
||||
}
|
||||
|
||||
if (verbose_port) {
|
||||
unsigned v = ret;
|
||||
PLOG("io_port: read [%04ux,%04zx) val 0x%ux", (unsigned short)addr,
|
||||
addr + sizeof(T), v);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static void X86API outx(X86emu::X86EMU_pioAddr addr, T val)
|
||||
{
|
||||
unsigned short port = static_cast<unsigned short>(addr);
|
||||
|
||||
if (hw_emul_handle_port_write(port, val))
|
||||
return;
|
||||
|
||||
Port_region *region = port_region_db.get_region(port, sizeof(T));
|
||||
|
||||
if (!region) return;
|
||||
|
||||
if (verbose_port) {
|
||||
unsigned v = val;
|
||||
PLOG("io_port: write [%04ux,%04zx) val 0x%ux", (unsigned short)addr,
|
||||
addr + sizeof(T), v);
|
||||
}
|
||||
|
||||
switch (sizeof(T)) {
|
||||
case 1:
|
||||
region->outb(port, val);
|
||||
break;
|
||||
case 2:
|
||||
region->outw(port, val);
|
||||
break;
|
||||
default:
|
||||
region->outl(port, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Port access hooks
|
||||
*/
|
||||
X86emu::X86EMU_pioFuncs port_funcs = {
|
||||
&inx, &inx, &inx,
|
||||
&outx, &outx, &outx
|
||||
};
|
||||
|
||||
|
||||
/************************
|
||||
** API implementation **
|
||||
************************/
|
||||
|
||||
/* instantiate externally used template funciton */
|
||||
template char* X86emu::virt_addr<char, uint32_t>(uint32_t addr);
|
||||
template uint16_t* X86emu::virt_addr<uint16_t, uint32_t>(uint32_t addr);
|
||||
|
||||
template <typename TYPE, typename ADDR_TYPE>
|
||||
TYPE * X86emu::virt_addr(ADDR_TYPE addr)
|
||||
{
|
||||
addr_t local_addr = static_cast<addr_t>(addr);
|
||||
Mem_region *region;
|
||||
|
||||
/* retrieve local mapping for given address */
|
||||
|
||||
/* page 0 */
|
||||
if (local_addr >= 0 && local_addr < PAGESIZE)
|
||||
local_addr += x86_mem.bios_addr();
|
||||
|
||||
/* fake code segment */
|
||||
else if (local_addr >= PAGESIZE && local_addr < (PAGESIZE + CODESIZE))
|
||||
local_addr += (x86_mem.data_addr() - PAGESIZE);
|
||||
|
||||
/* any other I/O memory allocated on demand */
|
||||
else if ((region = mem_region_db.get_region(addr & ~(PAGESIZE-1), PAGESIZE)))
|
||||
return region->virt_addr<TYPE>(local_addr);
|
||||
|
||||
else {
|
||||
PWRN("Invalid address 0x%08lx", local_addr);
|
||||
local_addr = 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<TYPE *>(local_addr);
|
||||
}
|
||||
|
||||
|
||||
uint16_t X86emu::x86emu_cmd(uint16_t eax, uint16_t ebx, uint16_t ecx,
|
||||
uint16_t edi, uint16_t *out_ebx)
|
||||
{
|
||||
using namespace X86emu;
|
||||
M.x86.R_EAX = eax; /* int10 function number */
|
||||
M.x86.R_EBX = ebx;
|
||||
M.x86.R_ECX = ecx;
|
||||
M.x86.R_EDI = edi;
|
||||
M.x86.R_IP = 0; /* address of "int10; ret" */
|
||||
M.x86.R_SP = PAGESIZE; /* SS:SP pointer to stack */
|
||||
M.x86.R_CS =
|
||||
M.x86.R_DS =
|
||||
M.x86.R_ES =
|
||||
M.x86.R_SS = PAGESIZE >> 4;
|
||||
|
||||
X86EMU_exec();
|
||||
|
||||
if (out_ebx)
|
||||
*out_ebx = M.x86.R_EBX;
|
||||
|
||||
return M.x86.R_AX;
|
||||
}
|
||||
|
||||
|
||||
int X86emu::init(void)
|
||||
{
|
||||
if (map_code_area())
|
||||
return -1;
|
||||
|
||||
if (verbose) {
|
||||
PDBG("--- x86 bios area is [0x%lx - 0x%lx) ---",
|
||||
x86_mem.bios_addr(), x86_mem.bios_addr() + PAGESIZE);
|
||||
PDBG("--- x86 data area is [0x%lx - 0x%lx) ---",
|
||||
x86_mem.data_addr(), x86_mem.data_addr() + CODESIZE);
|
||||
}
|
||||
|
||||
X86emu::M.x86.debug = 0;
|
||||
X86emu::X86EMU_setupPioFuncs(&port_funcs);
|
||||
X86emu::X86EMU_setupMemFuncs(&mem_funcs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void X86emu::print_regions()
|
||||
{
|
||||
printf("I/O port regions:\n");
|
||||
port_region_db.print_regions();
|
||||
|
||||
printf("I/O memory regions:\n");
|
||||
mem_region_db.print_regions();
|
||||
}
|
53
os/src/drivers/framebuffer/vesa/include/framebuffer.h
Normal file
53
os/src/drivers/framebuffer/vesa/include/framebuffer.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* \brief Framebuffer driver interface, X86emu interface
|
||||
* \author Christian Helmuth
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2006-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _FRAMEBUFFER_H_
|
||||
#define _FRAMEBUFFER_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
#include "vbe.h"
|
||||
|
||||
namespace Framebuffer_drv {
|
||||
|
||||
/**
|
||||
* Return capability for h/w framebuffer dataspace
|
||||
*/
|
||||
Genode::Dataspace_capability hw_framebuffer();
|
||||
|
||||
/**
|
||||
* Initialize driver, x86emu lib, set up memory
|
||||
*/
|
||||
int init();
|
||||
|
||||
/**
|
||||
* Set video, initialize framebuffer dataspace
|
||||
*
|
||||
* \return 0 on success,
|
||||
* non-zero otherwise
|
||||
*/
|
||||
int set_mode(unsigned long width, unsigned long height, unsigned long mode);
|
||||
|
||||
int use_current_mode();
|
||||
|
||||
/**
|
||||
* Map given device memory, return out_addr (map address)
|
||||
*/
|
||||
int map_io_mem(Genode::addr_t base, Genode::size_t size, bool write_combined,
|
||||
void **out_addr, Genode::addr_t addr = 0,
|
||||
Genode::Dataspace_capability *out_io = 0);
|
||||
}
|
||||
|
||||
#endif /* _FRAMEBUFFER_H_ */
|
34
os/src/drivers/framebuffer/vesa/include/hw_emul.h
Normal file
34
os/src/drivers/framebuffer/vesa/include/hw_emul.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* \brief Hardware emulation interface
|
||||
* \author Christian Helmuth
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-06-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _HW_EMUL_H_
|
||||
#define _HW_EMUL_H_
|
||||
|
||||
/**
|
||||
* Handle port-read access
|
||||
*
|
||||
* \return true if the port access referred to emulated hardware
|
||||
*/
|
||||
template <typename T>
|
||||
bool hw_emul_handle_port_read(unsigned short port, T *val);
|
||||
|
||||
/**
|
||||
* Handle port-write access
|
||||
*
|
||||
* \return true if the port access referred to emulated hardware
|
||||
*/
|
||||
template <typename T>
|
||||
bool hw_emul_handle_port_write(unsigned short port, T val);
|
||||
|
||||
#endif /* _HW_EMUL_H_ */
|
90
os/src/drivers/framebuffer/vesa/include/ifx86emu.h
Normal file
90
os/src/drivers/framebuffer/vesa/include/ifx86emu.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* \brief x86 emulation binding and support
|
||||
* \author Sebastian Sumpf
|
||||
* \author Christian Helmuth
|
||||
* \date 2007-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _IFX86EMU_H_
|
||||
#define _IFX86EMU_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace X86emu {
|
||||
|
||||
using Genode::addr_t;
|
||||
using Genode::uint16_t;
|
||||
|
||||
enum {
|
||||
PAGESIZE = 0x01000, /* x86 page size */
|
||||
CODESIZE = 2 * PAGESIZE, /* size of fake code segment */
|
||||
};
|
||||
|
||||
/**
|
||||
* Emulation memory/code area structure
|
||||
*/
|
||||
struct X86emu_mem
|
||||
{
|
||||
addr_t _bios_addr;
|
||||
addr_t _data_addr;
|
||||
|
||||
/**
|
||||
* Constructur
|
||||
*/
|
||||
X86emu_mem() : _bios_addr(0), _data_addr(0) { }
|
||||
|
||||
inline addr_t _addr(addr_t* obj_addr, void* addr = 0)
|
||||
{
|
||||
if (addr != 0)
|
||||
*obj_addr = reinterpret_cast<addr_t>(addr);
|
||||
return *obj_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* set/get functions
|
||||
*/
|
||||
inline addr_t bios_addr(void *addr = 0) {
|
||||
return _addr(&_bios_addr, addr); }
|
||||
inline addr_t data_addr(void *addr = 0) {
|
||||
return _addr(&_data_addr, addr); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory/code area instance
|
||||
*/
|
||||
extern struct X86emu_mem x86_mem;
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
*/
|
||||
int init(void);
|
||||
|
||||
/**
|
||||
* Execute real mode command
|
||||
*/
|
||||
uint16_t x86emu_cmd(uint16_t eax, uint16_t ebx = 0, uint16_t ecx = 0,
|
||||
uint16_t edi = 0, uint16_t *out_ebx = 0);
|
||||
|
||||
/**
|
||||
* Map requested address to local virtual address
|
||||
*
|
||||
* Note, virtual addresses cannot be cached as mappings may change on
|
||||
* 'x86emu_cmd' and subsequent invocations of this function.
|
||||
*/
|
||||
template <typename TYPE, typename ADDR_TYPE>
|
||||
TYPE * virt_addr(ADDR_TYPE addr);
|
||||
|
||||
/**
|
||||
* Log I/O resources for debugging
|
||||
*/
|
||||
void print_regions();
|
||||
}
|
||||
|
||||
#endif /* _IFX86EMU_H_ */
|
103
os/src/drivers/framebuffer/vesa/include/vbe.h
Normal file
103
os/src/drivers/framebuffer/vesa/include/vbe.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* \brief VBE constants and definitions
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2007-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _VBE_H_
|
||||
#define _VBE_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Vesa {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/* VBE controller information */
|
||||
struct mb_vbe_ctrl_t
|
||||
{
|
||||
uint8_t signature[4];
|
||||
uint16_t version;
|
||||
uint32_t oem_string;
|
||||
uint32_t capabilities;
|
||||
uint32_t video_mode;
|
||||
uint16_t total_memory;
|
||||
uint16_t oem_software_rev;
|
||||
uint32_t oem_vendor_name;
|
||||
uint32_t oem_product_name;
|
||||
uint32_t oem_product_rev;
|
||||
uint8_t reserved[222];
|
||||
uint8_t oem_data[256];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/* VBE mode information */
|
||||
struct mb_vbe_mode_t
|
||||
{
|
||||
/* all VESA versions */
|
||||
uint16_t mode_attributes;
|
||||
uint8_t win_a_attributes;
|
||||
uint8_t win_b_attributes;
|
||||
uint16_t win_granularity;
|
||||
uint16_t win_size;
|
||||
uint16_t win_a_segment;
|
||||
uint16_t win_b_segment;
|
||||
uint32_t win_func;
|
||||
uint16_t bytes_per_scanline;
|
||||
|
||||
/* >= VESA version 1.2 */
|
||||
uint16_t x_resolution;
|
||||
uint16_t y_resolution;
|
||||
uint8_t x_char_size;
|
||||
uint8_t y_char_size;
|
||||
uint8_t number_of_planes;
|
||||
uint8_t bits_per_pixel;
|
||||
uint8_t number_of_banks;
|
||||
uint8_t memory_model;
|
||||
uint8_t bank_size;
|
||||
uint8_t number_of_image_pages;
|
||||
uint8_t reserved0;
|
||||
|
||||
/* direct color */
|
||||
uint8_t red_mask_size;
|
||||
uint8_t red_field_position;
|
||||
uint8_t green_mask_size;
|
||||
uint8_t green_field_position;
|
||||
uint8_t blue_mask_size;
|
||||
uint8_t blue_field_position;
|
||||
uint8_t reserved_mask_size;
|
||||
uint8_t reserved_field_position;
|
||||
uint8_t direct_color_mode_info;
|
||||
|
||||
/* >= VESA version 2.0 */
|
||||
uint32_t phys_base;
|
||||
uint32_t reserved1;
|
||||
uint16_t reversed2;
|
||||
|
||||
/* >= VESA version 3.0 */
|
||||
uint16_t linear_bytes_per_scanline;
|
||||
uint8_t banked_number_of_image_pages;
|
||||
uint8_t linear_number_of_image_pages;
|
||||
uint8_t linear_red_mask_size;
|
||||
uint8_t linear_red_field_position;
|
||||
uint8_t linear_green_mask_size;
|
||||
uint8_t linear_green_field_position;
|
||||
uint8_t linear_blue_mask_size;
|
||||
uint8_t linear_blue_field_position;
|
||||
uint8_t linear_reserved_mask_size;
|
||||
uint8_t linear_reserved_field_position;
|
||||
uint32_t max_pixel_clock;
|
||||
|
||||
uint8_t reserved3[190];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
}
|
||||
|
||||
#endif /* _VBE_H_ */
|
105
os/src/drivers/framebuffer/vesa/include/vesa.h
Normal file
105
os/src/drivers/framebuffer/vesa/include/vesa.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* \brief VESA constants and definitions
|
||||
* \author Sebastian Sumpf
|
||||
* \author Christian Helmuth
|
||||
* \date 2007-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _VESA_H_
|
||||
#define _VESA_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Vesa {
|
||||
|
||||
/**
|
||||
* VESA mode definitions
|
||||
*/
|
||||
struct vesa_depth
|
||||
{
|
||||
unsigned long depth; /* in bit */
|
||||
Genode::uint16_t mode; /* 16 bit hex value */
|
||||
};
|
||||
|
||||
struct vesa_modes
|
||||
{
|
||||
unsigned long width; /* screen width in pixel */
|
||||
unsigned long height;
|
||||
int num_depth; /* number of struct vesa_depth entries */
|
||||
struct vesa_depth depth[4];
|
||||
};
|
||||
|
||||
/**
|
||||
* VESA constants
|
||||
*/
|
||||
enum {
|
||||
/* VESA functions */
|
||||
VBE_CONTROL_FUNC = 0x4F00,
|
||||
VBE_INFO_FUNC = 0x4F01,
|
||||
VBE_MODE_FUNC = 0x4F02,
|
||||
VBE_GMODE_FUNC = 0x4F03,
|
||||
|
||||
/* VESA return codes */
|
||||
VBE_SUPPORTED = 0x4F,
|
||||
VBE_SUCCESS = 0x00,
|
||||
|
||||
/* VESA MASKS/FLAGS */
|
||||
VBE_CUR_REFRESH_MASK = 0xF7FF, /* use current refresh rate */
|
||||
VBE_SET_FLAT_FB = 1 << 14, /* flat frame buffer flag */
|
||||
};
|
||||
|
||||
|
||||
/****************
|
||||
** VESA modes **
|
||||
****************/
|
||||
|
||||
static struct vesa_modes mode_table[] = {
|
||||
{640 , 480 , 3, {{15, 0x110}, {16, 0x111}, {24, 0x112}}},
|
||||
{800 , 600 , 3, {{15, 0x113}, {16, 0x114}, {24, 0x115}}},
|
||||
{1024, 768 , 3, {{15, 0x116}, {16, 0x117}, {24, 0x118}}},
|
||||
{1280, 1024, 3, {{15, 0x119}, {16, 0x11A}, {24, 0x11B}}},
|
||||
{1600, 1200, 3, {{15, 0x11d}, {16, 0x11e}, {24, 0x11f}}},
|
||||
};
|
||||
|
||||
enum {
|
||||
MODE_COUNT = sizeof(mode_table),
|
||||
VESA_CTRL_OFFS = 0x100,
|
||||
VESA_MODE_OFFS = 0x800,
|
||||
};
|
||||
|
||||
/**
|
||||
* Find vesa mode, return mode number or 0
|
||||
*/
|
||||
static inline Genode::uint16_t get_default_vesa_mode(unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long depth)
|
||||
{
|
||||
Genode::uint16_t mode = 0;
|
||||
|
||||
for (int i = 0; i < MODE_COUNT; i++) {
|
||||
|
||||
if (mode_table[i].width != width || mode_table[i].height != height)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < mode_table[i].num_depth; j++) {
|
||||
|
||||
if (mode_table[i].depth[j].depth != depth)
|
||||
continue;
|
||||
mode = mode_table[i].depth[j].mode;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode) break;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _VESA_H */
|
339
os/src/drivers/framebuffer/vesa/include/x86emu/regs.h
Normal file
339
os/src/drivers/framebuffer/vesa/include/x86emu/regs.h
Normal file
@ -0,0 +1,339 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for x86 register definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_REGS_H
|
||||
#define __X86EMU_REGS_H
|
||||
|
||||
/*---------------------- Macros and type definitions ----------------------*/
|
||||
|
||||
#ifdef PACK
|
||||
# pragma PACK
|
||||
#endif
|
||||
|
||||
/*
|
||||
* General EAX, EBX, ECX, EDX type registers. Note that for
|
||||
* portability, and speed, the issue of byte swapping is not addressed
|
||||
* in the registers. All registers are stored in the default format
|
||||
* available on the host machine. The only critical issue is that the
|
||||
* registers should line up EXACTLY in the same manner as they do in
|
||||
* the 386. That is:
|
||||
*
|
||||
* EAX & 0xff === AL
|
||||
* EAX & 0xffff == AX
|
||||
*
|
||||
* etc. The result is that alot of the calculations can then be
|
||||
* done using the native instruction set fully.
|
||||
*/
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
typedef struct {
|
||||
u32 e_reg;
|
||||
} I32_reg_t;
|
||||
|
||||
typedef struct {
|
||||
u16 filler0, x_reg;
|
||||
} I16_reg_t;
|
||||
|
||||
typedef struct {
|
||||
u8 filler0, filler1, h_reg, l_reg;
|
||||
} I8_reg_t;
|
||||
|
||||
#else /* !__BIG_ENDIAN__ */
|
||||
|
||||
typedef struct {
|
||||
u32 e_reg;
|
||||
} I32_reg_t;
|
||||
|
||||
typedef struct {
|
||||
u16 x_reg;
|
||||
} I16_reg_t;
|
||||
|
||||
typedef struct {
|
||||
u8 l_reg, h_reg;
|
||||
} I8_reg_t;
|
||||
|
||||
#endif /* BIG_ENDIAN */
|
||||
|
||||
typedef union {
|
||||
I32_reg_t I32_reg;
|
||||
I16_reg_t I16_reg;
|
||||
I8_reg_t I8_reg;
|
||||
} i386_general_register;
|
||||
|
||||
struct i386_general_regs {
|
||||
i386_general_register A, B, C, D;
|
||||
};
|
||||
|
||||
typedef struct i386_general_regs Gen_reg_t;
|
||||
|
||||
struct i386_special_regs {
|
||||
i386_general_register SP, BP, SI, DI, IP;
|
||||
u32 FLAGS;
|
||||
};
|
||||
|
||||
/*
|
||||
* Segment registers here represent the 16 bit quantities
|
||||
* CS, DS, ES, SS.
|
||||
*/
|
||||
|
||||
struct i386_segment_regs {
|
||||
u16 _CS, DS, SS, ES, FS, GS;
|
||||
};
|
||||
|
||||
/* 8 bit registers */
|
||||
#define R_AH gen.A.I8_reg.h_reg
|
||||
#define R_AL gen.A.I8_reg.l_reg
|
||||
#define R_BH gen.B.I8_reg.h_reg
|
||||
#define R_BL gen.B.I8_reg.l_reg
|
||||
#define R_CH gen.C.I8_reg.h_reg
|
||||
#define R_CL gen.C.I8_reg.l_reg
|
||||
#define R_DH gen.D.I8_reg.h_reg
|
||||
#define R_DL gen.D.I8_reg.l_reg
|
||||
|
||||
/* 16 bit registers */
|
||||
#define R_AX gen.A.I16_reg.x_reg
|
||||
#define R_BX gen.B.I16_reg.x_reg
|
||||
#define R_CX gen.C.I16_reg.x_reg
|
||||
#define R_DX gen.D.I16_reg.x_reg
|
||||
|
||||
/* 32 bit extended registers */
|
||||
#define R_EAX gen.A.I32_reg.e_reg
|
||||
#define R_EBX gen.B.I32_reg.e_reg
|
||||
#define R_ECX gen.C.I32_reg.e_reg
|
||||
#define R_EDX gen.D.I32_reg.e_reg
|
||||
|
||||
/* special registers */
|
||||
#define R_SP spc.SP.I16_reg.x_reg
|
||||
#define R_BP spc.BP.I16_reg.x_reg
|
||||
#define R_SI spc.SI.I16_reg.x_reg
|
||||
#define R_DI spc.DI.I16_reg.x_reg
|
||||
#define R_IP spc.IP.I16_reg.x_reg
|
||||
#define R_FLG spc.FLAGS
|
||||
|
||||
/* special registers */
|
||||
#define R_SP spc.SP.I16_reg.x_reg
|
||||
#define R_BP spc.BP.I16_reg.x_reg
|
||||
#define R_SI spc.SI.I16_reg.x_reg
|
||||
#define R_DI spc.DI.I16_reg.x_reg
|
||||
#define R_IP spc.IP.I16_reg.x_reg
|
||||
#define R_FLG spc.FLAGS
|
||||
|
||||
/* special registers */
|
||||
#define R_ESP spc.SP.I32_reg.e_reg
|
||||
#define R_EBP spc.BP.I32_reg.e_reg
|
||||
#define R_ESI spc.SI.I32_reg.e_reg
|
||||
#define R_EDI spc.DI.I32_reg.e_reg
|
||||
#define R_EIP spc.IP.I32_reg.e_reg
|
||||
#define R_EFLG spc.FLAGS
|
||||
|
||||
/* segment registers */
|
||||
#define R_CS seg._CS
|
||||
#define R_DS seg.DS
|
||||
#define R_SS seg.SS
|
||||
#define R_ES seg.ES
|
||||
#define R_FS seg.FS
|
||||
#define R_GS seg.GS
|
||||
|
||||
/* flag conditions */
|
||||
#define FB_CF 0x0001 /* CARRY flag */
|
||||
#define FB_PF 0x0004 /* PARITY flag */
|
||||
#define FB_AF 0x0010 /* AUX flag */
|
||||
#define FB_ZF 0x0040 /* ZERO flag */
|
||||
#define FB_SF 0x0080 /* SIGN flag */
|
||||
#define FB_TF 0x0100 /* TRAP flag */
|
||||
#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */
|
||||
#define FB_DF 0x0400 /* DIR flag */
|
||||
#define FB_OF 0x0800 /* OVERFLOW flag */
|
||||
|
||||
/* 80286 and above always have bit#1 set */
|
||||
#define F_ALWAYS_ON (0x0002) /* flag bits always on */
|
||||
|
||||
/*
|
||||
* Define a mask for only those flag bits we will ever pass back
|
||||
* (via PUSHF)
|
||||
*/
|
||||
#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF)
|
||||
|
||||
/* following bits masked in to a 16bit quantity */
|
||||
|
||||
#define F_CF 0x0001 /* CARRY flag */
|
||||
#define F_PF 0x0004 /* PARITY flag */
|
||||
#define F_AF 0x0010 /* AUX flag */
|
||||
#define F_ZF 0x0040 /* ZERO flag */
|
||||
#define F_SF 0x0080 /* SIGN flag */
|
||||
#define F_TF 0x0100 /* TRAP flag */
|
||||
#define F_IF 0x0200 /* INTERRUPT ENABLE flag */
|
||||
#define F_DF 0x0400 /* DIR flag */
|
||||
#define F_OF 0x0800 /* OVERFLOW flag */
|
||||
|
||||
#define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag))
|
||||
#define SET_FLAG(flag) (M.x86.R_FLG |= (flag))
|
||||
#define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag))
|
||||
#define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag))
|
||||
#define CLEARALL_FLAG(m) (M.x86.R_FLG = 0)
|
||||
|
||||
#define CONDITIONAL_SET_FLAG(COND,FLAG) \
|
||||
if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG)
|
||||
|
||||
#define F_PF_CALC 0x010000 /* PARITY flag has been calced */
|
||||
#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */
|
||||
#define F_SF_CALC 0x040000 /* SIGN flag has been calced */
|
||||
|
||||
#define F_ALL_CALC 0xff0000 /* All have been calced */
|
||||
|
||||
/*
|
||||
* Emulator machine state.
|
||||
* Segment usage control.
|
||||
*/
|
||||
#define SYSMODE_SEG_DS_SS 0x00000001
|
||||
#define SYSMODE_SEGOVR_CS 0x00000002
|
||||
#define SYSMODE_SEGOVR_DS 0x00000004
|
||||
#define SYSMODE_SEGOVR_ES 0x00000008
|
||||
#define SYSMODE_SEGOVR_FS 0x00000010
|
||||
#define SYSMODE_SEGOVR_GS 0x00000020
|
||||
#define SYSMODE_SEGOVR_SS 0x00000040
|
||||
#define SYSMODE_PREFIX_REPE 0x00000080
|
||||
#define SYSMODE_PREFIX_REPNE 0x00000100
|
||||
#define SYSMODE_PREFIX_DATA 0x00000200
|
||||
#define SYSMODE_PREFIX_ADDR 0x00000400
|
||||
#define SYSMODE_INTR_PENDING 0x10000000
|
||||
#define SYSMODE_EXTRN_INTR 0x20000000
|
||||
#define SYSMODE_HALTED 0x40000000
|
||||
|
||||
#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \
|
||||
SYSMODE_SEGOVR_CS | \
|
||||
SYSMODE_SEGOVR_DS | \
|
||||
SYSMODE_SEGOVR_ES | \
|
||||
SYSMODE_SEGOVR_FS | \
|
||||
SYSMODE_SEGOVR_GS | \
|
||||
SYSMODE_SEGOVR_SS)
|
||||
#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \
|
||||
SYSMODE_SEGOVR_CS | \
|
||||
SYSMODE_SEGOVR_DS | \
|
||||
SYSMODE_SEGOVR_ES | \
|
||||
SYSMODE_SEGOVR_FS | \
|
||||
SYSMODE_SEGOVR_GS | \
|
||||
SYSMODE_SEGOVR_SS | \
|
||||
SYSMODE_PREFIX_DATA | \
|
||||
SYSMODE_PREFIX_ADDR)
|
||||
|
||||
#define INTR_SYNCH 0x1
|
||||
#define INTR_ASYNCH 0x2
|
||||
#define INTR_HALTED 0x4
|
||||
|
||||
typedef struct {
|
||||
struct i386_general_regs gen;
|
||||
struct i386_special_regs spc;
|
||||
struct i386_segment_regs seg;
|
||||
/*
|
||||
* MODE contains information on:
|
||||
* REPE prefix 2 bits repe,repne
|
||||
* SEGMENT overrides 5 bits normal,DS,SS,CS,ES
|
||||
* Delayed flag set 3 bits (zero, signed, parity)
|
||||
* reserved 6 bits
|
||||
* interrupt # 8 bits instruction raised interrupt
|
||||
* BIOS video segregs 4 bits
|
||||
* Interrupt Pending 1 bits
|
||||
* Extern interrupt 1 bits
|
||||
* Halted 1 bits
|
||||
*/
|
||||
u32 mode;
|
||||
volatile int intr; /* mask of pending interrupts */
|
||||
int debug;
|
||||
#ifdef DEBUG
|
||||
int check;
|
||||
u16 saved_ip;
|
||||
u16 saved_cs;
|
||||
int enc_pos;
|
||||
int enc_str_pos;
|
||||
char decode_buf[32]; /* encoded byte stream */
|
||||
char decoded_buf[256]; /* disassembled strings */
|
||||
#endif
|
||||
u8 intno;
|
||||
u8 __pad[3];
|
||||
} X86EMU_regs;
|
||||
|
||||
/****************************************************************************
|
||||
REMARKS:
|
||||
Structure maintaining the emulator machine state.
|
||||
|
||||
MEMBERS:
|
||||
mem_base - Base real mode memory for the emulator
|
||||
mem_size - Size of the real mode memory block for the emulator
|
||||
private - private data pointer
|
||||
x86 - X86 registers
|
||||
****************************************************************************/
|
||||
typedef struct {
|
||||
unsigned long mem_base;
|
||||
unsigned long mem_size;
|
||||
void* private_ptr;
|
||||
X86EMU_regs x86;
|
||||
} X86EMU_sysEnv;
|
||||
|
||||
#ifdef END_PACK
|
||||
# pragma END_PACK
|
||||
#endif
|
||||
|
||||
/*----------------------------- Global Variables --------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
/* Global emulator machine state.
|
||||
*
|
||||
* We keep it global to avoid pointer dereferences in the code for speed.
|
||||
*/
|
||||
|
||||
extern X86EMU_sysEnv _X86EMU_env;
|
||||
#define M _X86EMU_env
|
||||
|
||||
/*-------------------------- Function Prototypes --------------------------*/
|
||||
|
||||
/* Function to log information at runtime */
|
||||
|
||||
#ifndef __KERNEL__
|
||||
void printk(const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_REGS_H */
|
108
os/src/drivers/framebuffer/vesa/include/x86emu/types.h
Normal file
108
os/src/drivers/framebuffer/vesa/include/x86emu/types.h
Normal file
@ -0,0 +1,108 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for x86 emulator type definitions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __X86EMU_TYPES_H
|
||||
#define __X86EMU_TYPES_H
|
||||
|
||||
#ifndef NO_SYS_HEADERS
|
||||
//#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following kludge is an attempt to work around typedef conflicts with
|
||||
* <sys/types.h>.
|
||||
*/
|
||||
|
||||
#define u8 x86emuu8
|
||||
#define u16 x86emuu16
|
||||
#define u32 x86emuu32
|
||||
#define u64 x86emuu64
|
||||
#define s8 x86emus8
|
||||
#define s16 x86emus16
|
||||
#define s32 x86emus32
|
||||
#define s64 x86emus64
|
||||
#define uint x86emuuint
|
||||
#define sint x86emusint
|
||||
|
||||
|
||||
/*---------------------- Macros and type definitions ----------------------*/
|
||||
|
||||
/* Currently only for Linux/32bit */
|
||||
#undef __HAS_LONG_LONG__
|
||||
#if defined(__GNUC__) && !defined(NO_LONG_LONG)
|
||||
#define __HAS_LONG_LONG__
|
||||
#endif
|
||||
|
||||
/* Taken from Xmd.h */
|
||||
#undef NUM32
|
||||
#if defined (_LP64) || \
|
||||
defined(__alpha) || defined(__alpha__) || \
|
||||
defined(__ia64__) || defined(ia64) || \
|
||||
defined(__sparc64__) || \
|
||||
defined(__s390x__) || \
|
||||
(defined(__hppa__) && defined(__LP64)) || \
|
||||
defined(__amd64__) || defined(amd64) || \
|
||||
(defined(__sgi) && (_MIPS_SZLONG == 64))
|
||||
#define NUM32 int
|
||||
#else
|
||||
#define NUM32 long
|
||||
#endif
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned NUM32 u32;
|
||||
#ifdef __HAS_LONG_LONG__
|
||||
typedef unsigned long long u64;
|
||||
#endif
|
||||
|
||||
typedef char s8;
|
||||
typedef short s16;
|
||||
typedef NUM32 s32;
|
||||
#ifdef __HAS_LONG_LONG__
|
||||
typedef long long s64;
|
||||
#endif
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef int sint;
|
||||
|
||||
typedef u16 X86EMU_pioAddr;
|
||||
|
||||
#undef NUM32
|
||||
|
||||
#endif /* __X86EMU_TYPES_H */
|
198
os/src/drivers/framebuffer/vesa/include/x86emu/x86emu.h
Normal file
198
os/src/drivers/framebuffer/vesa/include/x86emu/x86emu.h
Normal file
@ -0,0 +1,198 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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: Header file for public specific functions.
|
||||
* Any application linking against us should only
|
||||
* include this header
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __X86EMU_X86EMU_H
|
||||
#define __X86EMU_X86EMU_H
|
||||
|
||||
#ifdef SCITECH
|
||||
#include "scitech.h"
|
||||
#define X86API _ASMAPI
|
||||
#define X86APIP _ASMAPIP
|
||||
typedef int X86EMU_pioAddr;
|
||||
#else
|
||||
#include <x86emu/types.h>
|
||||
#define X86API __attribute__((regparm(3)))
|
||||
#define X86APIP * __attribute__((regparm(3)))
|
||||
#endif
|
||||
#include <x86emu/regs.h>
|
||||
|
||||
/*---------------------- Macros and type definitions ----------------------*/
|
||||
|
||||
#ifdef PACK
|
||||
# pragma PACK /* Don't pack structs with function pointers! */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
REMARKS:
|
||||
Data structure containing ponters to programmed I/O functions used by the
|
||||
emulator. This is used so that the user program can hook all programmed
|
||||
I/O for the emulator to handled as necessary by the user program. By
|
||||
default the emulator contains simple functions that do not do access the
|
||||
hardware in any way. To allow the emualtor access the hardware, you will
|
||||
need to override the programmed I/O functions using the X86EMU_setupPioFuncs
|
||||
function.
|
||||
|
||||
HEADER:
|
||||
x86emu.h
|
||||
|
||||
MEMBERS:
|
||||
inb - Function to read a byte from an I/O port
|
||||
inw - Function to read a word from an I/O port
|
||||
inl - Function to read a dword from an I/O port
|
||||
outb - Function to write a byte to an I/O port
|
||||
outw - Function to write a word to an I/O port
|
||||
outl - Function to write a dword to an I/O port
|
||||
****************************************************************************/
|
||||
typedef struct {
|
||||
u8 (X86APIP inb)(X86EMU_pioAddr addr);
|
||||
u16 (X86APIP inw)(X86EMU_pioAddr addr);
|
||||
u32 (X86APIP inl)(X86EMU_pioAddr addr);
|
||||
void (X86APIP outb)(X86EMU_pioAddr addr, u8 val);
|
||||
void (X86APIP outw)(X86EMU_pioAddr addr, u16 val);
|
||||
void (X86APIP outl)(X86EMU_pioAddr addr, u32 val);
|
||||
} X86EMU_pioFuncs;
|
||||
|
||||
/****************************************************************************
|
||||
REMARKS:
|
||||
Data structure containing ponters to memory access functions used by the
|
||||
emulator. This is used so that the user program can hook all memory
|
||||
access functions as necessary for the emulator. By default the emulator
|
||||
contains simple functions that only access the internal memory of the
|
||||
emulator. If you need specialised functions to handle access to different
|
||||
types of memory (ie: hardware framebuffer accesses and BIOS memory access
|
||||
etc), you will need to override this using the X86EMU_setupMemFuncs
|
||||
function.
|
||||
|
||||
HEADER:
|
||||
x86emu.h
|
||||
|
||||
MEMBERS:
|
||||
rdb - Function to read a byte from an address
|
||||
rdw - Function to read a word from an address
|
||||
rdl - Function to read a dword from an address
|
||||
wrb - Function to write a byte to an address
|
||||
wrw - Function to write a word to an address
|
||||
wrl - Function to write a dword to an address
|
||||
****************************************************************************/
|
||||
typedef struct {
|
||||
u8 (X86APIP rdb)(u32 addr);
|
||||
u16 (X86APIP rdw)(u32 addr);
|
||||
u32 (X86APIP rdl)(u32 addr);
|
||||
void (X86APIP wrb)(u32 addr, u8 val);
|
||||
void (X86APIP wrw)(u32 addr, u16 val);
|
||||
void (X86APIP wrl)(u32 addr, u32 val);
|
||||
} X86EMU_memFuncs;
|
||||
|
||||
/****************************************************************************
|
||||
Here are the default memory read and write
|
||||
function in case they are needed as fallbacks.
|
||||
***************************************************************************/
|
||||
extern u8 X86API rdb(u32 addr);
|
||||
extern u16 X86API rdw(u32 addr);
|
||||
extern u32 X86API rdl(u32 addr);
|
||||
extern void X86API wrb(u32 addr, u8 val);
|
||||
extern void X86API wrw(u32 addr, u16 val);
|
||||
extern void X86API wrl(u32 addr, u32 val);
|
||||
|
||||
#ifdef END_PACK
|
||||
# pragma END_PACK
|
||||
#endif
|
||||
|
||||
/*--------------------- type definitions -----------------------------------*/
|
||||
|
||||
typedef void (X86APIP X86EMU_intrFuncs)(int num);
|
||||
extern X86EMU_intrFuncs _X86EMU_intrTab[256];
|
||||
|
||||
/*-------------------------- Function Prototypes --------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Use "C" linkage when in C++ mode */
|
||||
#endif
|
||||
|
||||
void X86EMU_setupMemFuncs(X86EMU_memFuncs *funcs);
|
||||
void X86EMU_setupPioFuncs(X86EMU_pioFuncs *funcs);
|
||||
void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]);
|
||||
void X86EMU_prepareForInt(int num);
|
||||
|
||||
/* decode.c */
|
||||
|
||||
void X86EMU_exec(void);
|
||||
void X86EMU_halt_sys(void);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define HALT_SYS() \
|
||||
printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \
|
||||
X86EMU_halt_sys()
|
||||
#else
|
||||
#define HALT_SYS() X86EMU_halt_sys()
|
||||
#endif
|
||||
|
||||
/* Debug options */
|
||||
|
||||
#define DEBUG_DECODE_F 0x000001 /* print decoded instruction */
|
||||
#define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */
|
||||
#define DEBUG_STEP_F 0x000004
|
||||
#define DEBUG_DISASSEMBLE_F 0x000008
|
||||
#define DEBUG_BREAK_F 0x000010
|
||||
#define DEBUG_SVC_F 0x000020
|
||||
#define DEBUG_SAVE_IP_CS_F 0x000040
|
||||
#define DEBUG_FS_F 0x000080
|
||||
#define DEBUG_PROC_F 0x000100
|
||||
#define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */
|
||||
#define DEBUG_TRACECALL_F 0x000400
|
||||
#define DEBUG_INSTRUMENT_F 0x000800
|
||||
#define DEBUG_MEM_TRACE_F 0x001000
|
||||
#define DEBUG_IO_TRACE_F 0x002000
|
||||
#define DEBUG_TRACECALL_REGS_F 0x004000
|
||||
#define DEBUG_DECODE_NOPRINT_F 0x008000
|
||||
#define DEBUG_EXIT 0x010000
|
||||
#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F)
|
||||
|
||||
void X86EMU_trace_regs(void);
|
||||
void X86EMU_trace_xregs(void);
|
||||
void X86EMU_dump_memory(u16 seg, u16 off, u32 amt);
|
||||
int X86EMU_trace_on(void);
|
||||
int X86EMU_trace_off(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of "C" linkage for C++ */
|
||||
#endif
|
||||
|
||||
#endif /* __X86EMU_X86EMU_H */
|
258
os/src/drivers/framebuffer/vesa/main.cc
Normal file
258
os/src/drivers/framebuffer/vesa/main.cc
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* \brief Framebuffer driver front end
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2007-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2011 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <root/component.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <framebuffer_session/framebuffer_session.h>
|
||||
#include <rom_session/connection.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <blit/blit.h>
|
||||
#include <os/config.h>
|
||||
|
||||
/* Local */
|
||||
#include "framebuffer.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/***************
|
||||
** Utilities **
|
||||
***************/
|
||||
|
||||
/**
|
||||
* Determine session argument value based on config file and session arguments
|
||||
*
|
||||
* \param attr_name attribute name of config node
|
||||
* \param args session argument string
|
||||
* \param arg_name argument name
|
||||
* \param default default session argument value if value is neither
|
||||
* specified in config node nor in session arguments
|
||||
*/
|
||||
unsigned long session_arg(const char *attr_name, const char *args,
|
||||
const char *arg_name, unsigned long default_value)
|
||||
{
|
||||
unsigned long result = default_value;
|
||||
|
||||
/* try to obtain value from config file */
|
||||
try { Genode::config()->xml_node().attribute(attr_name).value(&result); }
|
||||
catch (...) { }
|
||||
|
||||
/* check session argument to override value from config file */
|
||||
result = Arg_string::find_arg(args, arg_name).ulong_value(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool config_attribute(const char *attr_name)
|
||||
{
|
||||
|
||||
bool result = false;
|
||||
|
||||
try {
|
||||
result = Genode::config()->xml_node().attribute(attr_name).has_value("yes"); }
|
||||
catch (...) {}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************
|
||||
** Implementation of the framebuffer service **
|
||||
***********************************************/
|
||||
|
||||
namespace Framebuffer {
|
||||
|
||||
class Session_component : public Genode::Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned _scr_width, _scr_height, _scr_mode;
|
||||
bool _buffered;
|
||||
|
||||
/* dataspace uses a back buffer (if '_buffered' is true) */
|
||||
Genode::Ram_dataspace_capability _bb_ds;
|
||||
void *_bb_addr;
|
||||
|
||||
/* dataspace of physical frame buffer */
|
||||
Genode::Dataspace_capability _fb_ds;
|
||||
void *_fb_addr;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(unsigned scr_width, unsigned scr_height, unsigned scr_mode,
|
||||
Genode::Dataspace_capability fb_ds, bool buffered)
|
||||
:
|
||||
_scr_width(scr_width), _scr_height(scr_height), _scr_mode(scr_mode),
|
||||
_buffered(buffered), _fb_ds(fb_ds)
|
||||
{
|
||||
if (!_buffered) return;
|
||||
|
||||
if (scr_mode != 16) {
|
||||
PWRN("buffered mode not supported for mode %d", (int)scr_mode);
|
||||
_buffered = false;
|
||||
}
|
||||
|
||||
size_t buf_size = scr_width*scr_height*scr_mode/8;
|
||||
try { _bb_ds = Genode::env()->ram_session()->alloc(buf_size); }
|
||||
catch (...) {
|
||||
PWRN("could not allocate back buffer, disabled buffered output");
|
||||
_buffered = false;
|
||||
}
|
||||
PDBG("use buf size %zd", buf_size);
|
||||
|
||||
if (_buffered && _bb_ds.valid()) {
|
||||
_bb_addr = Genode::env()->rm_session()->attach(_bb_ds);
|
||||
_fb_addr = Genode::env()->rm_session()->attach(_fb_ds);
|
||||
}
|
||||
|
||||
if (_buffered)
|
||||
PINF("using buffered output");
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Session_component()
|
||||
{
|
||||
if (!_buffered) return;
|
||||
|
||||
Genode::env()->rm_session()->detach(_bb_addr);
|
||||
Genode::env()->ram_session()->free(_bb_ds);
|
||||
Genode::env()->rm_session()->detach(_fb_addr);
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
** Framebuffer session interface **
|
||||
***********************************/
|
||||
|
||||
Dataspace_capability dataspace() {
|
||||
return _buffered ? Dataspace_capability(_bb_ds)
|
||||
: Dataspace_capability(_fb_ds); }
|
||||
|
||||
void info(int *out_w, int *out_h, Mode *out_mode)
|
||||
{
|
||||
*out_w = _scr_width;
|
||||
*out_h = _scr_height;
|
||||
|
||||
switch (_scr_mode) {
|
||||
case 16: *out_mode = RGB565; break;
|
||||
default: *out_mode = INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* not implemented */
|
||||
void refresh(int x, int y, int w, int h)
|
||||
{
|
||||
if (!_buffered) return;
|
||||
|
||||
/* clip specified coordinates against screen boundaries */
|
||||
int x2 = min(x + w - 1, (int)_scr_width - 1),
|
||||
y2 = min(y + h - 1, (int)_scr_height - 1);
|
||||
int x1 = max(x, 0),
|
||||
y1 = max(y, 0);
|
||||
if (x1 > x2 || y1 > y2) return;
|
||||
|
||||
/* determine bytes per pixel */
|
||||
int bypp = 0;
|
||||
if (_scr_mode == 16) bypp = 2;
|
||||
if (!bypp) return;
|
||||
|
||||
/* copy pixels from back buffer to physical frame buffer */
|
||||
char *src = (char *)_bb_addr + bypp*(_scr_width*y + x),
|
||||
*dst = (char *)_fb_addr + bypp*(_scr_width*y + x);
|
||||
|
||||
blit(src, bypp*_scr_width, dst, bypp*_scr_width,
|
||||
bypp*(x2 - x1 + 1), y2 - y1 + 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shortcut for single-client root component
|
||||
*/
|
||||
typedef Genode::Root_component<Session_component, Genode::Single_client> Root_component;
|
||||
|
||||
class Root : public Root_component
|
||||
{
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args)
|
||||
{
|
||||
unsigned long scr_width = session_arg("width", args, "fb_width", 1024),
|
||||
scr_height = session_arg("height", args, "fb_height", 768),
|
||||
scr_mode = session_arg("depth", args, "fb_mode", 16);
|
||||
bool buffered = config_attribute("buffered");
|
||||
bool use_current_mode = config_attribute("preinit");
|
||||
|
||||
if (use_current_mode) {
|
||||
if (Framebuffer_drv::use_current_mode()) {
|
||||
PWRN("Could not use preinitialized VESA mode");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
} else if (Framebuffer_drv::set_mode(scr_width, scr_height, scr_mode)) {
|
||||
PWRN("Could not set vesa mode %lux%lu@%lu", scr_width, scr_height,
|
||||
scr_mode);
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
return new (md_alloc()) Session_component(scr_width, scr_height, scr_mode,
|
||||
Framebuffer_drv::hw_framebuffer(),
|
||||
buffered);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc)
|
||||
: Root_component(session_ep, md_alloc) { }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* We need to create capabilities for sessions. Therefore, we request the
|
||||
* CAP service. */
|
||||
static Cap_connection cap;
|
||||
|
||||
/* initialize server entry point */
|
||||
enum { STACK_SIZE = 8*1024 };
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "vesa_ep");
|
||||
|
||||
/* init driver back end */
|
||||
if (Framebuffer_drv::init()) {
|
||||
PERR("H/W driver init failed");
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* entry point serving framebuffer root interface */
|
||||
static Framebuffer::Root fb_root(&ep, env()->heap());
|
||||
|
||||
/* tell parent about the service */
|
||||
env()->parent()->announce(ep.manage(&fb_root));
|
||||
|
||||
/* main's done - go to sleep */
|
||||
|
||||
sleep_forever();
|
||||
return 0;
|
||||
}
|
10
os/src/drivers/framebuffer/vesa/target.mk
Normal file
10
os/src/drivers/framebuffer/vesa/target.mk
Normal file
@ -0,0 +1,10 @@
|
||||
TARGET = vesa_drv
|
||||
REQUIRES = vesa
|
||||
SRC_CC = main.cc framebuffer.cc ifx86emu.cc hw_emul.cc
|
||||
CC_OPT += -fomit-frame-pointer -DNO_SYS_HEADERS
|
||||
SRC_C = decode.c fpu.c ops.c ops2.c prim_ops.c sys.c
|
||||
LIBS = cxx env server blit
|
||||
INC_DIR += $(PRG_DIR)/include $(PRG_DIR)/contrib
|
||||
|
||||
vpath %.c $(PRG_DIR)/contrib
|
||||
|
Reference in New Issue
Block a user