/*
 * $Date: $
 * $Source: $
 * $Revision: $
 * $State: $
 *
 * $Log: $
 *
 * DANG_END_CHANGELOG
 */

#ifndef _i386_LINUX_CPU_H
#define _i386_LINUX_CPU_H

#include "arch/types.h"

#undef BIOSSEG
#include <linux/vm86.h>

#define _regs vm86s.regs

#define MACH_PORT_NULL    NULL
#define UNCHANGED         2

#define MASK8(x)	((x) & 0xff)
#define MASK16(x)	((x) & 0xffff)
#define HIGH(x)		MASK8((unsigned long)(x) >> 8)
#define LOW(x)		MASK8((unsigned long)(x))

#ifndef WORD
#define WORD(x)		MASK16((unsigned long)(x))
#endif

#define SETHIGH(x,y) 	(*(x) = (*(x) & ~0xff00) | ((MASK8(y))<<8))
#define SETLOW(x,y) 	(*(x) = (*(x) & ~0xff) | (MASK8(y)))
#define SETWORD(x,y)	(*(x) = (*(x) & ~0xffff) | (MASK16(y)))

#define Addr_8086(x,y)    (( ((x) & 0xffff) << 4) + ((y) & 0xffff))
#define Addr(s,x,y)       Addr_8086(((s)->x), ((s)->y))

/* all registers as a structure */
#define REGS  vm86s.regs

/* this is used like: REG(eax) = 0xFFFFFFF */
#define REG(reg) (REGS.##reg)
#define READ_SEG_REG(reg) (REGS.##reg)
#define WRITE_SEG_REG(reg, val) REGS.##reg = (val)

#define _AL      (*(Bit8u *)&REG(eax))
#define _BL      (*(Bit8u *)&REG(ebx))
#define _CL      (*(Bit8u *)&REG(ecx))
#define _DL      (*(Bit8u *)&REG(edx))
#define _AH      (*(((Bit8u *)&REG(eax))+1))
#define _BH      (*(((Bit8u *)&REG(ebx))+1))
#define _CH      (*(((Bit8u *)&REG(ecx))+1))
#define _DH      (*(((Bit8u *)&REG(edx))+1))
#define _AX      (*(Bit16u *)&REG(eax))
#define _BX      (*(Bit16u *)&REG(ebx))
#define _CX      (*(Bit16u *)&REG(ecx))
#define _DX      (*(Bit16u *)&REG(edx))
#define _SI      (*(Bit16u *)&REG(esi))
#define _DI      (*(Bit16u *)&REG(edi))
#define _BP      (*(Bit16u *)&REG(ebp))
#define _SP      (*(Bit16u *)&REG(esp))
#define _IP      (*(Bit16u *)&REG(eip))
#define _EAX     (REG(eax))
#define _EBX     (REG(ebx))
#define _ECX     (REG(ecx))
#define _EDX     (REG(edx))
#define _ESI     (REG(esi))
#define _EDI     (REG(edi))
#define _EBP     (REG(ebp))
#define _ESP     (REG(esp))
#define _EIP     (REG(eip))
#define _CS      (REG(cs))
#define _DS      (REG(ds))
#define _SS      (REG(ss))
#define _ES      (REG(es))
#define _FS      (REG(fs))
#define _GS      (REG(gs))
#define _EFLAGS  (REG(eflags))

/* these are used like:  LO(ax) = 2 (sets al to 2) */
#define LO(reg)  (*(Bit8u *)&REG(e##reg))
#define HI(reg)  (*((Bit8u *)&REG(e##reg) + 1))

#define _LO(reg) (*(Bit8u *)&(scp->e##reg))
#define _HI(reg) (*((Bit8u *)&(scp->e##reg) + 1))

/* these are used like: LWORD(eax) = 65535 (sets ax to 65535) */
#define LWORD(reg)	(*((Bit16u *)&REG(reg)))
#define HWORD(reg)	(*((Bit16u *)&REG(reg) + 1))

#define _LWORD(reg)	(*((Bit16u *)&(scp->##reg)))
#define _HWORD(reg)	(*((Bit16u *)&(scp->##reg) + 1))

/* this is used like: SEG_ADR((char *), es, bx) */
#define SEG_ADR(type, seg, reg)  type((LWORD(seg) << 4) + LWORD(e##reg))

