/***************************************************************************

	cpuintrf.h

	Core CPU interface functions and definitions.

***************************************************************************/

#ifndef CPUINTRF_H
#define CPUINTRF_H

#include "osd_cpu.h"
#include "memory.h"
#include "timer.h"

#ifdef __cplusplus
extern "C" {
#endif


/*************************************
 *
 *	Enum listing all the CPUs
 *
 *************************************/

/* the following list is automatically generated by makelist.pl - don't edit manually! */
enum
{
	CPU_DUMMY,
	CPU_Z80,
	CPU_M68000,
	CPU_M68020,
    CPU_COUNT
};



/*************************************
 *
 *	Interrupt line constants
 *
 *************************************/

enum
{
	/* line states */
	CLEAR_LINE = 0,				/* clear (a fired, held or pulsed) line */
	ASSERT_LINE,				/* assert an interrupt immediately */
	HOLD_LINE,					/* hold interrupt line until acknowledged */
	PULSE_LINE,					/* pulse interrupt line for one instruction */

	/* internal flags (not for use by drivers!) */
	INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE,
	INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE,

	/* interrupt parameters */
	MAX_IRQ_LINES =	8,			/* maximum number of IRQ lines per CPU */
	IRQ_LINE_NMI = 127			/* IRQ line for NMIs */
};



/*************************************
 *
 *	CPU information constants
 *
 *************************************/

/* get_reg/set_reg constants */
enum
{
	MAX_REGS = 128,				/* maximum number of register of any CPU */

	/* This value is passed to activecpu_get_reg to retrieve the previous
	 * program counter value, ie. before a CPU emulation started
	 * to fetch opcodes and arguments for the current instrution. */
	REG_PREVIOUSPC = -1,

	/* This value is passed to activecpu_get_reg to retrieve the current
	 * program counter value. */
	REG_PC = -2,

	/* This value is passed to activecpu_get_reg to retrieve the current
	 * stack pointer value. */
	REG_SP = -3,

	/* This value is passed to activecpu_get_reg/activecpu_set_reg, instead of one of
	 * the names from the enum a CPU core defines for it's registers,
	 * to get or set the contents of the memory pointed to by a stack pointer.
	 * You can specify the n'th element on the stack by (REG_SP_CONTENTS-n),
	 * ie. lower negative values. The actual element size (UINT16 or UINT32)
	 * depends on the CPU core. */
	REG_SP_CONTENTS = -4
};


/* endianness constants */
enum
{
	CPU_IS_LE = 0,				/* emulated CPU is little endian */
	CPU_IS_BE					/* emulated CPU is big endian */
};


/* Values passed to the cpu_info function of a core to retrieve information */
enum
{
	CPU_INFO_REG,
	CPU_INFO_FLAGS = MAX_REGS,
	CPU_INFO_NAME,
	CPU_INFO_FAMILY,
	CPU_INFO_VERSION,
	CPU_INFO_FILE,
	CPU_INFO_CREDITS,
	CPU_INFO_REG_LAYOUT,
	CPU_INFO_WIN_LAYOUT
};



/*************************************
 *
 *	Core CPU interface structure
 *
 *************************************/

struct cpu_interface
{
	/* index (used to make sure we mach the enum above */
	unsigned	cpu_num;

	/* table of core functions */
	void		(*init)(void);
	void		(*reset)(void *param);
	void		(*exit)(void);
	int			(*execute)(int cycles);
	void		(*burn)(int cycles);
	unsigned	(*get_context)(void *reg);
	void		(*set_context)(void *reg);
	const void *(*get_cycle_table)(int which);
	void		(*set_cycle_table)(int which, void *new_table);
	unsigned	(*get_reg)(int regnum);
	void		(*set_reg)(int regnum, unsigned val);
	void		(*set_irq_line)(int irqline, int linestate);
	void		(*set_irq_callback)(int(*callback)(int irqline));
	const char *(*cpu_info)(void *context,int regnum);
	unsigned	(*cpu_dasm)(char *buffer,unsigned pc);

	/* IRQ and clock information */
	unsigned	num_irqs;
	int			default_vector;
	int *		icount;
	double		overclock;

	/* memory information */
	int			databus_width;
	mem_read_handler memory_read;
	mem_write_handler memory_write;
	mem_read_handler internal_read;
	mem_write_handler internal_write;
	offs_t		pgm_memory_base;
	void		(*set_op_base)(offs_t pc);
	int			address_shift;
	unsigned	address_bits;
	unsigned	endianess;
	unsigned	align_unit;
	unsigned	max_inst_len;
};



/*************************************
 *
 *	 Core CPU interface functions
 *
 *************************************/

/* reset the internal CPU tracking */
int cpuintrf_init(void);

/* set up the interface for one CPU of a given type */
int	cpuintrf_init_cpu(int cpunum, int cputype);

/* clean up the interface for one CPU */
void cpuintrf_exit_cpu(int cpunum);

/* remember the previous context and set a new one */
void cpuintrf_push_context(int cpunum);

/* restore the previous context */
void cpuintrf_pop_context(void);



/*************************************
 *
 *	 Active CPU acccessors
 *
 *************************************/

/* apply a +/- to the current icount */
void activecpu_adjust_icount(int delta);

/* return the current icount */
int activecpu_get_icount(void);

/* ensure banking is reset properly */
void activecpu_reset_banking(void);

/* set the IRQ line on a CPU -- drivers use cpu_set_irq_line() */
void activecpu_set_irq_line(int irqline, int state);

/* return a pointer to the active cycle count table for the active CPU */
const void *activecpu_get_cycle_table(int which);

/* set a pointer to the active cycle count table for the active CPU */
void activecpu_set_cycle_tbl(int which, void *new_table);

/* return the value of a register on the active CPU */
unsigned activecpu_get_reg(int regnum);

/* set the value of a register on the active CPU */
void activecpu_set_reg(int regnum, unsigned val);

/* return the PC, corrected to a byte offset, on the active CPU */
offs_t activecpu_get_pc_byte(void);

/* update the banking on the active CPU */
void activecpu_set_op_base(unsigned val);

/* disassemble a line at a given PC on the active CPU */
unsigned activecpu_dasm(char *buffer, unsigned pc);

/* return a string containing the state of the flags on the active CPU */
const char *activecpu_flags(void);

/* return a string containing the value of a register on the active CPU */
const char *activecpu_dump_reg(int regnum);

/* return a string containing the state of the active CPU */
const char *activecpu_dump_state(void);

/* return the default IRQ vector for the active CPU */
int activecpu_default_irq_vector(void);

/* return the width of the address bus on the active CPU */
unsigned activecpu_address_bits(void);

/* return the active address mask on the active CPU */
unsigned activecpu_address_mask(void);

/* return the shift value to convert from address to bytes on the active CPU */
int activecpu_address_shift(void);

/* return the endianess of the active CPU */
unsigned activecpu_endianess(void);

/* return the width of the data bus on the active CPU */
unsigned activecpu_databus_width(void);

/* return the required alignment of data accesses on the active CPU */
unsigned activecpu_align_unit(void);

/* return the maximum length of one instruction on the active CPU */
unsigned activecpu_max_inst_len(void);

/* return a string containing the name of the active CPU */
const char *activecpu_name(void);

/* return a string containing the family of the active CPU */
const char *activecpu_core_family(void);

/* return a string containing the version of the active CPU */
const char *activecpu_core_version(void);

/* return a string containing the filename for the emulator of the active CPU */
const char *activecpu_core_file(void);

/* return a string containing the emulation credits for the active CPU */
const char *activecpu_core_credits(void);

/* return a string containing the registers of the active CPU */
const char *activecpu_reg_layout(void);

/* return a string containing the debugger layout of the active CPU */
const char *activecpu_win_layout(void);



/*************************************
 *
 *	 Specific CPU acccessors
 *
 *************************************/

/* execute the requested cycles on a given CPU */
int cpunum_execute(int cpunum, int cycles);

/* signal a reset and set the IRQ ack callback for a given CPU */
void cpunum_reset(int cpunum, void *param, int (*irqack)(int));

/* read a byte from another CPU's memory space */
data8_t cpunum_read_byte(int cpunum, offs_t address);

/* write a byte from another CPU's memory space */
void cpunum_write_byte(int cpunum, offs_t address, data8_t data);

/* return a pointer to the saved context of a given CPU, or NULL if the
   context is active (and contained within the CPU core */
void *cpunum_get_context_ptr(int cpunum);

/* return a pointer to the active cycle count table for a given CPU */
const void *cpunum_get_cycle_table(int cpunum, int which);

/* set a pointer to the active cycle count table for a given CPU */
void cpunum_set_cycle_tbl(int cpunum, int which, void *new_table);

/* return the value of a register on a given CPU */
unsigned cpunum_get_reg(int cpunum, int regnum);

/* set the value of a register on a given CPU */
void cpunum_set_reg(int cpunum, int regnum, unsigned val);

/* return the PC, corrected to a byte offset, on a given CPU */
offs_t cpunum_get_pc_byte(int cpunum);

/* update the banking on a given CPU */
void cpunum_set_op_base(int cpunum, unsigned val);

/* disassemble a line at a given PC on a given CPU */
unsigned cpunum_dasm(int cpunum, char *buffer, unsigned pc);

/* return a string containing the state of the flags on a given CPU */
const char *cpunum_flags(int cpunum);

/* return a string containing the value of a register on a given CPU */
const char *cpunum_dump_reg(int cpunum, int regnum);

/* return a string containing the state of a given CPU */
const char *cpunum_dump_state(int cpunum);

/* return the default IRQ vector for a given CPU */
int cpunum_default_irq_vector(int cpunum);

/* return the width of the address bus on a given CPU */
unsigned cpunum_address_bits(int cpunum);

/* return the active address mask on a given CPU */
unsigned cpunum_address_mask(int cpunum);

/* return the shift value to convert from address to bytes on a given CPU */
int cpunum_address_shift(int cpunum);

/* return the endianess of a given CPU */
unsigned cpunum_endianess(int cpunum);

/* return the width of the data bus on a given CPU */
unsigned cpunum_databus_width(int cpunum);

/* return the required alignment of data accesses on a given CPU */
unsigned cpunum_align_unit(int cpunum);

/* return the maximum length of one instruction on a given CPU */
unsigned cpunum_max_inst_len(int cpunum);

/* return a string containing the name of a given CPU */
const char *cpunum_name(int cpunum);

/* return a string containing the family of a given CPU */
const char *cpunum_core_family(int cpunum);

/* return a string containing the version of a given CPU */
const char *cpunum_core_version(int cpunum);

/* return a string containing the filename for the emulator of a given CPU */
const char *cpunum_core_file(int cpunum);

/* return a string containing the emulation credits for a given CPU */
const char *cpunum_core_credits(int cpunum);

/* return a string containing the registers of a given CPU */
const char *cpunum_reg_layout(int cpunum);

/* return a string containing the debugger layout of a given CPU */
const char *cpunum_win_layout(int cpunum);



/*************************************
 *
 *	 CPU type acccessors
 *
 *************************************/

/* return the default IRQ vector for a given CPU type */
int cputype_default_irq_vector(int cputype);

/* return the width of the address bus on a given CPU type */
unsigned cputype_address_bits(int cputype);

/* return the active address mask on a given CPU type */
unsigned cputype_address_mask(int cputype);

/* return the shift value to convert from address to bytes on a given CPU type */
int cputype_address_shift(int cputype);

/* return the endianess of a given CPU type */
unsigned cputype_endianess(int cputype);

/* return the width of the data bus on a given CPU type */
unsigned cputype_databus_width(int cputype);

/* return the required alignment of data accesses on a given CPU type */
unsigned cputype_align_unit(int cputype);

/* return the maximum length of one instruction on a given CPU type */
unsigned cputype_max_inst_len(int cputype);

/* return a string containing the name of a given CPU type */
const char *cputype_name(int cputype);

/* return a string containing the family of a given CPU type */
const char *cputype_core_family(int cputype);

/* return a string containing the version of a given CPU type */
const char *cputype_core_version(int cputype);

/* return a string containing the filename for the emulator of a given CPU type */
const char *cputype_core_file(int cputype);

/* return a string containing the emulation credits for a given CPU type */
const char *cputype_core_credits(int cputype);

/* return a string containing the registers of a given CPU type */
const char *cputype_reg_layout(int cputype);

/* return a string containing the debugger layout of a given CPU type */
const char *cputype_win_layout(int cputype);



/*************************************
 *
 *	 Miscellaneous functions
 *
 *************************************/

/* dump the states of all CPUs */
void cpu_dump_states(void);

/* set a callback function for reset on the 68k */
void cpu_set_m68k_reset(int cpunum, void (*resetfn)(void));



/*************************************
 *
 *	 Macros
 *
 *************************************/

#define		activecpu_get_previouspc()	activecpu_get_reg(REG_PREVIOUSPC)
#define		activecpu_get_pc()			activecpu_get_reg(REG_PC)
#define		activecpu_get_sp()			activecpu_get_reg(REG_SP)
#define		activecpu_set_pc(val)		activecpu_set_reg(REG_PC, val)
#define		activecpu_set_sp(val)		activecpu_set_reg(REG_SP, val)

#define		cpunum_get_previouspc(cpu)	cpunum_get_reg(cpu, REG_PREVIOUSPC)
#define		cpunum_get_pc(cpu)			cpunum_get_reg(cpu, REG_PC)
#define		cpunum_get_sp(cpu)			cpunum_get_reg(cpu, REG_SP)
#define		cpunum_set_pc(cpu, val)		cpunum_set_reg(cpu, REG_PC, val)
#define		cpunum_set_sp(cpu, val)		cpunum_set_reg(cpu, REG_SP, val)

/* this is kind of gross - is it necessary */
#define 	cpu_geturnpc() 				activecpu_get_reg(REG_SP_CONTENTS)



/*************************************
 *
 *	 CPU interface accessors
 *
 *************************************/

/* return a pointer to the interface struct for a given CPU type */
INLINE const struct cpu_interface *cputype_get_interface(int cputype)
{
	extern const struct cpu_interface cpuintrf[];
	return &cpuintrf[cputype];
}


/* return a the index of the active CPU */
INLINE int cpu_getactivecpu(void)
{
	extern int activecpu;
	return activecpu;
}


/* return a the total number of registered CPUs */
INLINE int cpu_gettotalcpu(void)
{
	extern int totalcpu;
	return totalcpu;
}



#ifdef __cplusplus
}
#endif

#endif	/* CPUINTRF_H */

