/*
 * power sim.h
 *
 * The integer instruction side of this emulator is portable if sizeof(long) >= 4
 * Floating point emulation assumes:
 *	sizeof(ulong) == sizeof(float)
 *	sizeof(ulong)*2 == sizeof(double) <= sizeof(vlong)
 *	unions of double & vlong have no padding
 *	vlongs provide at least 64 bits precision
 */
#include "/power/include/ureg.h"
#define	USERADDR	0xC0000000
#define	UREGADDR	(USERADDR+BY2PG-4-0xA0)
#define USER_REG(x)	(UREGADDR+(ulong)(x))
#define	REGOFF(x)	(USER_REG(&((struct Ureg *) 0)->x))

typedef struct Registers Registers;
typedef struct Segment Segment;
typedef struct Memory Memory;
typedef struct Inset Inset;
typedef struct Inst Inst;
typedef struct Icache Icache;
typedef struct Breakpoint Breakpoint;

enum
{
	Instruction	= 1,
	Read		= 2,
	Write		= 4,
	Access		= 2|4,
	Equal		= 4|8,
};

struct Breakpoint
{
	int		type;		/* Instruction/Read/Access/Write/Equal */
	ulong		addr;		/* Place at address */
	int		count;		/* To execute count times or value */
	int		done;		/* How many times passed through */
	Breakpoint	*next;		/* Link to next one */
};

enum
{
	Iload,
	Istore,
	Iarith,
	Ilog,
	Ibranch,
	Ireg,
	Isyscall,
	Ifloat,
	Inop,
	Icontrol,
};

struct Icache
{
	int	on;			/* Turned on */
	int	linesize;		/* Line size in bytes */
	int	stall;			/* Cache stalls */
	int	*lines;			/* Tag array */
	int*	(*hash)(ulong);		/* Hash function */
	char	*hashtext;		/* What the function looks like */
};

struct Inset
{
	Inst	*tab;		/* indexed by extended opcode */
	int	nel;
};

struct Inst
{
	void 	(*func)(ulong);
	char	*name;
	int	type;
	int	count;
	int	taken;
};

struct Registers
{
	ulong	pc;
	ulong	ir;
	Inst	*ip;
	long	r[32];
	ulong	ctr;
	ulong	cr;
	ulong	xer;
	ulong	lr;
	ulong	fpscr;
	ulong	dec;
	ulong	tbl;
	ulong	tbu;
	double	fd[32];
};

enum
{
	MemRead,
	MemReadstring,
	MemWrite,
};

enum
{
	Stack,
	Text,
	Data,
	Bss,
	Nseg,
};

struct Segment
{
	short	type;
	ulong	base;
	ulong	end;
	ulong	fileoff;
	ulong	fileend;
	int	rss;
	int	refs;
	uchar	**table;
};

struct Memory
{
	Segment	seg[Nseg];
};

void		fatal(int, char*, ...);
void		fpreginit(void);
void		run(void);
void		undef(ulong);
void		unimp(ulong);
void		dumpreg(void);
void		dumpfreg(void);
void		dumpdreg(void);
void*		emalloc(ulong);
void*		erealloc(void*, ulong, ulong);
void*		vaddr(ulong);
void		itrace(char *, ...);
void		segsum(void);
void		sc(ulong);
char*		memio(char*, ulong, int, int);
ulong		getmem_w(ulong);
ulong		ifetch(ulong);
ushort		getmem_h(ulong);
void		putmem_w(ulong, ulong);
uchar		getmem_b(ulong);
void		putmem_b(ulong, uchar);
uvlong		getmem_v(ulong);
ulong		getmem_4(ulong);
ulong		getmem_2(ulong);
void		putmem_v(ulong, uvlong);
void		putmem_h(ulong, short);
void		isum(void);
void		initicache(void);
void		updateicache(ulong addr);
long		lnrand(long);
void		randseed(long, long);
void		cmd(void);
void		brkchk(ulong, int);
void		delbpt(char*);
void		breakpoint(char*, char*);
char*		nextc(char*);
ulong		expr(char*);
void		initstk(int, char**);
void		initmap(void);
void		inithdr(int);
void		reset(void);
void		dobplist(void);
void		procinit(int);
void		printsource(long);
void		printparams(Symbol *, ulong);
void		printlocals(Symbol *, ulong);
void		stktrace(int);
void		iprofile(void);