#define WRITE_FLAGS(val)    REG(eflags) = (val)
#define READ_FLAGS()        REG(eflags)

/*
 * nearly directly stolen from Linus : linux/kernel/vm86.c
 *
 * Boy are these ugly, but we need to do the correct 16-bit arithmetic.
 * Gcc makes a mess of it, so we do it inline and use non-obvious calling
 * conventions..
 */
#define pushw(base, ptr, val) \
__asm__ __volatile__( \
	"decw %w0\n\t" \
	"movb %h2,(%1,%0)\n\t" \
	"decw %w0\n\t" \
	"movb %b2,(%1,%0)" \
	: "=r" (ptr) \
	: "r" (base), "q" (val), "0" (ptr))

#define popw(base, ptr) \
({ unsigned long __res; \
__asm__ __volatile__( \
	"movb (%1,%0),%b2\n\t" \
	"incw %w0\n\t" \
	"movb (%1,%0),%h2\n\t" \
	"incw %w0" \
	: "=r" (ptr), "=r" (base), "=q" (__res) \
	: "0" (ptr), "1" (base), "2" (0)); \
__res; })

#define popb(base, ptr) \
({ unsigned long __res; \
__asm__ __volatile__( \
	"movb (%1,%0),%b2\n\t" \
	"incw %w0\n\t" \
	: "=r" (ptr), "=r" (base), "=q" (__res) \
	: "0" (ptr), "1" (base), "2" (0)); \
__res; })

static __inline__ void set_revectored(int nr, struct revectored_struct * bitmap)
{
	__asm__ __volatile__("btsl %1,%0"
		: /* no output */
		:"m" (*bitmap),"r" (nr));
}

static __inline__ void reset_revectored(int nr, struct revectored_struct * bitmap)
{
	__asm__ __volatile__("btrl %1,%0"
		: /* no output */
		:"m" (*bitmap),"r" (nr));
}

/* flags */
#define CF  (1 <<  0)
#define PF  (1 <<  2)
#define AF  (1 <<  4)
#define ZF  (1 <<  6)
#define SF  (1 <<  7)
#define TF  TF_MASK	/* (1 <<  8) */
#define IF  IF_MASK	/* (1 <<  9) */
#define DF  (1 << 10)
#define OF  (1 << 11)
#define NT  NT_MASK	/* (1 << 14) */
#define RF  (1 << 16)
#define VM  VM_MASK	/* (1 << 17) */
#define AC  AC_MASK	/* (1 << 18) */
#define VIF VIF_MASK
#define VIP VIP_MASK
#define ID  ID_MASK

#ifndef IOPL_MASK
#define IOPL_MASK  (3 << 12)
#endif

#define vflags ((READ_FLAGS() & VIF)? WORD(READ_FLAGS()) | IF : WORD(READ_FLAGS()) & ~IF)

#define CARRY   ( WRITE_FLAGS(WORD(READ_FLAGS()) | CF) )
#define NOCARRY ( WRITE_FLAGS(WORD(READ_FLAGS()) & ~CF) )

struct sigcontext_struct {
  unsigned short gs, __gsh;
  unsigned short fs, __fsh;
  unsigned short es, __esh;
  unsigned short ds, __dsh;
  unsigned long edi;
  unsigned long esi;
  unsigned long ebp;
  unsigned long esp;
  unsigned long ebx;
  unsigned long edx;
  unsigned long ecx;
  unsigned long eax;
  unsigned long trapno;
  unsigned long err;
  unsigned long eip;
  unsigned short cs, __csh;
  unsigned long eflags;
  unsigned long esp_at_signal;
  unsigned short ss, __ssh;
  unsigned long i387;
  unsigned long oldmask;
  unsigned long cr2;
};

#define _gs     (scp->gs)
#define _fs     (scp->fs)
#define _es     (scp->es)
#define _ds     (scp->ds)
#define _edi    (scp->edi)
#define _esi    (scp->esi)
#define _ebp    (scp->ebp)
#define _esp    (scp->esp)
#define _ebx    (scp->ebx)
#define _edx    (scp->edx)
#define _ecx    (scp->ecx)
#define _eax    (scp->eax)
#define _err	(scp->err)
#define _trapno (scp->trapno)
#define _eip    (scp->eip)
#define _cs     (scp->cs)
#define _eflags (scp->eflags)
#define _ss     (scp->ss)

#endif /* EMU_CPU_H */