/* Globals */
Extern 		Registers reg;
Extern 		Memory memory;
Extern		int text;
Extern		int trace;
Extern 		int sysdbg;
Extern 		int calltree;
Extern		Icache icache;
Extern		int count;
Extern		jmp_buf errjmp;
Extern		Breakpoint *bplist;
Extern		int atbpt;
Extern		int membpt;
Extern		int cmdcount;
Extern		int nopcount;
Extern		ulong dot;
extern		char *file;
Extern		Biobuf *bioout;
Extern		Biobuf *bin;
Extern		Inst *ci;
Extern		ulong *iprof;
Extern		ulong	iprofsize;
Extern		ulong loadlock;
extern		int datasize;		
extern		int printcol;
Extern		Map *symmap;
extern		ulong bits[];

extern		Inset ops0, ops19, ops31, ops59, ops63a, ops63b;

/* Plan9 Kernel constants */
#define	BY2PG		4096
#define BY2WD		4
#define UTZERO		0x1000
#define TSTKSIZ		32
#define TSTACKTOP	0x20000000
#define STACKTOP	(TSTACKTOP-TSTKSIZ*BY2PG)
#define STACKSIZE	(4*1024*1024)

#define PROFGRAN	4
#define NOP		0x80300000
#define SIGNBIT		0x80000000


enum {
	CRLT = 1<<31,
	CRGT = 1<<30,
	CREQ = 1<<29,
	CRSO = 1<<28,
	CRFU = CRSO,

	CRFX = 1<<27,
	CRFEX = 1<<26,
	CRVX = 1<<25,
	CROX = 1<<24,
};

#define getCR(x,w) (((w)>>(28-(x*4)))&0xF)
#define mkCR(x,v) (((v)&0xF)<<(28-(x*4)))

#define simm(xx, ii)	xx = (short)(ii&0xFFFF);
#define uimm(xx, ii)	xx = ii&0xFFFF;
#define imms(xx, ii) xx = ii<<16;
#define getairr(i)	rd = (i>>21)&0x1f; ra = (i>>16)&0x1f; simm(imm,i)
#define getarrr(i)	rd = (i>>21)&0x1f; ra = (i>>16)&0x1f; rb = (i>>11)&0x1f;
#define getbobi(i)	bo = (i>>21)&0x1f; bi = (i>>16)&0x1f; xx = (i>>11)&0x1f;
#define getlirr(i)	rs = (i>>21)&0x1f; ra = (i>>16)&0x1f; uimm(imm,i)
#define getlrrr(i)	rs = (i>>21)&0x1f; ra = (i>>16)&0x1f; rb = (i>>11)&0x1f;

#define OP(o,xo) ((o<<26)|(xo<<1))	/* build an operation */
#define xop(a,b) ((b<<6)|a)	/* compact form for use in a decoding switch on op/xo */
#define getop(i) ((i>>26)&0x3F)
#define getxo(i) ((i>>1)&0x3FF)

#define	FPS_FX	(1<<31)	/* exception summary (sticky) */
#define	FPS_EX	(1<<30)	/* enabled exception summary */
#define	FPS_VX	(1<<29)	/* invalid operation exception summary */
#define	FPS_OX	(1<<28)	/* overflow exception OX (sticky) */
#define	FPS_UX	(1<<27)	/* underflow exception UX (sticky) */
#define	FPS_ZX	(1<<26)	/* zero divide exception ZX (sticky) */
#define	FPS_XX	(1<<25)	/* inexact exception XX (sticky) */
#define	FPS_VXSNAN (1<<24)	/* invalid operation exception for SNaN (sticky) */
#define	FPS_VXISI	(1<<23)	/* invalid operation exception for ∞-∞ (sticky) */
#define	FPS_VXIDI	(1<<22)	/* invalid operation exception for ∞/∞ (sticky) */
#define	FPS_VXZDZ (1<<21)	/* invalid operation exception for 0/0 (sticky) */
#define	FPS_VXIMZ	(1<<20)	/* invalid operation exception for ∞*0 (sticky) */
#define	FPS_VXVC	(1<<19)	/* invalid operation exception for invalid compare (sticky) */
#define	FPS_FR	(1<<18)	/* fraction rounded */
#define	FPS_FI	(1<<17)	/* fraction inexact */
#define	FPS_FPRF	(1<<16)	/* floating point result class */
#define	FPS_FPCC	(0xF<<12)	/* <, >, =, unordered */
#define	FPS_VXCVI	(1<<8)	/* enable exception for invalid integer convert (sticky) */
#define	FPS_VE	(1<<7)	/* invalid operation exception enable */
#define	FPS_OE	(1<<6)	/* enable overflow exceptions */
#define	FPS_UE	(1<<5)	/* enable underflow */
#define	FPS_ZE	(1<<4)	/* enable zero divide */
#define	FPS_XE	(1<<3)	/* enable inexact exceptions */
#define	FPS_RN	(3<<0)	/* rounding mode */

#define	XER_SO	(1<<31)
#define	XER_OV	(1<<30)
#define	XER_CA	(1<<29)

#define	Rc	1
#define	OE	0x400
